nftables 目標 nat 阻止本地訪問埠
我已經在我的伺服器上設置了 nftables,我想將所有進入某些受保護埠(例如 80)的流量重定向到更高的埠,該埠無需 root 權限(例如 13080)。我希望只能遠端訪問 80 個,但本地訪問兩個埠。這是我想出的設置:
#!/usr/bin/nft -f flush ruleset table inet firewall { chain inbound { type filter hook input priority filter; policy drop; ct status dnat counter accept # accept everything that came through destination nat (port 80) iifname lo counter accept oifname lo counter accept ct state { established, related } counter accept ct state invalid counter drop tcp dport 22 ct state new counter accept counter reject with icmpx type port-unreachable # reject everything else } chain destination-nat { type nat hook prerouting priority dstnat; policy accept tcp dport 80 counter redirect to 13080 # redirect 80 to 13080 } chain forward { type filter hook forward priority 0; policy drop; } chain outbound { type filter hook output priority 0; policy accept; } }
但是,由於某種原因,這會阻止對埠 80 的本地訪問(儘管仍然可以訪問 13080)。有人可以告訴我我做錯了什麼嗎?
這是Netfilter 和 General Networking 中的數據包流範例,它對 nftables保持有效:
寫了一個重要的細節:*“nat”表僅用於“NEW”連接。
對於本地啟動的連接,新連接的第一個數據包在輸出期間創建一個 NEW conntrack 狀態(輸出的 conntrack 框)。當這個連接被環回(在幾乎所有情況下通過lo介面)時,當數據包通過預路由(另一個 conntrack 框)返回時,相同的 conntrack 狀態匹配:本地環回連接沒有兩個 conntrack 狀態。
對於其他情況,新連接的第一個數據包通過預路由(預路由的 conntrack 框)到達並導致創建新的 conntrack 狀態。
因此,當發送連接的第一個環回數據包時,會在輸出期間創建一個新的 conntrack 條目,當該數據包通過預路由返回時,它匹配現有的 conntrack 條目:不再是新狀態。NAT 掛鉤(即 nat/prerouting 鏈
destination-nat
)不會被遍歷,因此不會影響此連接:在輸出步驟期間錯過了機會。相反,在 nat/output 中使用dnat語句將有一個 NEW conntrack 狀態將解決這種情況。由於預設情況下它會影響任何本地啟動的連接(即甚至到 Internet),因此必須注意僅將其用於保持本地的連接:通過lo介面。這條鍊和規則將做到這一點:
nft add chain inet firewall loopback-nat '{ type nat hook output priority -100; policy accept; }' nft add rule inet firewall loopback-nat oif lo tcp dport 80 counter redirect to :13080
您只需
conntrack
在事件模式下在其他地方執行命令即可遵循該行為:conntrack -E -p tcp --dport 80
並查看從外部發起的連接和本地發起的環回連接的區別,無論有沒有這個附加鏈。請記住,nat鉤子只會看到與
[NEW]
狀態一起顯示的條目(並且已經相應地更改了命令顯示的條目)。