Networking

使用 iptables 進行埠轉發

  • April 7, 2020

我得到了lo( 127.0.0.1) 和eth0( 172.17.0.8)。我想將登陸的數據包重定向127.0.0.1:80172.17.42.1:80(路由來自eth0)。

我試過

iptables -t nat -A OUTPUT -p tcp --dport 80 -d 127.0.0.1 -j DNAT --to 172.17.42.1:80

但是當我這樣做時,我curl localhost:80沒有得到回應,當我這樣做時curl 172.17.42.1:80,它就起作用了。

當您嘗試訪問 localhost 時,您的源地址是 127.0.0.1,目標地址也是如此。所以,數據包看起來像這樣:

| SRC        |  DST       |
| 127.0.0.1  |  127.0.0.1 |

由於本地生成的數據包首先遍歷 OUTPUT 鏈,因此您使用 DNAT 規則修改數據包:

iptables -t nat -A OUTPUT \
        -d 127.0.0.1 \
        -p tcp --dport 80 \
        -j DNAT \
        --to 172.17.42.1:80

在 OUTPUT 鏈之後,數據包如下所示:

| SRC        |  DST        |
| 127.0.0.1  |  172.17.42.1 |

因此,您看到的第一個錯誤是即使此數據包被路由到源設備之外,目的地也不知道如何正確返回它。因此,您還需要添加額外的 SNAT 規則:

iptables -t nat -A POSTROUTING \
        -d 172.17.42.1 \
        -p tcp --dport 80 \
        -j SNAT \
        --to-source <your_ip_addr>

現在,數據包在網路上退出看起來非常正確(源地址將是該設備的公共地址,而不是本地主機地址)。

但是,這還不能解決你的痛苦。

本地機器上生成的數據包的路由決策在兩個地方進行。

  • 在 OUTPUT 鏈之前
  • 在 OUTPUT 鏈之後和 POSTROUTING 之前

此數據包的決定將在第二階段做出,在 POSTROUTING 鏈中重寫源 IP 之前…

因此,核心安全機制將丟棄數據包,因為預設情況下核心拒絕路由 src 為 127.0.0.1 的數據包。這意味著即使 mangle 與 fwmark 結合也無濟於事。為此,需要啟用 route_localnet。這是 per-iface 變數,它允許將 127/8 用於本地路由目的(預設為 0 - 也就是禁用)。

sysctl -w net.ipv4.conf.all.route_localnet=1

在您的情況下,您可以安全地更改傳出介面名稱的“全部”。

現在,數據包將按照表中之前的規則進行路由,並且由於我們有 POSTROUTING SNAT,我們將修復源 ip 127.0.0.1 並重寫它。

希望這可以幫助。

PS。抱歉,在 2-3 次編輯之前,現在是凌晨 5 點,我還醒著 :)

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