Tinc

tinc

Tips

# 稳定版 1.0 版
# 只有 tincd 目录
# apk add tinc
# PreRelease 版 1.1
apk add tinc-pre
modprobe tun
echo tun >> /etc/modules
# echo tun >> /etc/modules-load.d/netdev.conf
# 基础配置
tinc init first
tinc set Interface tun0
tinc set AddressFamily ipv4
# 第一个节点可考虑不设置链接节点
tinc set ConnectTo other
# 变量设置可以指定 host
tinc set sec.Subnet=10.0.0.2/32
# 在配置单个网络时, 设置个别名会比较方便, 使用不同目录或 pid 也可以这样操作
alias tinc='tinc -n main'
# 操作指定网络名时, 可使用环境变量
export NETNAME=main
tinc dump nodes
# 如果执行的命令比较多, 也可以加入交互模式操作
tinc -c .
ADDRESS=10.0.0.1
NETMASK=255.255.255.0
cat > tinc-up <<SH
#!/bin/sh
ifconfig \$INTERFACE $ADDRESS netmask $NETMASK
SH
cat > tinc-down <<SH
#!/bin/sh
ifconfig \$INTERFACE down
SH
chmod +x tinc-*
tincd -Dd4
# 导入别处 export 的配置
tinc import
# 生成邀请码
# 最简便的配置方式
tinc invite 节点名
# 加入
# 会在远程添加主机信息
# 会使用相同的 netname
# tinc-up 和 tinc-down 需要自己配置
tinc join 邀请码
tinc -n main invite thd
# 配置要启动的网络
# NETWORK: main
# 会使用 /etc/tinc/main 配置
nano /etc/conf.d/tinc.networks
rc-service tincd start
# 自启动
rc-update add tincd
# 启动后可以查看日志, 1-5
tinc -n main log 5
# Docker
# ======
# 先在 docker 中进行配置和测试
NETNAME=name
docker run --rm -it -e NETNAME=$NETNAME --cap-add=NET_ADMIN --device=/dev/net/tun -v $PWD/tinc:/etc/tinc wener/tinc sh
# 导入配置
docker run --rm -it -e NETNAME=$NETNAME -v $PWD/tinc:/etc/tinc wener/tinc tinc import
# 启动
docker run -d --restart always \
--net host --cap-add=NET_ADMIN --device=/dev/net/tun \
-e NETNAME=$NETNAME -v $PWD/tinc:/etc/tinc \
--name tinc-$NETNAME wener/tinc
# macOS
# http://tuntaposx.sourceforge.net/
# 新版没有了 devel 参数
# https://github.com/Homebrew/homebrew-core/tree/master/Formula/tinc.rb
curl https://raw.githubusercontent.com/wenerme/homebrew-core/tinc-pre/Formula/tinc-pre.rb > /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/Formula/tinc-pre.rb
brew install tinc-pre
# utun
# ===============
# 在 mac 下, tinc 支持 utun, 可能需要 root 权限
tinc set DeviceType utun
# 确保路径存在, 否则 pid 会存在当前目录
mkdir -p /usr/local/Cellar/tinc/1.1pre15/var/run/
# tun/tap
# ===============
# tuntap 10.13 会安装失败
brew cask install tuntap
# /Library/Extensions/tap.kext
# /Library/Extensions/tun.kext
# /Library/StartupItems/tap
# /Library/StartupItems/tun
# 手动加载
sudo kextload /Library/Extensions/tun.kext
# 失败日志
sudo dmesg
# tun: could not register PF_INET protocol family: 17
# Kext net.sf.tuntaposx.tun start failed (result 0x5).
# Kext net.sf.tuntaposx.tun failed to load (0xdc008017).
# Failed to load kext net.sf.tuntaposx.tun (error 0xdc008017).
# 查看现有的
kextstat | grep tun
# 写在
sudo kextunload -b 名字
# https://tunnelblick.net
# 包含了新的 kext
# 查看具体出错信息
sudo kextutil /Volumes/Tunnelblick/Tunnelblick.app/Contents/Resources/tun-signed.kext
sudo kextutil /Library/Extensions/tun.kext
# Memory allocation failure.
# Untrusted kexts are not allowed

tinc-up

#!/bin/sh
brctl addif br0 $INTERFACE
ifconfig $INTERFACE 0.0.0.0 promisc up
# 该节点作为路由
# iptables -I FORWARD -i $INTERFACE -j ACCEPT
# iptables -t nat -A POSTROUTING -d 10.88.0.0/16 -o $INTERFACE -j MASQUERADE

tinc-fw

#!/bin/sh
iptables -I INPUT -p udp --dport 20656 -j ACCEPT
iptables -I INPUT -p tcp --dport 20656 -j ACCEPT
iptables -I INPUT -i tinc -j ACCEPT
iptables -I FORWARD -i tinc -j ACCEPT

完整的网络配置

# 主节点
export NETNAME=mynet
export NODE=mynet
tinc init $NETNAME
cd /etc/tinc/$NETNAME
# 配置启动脚本
ADDRESS=10.66.1.1
NETMASK=255.255.0.0
cat > tinc-up <<SH
#!/bin/sh
ifconfig \$INTERFACE $ADDRESS netmask $NETMASK
SH
cat > tinc-down <<SH
#!/bin/sh
ifconfig \$INTERFACE down
SH
chmod +x tinc-*
# 配置主节点地址
# 用于其它节点请求的地址, 如果有外网地址
tinc set $NODE.Address=$(curl ipv4.icanhazip.com)
# 如果不想使用默认端口
tinc set $NODE.Port=12345
# 私有子网
tinc set $NODE.Subnet=$ADDRESS/32
# 启动
tinc start
# 邀请其它节点
tinc invite home
# home 节点
# =============
export NETNAME=mynet
export NODE=home
tinc join <INVITE>
cd /etc/tinc/$NETNAME
# 配置启动脚本
ADDRESS=10.66.1.2
NETMASK=255.255.0.0
cat > tinc-up <<SH
#!/bin/sh
ifconfig \$INTERFACE $ADDRESS netmask $NETMASK
SH
cat > tinc-down <<SH
#!/bin/sh
ifconfig \$INTERFACE down
SH
chmod +x tinc-*
# 如果不想使用默认端口
tinc set $NODE.Port=45678
# 私有子网
tinc set $NODE.Subnet=$ADDRESS/32
# svr 节点
# =============
# 如果不能安装 tinc-1.1+ 则可以使用 docker
export NETNAME=mynet
export NODE=home
docker run --rm -it -e NODE=$NODE -e NETNAME=$NETNAME --cap-add=NET_ADMIN --device=/dev/net/tun -v /data/tinc/$NETNAME/$NODE:/etc/tinc wener/tinc sh
tinc join <INVITE>
cd /etc/tinc/$NETNAME
# 配置启动脚本
ADDRESS=10.66.1.3
NETMASK=255.255.0.0
cat > tinc-up <<SH
#!/bin/sh
ifconfig \$INTERFACE $ADDRESS netmask $NETMASK
SH
cat > tinc-down <<SH
#!/bin/sh
ifconfig \$INTERFACE down
SH
chmod +x tinc-*
# 如果不想使用默认端口
tinc set $NODE.Port=45678
# 私有子网
tinc set $NODE.Subnet=$ADDRESS/32
# 退出配置容器
exit
# 运行服务
docker run -d --restart always -v /etc/localtime:/etc/localtime:ro \
--cap-add=NET_ADMIN --device=/dev/net/tun \
-e NETNAME=$NETNAME \
-v /data/tinc/$NETNAME/$NODE:/etc/tinc \
--name tinc-$NETNAME-$NODE wener/tinc

新手教程

基于容器组件网络

Turning

https://www.tinc-vpn.org/documentation-1.1/tinc.conf.5

# The symmetric cipher algorithm used to encrypt UDP packets. 默认 blowfish
# 检测 CPU 是否支持 aes
# grep aes /proc/cpuinfo --color auto
# SHA1 HMAC
# 对启用了 ExperimentalProtocol 不生效
Cipher = aes-128-cbc
# 启用后, 会尝试使用 SPTPS 协议, key 交换会使用 Ephemeral ECDH, 会使用 Ed25519 作为授权, 而不是 RSA, 因此需要先生成 Ed25519
ExperimentalProtocol = yes
# 影响监听和外部 sockets 包, any 会根据操作系统进行创建 ipv4 和 ipv6
# ipv4 | ipv6 | any
AddressFamily = any
# 如果启用, 会自动尝试与其他节点建立 meta 链接, 而不需要设置 ConnectTo
# 该模式下不能使用 0 端口(系统指定的)
# 试验阶段
# yes | no
AutoConnect = no
# 设置广播包发到其他节点的方式, 所有节点需要使用相同的方式, 否则可能会产生路由循环
# no 不发送广播包
# mst 使用 Minimum Spanning Tree, 保证发往每个节点
# direct 只发送给直接访问的节点, 从其他节点接收到的不转发. 如果设置了 IndirectData, 广播包也会发送给有 meta 链接的节点
# 试验阶段
# no | mst | direct
Broadcast = mst
# 转发策略
# 实验阶段
# off 不转发
# internal 内部转发
# kernel 包发往 TUN/TAP 设备, 交由内核转发, 性能更低, 但能使用内核的路由功能
Forwarding = internal
# 尝试发现本机网络中的节点
# 允许与本地节点地址建立直接连接
# 目前, 本地发现机制是通过在 UDP 发现阶段发送本地地址的方式
LocalDiscovery = yes
# 启用后之后使用 /etc/tinc/NETNAME/hosts/ 下的配置信息, 而不会通过连接到别的节点发现新的子网
# experimental
StrictSubnets = no
# 启用后不会转发其他节点间的信息, 只会允许 /etc/tinc/NETNAME/hosts/ 下的节点进行连接, 隐性指定 StrictSubnets
# experimental
TunnelServer = no
# UDP 包的摘要算法, 可使用 LibreSSL 或 OpenSSL 支持的算法, 指定 none 可关闭包验证.
# 对使用 ExperimentalProtocol 的节点不生效
Digest = sha1

FAQ

Peer tries to roll back protocol version to 17.0

使用 1.0 协议

ExperimentalProtocol = no

Could not open /dev/net/tun: No such file or directory

加载 tun 内核模块

modprobe tun
echo tun >> /etc/modules

route

sysctl net.ipv4.ip_forward
sysctl -w net.ipv4.ip_forward=1
# 1. 允许包转发, 会将 eth0 子网的转发到 mynet, 需要在网关节点添加 eth0 的子网才能做到互通
iptables -I FORWARD -i mynet -j ACCEPT
iptables -I FORWARD -i eth0 -j ACCEPT
# 2. NAT 使得 eth0 子网能访问私网
# 如果做了桥接, 这里需要换成桥接网卡
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o mynet -j MASQUERADE
# 如果有多个私网, 也可以考虑限制目标网段
# iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -d 10.10.0.0/16 -o mynet -j MASQUERADE
# 创建用于 docker 使用的网络
# 假设当前节点的子网是 10.10.1.0/24 当前节点的地址是 10.10.1.0
docker network create \
--driver=bridge \
--subnet=10.10.0.0/16 \
--ip-range=10.10.1.0/24 \
--gateway=10.10.1.0 \
--aux-address="my-host=10.10.1.1" \
-o com.docker.network.bridge.name=brmynet \
brmynet
# 允许桥接网卡转发
iptables -I FORWARD -i brmynet -j ACCEPT
# 将 tinc 作为该桥接的 slave
ip li set master brmynet dev mynet
# 或者在 tinc-up 中设置
cat > tinc-up <<SH
#!/bin/sh
ip li set master br$INTERFACE dev $INTERFACE
ip li set dev $INTERFACE up
SH
# 调试
tcpdump -nni mynet icmp

How can I set my linux box as a router to forward ip packets? https://askubuntu.com/q/227369/267103

Linux IP Masquerade HOWTO http://tldp.org/HOWTO/IP-Masquerade-HOWTO/

iptables -I FORWARD -i brwenet -j ACCEPT