RouterOS单系统实现透明网关
自从接触mikrotik公司的RouterOS系统以来,一直都想以routeros单系统实现内外网自动分流、dns防污染的透明网关。
由于routeros是商业公司开发的闭源路由系统,虽然是基于linux内核,但是并不像openwrt一样可以安装任意软件。
所以在v6版本时代尝试过ipsec、ipip、gre隧道等方式穿墙,效果并不是很好,要么会受到墙的干扰,要么运营商qos太厉害,
要么协议本身限制再公网跑不起速度来。
所以引入了openwrt旁路由,routeros导入国内IP地址表,通过rooting mark的方式实现国内外IP地址分流,把国外IP地址转发给openwrt,openwrt通过ssr+或者passwall等使用ss、ssr、trojen、vless、hysteria等穿墙协议实现国外流量送出墙。
由于openwrt自身的复杂、开源软件质量,以及编译时的细节选项的各种问题,导致openwrt并不是十分稳定,且排查较为困难。
一直认为使用openwrt作为旁路由并不完美。后来routeros系统增加了wireguard,选择合适线路的vps后,可以实现勉强能做到单系统的透明网关,但是最近一段时间wireguard被墙阻断越来越严重,更换端口勉强能用几天。
再后来routeros内置了容器功能,极大的增大了发挥空间,虽然是个严重严格的容器功能。
通过以容器方式起mosdns实现了dns防污染、IPv4和IPv6自定义优先级等功能。
最近研究了一些前人的教程方法后,实现了容器内clash、sing-box、hysteria等程序路由功能。
RouterOS容器实现路由方式穿墙的方法,以hysteria这个简单程序为例。
1,通过hub.docker.com远程仓库拉去镜像或者导入tar文件方式创建容器。
以tar文件方式为例
电脑安装docker desktop并启动
命令行
docker pull alpine
docker save -o alpine.tar alipine
如果routeros是arm版的话
docker pull alpine@sha256:30e6d35703c578ee703230b9dc87ada2ba958c1928615ac8a674fcbbcbb0f281
#sha256:30e6d35703c578ee703230b9dc87ada2ba958c1928615ac8a674fcbbcbb0f281可在docker hub的网页上找到
2,然后把tar文件上传到routeros,建议开启smb功能,通过smb新建的文件权限比sftp或者scp要高
3,然后是创建容器,详细参考官方文档
创建完后,修改cmd属性
tail -f /dev/null
然后启动容器
4,通过shell 0 容器编号进入容器字符界面
使用wget命令下载hysteria,并解压
创建hysteria的配置文件,供参考,以服务端配置为准
{
"insecure": true,
"protocol": "wechat-video",
"down_mbps": 330,
"server": "x.x.x.x:x",
"tun": {
"name": "tun0"
},
"auth_str": "xxxx",
"disable_mtu_discovery": false,
"up_mbps": 110,
"alpn": "h3",
"server_name": "wechat.com"
}
5,然后创建tun
apk update
apk add iproute2
ip tuntap add mode tun dev tun0
ip addr add 198.18.0.1/15 dev tun0
ip link set dev tun0 up
6,修改路由,可以通过修改默认路由metric方式
假设 eth0 是原本的网卡,网关地址为 192.168.1.1,x.x.x.x是vps的IP地址
ip route del default
ip route add default via 198.18.0.1 dev tun0 metric 1
ip route add default via 192.168.1.1 dev eth0 metric 10
ip route add 192.168.0.0/16 via 192.168.1.1
ip route add 10.0.0.0/8 via 192.168.1.1
ip route add x.x.x.x via 192.168.1.1
也可以通分解0.0.0.0/0方式添加路由
ip route add 0.0.0.0/1 via 198.18.0.1
ip route add 128.0.0.0/1 via 198.18.0.1
ip route add 192.168.0.0/16 via 192.168.1.1
ip route add 10.0.0.0/8 via 192.168.1.1
ip route add x.x.x.x via 192.168.1.1
7,退出容器,停止容器
修改容器cmd参数
/root/hysteria client --config /root/hk.json
启动容器
8,配置routeros转发国外流量给容器,参考Routeros V7配置策略路由
9,容器内hysteia一键启动脚本start.sh
#!/bin/sh
cp /hysteria/hysteria /bin/
ip route del default
ip route add default via 192.168.0.1
if ! ip tuntap >/dev/null 2>&1; then
echo "nameserver 114.114.114.114" >>/etc/resolv.conf
apk update
apk add iproute2
sed -i '/114.114.114.114/d' /etc/resolv.conf
ip tuntap add mode tun dev tun0
fi
ip tuntap add mode tun dev tun0
ip addr add 198.18.0.1 dev tun0
ip link set dev tun0 up
ip route del default
ip route add default via 198.18.0.1
ip route add 10.0.0.0/8 via 192.168.1.1
ip route add 192.168.0.0/16 via 192.168.1.1
awk -F'"|:' '/\"server\"/ {cmd="ip route add "$5" via 192.168.1.1";system(cmd)}' /hysteria/$1
hysteria client --config /hysteria/$1
在routeros上传hysteria可执行文件、hysteria配置文件和上面启动脚本到/container/etc/hysteria里
routeros新建容器命令
/container/mounts add name="hysteria" src="/container/etc/hysteria" dst="/hysteria"
/container add file=container/tmp/alpine_v3.18.2.tar interface=container-hysteria hostname=hysteria mounts=hysteria root-dir=container/root-dir/hysteria cmd="sh /hysteria/start.sh hk.json" start-on-boot=yes
/container start [find hostname=hysteria]
说明
由于routeros的容器功能细节一直在变动,有时候上一个版本还能使用,更新之后容器就不能启动了,而且日志一点信息都没有,所以采取了最保守的方式手动配置容器内应用的方式。
容器的网卡配置既不在容器内部存储,也不在routeros的veth里存储,似乎在一个容器外部不可见的地方,只能在容器内部操作,删除重建容器使用原来veth发现原有tun、静态路由居然还在。在routeros里修改veth的ip地址,居然不会同步修改容器内IP地址。
7.6版能启动的openwrt容器,新版就不能启动,一点日志都没有。
之前容器内可以写入mount的目录,新版就没有写权限,也没有执行权限,虽然容器内显示有权限。
也研究了tinyserve的bird+clash容器实现ospf动态路由透明网关方式,他使用了s6在容器内看护了几个应用,导致容器内存需求较大,小于4G内存的就别测试了。我使用rb5009,内存只有1gb,遇到routeros内存不足重启的问题。
动态路由这种透明网关方式早在ssr出现之前就有人提出,使用树莓派上跑bird+ss实现,但是我一直觉得一旦穿墙失效,所有数据包都会被运营商和墙捕捉到,为了高可用牺牲安全性不太值得,所以一直没用。