來自環回的 iptables DNAT
我試圖了解將 iptables DNAT 與環回地址一起使用的局限性。考慮我們有一個只能連接到 127.0.0.1 的應用程序;使伺服器和客戶端在不同節點上工作的明顯解決方案是使用 NAT,如下所示:
確保所有傳出數據包都具有主客戶端主機的 IP 地址:
iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source <CLIENT_IP>
現在讓我們嘗試欺騙客戶端和 DNAT 與外界的連接:
iptables -t nat -A OUTPUT -d 127.0.0.1/32 -p tcp -m tcp --dport <SERVICE_PORT> -j DNAT --to-destination <SERVER_IP>
不幸的是,這不起作用,當嘗試連接到
127.0.0.1:<SERVICE_PORT>
程序時,它只是掛在connect
系統呼叫上。有趣的是,我在任何介面上都看不到任何 SYN 數據包(tcpdump -qn -i any port <SERVICE_PORT>
),但是在查看 iptables 統計資訊時,我可以看到數據包計數器增加(iptables -nvL -t nat
)。Google搜尋解決方案我找到了一個核心建構選項
CONFIG_IP_NF_NAT_LOCAL
,它在核心 2.6.0-2.6.10 中用於解決將 NAT 與本地發起的連接一起使用的問題。不幸的是,目前的 git 核心樹包含 2.6.11 及更高版本的資訊,所以我在這裡遇到了死胡同。進一步看,我遇到了這個執行緒,關於 2.6.11 中一些 DNAT 環回問題的修復;其中一個更新檔刪除了
CONFIG_IP_NF_NAT_LOCAL
建構選項並無條件地啟用了程式碼(這是實際的差異)。但是,這個問題的目前狀態對我來說還不是很清楚。我想找到一些解釋或參考來證明這是一個核心錯誤或一些沒有很好記錄的功能。我知道網路 127.0.0.0/8 路由是由核心以特殊方式處理的,但是從 iptables 文件中可以清楚地看出,nat table OUTPUT 鍊是唯一對這種規則有意義的地方,並且沒有例外或有關 127/8 網路的任何註釋。
請不要建議使用第三方工具的一些解決方法,我已經有了一些,我只是想解釋一下為什麼這個確切的配置不起作用以及為什麼它不應該起作用。歡迎任何關於如何使用任何其他 iptables 規則來完成此 DNAT 的範例。
上面的配置在 Debian Squeeze 和 wheezy 上進行了測試,核心為 2.6.32、3.1.0、3.2.0。
深入探勘可以證實上述行為是完全正確的。
根據 RFC 5735,網路 127.0.0.0/8 不應路由到主機本身之外:
127.0.0.0/8 - 此塊被分配用作 Internet 主機環回地址。由更高級別協議發送到該塊內任何地址的數據報在主機內部循環返回。這通常僅使用 127.0.0.1/32 進行環回來實現。如中所述
$$ RFC1122 $$,第 3.2.1.3 節,整個 127.0.0.0/8 塊內的地址不會合法地出現在任何地方的任何網路上。
RFC 1700,第 5 頁還指出這些地址«不應出現在主機之外»。
RFC 1812,第 5.3.7 節火星地址過濾聲明“路由器不應該轉發,除了通過環回介面,任何在網路 127 上具有源地址的數據包”,這正是我的情況。
關於這些引用,我認為第一篇文章中的案例確實是一個特性,相反的行為將是違反標準的。