我的网络设置如下:
┌──────┬────────┐ ┌───────────┐
│ │ eno1.1 │ │ Network A │
│ │ ├─┤ │
┌────────┐ ┌────────┤ │10.0.1.2│ │10.0.1.0/24│
│ Client │ │ eno2 │ ├────────┘ └───────────┘
│ ├─┤ │Router│
│10.0.0.2│ │10.0 0.1│ ├────────┐ ┌───────────┐
└────────┘ └────────┤ │ eno1.2 │ │ Network B │
│ │ ├─┤ │
│ │10.0.2.2│ │10.0.2.0/24│
└──────┴────────┘ └───────────┘
我正在尝试配置路由器以执行以下操作:
- 路由所有
eno2
来自的流量eno1.2
,将其伪装成10.0.2.2
- 路由所有其他流量(例如来自路由器本身的流量)通过
eno1.1
我可以通过在 nftables 中启用 IP 转发和设置伪装规则来让流量从eno2
路由(路由器的默认网关)通过:eno1.1
$ sysctl -w net.ipv4.ip_forward=1
$ nft -f - <<EOF
table inet test {
chain postrouting {
type nat hook postrouting priority filter; policy accept;
iifname "eno2" oifname "eno1.1" masquerade
}
}
EOF
但我似乎无法让它通过路由流量eno1.2
。这是初始系统路由:
default via 10.0.1.1 dev eno1.1 proto dhcp src 10.0.1.2 metric 1024
10.0.1.0/24 dev eno1.1 proto kernel scope link src 10.0.1.2 metric 1024
10.0.2.0/24 dev eno1.2 proto kernel scope link src 10.0.2.2 metric 1024
10.0.0.0/24 dev eno2 proto kernel scope link src 10.0.0.1
我设置了一个新的路由表并伪装成eno2
这样:
$ echo "100 eno2" >> /etc/iproute2/rt_tables
$ ip route add default via 10.0.2.1 dev eno1.2 src 10.0.2.2 table eno2
$ ip route add 10.0.0.0/24 dev eno2 src 10.0.0.1 table eno2
$ ip rule add iif eno2 lookup eno2
$ nft -f - <<EOF
table inet test {
chain postrouting {
type nat hook postrouting priority filter; policy accept;
iifname "eno2" oifname "eno1.2" masquerade
}
}
这似乎让我完成了大部分工作。10.0.2.1
从客户端 ping “网络 B”路由器 ( ) 工作正常,但是尝试 ping 任何非本地 IP 会导致路由器丢弃回复。我可以看到数据包从 发出eno1.2
(正确伪装)并从 回来eno1.2
,但是它们从未被转发到eno2
。
我设法将其追溯到我的操作系统(NixOS)自动添加的以下 nftables 规则:
table inet nixos-fw {
chain rpfilter {
type filter hook prerouting priority mangle + 10; policy drop;
fib saddr . mark . iif oif exists accept
}
}
这似乎是在实施反向路径过滤,我开始认为问题可能在于它只检查默认路由表,而不是eno2
。nftables wiki 文章关于fib
只是说“查询路由表”,并没有提到它是所有路由表还是仅仅是默认路由表(它也没有提到如何指定路由表)。
eno1.2
我尝试添加一条附加规则来通过eno2
路由表 ( )路由所有传入的数据包ip rule add iif eno1.2 table eno2
,但这并不能解决问题。
这里可能有什么问题?是否可以指定要fib
使用的表?
答案1
根据我的测试,该fib
语句似乎仅使用默认路由表,而不检查任何其他表。为了解决这个问题,我删除了该rpfilter
链,并启用了内核的反向路径过滤。