RouterOS路由OSPF协议+树莓派分流国外流量

跟原文作者一样,之前尝试过使用RouterOS的iptables给链接打标记的方式配置过,但不知道为什么,速度奇慢无比,直到看到通过动态路由协议的方式进行分流。

OSPF简介

OSPF (Open Shortest Path First) 是一种常用的 IGP 路由协议,相对于 BGP 这种主要是为自治域之间通信设计的协议,OSPF 的配置相对来说要简单易懂的多,而且收敛速度非常的快,适合用来在内网快速发布大量的路由。

OSPF 唯一不足的地方是一开始设计的时候没有考虑到多种协议的支持,导致 IPv6 出来后又设计了 OSPFv3 这个新的协议。因为我们希望有 IPv6 支持,所以后面会同时配置 OSPFv2 和 OSPFv3 的实例。但是相对于 IS-IS 和 iBGP 这些支持原生双栈的协议还是配置起来要简单了不少。

额外需要的信息

为了让树莓派能把国外的 IP 地址路由牵引过来,我们需要国外的 IP 段信息。注意这个跟 chnroutes 不一样,前者是中国的 IP 段,而我们需要取反获得不是中国的 IP 段,因为路由协议只能宣告哪些 IP 段应该被转发到树莓派。

在网上搜了半天无果后我自己写了一个简单的 Python 脚本可以生成符合要求的路由。项目已开源,可以在这里下载:

https://github.com/dndx/nchnroutes

下载了以后 make 即可生成国外 IP 地址的路由表。注意如果树莓派上的隧道连接的是国外的 IP,那么需要从生成的 IP 段里剔除,否则隧道的流量也会被 RouterOS 发给树莓派,形成路由环路。可以参考 README.md 的说明通过 --exclude 选项把这些不应该走隧道的 IP 排除。

另外脚本支持 --next 选项,可以用来指定隧道的下一跳。

运行后会生成两个文件 routes4.conf 和 routes6.conf,这两个文件是 BIRD 的静态路由格式,后面做 OSPF 宣告的时候会用到。

另外要注意,在树莓派上配置隧道的时候,不可以创建去往隧道的默认路由。因为我们后面需要用 BIRD 来动态的插入国外的路由走隧道。对于 WireGuard,可以用 Table = off 这个选项来不安装默认路由。

树莓派配置

建立虚拟网卡

使用go-tun2socks在树莓派中建立一个虚拟网卡,用作分流,直接下载releases即可,下载完后,使用以下命令开启虚拟网卡

root@aml:~# tun2socks-linux-arm64 -tunGw 192.168.171.1 -proxyServer 127.0.0.1:10808 -tunDns 8.8.8.8,8.8.4.4 -tunName wg0 -loglevel info &
root@aml:~# ip addr add 192.168.171.1 dev wg0
root@aml:~# ip link set dev wg0 up

开启转发

树莓派应该开启 IP 转发功能,编辑 /etc/sysctl.conf 把 net.ipv4.ip_forward=1 和 net.ipv6.conf.all.forwarding=1 的注释删掉,然后 sudo sysctl -p /etc/sysctl.conf 来应用设置。

IPTABLES

下一步在树莓派上配置一些基本的防火墙规则。 sudo apt install iptables-persistent 安装 iptables 规则持久化包,安装时询问是否要保存当前的规则可以选 No,因为下面我们要手动创建规则文件。

原文中,作者详细描述了IPV4与IPV6的配置注意事项,由于我这里暂时不需要IPV6,仅对IPV4进行了配置,如果有需要,可以在文章底部找到原文链接。

编辑 iptables 规则。配置文件/etc/iptables/rules.v4如下:

*filter
:INPUT ACCEPT [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
-A FORWARD -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i eth0 -o wg0 -j ACCEPT
COMMIT

*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A POSTROUTING -o wg0 -j MASQUERADE
COMMIT

执行iptables-restore < /etc/iptables/rules.v4让配置立即生效

BIRD

下一步需要在树莓派上安装 BIRD 来与 RouterOS 建立 OSPF 邻居关系和进行路由宣告。在 Raspbian 上可以直接 sudo apt install bird 来安装。

安装好了后,BIRD 默认会自动启动。我们需要把上面生成的 routes4.conf  文件复制到 /etc/bird 目录下。然后编辑 /etc/bird/bird.conf 来导入生成的静态路由和启用 OSPF 支持:

# This is a minimal configuration file, which allows the bird daemon to start
# but will not cause anything else to happen.
#
# Please refer to the documentation in the bird-doc package or BIRD User's
# Guide on http://bird.network.cz/ for more information on configuring BIRD and
# adding routing protocols.

# Change this into your BIRD router ID. It's a world-wide unique identification
# of your router, usually one of router's IPv4 addresses.
router id 192.168.169.5;

# The Device protocol is not a real routing protocol. It doesn't generate any
# routes and it only serves as a module for getting information about network
# interfaces from the kernel.
protocol device {
        scan time 60;
}

# The Kernel protocol is not a real routing protocol. Instead of communicating
# with other routers in the network, it performs synchronization of BIRD's
# routing tables with the OS kernel.
protocol kernel {
        metric 64;      # Use explicit kernel route metric to avoid collisions
                        # with non-BIRD routes in the kernel routing table
        scan time 60;
        import none;
        export all;     # Actually insert routes into the kernel routing table
}
protocol static {
        include "routes4.conf";
}

protocol ospf {
    export all;

    area 0.0.0.0 {
        interface "eth0" {
            authentication cryptographic;
            password "foobar";
        };
    };
}

需要根据实际情况修改以下配置:

router id 192.168.169.5; 是OSPF实例的唯一标识符,要求在局域网内唯一。惯例使用树莓派的局域网IP即可。同一台机器上的 OSPFv2 和 v3 实例可以共享 router id

password "foobar"; 这里是跟 RouterOS 握手使用的密码。选一个随机的字符串即可。

对于 IPv6,需要使用 OSPFv3,这里跳过,有需要可以在文章底部找到原文链接。

配置完成后需要reload bird 让配置生效:

pi@raspberrypi:~/nchnroutes $ sudo birdc configure
BIRD 1.6.6 ready.
Reading configuration from /etc/bird/bird.conf
Reconfigured

配置完后,验证树莓派的路由已经正确分流:

pi@raspberrypi:~/nchnroutes $ ip r get 1.1.1.1
1.1.1.1 dev wg0 src 192.168.88.2 uid 1000 
    cache 
pi@raspberrypi:~/nchnroutes $ ip r get 114.114.114.114
114.114.114.114 via 192.168.0.1 dev eth0 src 192.168.0.2 uid 1000 
    cache

可以看到国内外的 IP 已经返回了不同的路由。也可以 traceroute 国内外的 IP 地址来验证。

至此,树莓派的配置已经完成。接下来需要在 RouterOS 上启用 OSPF 实例来收取树莓派发过来的路由。

RouterOS配置

首先需要确保 RouterOS 的 routing package 是启用的状态。否则 OSPF 功能会不可用。

[user@MikroTik] > /system package        
[user@MikroTik] /system package> print
Flags: X - disabled 
 #   NAME                  VERSION                 SCHEDULED              
 0   routeros-mmips        6.48                                           
 1   system                6.48                                           
 2   ipv6                  6.48                                           
 3 X wireless              6.48                                           
 4 X hotspot               6.48                                           
 5 X mpls                  6.48                                           
 6 X routing               6.48
...
[user@MikroTik] /system package> enable routing
[user@MikroTik] /system package> print 
Flags: X - disabled 
 #   NAME                  VERSION                 SCHEDULED              
...
 6 X routing               6.48                    scheduled for enable

如果原来没有启用,启用了后需要重启才能生效:

[user@MikroTik] /system package> /system reboot 
Reboot, yes? [y/N]: 
y
system will reboot shortly

重启后,启用OSPF实例(IPv4):

/routing ospf instance
set [ find default=yes ] router-id=192.168.169.254
/routing ospf interface
add authentication=md5 authentication-key=foobar interface=bridge_lan network-type=broadcast
/routing ospf network
add area=backbone network=192.168.169.0/24

这里的 router-id 也应该设为 RouterOS 的局域网 IP 地址。不可以跟树莓派 router-id 的相同。

配置好了后,如果一切正常,树莓派应该会自动与 RouterOS 建立 OSPF 邻居关系:

[admin@MikroTik] /routing ospf neighbor> print 
 0 instance=default router-id=192.168.169.5 address=192.168.169.5 interface=bridge1 priority=1 dr-address=192.168.169.254 backup-dr-address=192.168.169.5 state="Full" state-changes=14 ls-retransmits=0 ls-requests=0 db-summaries=0 adjacency=5h5m22s

同时,可以看到 RouterOS 已经收到了树莓派发过来的路由:

[admin@MikroTik] /ip route> print 
Flags: X - disabled, A - active, D - dynamic, C - connect, S - static, r - rip, b - bgp, o - ospf, m - mme, B - blackhole, U - unreachable, P - prohibit 
 #      DST-ADDRESS        PREF-SRC        GATEWAY            DISTANCE
 0 X S  0.0.0.0/0                          pppoe-Unicom              1
 1 ADS  0.0.0.0/0                          pppoe-Telecom             1
 2 ADo  1.0.0.0/24                         192.168.169.5           110
 3 ADo  1.0.4.0/22                         192.168.169.5           110
...

效果

在局域网里任何一台机器上 traceroute 114.114.114.114 和 traceroute 1.1.1.1 ,可以看到前者走的是运营商的出口,而后者被转发到了树莓派后走隧道出国。

重启树莓派,模拟树莓派宕机,同时立刻在局域网里任何一台机器上 ping 一个国外的地址,可以看到一开始走的是运营商链路,树莓派重启完毕以后会自动把路由拉回到隧道:

来自 1.1.1.1 的回复: 字节=32 时间=151ms TTL=54
来自 1.1.1.1 的回复: 字节=32 时间=152ms TTL=54
来自 1.1.1.1 的回复: 字节=32 时间=160ms TTL=54
来自 1.1.1.1 的回复: 字节=32 时间=153ms TTL=54
来自 1.1.1.1 的回复: 字节=32 时间=151ms TTL=54
来自 1.1.1.1 的回复: 字节=32 时间=156ms TTL=54
来自 1.1.1.1 的回复: 字节=32 时间=151ms TTL=54
来自 1.1.1.1 的回复: 字节=32 时间=156ms TTL=54
来自 1.1.1.1 的回复: 字节=32 时间=1869ms TTL=54
来自 1.1.1.1 的回复: 字节=32 时间=7ms TTL=62
来自 1.1.1.1 的回复: 字节=32 时间=1ms TTL=62
来自 1.1.1.1 的回复: 字节=32 时间=2ms TTL=62
来自 1.1.1.1 的回复: 字节=32 时间=2ms TTL=62
来自 1.1.1.1 的回复: 字节=32 时间=13ms TTL=62
来自 1.1.1.1 的回复: 字节=32 时间=1ms TTL=62
root@aml:~# curl ip.sb
74.12.74.5
root@aml:~# curl -s members.3322.org/dyndns/getip
39.156.69.79

链接

V2RAY性能调优 

原文链接

 

 

RouterOS路由OSPF协议+树莓派分流国外流量》有6个想法

  1. sail-liu

    请问博主,使用go-tun2socks在树莓派中建立一个虚拟网卡说明看不大明白,因为我wg隧道已经建立好了,赋予了ip,跟vps联通后,ifconfig就有eth0和wg0。为什么这里还要建立一个呢?

    看到后文还说到测试树莓派的分流,测试1.1.1.1的出口,看到反馈结果是dev wg0 src 192.168.88.2 uid 1000 ,也就是说wg0隧道的ip是192.168.88.2。跟之前建立的wg0不一样啊

    感谢解惑。

    回复
    1. admin 文章作者

      v2ray这类应用是不会建立虚拟网卡的,所以要用go-tun2socks。当然如果应用直接建立了虚拟网卡就不需要这一步了

      回复
  2. 蜡笔小新

    请问博主,我通过OSPF接受路由表后,与vt的wireguard通到就断了,只要关闭OSPF wireguard隧道就通了,这种情况要怎么处理呢。

    回复
    1. admin 文章作者

      在routeros中ospf的优先级比静态路由的优先级高,可以把通道的目的地址在ospf中删除试试

      回复

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注