IPTables -j DNAT 在某些情況下似乎不起作用
我正在嘗試更改 ICMP 回複數據包的目標 IP 地址。
ICMP 回复這樣從我的 IPSEC 隧道進入路由器(我不完全確定它為什麼在 tcpdump 中顯示兩次):
14:28:09.562030 IP 35.182.188.86 > 54.76.131.136: ICMP echo request, id 28997, seq 1259, length 64 14:28:09.641595 IP 54.76.131.136 > 35.182.188.86: ICMP echo reply, id 28997, seq 1259, length 64 14:28:09.641645 IP 54.76.131.136 > 35.182.188.86: ICMP echo reply, id 28997, seq 1259, length 64
我嘗試將 PREROUTING 表上的目標 ip 更改為本地 ip (172.31.20.219):
sudo iptables -t nat -A PREROUTING --source 54.76.131.136 --destination 35.182.188.86 -j DNAT --to-destination 172.31.20.219
所以表格看起來像這樣:
ubuntu@ip-172-31-23-13:~$ sudo iptables-save -c # Generated by iptables-save v1.6.0 on Tue Oct 3 14:58:19 2017 *nat :PREROUTING ACCEPT [33:2711] :INPUT ACCEPT [32:2627] :OUTPUT ACCEPT [8:1080] :POSTROUTING ACCEPT [9:1164] [0:0] -A PREROUTING -s 54.76.131.136/32 -d 35.182.188.86/32 -j DNAT --to-destination 172.31.20.219 COMMIT # Completed on Tue Oct 3 14:58:19 2017 # Generated by iptables-save v1.6.0 on Tue Oct 3 14:58:19 2017 *raw :PREROUTING ACCEPT [2646:283498] :OUTPUT ACCEPT [998:168846] [1954:164136] -A PREROUTING -s 54.76.131.136/32 -d 35.182.188.86/32 -j LOG [821:68964] -A PREROUTING -s 54.76.131.136/32 -d 35.182.188.86/32 -j TRACE COMMIT # Completed on Tue Oct 3 14:58:19 2017
但是,不會發生 ip 更改。
使用
sudo iptables -t raw -A PREROUTING --source 54.76.131.136 --destination 35.182.188.86 -j LOG
我可以看到可以在原始表上進行匹配:
Oct 3 14:25:20 ip-172-31-23-13 kernel: [ 889.588090] IN=eth0 OUT= MAC=02:fc:a0:12:56:64:02:7f:fe:dc:a4:0d:08:00 SRC=54.76.131.135 DST=35.182.188.85 LEN=84 TOS=0x00 PREC=0x00 TTL=63 ID=64700 PROTO=ICMP TYPE=0 CODE=0 ID=28997 SEQ=1091
但它似乎並沒有在 nat 表上匹配。
任何人都可以提供有關為什麼沒有更改目標 ip 或如何進一步調試的建議嗎?看起來很奇怪。
我正在使用 Ubuntu 16.04。傳入流量通過 StrongSwan 的 IPSEC 隧道設置進入。
謝謝
ICMP Echo 回複數據包是已建立流的一部分。這意味著,當核心在正常情況下接收到這樣的數據包時,它已經在期待它(在初始 ICMP Echo 請求之後),因此 nat 所需的基礎磚 conntrack 已經為它創建了一個期待條目。在這種情況下,nat 表將被短路,甚至不會對該回複數據包執行。
參考:https ://www.netfilter.org/documentation/HOWTO/netfilter-hacking-HOWTO-3.html#ss3.2 (NAT)
該表與“過濾器”表略有不同,因為只有新連接的第一個數據包會遍歷該表:此遍歷的結果隨後將應用於同一連接中的所有未來數據包。
要檢查此行為,請在事件監視器模式下使用 conntrack 命令(來自 conntrack 包)。這是一個 ping 到 Google 的範例:
# conntrack -E [NEW] icmp 1 30 src=192.168.3.2 dst=8.8.8.8 type=8 code=0 id=12837 [UNREPLIED] src=8.8.8.8 dst=198.51.100.5 type=0 code=0 id=12837 [UPDATE] icmp 1 30 src=192.168.3.2 dst=8.8.8.8 type=8 code=0 id=12837 src=8.8.8.8 dst=198.51.100.5 type=0 code=0 id=12837 [DESTROY] icmp 1 src=192.168.3.2 dst=8.8.8.8 type=8 code=0 id=12837 src=8.8.8.8 dst=198.51.100.5 type=0 code=0 id=12837
第一個數據包將創建
$$ NEW $$entry 等將通過 nat 表,從而有機會改變期望(在本例中為經典的 SNAT/MASQUERADE)。此流的其他數據包僅使用 conntrack 預期處理,直到條目被銷毀(此 icmp 超時 30 秒)。 使用 nat 規則可以處理初始的 ICMP Ping Echo 請求,因為這將是一個新流程。
你沒有告訴你真正想用這一切做什麼。如果您的目標是將數據包複製到 172.31.20.219,您應該嘗試 TEE 目標(man iptables-extensions)。