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即可,下载完后,使用以下命令开启虚拟网卡

1
2
3
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如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
*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 支持:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# 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 idpassword "foobar"; 这里是跟 RouterOS 握手使用的密码。选一个随机的字符串即可。 对于 IPv6,需要使用 OSPFv3,这里跳过,有需要可以在文章底部找到原文链接。 配置完成后需要reload bird 让配置生效:

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

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

1
2
3
4
5
6
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 功能会不可用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[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

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

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

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

1
2
3
4
5
6
/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 邻居关系:

1
2
[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 已经收到了树莓派发过来的路由:

1
2
3
4
5
6
7
8
[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

1
2
3
4
root@aml:~# curl ip.sb
74.12.74.5
root@aml:~# curl -s members.3322.org/dyndns/getip
39.156.69.79

链接

V2RAY性能调优 

原文链接