我有一个带有两个接口的树莓派:
- wlan0
- eth0
wlan0 连接到我的内部网络192.168.2.0/24
。eth0 连接到具有 LAN 网络的网络交换机10.0.0.0/8
。
目前,局域网中的所有流量都10.0.0.0/8
可以通过我的wlan0
接口使用互联网,而且我可以10.0.0.0/8
从 raspberry pi 连接到网络中的任何机器。例如,ssh 进入 10.0.0.2。
- 树莓派
wlan0
接口有IP地址192.168.2.30。 - 树莓派
eth0
接口有IP地址10.0.0.1。
我已通过启用 IP 转发来配置此功能net.ipv4.ip_forward=1
。
然后我添加了以下 iptables 规则:
sudo iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
sudo iptables -A FORWARD -i wlan0 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i eth0 -o wlan0 -j ACCEPT
但是,我现在需要能够拦截到达wlan0
端口 80 或端口 443 接口的流量(从另一端,(192.168.0.2/24)并将其直接路由到此 Raspberry Pi 所连接的 LAN 上的另一个 IP 地址(10.23.220.88)。
这是我当前的 iptables 过滤表:
pi@something:~ $ sudo iptables -L -n -v --line-numbers
Chain INPUT (policy ACCEPT 48847 packets, 20M bytes)
num pkts bytes target prot opt in out source destination
Chain FORWARD (policy ACCEPT 157 packets, 9952 bytes)
num pkts bytes target prot opt in out source destination
1 319K 467M ACCEPT all -- wlan0 eth0 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
2 161K 12M ACCEPT all -- eth0 wlan0 0.0.0.0/0 0.0.0.0/0
Chain OUTPUT (policy ACCEPT 26150 packets, 18M bytes)
num pkts bytes target prot opt in out source destination
这是我的 iptables 当前的 NAT 表:
pi@something:~ $ sudo iptables -t nat -L --line-numbers
Chain PREROUTING (policy ACCEPT)
num target prot opt source destination
Chain INPUT (policy ACCEPT)
num target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
num target prot opt source destination
1 MASQUERADE all -- anywhere anywhere
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
如何在不影响通过这台树莓派将互联网路由到我的 10.0.0.0/8 网络以及我可以连接到 10.0.0.0/8 网络的情况下实现这一点?
答案1
这个很简单。只需添加:
iptables -t nat -A PREROUTING -p tcp -d 192.168.2.X --dport 80 -jDNAT --to-destination 10.23.220.88:80
iptables -t nat -A PREROUTING -p tcp -d 192.168.2.X --dport 443 -jDNAT --to-destination 10.23.220.88:443
其中 X 是您的 wlan0 IP 的最后一个字节。
如果您想要一个特定的源(来自您的 wlan0 网络的特定某个人),您只需添加 --source 192.168.2.Y,其中 Y 是网络中该机器 IP 的最后一个字节。
答案2
Zatarra 的回答帮助我找到了部分答案,但在尝试之后,我又重新阅读了 NAT 的工作原理,并意识到我仍然需要一个 POSTROUTING(SNAT)规则来确保数据包的源地址从原始 HTTP 客户端的地址更改为树莓派路由器(执行 NAT)的地址。
这样,树莓派路由器就会10.23.220.88
在其接口(10.0.0.1)上接收从主机发回的数据包,然后知道它实际上应该从那里通过网络上的原始 HTTP 客户端eth0
再次返回。wlan0
192.168.2.0/24
所以我需要 Zatarra 提到的 PREROUTING 规则(而且重要的是,需要修改它以使源接口成为外部流量进入的 wlan0 接口 - 这样通过路由器通过 eth0 返回到互联网的内部流量就不会也被这个规则捕获并再次发送回我的 10.23.220.88 地址),但还需要 SNAT / POSTROUTING 规则。
因此,对我来说,解决方案最终是以下组合:
sudo iptables -t nat -A PREROUTING -i wlan0 -p tcp --dport 80 -j DNAT --to-destination 10.23.220.88:80
sudo iptables -t nat -A POSTROUTING -p tcp -d 10.23.220.88 --dport 80 -j SNAT --to-source 10.0.0.1
当然,对于端口443
也重复上述操作。
这是对已经为 POSTROUTING 设置了 MASQUERADE 规则的补充(根据我最初的帖子,我在帖子中解释过我已经启用了 MASQUERADE)。
所以我的最终 NAT iptables 规则如下所示:
pi@somehost:~ $ sudo iptables -t nat -L --line-numbers -v
Chain PREROUTING (policy ACCEPT 18635 packets, 3477K bytes)
num pkts bytes target prot opt in out source destination
1 11 628 DNAT tcp -- wlan0 any anywhere anywhere tcp dpt:http to:10.23.220.88:80
Chain INPUT (policy ACCEPT 17050 packets, 3354K bytes)
num pkts bytes target prot opt in out source destination
Chain POSTROUTING (policy ACCEPT 118 packets, 10432 bytes)
num pkts bytes target prot opt in out source destination
1 28 1843 MASQUERADE all -- any wlan0 anywhere anywhere
2 11 628 SNAT tcp -- any any anywhere 10.23.220.88 tcp dpt:http to:10.0.0.1
以下是我的 iptables 过滤规则:
pi@somehost:~ $ sudo iptables -t filter -L --line-numbers -v
Chain INPUT (policy ACCEPT 775K packets, 142M bytes)
num pkts bytes target prot opt in out source destination
Chain FORWARD (policy ACCEPT 2013 packets, 145K bytes)
num pkts bytes target prot opt in out source destination
1 153K 213M ACCEPT all -- wlan0 eth0 anywhere anywhere state RELATED,ESTABLISHED
2 71327 5506K ACCEPT all -- eth0 wlan0 anywhere anywhere
Chain OUTPUT (policy ACCEPT 38847 packets, 4782K bytes)
num pkts bytes target prot opt in out source destination
我发现这两篇文章很好地解释了整个 iptables 过程并让我重新认识了 NAT 的工作原理: