记一次openwrt上折腾使用xkcptun,openvpn,ipset的策略路由

工作需求,需要加速外网访问,因此一个国外VPS服务器是必须的。由于外网条件限制,常常会有丢包,因此使用KCP进行加速可以极大的改善高丢包网络下的通讯速度,副作用是会重复发包放大流量,不过一般流量管够随便用,不需要担心。

首先要安装xkcptun:

基于Golang的kcptun无法很好的运行在MIPS环境上,因此使用C编写的xkcptun。

服务端:

我在repo中加入了可以build使用的Dockerfile,直接clone:

git clone https://github.com/ryncsn/xkcptun

之后直接进入目录,修改一下Dockerfile里面的参数,比如密码,端口地址等等,可以直接build了。这些参数应该单独拿出来,不过一时省事先不管了。

docker build -t xkcptun .

我一般习惯用docker-compose来管理:

xkcptun-ovpn:
  image: xkcptun
  net: "host"
  command: xkcp_server -c /etc/xkcptun.json -f
  restart: always
Openwrt(客户端):

直接从这里下载包安装:

https://github.com/gigibox/openwrt-xkcptun/releases

之后修改/etc/config/xkcptun,之后执行

/etc/init.d/xkcptun_client start
/etc/init.d/xkcptun_client enable

没研究UI,我的WNDR4300上只安装openwrt_xkcptun_0.4.409-1_ar71xx.ipk就够了。

此处挖坑

Openwrt-xkcptun release的build编译的有问题,用原repo的编译出来client和server无法连接,经过各种抓包和调试,发现是竟然是大小端的问题。应该重新编译一下修复大小端问题,考虑到Openwrt编译又要好久,就先在自己的repo里dirty hack了一下来兼容老的ar71xx build,因此这个repo编译出的xkcptun与其他的不兼容。

Openvpn配置:

直接使用docker-openvpn进行配置:

https://github.com/kylemanna/docker-openvpn

其中udp://VPN.SERVERNAME.COM换成vpn的地址,并且换成tcp协议,方便kcp进行包装。可以加上一个不存在的子域名前缀,方便之后添加hosts项来让kcp充当代理的作用。

CLIENTNAME是要链接的client name。

生成ovpn文件之后,将其拷到Openwrt设备上,并且在/etc/hosts中添加127.0.0.1 VPN.SERVERNAME.COM,让xkcp监听本地的1194转发到远端的1194,这样就可以让openvpn跑在kcp上面了。

策略路由:

为了完成策略路由,要先安装相关包:

opkg install iptables-mod-nat-extra ipset

opkg remove dnsmasq && opkg install dnsmasq-full

修改/etc/dnsmasq.conf,加入confdir=/etc/dnsmasq.d

建立/etc/dnsmasq.d,使用下面的脚本生成一个配置文件,命名dnsmasq_flist_ipset.conf,扔到/etc/dnsmasq.d/文件夹中:

https://github.com/cokebar/gfwlist2dnsmasq/blob/master/gfwlist2dnsmasq.sh

使用如下命令建立一个ipset list:

ipset -N flist iphash

防止DNS解析问题,先加入两个DNS服务器:

ipset add flist 8.8.8.8
ipset add flist 8.8.4.4

使用iptables做一下标记和允许转发,让标记包走特定路由表:

# iptables mark package matches the ipset
iptables -t mangle -A OUTPUT -j fwmark
iptables -t mangle -A fwmark -m set --match-set flist dst -j MARK --set-mark 0xffff

# Masquirade the package as routing is done before iptables mangle
iptables -t nat -A POSTROUTING -m mark --mark 0xffff -j MASQUERADE

# Route all package using ovpn table
ip rule add fwmark 0xffff table ovpn

# And allow forwarding
iptables -I FORWARD 1 -o tun0 -j ACCEPT

在之前的ovpn文件中加入,实现自动恢复:

script-security 2

up '/bin/sh -c "ip route add default dev tun0 table ovpn"'

这样便可以实现vpn连接自动添加路由和允许iptables转发的功能了,大功告成。

将iptables和ipset相关命令放入/etc/firewall.user,iproute2相关放入/etc/rc.local即可完成自动恢复。