多年前发现了autoddvpn项目以后,从之前使用dd-wrt到现在用Tomato,都是把这套没人维护的代码不断的修修补补地放到路由上面用。虽然有一些其他搭梯子的方案,但是用OpenVPN加上自定义的routes,用起来感觉是最干净的,所有的用户都不需要在自己的电脑中设置,连接这个路由器的网络就可以自动爬梯了。
不过随着最近GFW越来越强大,它的Advanced DPI对普通的OpenVPN连接会进行干扰,导致使用一段时间就断开,或者干脆就连不上。按照我一贯的作风(懒),装个stunnel以后,把OpenVPN以TCP模式通过stunnel连接也将就用着了。
然后慢慢地发现,在吞吐量高的情况下,通过OpenVPN的所有流量,延迟都会变成非常高(4000ms+),要是看YouTube 1080p的话,别说开其他网页,能不buffering就不错了。OpenVPN用TCP的性能本来就没有UDP的好,加上一层stunnel,性能就更加不要提了。而且stunnel和OpenVPN全部都在路由器上面跑,除非你的是RT-AC68U、R7000这样的ARM路由,否则性能也就别想好到什么地方去了。
也因为这个原因,每当打开Google+各种卡的时候,我都会很自然地打开Chrome寻找替代方案……直到最近,我遇见了tinc。
其实之前也已经看到过关于tinc的一些介绍,但是总觉得挺麻烦的,许多东西都要自己手动去配置(其实还是懒……)。但是实在忍无可忍了,既然决定折腾,那么就动手吧~
经过无数次trial and error,以及在网上参考了一些资料以及tinc的mail list以后,最终成功搭起来了!然后我把我用的脚本以及配置上传到了GitHub。
虽然tinc支持IPv4 and IPv6,但是由于IPv6现在还比较少用的,所以这里就只针对IPv4了。
下面来简单说一下整个过程(以Tomato为例,其他平台配置应该也相似):
Prerequisites
- 首先你得有一个不在GFW里的服务器。我用的是Linode东京的VPS,系统使用Arch Linux。最便宜的套餐$10一个月,一次性购买一年/两年有打折~ 购买链接
- 你需要在路由上安装tinc。这意味着你需要现在路由上部署Optware/Entware。本文使用Entware为例。
- The ability to RTFM and follow instructions.
服务器端配置
i. Enable IPv4 Forwarding in sysctl.conf
首先,你必须把服务器的IPv4转发打开。在大多数Linux发行版中,这个选项默认是关闭的。
在Arch Linux中,你需要在/etc/sysctl.d/
中新建一个文件(例如50-ip_forward.conf
)来让这个设置在启动时自动生效。
在Debian/Ubuntu等系统中,你需要在/etc/sysctl.conf
中添加net.ipv4.ip_forward=1
来让这个设置在启动时自动生效。
CentOS的话……请自行Google,真没什么使用经验。
ii. 安装tinc
我使用的是Arch Linux的community中的tinc,版本为1.0.24-2。AUR中有一个tinc-pre,版本为1.1pre10,这个版本不建议使用,它使用新的experimental协议,配置上会有出入,而且据闻性能没有原来的版本好。
在Debian/Ubuntu中则是
iii. 配置tinc
Arch Linux:
tinc在安装后不会自动在/etc
目录下建立文件夹,我们要手动建立:
这里面的server
是你的NETNAME
,这个名字将用于后面启用服务时使用。hosts
文件夹用于存放每个host的信息,后面会讲到。
写入配置文件:
(a) tinc.conf
的内容
当中Name
的值server
为本机(服务器端)的名称。记住你的名称,在后面还会用到。
(b) tinc-up
的内容
我使用的网段是192.168.4.0/24,你可以根据自己的需要对这个进行更改。记得把其他地方的subnet也改掉哦!最后的iptables规则中,第三条的eth0是你的VPS面向公网的网卡。
(c) tinc-down
的内容
同样,根据需要修改subnet,必须与tinc-up中的保持一致。
(d) hosts/server
的内容
在这里,server
这个文件名必须对应前面在tinc.conf
中设置的Name
参数的值。tinc会根据Name
去匹配hosts
目录下的配置文件。
需要填写的配置文件只有这四个。完成以后,生成private key:
这样会生成一个4096 bit的私钥,生成的密钥保存在默认路径即可。-n
参数后面的server
为你的NETNAME
,即/etc/tinc/server
中server
部分。
Debian/Ubuntu
配置的过程基本相同,但是因为手上没有Debian/Ubuntu的机器,也懒得整VM,所以不能保证正确性。
根据Ubuntu的manpage,Debian/Ubuntu上的tinc所使用的config结构与Arch Linux不同:tincd
将直接读取/etc/tinc
中的内容,无需指定NETNAME
。即:
服务器端的配置暂时告一段落。
客户端(路由器)配置
这里我仅以Tomato + Entware为例。使用其他平台的配置应该大同小异,请自行摸索。
路由器默认你已刷Tomato固件,并且配置Entware环境。具体操作不在此介绍,请自行Google。
文中Entware安装路径为默认的/opt
。
i. 安装tinc
使用Entware的opkg
工具安装tinc
以及git
:
完成安装后,git
可能需要进行额外配置,步骤不在此细述。
ii. 配置tinc
安装完成后,从GitHub上将脚本clone下来:
执行配置脚本setup.sh
(随手写的,有bug请大喊)
客户端的配置暂告一段落。
交换公钥
完成两边的配置以后,需要把生成的公钥放到另外的节点上。如果你是一直按照本文的设置进行的话,那么:
服务器端公钥位于:
Arch Linux
Debian/Ubuntu
客户端公钥位于:
tinc的公钥,当中实际上还包括对应节点的连接信息。例如,在/etc/tinc/server/hosts/server
中:
这代表tincd
将会在YOUR.IP.ADDRESS
的655
端口上监听,允许来自0.0.0.0/0
子网的用户。
在/etc/tinc/hosts/client
中:
则表示该节点被分配到的子网为192.168.4.2/32
。从这里其实可以看出,tinc支持将一个Subnet分配给一个节点,让该节点通过DHCP或者static routing的方式来对整个VPN进行访问。但是我们只是用于简单的routing作gateway,因此分配一个地址就足够了。
那么,交换公钥这个动作就如字面所说的一样了。将服务器端的/etc/tinc/server/hosts/server
放到客户端(路由器)的/opt/etc/tinc/hosts
下;再将客户端的/opt/etc/tinc/hosts/client
放到服务器端的/etc/tinc/server/hosts
下。
这样,两边通过读取tinc.conf
中的Name
来决定自己的身份,客户端通过其中的ConnectTo
参数来决定连接的节点,然后再通过hosts
中的公钥和各自的私钥来进行身份的验证,最后建立连接。
tinc服务自启动
其实都比较简单:
服务器端:
Arch Linux
注意@
后面的server
是你的NETNAME
,即/etc/tinc/server
中server
部分。
Debian/Ubuntu
客户端(路由器):
Tomato的网页GUI中,找到Administration -> Scripts -> WAN Up,填入:
大功告成!
PS: GitHub上我放的脚本其实跟autoddvpn的非常相似,基本上只是把OpenVPN换成了tinc而已。在GitHub的README中,我会简单说明里面各个文件的用途。另外,如果你需要配置多于一个客户端,你只需要把客户端的Subnet地址(即上文中的192.168.4.2)换一下,重新生成private key,和服务器端再交换一下公钥就可以了。
from