Linux

IPTables -j DNAT 在某些情況下似乎不起作用

  • October 3, 2017

我正在嘗試更改 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)。

引用自:https://serverfault.com/questions/876649