Linux 向局域网内设备分享网络
UPDATE 2022-09-03:
添加了在装有 ufw 时的配置。
======
UPDATE 2022-07-24:
将使用 firewalld 的方法添加到了 Arch Wiki - Internet sharing 上。
======
现某台 Linux 服务器 a 能访问网络 A 、 B 与 C ,希望能通过 a 使 C 下的其他设备访问网络 A 、 B 。具体配置如下:
- 网络 C : 192.168.44.0/24
- C 中路由器: 192.168.44.1
- a 在 C 中的 IP : 192.168.44.2
- a 中的网络 A 、 B 与 C 对应的网卡: eno1, eno2, eno3
服务器 a 上的设置
使用 nftables
首先允许网络转发:
# sysctl net.ipv4.ip_forward=1
再使用 nftables 建立一个新表,设置转发规则:
# nft add table inet nat
# nft 'add chain inet nat postrouting { type nat hook postrouting priority 100 ; }'
# nft add rule inet nat postrouting ip saddr 192.168.44.0/24 masquerade
值得一提的是, Arch Wiki 上的操作是指定 oifname
,但没有指定 ip saddr
。我的理解是:
- 不指定 source address 留下了安全风险
- 使用 oifname 假定了只有一个需要做 NAT 的网络区域。即使是只有一个区域,一般情况下机器在这个网络区域里也只有一个 IP 地址,这种情况下应该去设置 snat 而不是 masquerade 以获得更好的性能。
如果服务器上还装了 ufw
ufw 默认把所有 IP Forward 都 block 掉。网络上的大部分方法都是把默认策略改成 ACCEPT 。。我们装防火墙是为了防止攻击的,这种引入其他风险的策略听上去就有很大问题。 ufw 的用户界面应该是没有提供相关选项,我们需要手工写 iptables 策略(是的, ufw 用 iptables ,导致我们同时写了 nftables 规则和 iptables 规则)
编辑 /etc/ufw/before.rules
,添加以下内容:
-A ufw-before-forward -s 192.168.44.0/24 -j ACCEPT
使用 firewalld
firewalld 的 external 区域应该是默认开启 masquerade ,意味着 firewalld 也会为我们开启网络转发,所以聚焦于 firewalld 的设置就好。
设置网口区域并检查设置:
# firewall-cmd --zone=external --change-interface=eno1 --permanent
# firewall-cmd --zone=external --change-interface=eno2 --permanent
# firewall-cmd --zone=internal --change-interface=eno3 --permanent
# firewall-cmd --zone=internal --set-target=ACCEPT --permanent
# firewall-cmd --reload
# firewall-cmd --get-active-zones
添加配置规则:
# firewall-cmd --zone=internal --permanent --add-rich-rule='rule family="ipv4" source address="192.168.44.0/24" masquerade'
# firewall-cmd --reload
网络 C 路由器上的配置
路由网关指向该服务器即可。
后记
因为最开始忘记了网络出口的问题,导致折腾了很长时间也没明白出了什么问题。
firewalld 生成 nftables 表时,内容非常冗杂,但都有规则可循。但是前一段时间折腾 docker (仍然使用 iptables 后端配置网络,对 ipv6 支持还是很差)与 firewalld 的共存时留下了心理阴影,遂开始手工编写 nftables chain ,并在规则中加入 log 来排查问题,具体步骤可以参考 nftables wiki - Loggin traffic 。