使用NAT打造FTP服務新法

 

FTP(File Transfer Protocol,文件傳輸協議)是Internet的傳統服務之一。FTP使用戶能在兩個聯網的計算機之間傳輸文件,是Internet傳遞文件最主要的方法。除此之外,FTP還提供登錄、目錄查詢、文件操作及其它會話控制功能。在系統中FTP服務使用23端口進行通信,在Window、Linux系統中都可以設置FTP服務。

NAT(Network Address Translation)網絡地址轉換,NAT服務器就是支持地址轉換的代理服務器。當有幾個工作站卻只有一個合法的上網賬戶和IP地址時,可以用NAT服務器來實現地址轉換。

本文主要介紹在NAT服務器上設置FTP服務。這樣的FTP服務設置比起其它一些服務,如WWW, E-mial等要複雜得多。這是由於FTP自身的原因,因爲FTP在連接過程中,分別需要Command和Data兩個通道才能實現,而其連接的起始方向,對NAT服務器規則的設置有相當重要的影響。

設置規則

假設現在NAT服務器上有3塊網卡,它們分別連接不同的網絡且分配不同的IP地址。例如,第一張網卡A是用外網C類IP地址:221.7.128.1;第二張網卡接DMZ,使用A類IP:10.0.0.1;第三張網卡接內部網絡,使用C類IP地址:192.168.0.1;DMZ內有一臺主機,IP:10.0.0.2,並且準備提供FTP 服務(使用port 21和port 2121)。

如果DMZ和外網的路由是通的,那麼NAT服務器上只進行單純的封包過濾,沒有修改packet,而且預設的policy都是DENY。如果DMZ和外網的路由是不通的,要如何設置規則,使得FTP能順利向外部提供服務呢?可以用如下命令將第一塊網卡的port 21連接請求轉至10.0.0.2的port 21來提供服務。

方法一:ipchains

我們用命令:ipmasqadm portfw -a -P tcp -L 221.7.128.1 21 -R 10.0.0.2 21來進行操作。

NAT服務器上的預設policy全爲DENY,要設置所有必須的規則,讓FTP能順利向外提供服務。以如下示例說明:

ipchains -A input -i eth0 -p TCP -d 10.0.0.2 21 -j ACCEPT 
ipchains -A forward -p TCP -d 10.0.0.2 21 -j ACCEPT 
ipchains -A output -i eth1 -p TCP -d 10.0.0.2 21 -j ACCEPT 
ipchains -A input -i eth1 -p TCP -s 10.0.0.2 21 -j ACCEPT 
ipchains -A forward -p TCP -s 10.0.0.2 21 -j ACCEPT 
ipchains -A output -i eth0 -p TCP -s 10.0.0.2 21 -j ACCEPT 
ipchains -A input -i eth0 -p TCP -d 10.0.0.2 2121 -j ACCEPT 
ipchains -A forward -p TCP -d 10.0.0.2 2121 -j ACCEPT 
ipchains -A output -i eth1 -p TCP -d 10.0.0.2 2121 -j ACCEPT 
ipchains -A input -i eth1 -p TCP -s 10.0.0.2 2121 -j ACCEPT 
ipchains -A forward -p TCP -s 10.0.0.2 2121 -j ACCEPT 
ipchains -A output -i eth0 -p TCP -s 10.0.0.2 2121 -j ACCEPT

以上是在沒有考慮其它安全要求、單就FTP服務進行設置的情況下,以ipchains作爲命令的操作。

ipchains -A input -i eth0 -p TCP -d 221.7.128.1 21 -j ACCEPT 
ipchains -A forward -p TCP -d 221.7.128.1 21 -j MASQ 
ipchains -A output -i eth1 -p TCP -d 10.0.0.2 21 -j ACCEPT 
ipchains -A input -i eth1 -p TCP -s 10.0.0.2 21 -j ACCEPT 
ipchains -A forward -p TCP -s 10.0.0.2 21 -j MASQ 
ipchains -A output -i eth0 -p TCP -s 221.7.128.1 21 -j ACCEPT 
ipmasqadm portfw -a -P tcp -L 221.7.128.1 2121 -R 10.0.0.2 2121 
ipchains -A input -i eth0 -p TCP -d 221.7.128.1 2121 -j ACCEPT 
ipchains -A forward -p TCP -d 10.0.0.2 2121 -j MASQ 
ipchains -A output -i eth1 -p TCP -d 10.0.0.2 2121 -j ACCEPT 
ipchains -A input -i eth1 -p TCP -s 10.0.0.2 2121 -j ACCEPT 
ipchains -A forward -p TCP -s 10.0.0.2 2121 -j MASQ 
ipchains -A output -i eth0 -p TCP -s 221.7.128.1 2121 -j ACCEPT

下面對上述命令進行說明。

命令1:ipchains -A input -i eth0 -p TCP -d 221.7.128.1 21 -j ACCEPT

建立連接用,因爲使用ipmasqadm命令來實現DNAT服務器(port forward),因此,destiNAT服務器就成了NAT服務器的外部界面。

命令2:ipchains -A forward -p TCP -d 221.7.128.1 21 -j MASQ *

值得注意的是,因爲在DNAT服務器時已經將destiNAT服務器socket修改過了,也就是封包input進來後,外網的IP:221.7.128.1會改變爲10.0.0.2。而且還要了解ipmasqadm這個程序的特點,是當它修改了input packet後,就不會再有ipchains的forward檢測,而是直接根據路由判斷後進行output。所以,這行是多餘的,可以不要。

命令3:ipchains -A output -i eth1 -p TCP -d 10.0.0.2 21 -j ACCEPT

這是經過DNAT服務器修改後從NAT服務器主機輸出到FTP Server的封包,必須ACCEPT,否則連接請求沒辦法到達Server。

命令4:ipchains -A input -i eth1 -p TCP -s 10.0.0.2 21 -j ACCEPT

這是從FTP Server迴應進來的封包,也一定要ACCEPT。

命令5:ipchains -A forward -p TCP -s 10.0.0.2 21 -j MASQ

這裏要非常小心,因爲假設的前提是DMZ和外網不能路由,如果封包沒做MASQ處理,那麼將無法傳送。而且,不要忽略當封包經過ipmasqadm處理進行MASQ後,出去的封包會被還原成Client所expect的socket。如果用ACCEPT的話是不行的,ipmasqadm不會對ACCEPT規則做還原動作,只有使用MASQ才能將當初被DNAT服務器處理過的連接正確的還原爲原來的socket,即port 21。

命令6:ipchains -A output -i eth0 -p TCP -s 221.7.128.1 21 -j ACCEPT

這是還原socket後送回到Client的迴應封包,所以要ACCEPT。

命令7:ipmasqadm portfw -a -P tcp -L 221.7.128.1 2121 -R 10.0.0.2 2121 *

照理說,ftp-data連接應該是從port 2121出去的,換句話說,基本上第一個syn的連接封包是output而不是input。這樣的話,要能成功地將回應封包(不是起始封包)forward到FTP Server去,要看Client是否知道ftp-data的建立socket會在Server端的port 2121上面,也就取決於DMZ的Server經過SNAT服務器之後是否能夠成功地用port 2121來起始ftp-data通道。

命令8:ipchains -A input -i eth0 -p TCP -d 221.7.128.1 2121 -j ACCEPT *

只有上一句的條件成立時,這行命令纔有用。

命令9:ipchains -A forward -p TCP -d 10.0.0.2 2121 -j MASQ *

這行和命令5的道理一樣,如果用命令7處理後,這行就無須使用了。

命令10:ipchains -A output -i eth1 -p TCP -d 10.0.0.2 2121 -j ACCEPT

不管命令7和上一句是否被執行,這行是必須的,因爲對於DMZ的FTP Server來說,不管NAT服務器怎麼處理,用來做ftp-data的port還是2121。

命令11:ipchains -A input -i eth1 -p TCP -s 10.0.0.2 2121 -j ACCEPT

這行也是必須的,理由同上。

命令12:ipchains -A forward -p TCP -s 10.0.0.2 2121 -j MASQ

這行非常重要!因爲ftp-data的連接是從Server端起始的,也就是當DMZ的FTP Server要建立ftp-data連接時,因爲無法路由,所以一定要用MASQ。但與命令5比較,因爲命令5的連接之前已經被ipmasqadm處理過,所以能正確地還原到原來的socket(port 21)。但在這裏,因爲是第一個連接封包,之前不可能被ipmasaqdm處理過,是不可能被還原爲port 2121的。取而代之的是,ipchains會根據MASQ的請求,重新建立一個對外的socket,而port則是隨機產生的,也就是說在1024~65535之間。請記住這個特點,我們必須增加下面兩行規則:

ipchains -A output -i eth0 -p TCP -s 221.7.128.1 1024:65355 -d 0/0 1024:65535 -j ACCEPT 
ipchains -A input -i eth0 -p TCP -s 0/0 1024:65535 -d 221.7.128.1 1024:65535 -j ACCEPT

這樣結果是,1024以上的port都能打開連接。這是非常危險的一個操作,因爲開放的範圍太大,至少應該將來自外網的第一個syn封包攔截下來,所以上面的input可以修改爲:

ipchains -A input -i eth0 -p TCP -s 0/0 1024:65535 -d 221.7.128.1 1024:65355 ! -y -j ACCEPT

所以,命令7和其後緊接着的兩行也就沒什麼作用,可以不要。

命令13:ipchains -A output -i eth0 -p TCP -s 221.7.128.1 2121 -j ACCEPT *

同樣,這最後一行也可以不設,因爲是多餘的。事實上,ftp-data的socket從NAT服務器主機出去Client的時候,是不會使用到port 2121的。

這裏,我們並沒有使用passive模式,所有被*標識的句子,事實上都可省略掉。

方法二:iptalbes

首先進行iptables的設置如下:

# Generated by iptables-save v1.2.1a on Thu Jun 28 14:45:26 212101 
# NAT服務器 
:PREROUTING DROP [3:144] 
:POSTROUTING ACCEPT [2:108] 
:OUTPUT ACCEPT [4:948] 
-A PREROUTING -p udp -m udp --dport 53 -j ACCEPT 
-A PREROUTING -p udp -m udp --sport 53 -j ACCEPT 
-A PREROUTING -p tcp -m tcp --dport 113 -j ACCEPT 
-A PREROUTING -p tcp -m tcp --sport 113 -j ACCEPT 
-A PREROUTING -p icmp -j ACCEPT 
-A PREROUTING -d 10.0.0.2 -i eth0 -p tcp -m tcp --dport 21 -j ACCEPT 
-A PREROUTING -s 10.0.0.2 -i eth1 -p tcp -m tcp --sport 2121 -j ACCEPT 
COMMIT 
# Completed on Thu Jun 28 14:45:26 212101 
# Generated by iptables-save v1.2.1a on Thu Jun 28 14:45:26 212101 
# filter 
:INPUT DROP [0:0] 
:FORWARD DROP [0:0] 
:OUTPUT DROP [4:948] 
-A INPUT -p udp -m udp --dport 53 -j ACCEPT 
-A INPUT -p udp -m udp --sport 53 -j ACCEPT 
-A INPUT -p tcp -m tcp --dport 113 -j ACCEPT 
-A INPUT -p tcp -m tcp --sport 113 -j ACCEPT 
-A INPUT -p icmp -j ACCEPT 
-A INPUT -i lo -j ACCEPT 
-A FORWARD -p tcp -m tcp --sport 53 -j ACCEPT 
-A FORWARD -p tcp -m tcp --dport 53 -j ACCEPT 
-A FORWARD -s 10.0.0.2 -i eth1 -p tcp -m tcp --sport 21 -j ACCEPT 
-A FORWARD -d 10.0.0.2 -i eth0 -p tcp -m tcp --dport 21 -j ACCEPT 
-A FORWARD -s 10.0.0.2 -o eth0 -p tcp -m tcp --sport 2121 -j ACCEPT 
-A FORWARD -d 10.0.0.2 -o eth1 -p tcp -m tcp --dport 2121 -j ACCEPT 
-A FORWARD -p icmp -j ACCEPT 
-A OUTPUT -o lo -j ACCEPT 
-A OUTPUT -p icmp -j ACCEPT 
-A OUTPUT -p udp -m udp --dport 53 -j ACCEPT 
-A OUTPUT -p udp -m udp --sport 53 -j ACCEPT 
-A OUTPUT -p tcp -m tcp --dport 113 -j ACCEPT 
-A OUTPUT -p tcp -m tcp --sport 113 -j ACCEPT 
COMMIT 
# Completed on Thu Jun 28 14:45:26 212101

# Generated by iptables-save v1.2.1a on Sat Jun 30 16:35:09 212101 
# NAT服務器 
:PREROUTING DROP [0:0] 
:POSTROUTING ACCEPT [0:0] 
:OUTPUT ACCEPT [0:0] 
-A PREROUTING -p udp -m udp --dport 53 -j ACCEPT 
-A PREROUTING -p udp -m udp --sport 53 -j ACCEPT 
-A PREROUTING -p tcp -m tcp --dport 113 -j ACCEPT 
-A PREROUTING -p tcp -m tcp --sport 113 -j ACCEPT 
-A PREROUTING -p icmp -j ACCEPT 
-A PREROUTING -d 221.7.128.1 -i eth0 -p tcp -m tcp --dport 21 -j 
# DNAT服務器到destiNAT服務器的地址10.0.0.2:21
# (注一):不用爲port 2121做 DNAT服務器
-A PREROUTING -s 10.0.0.2 -i eth1 -p tcp -m tcp --sport 21 -j ACCEPT 
-A PREROUTING -s 10.0.0.2 -i eth1 -p tcp -m tcp --sport 2121 -j ACCEPT 
-A POSTROUTING -p tcp -m tcp -s 10.0.0.2 --sport 2121 -j MASQUERADE 
# (注二):請留意上一行,在ipchains中也有相同的設計。 
COMMIT 
# Completed on Sat Jun 30 16:35:09 212101 
# Generated by iptables-save v1.2.1a on Sat Jun 30 16:35:09 212101 
# filter 
:INPUT DROP [0:0] 
:FORWARD DROP [0:0] 
:OUTPUT DROP [0:0] 
-A INPUT -p udp -m udp --dport 53 -j ACCEPT 
-A INPUT -p udp -m udp --sport 53 -j ACCEPT 
-A INPUT -p tcp -m tcp --dport 113 -j ACCEPT 
-A INPUT -p tcp -m tcp --sport 113 -j ACCEPT 
-A INPUT -p icmp -j ACCEPT 
-A INPUT -i lo -j ACCEPT 
-A FORWARD -p udp -m udp --sport 53 -j ACCEPT 
-A FORWARD -p udp -m udp --dport 53 -j ACCEPT 
-A FORWARD -s 10.0.0.2 -i eth1 -p tcp -m tcp --sport 21 -j ACCEPT 
-A FORWARD -d 10.0.0.2 -i eth0 -p tcp -m tcp --dport 21 -j ACCEPT 
-A FORWARD -s 10.0.0.2 -o eth0 -p tcp -m tcp --sport 2121 -j ACCEPT 
-A FORWARD -d 10.0.0.2 -o eth1 -p tcp -m tcp --dport 2121 -j ACCEPT 
-A FORWARD -p icmp -j ACCEPT 
-A OUTPUT -p icmp -j ACCEPT 
-A OUTPUT -o lo -j ACCEPT 
-A OUTPUT -p udp -m udp --dport 53 -j ACCEPT 
-A OUTPUT -p udp -m udp --sport 53 -j ACCEPT 
-A OUTPUT -p tcp -m tcp --dport 113 -j ACCEPT 
-A OUTPUT -p tcp -m tcp --sport 113 -j ACCEPT 
COMMIT 
# Completed on Sat Jun 30 16:35:09 212101

iptables和ipchains的最大分別是對來自FTP Server的ftp-data封包的處理上。如果用ipchains,在MASQ後會另外建一個source socket,但不是使用port 2121;如果用iptables,在MASQ後也會另建一個source socket,卻保留原來的port 2121。因爲連接是從Server端由內至外建立的,所以在NAT服務器上已經有這個連接的MASQ記錄存在,也就不必爲port 2121做DNAT服務器了。不過,在進行passive模式測試時,儘管將ip_NAT服務器_ftp模塊載入,還是不能建立ftp-data的連接。抓幾個封包就可以發現:Client端從command channel中接收Server的port命令後,會嘗試直接以FTP Server的IP地址作爲destiNAT服務器,而不是以NAT服務器的外部界面爲目標,所以連接無法建立。

結論

如果Server和Client兩端都各自“躲”在NAT服務器背後,無論用ipchains或iptalbes方法都無法使用passive 模式來建立data channel。解決的方法只能是在Client端的NAT服務器上,將ip_NAT服務器_ftp的模塊載入(ipchains 是用ip_masq_ftp 模塊),而Server端使用標準的port 2121和port 21來提供FTP服務。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章