FTP協議的特點就是數據流端口與控制流端口分離,這使得管理員在設置防火牆規則時,需要多考慮一些因素.同時由於FTP服務器本身的重要性和不安全性,許多管理員想將其置於防火牆機器後,這樣一來就更麻煩了.通常是客戶端能登錄上服務器,但無法列出目錄,無法傳輸數據等等,讓許多新手管理員摸不清頭腦,到論壇裏撒分“跪求”解決辦法.其實這並不是想像的那麼難,看了本文後,你將明白這一切.
第一部分.理解FTP的主動模式與被動模式
其實網上關於FTP傳輸的主被動模式的講解已很多,要想讓客戶機與服務器之間暢通無阻的傳輸數據,必須首先理解它們的傳輸原理,這樣我們遇到問題時纔可以對症下藥.我們通過抓包分析來理解其轉輸過程.
主動模式(Port模式)
主動模式的傳輸數據流程如下(服務器ip:192.168.200.1,客戶端ip:192.168.200.8):
1..192.168.200.8.55722 > 192.168.200.1.ftp: PORT 192,168,200,8,178,210
2..192.168.200.1.ftp > 192.168.200.8.55722: 200 PORT command successful. Consider using PASV.
3..192.168.200.8.55722 > 192.168.200.1.ftp: ......ACK
4..192.168.200.8.55722 > 192.168.200.1.ftp: LIST
5..192.168.200.1.ftp-data > 192.168.200.8.45778:......SYN
6..192.168.200.8.45778 > 192.168.200.1.ftp-data: ......SYN.ACK
7..192.168.200.1.ftp-data > 192.168.200.8.45778: ......ACK
8..192.168.200.1.ftp > 192.168.200.8.55722: 150 Here comes the directory listing.
9..192.168.200.1.ftp-data > 192.168.200.8.45778:
-rw-r--r-- 1 0 0 6 Mar 23 08:53 filetest
drwxr-xr-x 2 0 0 4096 Dec 13 2007 pub
從上面的數據得出主動模式的傳輸過程如下:
A.(第1行)客戶端向服務器申請PORT模式的數據傳輸,並通過PORT命令告知服務器"我的IP是192.168.200.8,我開放端口45778等你".
(45778是通過PORT命令後的最後兩個數字算出來的.178*256 + 210 = 45778)
B.(第2行)服務器在檢查所收到的PORT命令的語法和安全性等因素後,向客戶端告知PORT命令成功,並同時建議客戶端考慮使用PASV.
(PASV就是我們接下來要講的被動模式)
C.(第3行)客戶端確認收到從服務器傳來的信息並應答.
D.(第4行)客戶端向服務器申請列出目錄信息的數據.
E.(第5,6,7行)服務器收到客戶端的申請後,主動用自己的20端口去連接客戶端的45778端口,以便傳送數據.
(注意:這是重要的地方,所謂主動模式,就是指服務器從自己的數據端口主動去連接客戶端)
F.(第8行)當服務器與客戶端的數據流端口成功連接後,服務器便通過控制端口21向客戶發送信息:你需要的目錄列表傳來了.
G.(第9行)服務器通過數據流端口,將用戶所需要的目錄數據信息發向客戶端.
在整個通信過程中,服務器僅用了兩個固定的低端端口,即控制端口21(ftp)和數據端口20(ftp-data),防火牆規則很好設置,只需放開這兩個 端口就行.而客戶端就沒那麼幸運了,動態的開放了一個高端端口等待連接,這讓處於局域網內部,通過共享同一IP上網的用戶而言基本沒轍.但是,有其它的解 決辦法麼?有!就是我們接下來要談到的被動模式.
主動模式的傳輸數據流程如下(服務器ip:192.168.200.1,客戶端ip:192.168.200.8):
1..192.168.200.8.55722 > 192.168.200.1.ftp: PORT 192,168,200,8,178,210
2..192.168.200.1.ftp > 192.168.200.8.55722: 200 PORT command successful. Consider using PASV.
3..192.168.200.8.55722 > 192.168.200.1.ftp: ......ACK
4..192.168.200.8.55722 > 192.168.200.1.ftp: LIST
5..192.168.200.1.ftp-data > 192.168.200.8.45778:......SYN
6..192.168.200.8.45778 > 192.168.200.1.ftp-data: ......SYN.ACK
7..192.168.200.1.ftp-data > 192.168.200.8.45778: ......ACK
8..192.168.200.1.ftp > 192.168.200.8.55722: 150 Here comes the directory listing.
9..192.168.200.1.ftp-data > 192.168.200.8.45778:
-rw-r--r-- 1 0 0 6 Mar 23 08:53 filetest
drwxr-xr-x 2 0 0 4096 Dec 13 2007 pub
從上面的數據得出主動模式的傳輸過程如下:
A.(第1行)客戶端向服務器申請PORT模式的數據傳輸,並通過PORT命令告知服務器"我的IP是192.168.200.8,我開放端口45778等你".
(45778是通過PORT命令後的最後兩個數字算出來的.178*256 + 210 = 45778)
B.(第2行)服務器在檢查所收到的PORT命令的語法和安全性等因素後,向客戶端告知PORT命令成功,並同時建議客戶端考慮使用PASV.
(PASV就是我們接下來要講的被動模式)
C.(第3行)客戶端確認收到從服務器傳來的信息並應答.
D.(第4行)客戶端向服務器申請列出目錄信息的數據.
E.(第5,6,7行)服務器收到客戶端的申請後,主動用自己的20端口去連接客戶端的45778端口,以便傳送數據.
(注意:這是重要的地方,所謂主動模式,就是指服務器從自己的數據端口主動去連接客戶端)
F.(第8行)當服務器與客戶端的數據流端口成功連接後,服務器便通過控制端口21向客戶發送信息:你需要的目錄列表傳來了.
G.(第9行)服務器通過數據流端口,將用戶所需要的目錄數據信息發向客戶端.
在整個通信過程中,服務器僅用了兩個固定的低端端口,即控制端口21(ftp)和數據端口20(ftp-data),防火牆規則很好設置,只需放開這兩個 端口就行.而客戶端就沒那麼幸運了,動態的開放了一個高端端口等待連接,這讓處於局域網內部,通過共享同一IP上網的用戶而言基本沒轍.但是,有其它的解 決辦法麼?有!就是我們接下來要談到的被動模式.
被動模式(Passive模式)
被動模式的傳輸數據流程如下(服務器ip:192.168.200.1,客戶端ip:192.168.200.8):
1..192.168.200.8.40137 > 192.168.200.1.ftp: PASV
2..192.168.200.1.ftp > 192.168.200.8.40137: Entering Passive Mode (192,168,200,1,11,187)
3..192.168.200.8.40137 > 192.168.200.1.ftp: ......ACK
4..192.168.200.8.43422 > 192.168.200.1.3003: ......SYN
5..192.168.200.1.3003 > 192.168.200.8.43422: ......SYN.ACK
6..192.168.200.8.43422 > 192.168.200.1.3003: ......ACK
7..192.168.200.8.40137 > 192.168.200.1.ftp: LIST
8..192.168.200.1.ftp > 192.168.200.8.40137: 150 Here comes the directory listing.
9..192.168.200.1.3003 > 192.168.200.8.43422:
-rw-r--r-- 1 0 0 6 Mar 23 08:53 filetest
drwxr-xr-x 2 0 0 4096 Dec 13 2007 pub
從上面的數據得出主動模式的傳輸教程如下:
A.(第1行)客戶端向服務器申請PASV模式的數據傳輸.
B.(第2行)服務器新開放一個數據流端口,進入監聽模式.並告訴客戶"你連接192.168.200.1吧,我開放了3003端口等你呢".
(3003端口是通過第2行最後兩個數字計算出來的,11*256 + 187 = 3003)
C.(第3行)客戶端確認收到從服務器傳來的信息並應答.
D.(第4,5,6行)當客戶端獲知服務器已新開了一個數據流端口讓自己去連接後,便從本地隨機選擇一個端口去連接服務器指定的端口,以便傳送數據.
(注意:這是重要的地方,與主動模式不一樣,服務器不會去主動連接客戶端,而是新開一個端口,被動的等客戶端來連接,這就是所謂的被動模式)
E.(第7行)當客戶端與服務器的數據流端口成功連接後,客戶端便向服務器申請列出目錄信息的數據.
F.(第8行)服務器便通過控制端口21向客戶發送信息:你需要的目錄列表傳來了.
G.(第9行)服務器通過數據流端口,將用戶所需要的目錄數據信息發向客戶端.
在整個通信過程中,客戶端都是主動去連接服務器,並沒有開放端口被連接,這確實爲客戶端的防火牆減輕了不少麻煩.但麻煩消失了麼?沒有!被動模式只是把麻 煩"移"到了服務器上而已,服務器則需要動態的開一個高端端口來傳輸數據,怎樣處理這個端口是我們面臨着的困難.不過不用怕,天才的程序員們爲我們想好了 一切,我們只需要按我們的要求設置參數就行.接下來讓我們分析各種可能存在的情況.
被動模式的傳輸數據流程如下(服務器ip:192.168.200.1,客戶端ip:192.168.200.8):
1..192.168.200.8.40137 > 192.168.200.1.ftp: PASV
2..192.168.200.1.ftp > 192.168.200.8.40137: Entering Passive Mode (192,168,200,1,11,187)
3..192.168.200.8.40137 > 192.168.200.1.ftp: ......ACK
4..192.168.200.8.43422 > 192.168.200.1.3003: ......SYN
5..192.168.200.1.3003 > 192.168.200.8.43422: ......SYN.ACK
6..192.168.200.8.43422 > 192.168.200.1.3003: ......ACK
7..192.168.200.8.40137 > 192.168.200.1.ftp: LIST
8..192.168.200.1.ftp > 192.168.200.8.40137: 150 Here comes the directory listing.
9..192.168.200.1.3003 > 192.168.200.8.43422:
-rw-r--r-- 1 0 0 6 Mar 23 08:53 filetest
drwxr-xr-x 2 0 0 4096 Dec 13 2007 pub
從上面的數據得出主動模式的傳輸教程如下:
A.(第1行)客戶端向服務器申請PASV模式的數據傳輸.
B.(第2行)服務器新開放一個數據流端口,進入監聽模式.並告訴客戶"你連接192.168.200.1吧,我開放了3003端口等你呢".
(3003端口是通過第2行最後兩個數字計算出來的,11*256 + 187 = 3003)
C.(第3行)客戶端確認收到從服務器傳來的信息並應答.
D.(第4,5,6行)當客戶端獲知服務器已新開了一個數據流端口讓自己去連接後,便從本地隨機選擇一個端口去連接服務器指定的端口,以便傳送數據.
(注意:這是重要的地方,與主動模式不一樣,服務器不會去主動連接客戶端,而是新開一個端口,被動的等客戶端來連接,這就是所謂的被動模式)
E.(第7行)當客戶端與服務器的數據流端口成功連接後,客戶端便向服務器申請列出目錄信息的數據.
F.(第8行)服務器便通過控制端口21向客戶發送信息:你需要的目錄列表傳來了.
G.(第9行)服務器通過數據流端口,將用戶所需要的目錄數據信息發向客戶端.
在整個通信過程中,客戶端都是主動去連接服務器,並沒有開放端口被連接,這確實爲客戶端的防火牆減輕了不少麻煩.但麻煩消失了麼?沒有!被動模式只是把麻 煩"移"到了服務器上而已,服務器則需要動態的開一個高端端口來傳輸數據,怎樣處理這個端口是我們面臨着的困難.不過不用怕,天才的程序員們爲我們想好了 一切,我們只需要按我們的要求設置參數就行.接下來讓我們分析各種可能存在的情況.
第二部分.服務器相關設置實戰
(注:本文所有例子均採用RHEL5+VSFTPD服務器,且默認客戶端無防火牆.)
機器佈局如下:
|客戶機|:::::::::::::::::|LINUX網關|------|VSFTPD服務器|
客戶機的IP: 10.10.10.10/8
LINUX網關IP: 10.10.10.20/8, 192.168.1.1
VSFTPD服務器IP: 192.168.1.8/24
1.配置VSFTPD服務器,配置文件如下:
listen=yes
anonymous_enable=yes
listen=yes
anonymous_enable=yes
port_enable=yes
connect_from_port_20=yes
connect_from_port_20=yes
pasv_enable=yes
pasv_min_port=10000
pasv_max_port=10100
這是一個簡單的VSFTPD配置,第一部分允許匿名用戶訪問,第二部分聲明允許主動模式,第三部分聲明允許被動模式,並把服務器開放的被動連接的端口限制 在10000-10100範圍以內,以便我們設置相應的防火牆規則.我在內網測試了,可以正常使用,更詳細的VSFTPD配置可查看man文檔或訪問http://blog.chinaunix.net/u3/94705/showart_1917230.html.
2.網關設置
首先開啓轉發功能.
#echo 1 > /proc/sys/net/ipv4/ip_forward
再設置相關NAT規則.
#iptables -t nat -A POSTROUTING -p tcp -s 192.168.1.8 --sport 20:21 -j SNAT --to 10.10.10.20
#iptables -t nat -A POSTROUTING -p tcp -s 192.168.1.8 --sport 10000:10100 -j SNAT --to 10.10.10.20
#iptables -t nat -A PREROUTING -p tcp -d 10.10.10.20 --dport 21 -j DNAT --to-destination 192.168.1.8
#iptables -t nat -A PREROUTING -p tcp -d 10.10.10.20 --dport 10000:10100 -j DNAT --to-destination 192.168.1.8
前兩條規則把內網的FTP服務器的相關端口的數據轉發出去.
後兩條規則把外網對網關的相關端口的數據轉發給FTP服務器.
首先開啓轉發功能.
#echo 1 > /proc/sys/net/ipv4/ip_forward
再設置相關NAT規則.
#iptables -t nat -A POSTROUTING -p tcp -s 192.168.1.8 --sport 20:21 -j SNAT --to 10.10.10.20
#iptables -t nat -A POSTROUTING -p tcp -s 192.168.1.8 --sport 10000:10100 -j SNAT --to 10.10.10.20
#iptables -t nat -A PREROUTING -p tcp -d 10.10.10.20 --dport 21 -j DNAT --to-destination 192.168.1.8
#iptables -t nat -A PREROUTING -p tcp -d 10.10.10.20 --dport 10000:10100 -j DNAT --to-destination 192.168.1.8
前兩條規則把內網的FTP服務器的相關端口的數據轉發出去.
後兩條規則把外網對網關的相關端口的數據轉發給FTP服務器.
3.客戶端測試
登錄10.10.10.10,測試結果如下:
[root@X ~]# ftp 10.10.10.20
Connected to 10.10.10.20 (10.10.10.20).
220 (vsFTPd 2.0.5)
Name (10.10.10.20:root): anonymous
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> passive //關掉被動模式,我們先測試主動模式.
Passive mode off.
ftp> ls
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
-rw-r--r-- 1 0 0 13 May 06 20:24 filetest
drwxr-xr-x 2 0 0 4096 Dec 13 2007 pub
226 Directory send OK.
(到此,我們發現主動模式是配置無誤了,可以成功連接.可是在上部分我們說過,主動模式的可應用性不高,接着我們再測試一下被動模式)
ftp> passive
Passive mode on.
ftp> ls
227 Entering Passive Mode (192,168,1,8,39,109)
ftp: connect: Connection timed out
當我輸入ls命令後,系統返回了一條信息"227 Entering Passive Mode (192,168,1,8,39,109)".接着我等啊等,等來的是不幸的消息,系統提醒我連接超時了.
這是怎麼回事兒?回過頭去看看第一部分被動模式傳輸過程就知道了,原來我們是"第D步"失敗了!
當然會失敗啊!服務器告訴我們,可以去連接192.168.1.8的39*256+109=10093端口以便傳輸數據,可是192.168.1.8對客戶端10.10.10.10來說是不可見的,它在10.10.10.20後面躲貓貓呢.
此時,我們的解決辦法有兩個.其一,截獲服務器傳向客戶端的數據(被動模式傳輸過程的第B步),修改相關數據,以欺騙客戶端讓它連接服務器的網關 10.10.10.20,因爲服務器192.168.1.8在10.10.10.20背後,對客戶端來說是不可見的.其二,由服務器親自出面發佈"假"信 息欺騙客戶端,達到同樣的效果.
這兩種解決辦法都很好實現,關於第一種,我們在網關服務器上加載兩個模塊,以截獲並修改數據.登錄10.10.10.20操作如下:
#modprobe ip_nat_ftp
#modprobe ip_conntrack_ftp
然後我們再在客戶端上測試.
ftp> ls
227 Entering Passive Mode (10,10,10,20,39,108)
150 Here comes the directory listing.
-rw-r--r-- 1 0 0 13 May 06 20:24 filetest
drwxr-xr-x 2 0 0 4096 Dec 13 2007 pub
226 Directory send OK.
怎麼樣,一次性就成功了吧.我們看到第二行的信息,ip已被修改成10.10.10.20,客戶端在收到這信息後,就會去連接10.10.10.20,然後經過10.10.10.20的轉發,於是我們理所當然的成功了.
再看看第二種解決辦法,我們怎樣讓服務器出面發佈"假"消息去欺騙客戶端呢?vsftp的作者早想到這點了,我們只需要在vsftpd的配置文件中加入如下兩行即可.
pasv_addr_resolve=yes //允許vsftpd去欺騙客戶
pasv_address=10.10.10.20 //讓vsftpd以這個地址去欺騙客戶
重啓vsftpd後,我們再從客戶端測試發現也可以正常使用.
登錄10.10.10.10,測試結果如下:
[root@X ~]# ftp 10.10.10.20
Connected to 10.10.10.20 (10.10.10.20).
220 (vsFTPd 2.0.5)
Name (10.10.10.20:root): anonymous
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> passive //關掉被動模式,我們先測試主動模式.
Passive mode off.
ftp> ls
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
-rw-r--r-- 1 0 0 13 May 06 20:24 filetest
drwxr-xr-x 2 0 0 4096 Dec 13 2007 pub
226 Directory send OK.
(到此,我們發現主動模式是配置無誤了,可以成功連接.可是在上部分我們說過,主動模式的可應用性不高,接着我們再測試一下被動模式)
ftp> passive
Passive mode on.
ftp> ls
227 Entering Passive Mode (192,168,1,8,39,109)
ftp: connect: Connection timed out
當我輸入ls命令後,系統返回了一條信息"227 Entering Passive Mode (192,168,1,8,39,109)".接着我等啊等,等來的是不幸的消息,系統提醒我連接超時了.
這是怎麼回事兒?回過頭去看看第一部分被動模式傳輸過程就知道了,原來我們是"第D步"失敗了!
當然會失敗啊!服務器告訴我們,可以去連接192.168.1.8的39*256+109=10093端口以便傳輸數據,可是192.168.1.8對客戶端10.10.10.10來說是不可見的,它在10.10.10.20後面躲貓貓呢.
此時,我們的解決辦法有兩個.其一,截獲服務器傳向客戶端的數據(被動模式傳輸過程的第B步),修改相關數據,以欺騙客戶端讓它連接服務器的網關 10.10.10.20,因爲服務器192.168.1.8在10.10.10.20背後,對客戶端來說是不可見的.其二,由服務器親自出面發佈"假"信 息欺騙客戶端,達到同樣的效果.
這兩種解決辦法都很好實現,關於第一種,我們在網關服務器上加載兩個模塊,以截獲並修改數據.登錄10.10.10.20操作如下:
#modprobe ip_nat_ftp
#modprobe ip_conntrack_ftp
然後我們再在客戶端上測試.
ftp> ls
227 Entering Passive Mode (10,10,10,20,39,108)
150 Here comes the directory listing.
-rw-r--r-- 1 0 0 13 May 06 20:24 filetest
drwxr-xr-x 2 0 0 4096 Dec 13 2007 pub
226 Directory send OK.
怎麼樣,一次性就成功了吧.我們看到第二行的信息,ip已被修改成10.10.10.20,客戶端在收到這信息後,就會去連接10.10.10.20,然後經過10.10.10.20的轉發,於是我們理所當然的成功了.
再看看第二種解決辦法,我們怎樣讓服務器出面發佈"假"消息去欺騙客戶端呢?vsftp的作者早想到這點了,我們只需要在vsftpd的配置文件中加入如下兩行即可.
pasv_addr_resolve=yes //允許vsftpd去欺騙客戶
pasv_address=10.10.10.20 //讓vsftpd以這個地址去欺騙客戶
重啓vsftpd後,我們再從客戶端測試發現也可以正常使用.
安全性的參數,確實有點兒得不償失,如果你看完我的建議,仍然堅持要使用它,那祝你好運.