在 iptables 中新增重定向規則後,Tcpdump 顯示不同的重定向端口

在 iptables 中新增重定向規則後,Tcpdump 顯示不同的重定向端口

我正在嘗試將客戶端流量定向到正在偵聽的 kubernetes 叢集 NodePort 192.168.1.100.30000

客戶端需要發出請求,192.168.1.100.8000所以我在 iptables 中新增了以下 REDIRECT 規則:

iptables -t nat -I PREROUTING -p tcp --dst 192.168.1.100 --dport 8000 -j REDIRECT --to-port 30000

然後我發出一個curl 192.168.1.100:8000,但在 tcpdump 中我看到一個不同的連接埠:

# tcpdump -i lo -nnvvv host 192.168.1.100 and port 8000
tcpdump: listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
[Interface: lo] 20:39:22.685968 IP (tos 0x0, ttl 64, id 20590, offset 0, flags [DF], proto TCP (6), length 40)
[Interface: lo]     192.168.1.100.8000 > 192.168.1.100.49816: Flags [R.], cksum 0xacda (correct), seq 0, ack 3840205844, win 0, length 0
[Interface: lo] 20:39:37.519256 IP (tos 0x0, ttl 64, id 34221, offset 0, flags [DF], proto TCP (6), length 40)

我希望 tcpdump 顯示類似的內容

192.168.1.100.8000 > 192.168.1.100.30000

但是,它顯示並導致連線被拒絕錯誤,因為 上沒有列出任何進程192.168.1.100.49816

192.168.1.100.8000 > 192.168.1.100.49816

我正在使用測試環境,因此我無法存取遠端設備,這就是我使用curl測試 iptables 重定向路徑的原因。

新增 REDIRECT 規則是否有原因導致 tcpdump 將流量重定向到與指定連接埠不同的連接埠?

編輯:

在 @AB 建議後新增了以下 OUTPUT 規則:

iptables -t nat -I OUTPUT -d 192.168.1.100 -p tcp --dport 8000 -j REDIRECT --to-port 30000

而curl確實繼續進行,OUTPUT鏈的資料包計數確實增加(但PREROUTING REDIRECT鏈資料包沒有增加):

2       10   600 REDIRECT   tcp  --  *      *       0.0.0.0/0            192.168.1.100         tcp dpt:8000 redir ports 30000

但是,出現以下錯誤:

# curl -vk https://192.168.1.100:8000/v1/api
* About to connect() to 192.168.1.100 port 8000 (#0)
*   Trying 192.168.1.100...
* Connected to 192.168.1.100 (192.168.1.100) port 8000 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* NSS error -12263 (SSL_ERROR_RX_RECORD_TOO_LONG)
* SSL received a record that exceeded the maximum permissible length.
* Closing connection 0
curl: (35) SSL received a record that exceeded the maximum permissible length.

另外,嘗試新增遠端系統網絡,這次執行後 PREROUTING REDIRECT CHAIN 封包計數增加remotesystem curl ...(但 OUTPUT CHAIN 不會增加):

2       34  2040 REDIRECT   tcp  --  *      *       0.0.0.0/0            172.16.128.1         tcp dpt:8000 redir ports 30000

錯誤:

# ip netns exec remotesystem curl -vk https://192.168.1.100:8000/v1/api
* About to connect() to 192.168.1.100 port 8000 (#0)
*   Trying 192.168.1.100...
* Connection timed out
* Failed connect to 192.168.1.100:8000; Connection timed out
* Closing connection 0
curl: (7) Failed connect to 192.168.1.100:8000; Connection timed out

答案1

需要明確的是:OP 的測試是從系統 192.168.1.100 對其自身進行的,而不是從遠端系統進行的,這就是問題的原因。在這種情況下,連接埠沒有更改,因為沒有匹配的 NAT 規則,而如果從遠端系統完成,則連接埠會匹配。

下圖顯示如何對資料包執行操作順序:

Netfilter 和通用網路中的封包流

原因在於 NAT 在 Linux 上的運作原理:iptablesnat僅在新 conntrack 流的第一個資料包(因此處於 NEW 狀態)中看到表中的資料包。

當來自遠端系統時,此規則運作良好。在這種情況下,看到的第一個資料包將是傳入資料包:

to port 8000 --> AF_PACKET (tcpdump) --> conntrack --> nat/PREROUTING (iptables REDIRECT): to port 30000
--> routing decision --> ... --> local process receiving on port 30000

同一流中的所有後續資料包將讓 conntrack 直接處理連接埠變更(或用於回應的連接埠復原),並將跳過表中的任何 iptables 規則nat(如示意圖所示:nat僅針對NEW連接查詢表)。因此,(跳過回覆資料包部分),下一個傳入資料包將經歷以下情況:

to port 8000 --> AF_PACKET (tcpdump) --> conntrack: to port 30000
--> routing decision --> ... --> local process receiving on port 30000

對於系統本身的測試,第一個資料包不是傳入資料包,而是傳出資料包。相反,使用傳出lo介面會發生這種情況:

local process client curl --> routing decision --> conntrack --> nat/OUTPUT (no rule here)
--> reroute check --> AF_PACKET (tcpdump) --> to port 8000

現在這個資料包在介面上環回lo,它重新顯示為一個資料包,不再是連接中的第一個資料包,因此遵循上面的第二種情況: conntrack 單獨處理 NAT 並且不呼叫nat/PREROUTING.除了先前的步驟中沒有指示執行任何 NAT 之外:

to port 8000 --> AF_PACKET (tcpdump) --> conntrack
--> routing decision --> ... -->nolocal process receiving on port8000

由於連接埠 8000 上沒有任何監聽,作業系統會發回 TCP RST。

為了使其在本機系統上運行,REDIRECT還必須將規則放入nat/OUTPUT鏈中:

iptables -t nat -I OUTPUT -d 192.168.1.100 -p tcp --dport 8000 -j REDIRECT --to-port 30000

補充筆記

  • 如果該案例用於遠端使用,請不要從本機系統進行測試:測試遍歷的規則不相同。這使得測試不能反映現實。

    只需使用網路命名空間來建立​​袖珍遠端系統,以防沒有其他系統可用。應該與僅具有 OPnat/PREROUTING規則和操作的系統一起使用的範例curl http://192.168.1.100/(不需要 DNS):

    ip netns add remotesystem
    ip link add name vethremote up type veth peer netns remotesystem name eth0
    ip address add 192.0.2.1/24 dev vethremote
    ip -n remotesystem address add 192.0.2.2/24 dev eth0
    ip -n remotesystem link set eth0 up
    ip -n remotesystem route add 192.168.1.100 via 192.0.2.1
    ip netns exec remotesystem curl http://192.168.1.100:8000/
    
  • tcpdump和網路位址轉換

    tcpdump發生在AF_PACKET上面示意圖中的步驟:入口非常早,出口非常晚。這意味著對於遠端系統情況,即使它正在工作,它也永遠不會捕獲連接埠 30000。對於本機系統情況,一旦nat/OUTPUT新增規則,它將捕獲連接埠 30000。

    只是不要盲目相信進行 NAT 時顯示的位址/連接埠tcpdump:這取決於情況以及捕獲發生的位置。

相關內容