Linux
具有多個內部和外部介面的 NAT 盒
之前有人問 過類似的問題,但我的設置有點不同,這些問題的解決方案不起作用。A 有一個執行 iptables 的 CentOS 6 伺服器,有 5 個介面:
- eth0:管理 136.2.188.0/24
- eth1:Cluster1 內部 10.1.0.0/16
- eth2:Cluster1 外部 136.2.217.96/27
- eth3:Cluster2 內部 10.6.0.0/20
- eth4:Cluster2 外部 136.2.178.32/28
我要做的是讓來自 eth1 的流量從 eth2 出去並進行 NATd,來自 eth3 的流量從 eth4 出去並進行 NATd,所有其他流量(例如 SSH 到盒子本身)使用 eth0。
為此,我像這樣配置了路由表:
ip route add default via 136.2.178.33 src 136.2.178.37 table 1 ip route add default via 136.2.217.97 src 136.2.217.124 table 2 ip rule add fwmark 1 pref 1 table 1 ip rule add fwmark 2 pref 2 table 2
源 IP 是 NAT 框的 IP。管理介面將使用的正常預設路由通常在表 0 中。
然後,我將 iptables 配置為使用 mangle 表標記數據包,以便它們使用特定的路由表(如果我理解正確的話)並將特定源流量 NAT 到特定介面:
iptables -A PREROUTING -t mangle -j CONNMARK --restore-mark iptables -A PREROUTING -t mangle -m mark --mark 0x0 -s 10.6.0.0/20 -j MARK --set-mark 1 iptables -A PREROUTING -t mangle -m mark --mark 0x0 -s 10.1.0.0/16 -j MARK --set-mark 2 iptables -A POSTROUTING -t mangle -j CONNMARK --save-mark iptables -A POSTROUTING -t nat -s 10.6.0.0/20 -o eth4 -j MASQUERADE iptables -A POSTROUTING -t nat -s 10.1.0.0/16 -o eth2 -j MASQUERADE iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A FORWARD -j LOG --log-level debug iptables -A FORWARD -m state --state NEW -s 10.6.0.0/20 -o eth4 -j ACCEPT iptables -A FORWARD -m state --state NEW -s 10.1.0.0/16 -o eth2 -j ACCEPT iptables -A FORWARD -j DROP
當我測試這個(來自客戶端機器的 google.com 的簡單 wget)時,我可以看到流量進入內部介面(測試中的 eth3),然後以 NAT 框的外部 IP 作為外部介面(eth4)源IP。因此,NAT 本身可以工作。但是,當系統收到響應數據包時,它應該進入 eth4,但沒有任何反應,它永遠不會被取消 NAT,也永遠不會出現在 eth3 上以返回客戶端電腦。
內部介面:
11:52:08.570462 IP 10.6.0.50.50783 > 74.125.198.103.80: Flags [S], seq 4030201376, win 14600, options [mss 1460,sackOK,TS val 34573 ecr 0,nop,wscale 7], length 0 11:52:09.572867 IP 10.6.0.50.50783 > 74.125.198.103.80: Flags [S], seq 4030201376, win 14600, options [mss 1460,sackOK,TS val 35576 ecr 0,nop,wscale 7], length 0 11:52:11.576943 IP 10.6.0.50.50783 > 74.125.198.103.80: Flags [S], seq 4030201376, win 14600, options [mss 1460,sackOK,TS val 37580 ecr 0,nop,wscale 7], length 0 11:52:15.580846 IP 10.6.0.50.50783 > 74.125.198.103.80: Flags [S], seq 4030201376, win 14600, options [mss 1460,sackOK,TS val 41584 ecr 0,nop,wscale 7], length 0 11:52:23.596897 IP 10.6.0.50.50783 > 74.125.198.103.80: Flags [S], seq 4030201376, win 14600, options [mss 1460,sackOK,TS val 49600 ecr 0,nop,wscale 7], length 0
外部介面:
11:52:08.570524 IP 136.2.178.37.50783 > 74.125.198.103.80: Flags [S], seq 4030201376, win 14600, options [mss 1460,sackOK,TS val 34573 ecr 0,nop,wscale 7], length 0 11:52:08.609213 IP 74.125.198.103.80 > 136.2.178.37.50783: Flags [S.], seq 1197168065, ack 4030201377, win 42540, options [mss 1380,sackOK,TS val 1835608368 ecr 34573,nop,wscale 7], length 0 11:52:08.909188 IP 74.125.198.103.80 > 136.2.178.37.50783: Flags [S.], seq 1197168065, ack 4030201377, win 42540, options [mss 1380,sackOK,TS val 1835608668 ecr 34573,nop,wscale 7], length 0 11:52:09.572882 IP 136.2.178.37.50783 > 74.125.198.103.80: Flags [S], seq 4030201376, win 14600, options [mss 1460,sackOK,TS val 35576 ecr 0,nop,wscale 7], length 0 11:52:09.611414 IP 74.125.198.103.80 > 136.2.178.37.50783: Flags [S.], seq 1197168065, ack 4030201377, win 42540, options [mss 1380,sackOK,TS val 1835609370 ecr 34573,nop,wscale 7], length 0 11:52:11.576967 IP 136.2.178.37.50783 > 74.125.198.103.80: Flags [S], seq 4030201376, win 14600, options [mss 1460,sackOK,TS val 37580 ecr 0,nop,wscale 7], length 0
那麼,為什麼流量出來了,但 iptables 沒有將返回的流量發送回客戶端?似乎路由是正確的,因為數據包離開並到達正確的介面,那麼 iptables 對返回流量做了什麼?
好的,我想通了。我必須做的是將內部子網路由添加到每個路由表,然後設置規則來控制進出的介面流量路由。然後在 iptables 中,不需要使用 mangle 表標記數據包,只需要典型的 forward 和 nat 規則。
ip route add 136.2.178.32/28 dev eth4 table 1 ip route add 10.6.0.0/20 dev eth3 table 1 ip route add default via 136.2.178.33 src 136.2.178.37 table 1 ip rule add iif eth4 table 1 ip rule add from 10.6.0.0/20 table 1 ip route add 136.2.217.96/28 dev eth2 table 2 ip route add 10.1.0.0/16 dev eth1 table 2 ip route add default via 136.2.217.113 src 136.2.217.124 table 2 ip rule add iif eth2 table 2 ip rule add from 10.1.0.0/16 table 2 iptables -A FORWARD -i eth2 -o eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT iptables -A FORWARD -i eth1 -o eth2 -m state --state NEW -j LOG --log-level debug iptables -A FORWARD -i eth1 -o eth2 -j ACCEPT iptables -A FORWARD -i eth4 -o eth3 -m state --state RELATED,ESTABLISHED -j ACCEPT iptables -A FORWARD -i eth3 -o eth4 -m state --state NEW -j LOG --log-level debug iptables -A FORWARD -i eth3 -o eth4 -j ACCEPT iptables -A FORWARD -j REJECT --reject-with icmp-host-prohibited iptables -t nat -A POSTROUTING -o eth2 -j MASQUERADE iptables -t nat -A POSTROUTING -o eth4 -j MASQUERADE