Ftp

nft config 使本地 NATed FTP 伺服器公開可用

  • September 4, 2020

一切都將在一個孤立的網路上,安全不是問題。

eth0 連接到“公共”網路。DHCP 分配的地址。

eth1 連接到提供 ssh、telnet、“其他”和 ftp 的“專用網路”伺服器。

在此範例中,此伺服器將具有固定 IP (192.168.1.2)。

網關正在執行 debian buster 和 Linux 核心 4.19.94

nft 與 NAT 一起使用

這是到目前為止我的“網關”nft 配置:

table ip my_nat {
   chain my_prerouting { type nat hook prerouting priority 0;
   tcp dport { 2222 } dnat to :22 # 2222 backdoor for ssh to the gateway
   tcp dport { 1-1023 } dnat to 192.168.1.2
 }
 chain my_postrouting {
   type nat hook postrouting priority 100;
   ip daddr 192.168.1.2  masquerade
 }
}

我需要添加什麼才能使 FTP 工作

TL;博士

# nft add ct helper ip my_nat ftp-incoming '{ type "ftp" protocol tcp; }'
# nft add chain ip my_nat my_helpers '{ type filter hook prerouting priority 10; }'
# nft add rule ip my_nat my_helpers iif eth0 ip daddr 192.168.1.2 tcp dport 21 ct helper set ftp-incoming
# modprobe nf_nat_ftp

下面有更多細節……

用於有問題的協議的協議助手模組

FTP 是一個舊協議,對防火牆不是很友好:FTP 命令通道 (21/TCP) 上的命令協商一個臨時埠以用於下一個傳輸命令。因此,狀態防火牆必須窺探這些命令和回复,以臨時預先允許即將使用的足夠埠。

在 Linux 上,這是由特定於協議的幫助模組提供的,這些模組是conntrack的外掛,Netfilter 子系統跟踪 NAT 和狀態防火牆的連接。對於 FTP,當在 FTP 命令埠上看到下一次傳輸的埠協商(主要是 PORT、EPRT、PASV 或 EPSV)時,助手會在特殊的conntrack表(conntrack 期望表)中添加一個短期條目,該表將等待下一個相關且預期的數據連接。

我的回答使用了現代“安全”處理,如本部落格中關於iptables的一般性描述和nftables wiki以及與iptables不同的nftablesman nft處理。

安全使用助手和 nftables 規則

Linux 核心 4.7+(包括 4.19)預設使用安全方法:載入(此處為 FTP)幫助程序模組將不會再窺探具有 TCP 源或目標埠 21 的所有數據包,直到特定的 nftables(或iptables ) 語句告訴它在什麼(受限)情況下它應該窺探。這避免了不必要的 CPU 使用,並允許通過更改一些規則(或設置)隨時更改 FTP 埠以進行偵聽。

第一部分是聲明可以觸發監聽的流。它在nftables中的處理方式與在iptables中不同。這裡它是使用有ct helper狀態對象聲明的,並且必須在conntrack之後進行過濾以啟動它(而iptables需要之前完成的操作)。man nft告訴:

與 iptables 不同,助手分配需要在 conntrack 查找完成後執行,例如使用預設的 0 掛鉤優先級。

nft add ct helper ip my_nat ftp-incoming '{ type "ftp" protocol tcp; }'

nft add chain ip my_nat my_helpers '{ type filter hook prerouting priority 10; }'
nft add rule ip my_nat my_helpers iif eth0 ip daddr 192.168.1.2 tcp dport 21 ct helper set ftp-incoming

我選擇了同一個表,但它可以在另一個表中創建,只要有狀態對象聲明和引用它的規則在同一個表中。

當然可以選擇限制較少的規則。用以下規則替換最後一條規則將具有與傳統模式相同的效果:

nft add rule ip my_nat my_helpers tcp dport 21 ct helper set ftp-incoming

僅供參考,不應再使用的傳統模式不需要上述規則,而只需要此切換(以及相關核心模組的手動載入):

sysctl -w net.netfilter.nf_conntrack_helper=1

確保nf_nat_ftp已載入

核心模組nf_conntrack_ftp會自動載入由ct helper ... type "ftp". 情況並非如此nf_nat_ftp,但是當在數據流埠上完成 NAT 時,還需要在命令埠中啟用數據包修改。

例如,要在載入nf_nat_ftp時拉取模組,可以在文件中添加以下內容:nf_conntrack_ftp``/etc/modprobe.d/local-nat-ftp.conf

install nf_conntrack_ftp /sbin/modprobe --ignore-install nf_conntrack_ftp; /sbin/modprobe --ignore-install nf_nat_ftp

或者,只需添加例如/etc/modules-load.d/local-nat-ftp.conf

nf_nat_ftp

無論如何,現在應該執行此命令以確保已載入:

modprobe nf_nat_ftp

關於防火牆

這是防火牆的附加說明。也可以有一些限制的防火牆規則,而不是允許任何由conntrack標記為**相關的新流。

例如,雖然 FTP 幫助模組同時處理被動和主動模式,但如果出於某種原因只想允許被動模式(從客戶端到伺服器的數據連接)而不是“主動”ftp(從伺服器源埠 20 到客戶端)例如可以在規則集的防火牆部分使用這些規則,而不是通常的ct state established,related accept

ct state established accept
ct state related ct helper "ftp" iif eth0 oif eth1 tcp sport 1024-65535 accept
ct state related ct helper "ftp" drop
ct state related accept 

與 FTP 無關的其他類型的相關流仍然被接受(或可以進一步分開)


助手處理範例

這裡(在模擬環境中)是在期望表和帶有 OP 規則的conntrack表上測量的兩個事件的conntrack列表+ 上面的附加規則,其中 Internet 客戶端 203.0.113.101 以路由器的公共 IP 地址 192.0 以被動模式執行 FTP。 2.2 並在登錄後使用 LIST 命令:

# conntrack -E expect
   [NEW] 300 proto=6 src=203.0.113.101 dst=192.0.2.2 sport=0 dport=37157 mask-src=0.0.0.0 mask-dst=0.0.0.0 sport=0 dport=65535 master-src=203.0.113.101 master-dst=192.0.2.2 sport=50774 dport=21 class=0 helper=ftp
[DESTROY] 300 proto=6 src=203.0.113.101 dst=192.0.2.2 sport=0 dport=37157 mask-src=0.0.0.0 mask-dst=0.0.0.0 sport=0 dport=65535 master-src=203.0.113.101 master-dst=192.0.2.2 sport=50774 dport=21 class=0 helper=ftp

同時地:

# conntrack -E
   [NEW] tcp      6 120 SYN_SENT src=203.0.113.101 dst=192.0.2.2 sport=50774 dport=21 [UNREPLIED] src=192.168.1.2 dst=192.168.1.1 sport=21 dport=50774 helper=ftp
[UPDATE] tcp      6 60 SYN_RECV src=203.0.113.101 dst=192.0.2.2 sport=50774 dport=21 src=192.168.1.2 dst=192.168.1.1 sport=21 dport=50774 helper=ftp
[UPDATE] tcp      6 432000 ESTABLISHED src=203.0.113.101 dst=192.0.2.2 sport=50774 dport=21 src=192.168.1.2 dst=192.168.1.1 sport=21 dport=50774 [ASSURED] helper=ftp
   [NEW] tcp      6 120 SYN_SENT src=203.0.113.101 dst=192.0.2.2 sport=55835 dport=37157 [UNREPLIED] src=192.168.1.2 dst=192.168.1.1 sport=37157 dport=55835
[UPDATE] tcp      6 60 SYN_RECV src=203.0.113.101 dst=192.0.2.2 sport=55835 dport=37157 src=192.168.1.2 dst=192.168.1.1 sport=37157 dport=55835
[UPDATE] tcp      6 432000 ESTABLISHED src=203.0.113.101 dst=192.0.2.2 sport=55835 dport=37157 src=192.168.1.2 dst=192.168.1.1 sport=37157 dport=55835 [ASSURED]
[UPDATE] tcp      6 120 FIN_WAIT src=203.0.113.101 dst=192.0.2.2 sport=55835 dport=37157 src=192.168.1.2 dst=192.168.1.1 sport=37157 dport=55835 [ASSURED]
[UPDATE] tcp      6 30 LAST_ACK src=203.0.113.101 dst=192.0.2.2 sport=55835 dport=37157 src=192.168.1.2 dst=192.168.1.1 sport=37157 dport=55835 [ASSURED]
[UPDATE] tcp      6 120 TIME_WAIT src=203.0.113.101 dst=192.0.2.2 sport=55835 dport=37157 src=192.168.1.2 dst=192.168.1.1 sport=37157 dport=55835 [ASSURED]

期望的開始proto=6 src=203.0.113.101 dst=192.0.2.2 sport=0 dport=37157告訴從 203.0.113.101:* 到 192.0.2.2:37157 的下一個 TCP 連接將與 FTP 連接相關聯(狀態*相關)。*不直接可見,但由於還載入了 NAT FTP 幫助程序模組,伺服器響應 PASV/EPSV 命令發送的實際數據被截獲並轉換,因此客戶端連接到 192.0.2.2 而不是 192.168.1.2當然在客戶端上失敗了。

儘管第二個流(第二個新行)在**my_prerouting中沒有明確的規則,但它已成功地 DNATed 到路由器後面的伺服器。


筆記

  • 如果 FTP 控制埠被加密(AUTH TLS…),那麼輔助模組就不能再窺探協商的埠,這將無法工作。必須求助於在 FTP 伺服器配置和防火牆/NAT 路由器上配置保留的埠範圍,並配置伺服器以便在協商時發送正確的(公共)IP 地址而不是它自己的。如果伺服器沒有到 Internet 的路由,則不能使用主動 FTP 模式(就像這裡的情況一樣)。
  • 挑剔:10 的預路由優先級確保即使對於小於 4.18 的核心,NAT 已經為新流發生(OP 選擇了鉤子預路由優先級 0 而不是通常的 -100,因為這在 nftables 中很少重要),因此daddr 192.168.1.2可以使用。如果優先級為 0(或低於 0),則規則可能會(未驗證)看到第一個數據包仍未使用公共 IP 目標地址進行 NAT,但會擷取同一流的以下數據包,因為它們已被處理直接通過conntrack優先級 -200。更好地保持安全並使用 10。實際上這與核心 4.18 無關(請參閱此中的送出參考待處理的更新檔),其中 NAT 優先級僅與多個 nat 鏈之間的比較相關(並允許在 iptables legacy 中沿 nftables 混合 NAT)。

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