EdgeRouter 策略路由实现分析

最近家里的路由规则越来越复杂,而且越来越好用。正好昨天跟朋友讨论他的家用路由改造方案,所以研究了一下EdgeRouter的策略路由(Policy-based Routing,PBR)的实现。

我家里的路由是EdgeRouter Lite,固件1.9.1.1,这个实现跟固件关系不大。

首先,我们可以参考一下官方的文档:EdgeRouter – Policy-based routing (source address based)

IP规则配置

我的路由里:
1. 把Google的IP段配置到了一个firewall group里,组名是 G1,所有访问G1的流量都会走wg0转发,G1的成员是固定的;
2. 把DNSMASQ的一个域名列表的解析结果加到了另外一个group,G2,所有访问G2的流量都会走wg0转发,如前边所述,G2的成员由dnsmasq解析的结果来动态生成;
3. 把我家的一个单独的网段,设置为组G3,所有来自G3的流量都走wg0转发;后来我写了一个简单的页面,可以支持客户端把自己的IP添加到G3或从G3移除,后话再说。

我的路由上,G1,G2,G3都使用了network-group,配置命令

具体实现上,相当于如下的命令:

路由表

接下来,配置的是route table。
192.168.10.1 是wg0 网络的远端网关地址,wg0本地ip是 192.168.10.50,所以不需要额外配置192.168.10.0/24的设备路由。

对应的实现,

如果配置使用的wg0是TUN模式,例如openvpn tun,这个时候应该使用interface-route,对应的实现改为 dev xxx。

查看路由表
EdgeRouter的操作模式下

对应的实现

防火墙策略

防火墙配置如下

上述配置中,我定义了AUTO_VPN的规则,把前边提到的G1, G2, G3配置进来。我的路由LAN口在eth0上,所以对于eth0的流入流量应用了这个AUTO_VPN规则。

对应的实现,需要查看iptables。

继续查看 UBNT_PBR_6 的规则

上述规则都在 mangle

这里,我们看到了对于 UBNT_PBR_6 的规则,iptables给数据包打了个 0x3000000/0x7f800000 的标记。

从iptables的文档里可以看到:

connmark

This module matches the netfilter mark field associated with a connection (which can be set using the CONNMARK target below).
[!] –mark value[/mask]
Matches packets in connections with the given mark value (if a mask is specified, this is logically ANDed with the mark before the comparison).

而这个规则的使用在 ip rule list 里可以看到

添加方法:

回过头来,还得看看 VYATTA_FW_IN_HOOK 这个规则是如何进入的:

PREROUTING 在 nat 表里;
FORWARD 在 mangle 表里。

NAT

对于 wg0,或者所有需要流出流量的设备,需要启用nat,才能保证流量正常流入流出。

对应的实现是 在 nat.POSTROUTING 配置 MASQUERADE

完结

按上述的结构,我们实现了:
1 定义好组的规则
2 从 mangle.PREROUTING 里,把流量都转向 mangle.VYATTA_FW_IN_HOOK
3 从 mangle.VYATTA_FW_IN_HOOK 里筛选 eth0 的入站流量,应用到 mangle.AUTO_VPN
4 从 mangle.AUTO_VPN 匹配1中定义的规则,应用请求到 mangle.UBNT_PBR_6
5 对 mangle.UBNT_PBR_6 的数据包执行 ACCEPT操作,同时标记为 0x3000000/0x7f800000
6 使用 iproute2 添加一个 0.0.0.0/0 的routing table,指向目标设备/IP
7 使用 iproute2 添加一个规则,把 0x3000000/0x7f800000 的数据包指向 6 中添加的routing table
8 对于目标设备,启用 MASQUERADE

EdgeRouter 策略路由实现分析 by @sskaje: https://sskaje.me/2017/06/edgerouter-policy-based-routing-analysis/