iptables下udp穿越實用篇----iptables與natcheck [轉(zhuǎn)]
--------------------------------------------------------------------------------
作者:shixudong@163.com 2005-01-18 16:59:24 來自:中國Linux論壇
iptables與natcheck
Stun協(xié)議(Rfc3489、詳見
http://www.ietf.org/rfc/rfc3489.txt)提出了4種NAT類型的定義及其分類,并給出了如何檢測在用的NAT究竟屬于哪種分類的標(biāo)準(zhǔn)。但是,具體到P2P程序如何應(yīng)用Stun協(xié)議及其分類法穿越 NAT,則是仁者見仁、智者見智。(因為Stun協(xié)議并沒有給出也沒有必要給出如何穿越NAT的標(biāo)準(zhǔn))
在拙作“iptables與stun”一文中,筆者花大幅精力闡述了iptables理論上屬于Symmetric NAT而非Port Restricted Cone。對此,很多人(包括筆者最初學(xué)習(xí)Stun協(xié)議時)心中都有一個疑惑,即僅就Stun協(xié)議本身來說,Port Restricted Cone和Symmetric NAT的區(qū)別似乎不大,雖然兩者的映射機制是有點不同,但他們都具有端口受限的屬性。初看起來,這兩者在穿越NAT方面的特性也差不多,尤其是對于外部地址欲往NAT內(nèi)部地址發(fā)包的情況。既然如此,又為何有必要把iptables分得這么清呢,本文順帶解決了讀者在這一方面的疑惑。
網(wǎng)站
http://midcom-p2p.sourceforge.net/給出了P2P程序具體如何穿越NAT的一個思路,并提供了一個P2P協(xié)議穿越NAT兼容性的測試工具natcheck。讓我們?nèi)耘f用實例(例1)來說明這一思路吧! A機器在私網(wǎng)(192.168.0.4)
A側(cè)NAT服務(wù)器(210.21.12.140)
B機器在另一個私網(wǎng)(192.168.0.5)
B側(cè)NAT服務(wù)器(210.15.27.140)
C機器在公網(wǎng)(210.15.27.166)作為A和B之間的中介
A機器連接過C機器,假使是 A(192.168.0.4:5000)-> A側(cè)NAT(轉(zhuǎn)換后210.21.12.140:8000)-> C(210.15.27.166:2000)
B機器也連接過C機器,假使是 B(192.168.0.5:5000)-> B側(cè)NAT(轉(zhuǎn)換后210.15.27.140:8000)-> C(210.15.27.166:2000)
A機器連接過C機器后,A向C報告了自己的內(nèi)部地址(192.168.0.4:5000),此時C不僅知道了A的外部地址(C通過自己看到的 210.21.12.140:8000)、也知道了A的內(nèi)部地址。同理C也知道了B的外部地址(210.15.27.140:8000)和內(nèi)部地址(192.168.0.5:5000)。之后,C作為中介,把A的兩個地址告訴了B,同時也把B的兩個地址告訴了A。
假設(shè)A先知道了B的兩個地址,則A從192.168.0.4:5000處同時向B的兩個地址192.168.0.5:5000和 210.15.27.140:8000發(fā)包,由于A和B在兩個不同的NAT后面,故從A(192.168.0.4:5000)到B (192.168.0.5:5000)的包肯定不通,現(xiàn)在看A(192.168.0.4:5000)到B(210.15.27.140:8000)的包,分如下兩種情況:
1、B側(cè)NAT屬于Full Cone NAT
則無論A側(cè)NAT屬于Cone NAT還是Symmetric NAT,包都能順利到達B。如果P2P程序設(shè)計得好,使得B主動到A的包也能借用A主動發(fā)起建立的通道的話,則即使A側(cè)NAT屬于Symmetric NAT,B發(fā)出的包也能順利到達A。
結(jié)論1:只要單側(cè)NAT屬于Full Cone NAT,即可實現(xiàn)雙向通信。
2、B側(cè)NAT屬于Restricted Cone或Port Restricted Cone
則包不能到達B。再細(xì)分兩種情況
(1)、A側(cè)NAT屬于Restricted Cone或Port Restricted Cone
雖然先前那個初始包不曾到達B,但該發(fā)包過程已經(jīng)在A側(cè)NAT上留下了足夠的記錄:A(192.168.0.4:5000)-> (210.21.12.140:8000)->B(210.15.27.140:8000)。如果在這個記錄沒有超時之前,B也重復(fù)和A一樣的動作,即向A(210.21.12.140:8000)發(fā)包,雖然A側(cè)NAT屬于Restricted Cone或Port Restricted Cone,但先前A側(cè)NAT已經(jīng)認(rèn)為A已經(jīng)向B(210.15.27.140:8000)發(fā)過包,故B向A(210.21.12.140:8000)發(fā)包能夠順利到達A。同理,此后A到B的包,也能順利到達。
結(jié)論2:只要兩側(cè)NAT都不屬于Symmetric NAT,也可雙向通信。換種說法,只要兩側(cè)NAT都屬于Cone NAT,即可雙向通信。
(2)、A側(cè)NAT屬于Symmetric NAT
因為A側(cè)NAT屬于Symmetric NAT,且最初A到C發(fā)包的過程在A側(cè)NAT留下了如下記錄:A(192.168.0.4:5000)->(210.21.12.140: 8000)-> C(210.15.27.166:2000),故A到B發(fā)包過程在A側(cè)NAT上留下的記錄為:A(192.168.0.4:5000)-> (210.21.12.140:8001)->B(210.15.27.140:8000)(注意,轉(zhuǎn)換后端口產(chǎn)生了變化)。而B向A的發(fā)包,只能根據(jù)C給他的關(guān)于A的信息,發(fā)往A(210.21.12.140:8000),因為A端口受限,故此路不通。再來看B側(cè)NAT,由于B也向A發(fā)過了包,且 B側(cè)NAT屬于Restricted Cone或Port Restricted Cone,故在B側(cè)NAT上留下的記錄為:B(192.168.0.5:5000)->(210.15.27.140:8000)->A (210.21.12.140:8000),此后,如果A還繼續(xù)向B發(fā)包的話(因為同一目標(biāo),故仍然使用前面的映射),如果B側(cè)NAT屬于 Restricted Cone,則從A(210.21.12.140:8001)來的包能夠順利到達B;如果B側(cè)NAT屬于Port Restricted Cone,則包永遠(yuǎn)無法到達B。
結(jié)論3:一側(cè)NAT屬于Symmetric NAT,另一側(cè)NAT屬于Restricted Cone,也可雙向通信。
顯然,還可得出另一個不幸的結(jié)論4,兩個都是Symmetric NAT或者一個是Symmetric NAT、另一個是Port Restricted Cone,則不能雙向通信。
上面的例子雖然只是分析了最初發(fā)包是從A到B的情況,但是,鑒于兩者的對稱性,并且如果P2P程序設(shè)計得足夠科學(xué),則前面得出的幾條結(jié)論都是沒有方向性,雙向都適用的。
通過上述分析,我們得知,在穿越NAT方面,Symmetric NAT和Port Restricted Cone是有本質(zhì)區(qū)別的,盡管他們表面上看起來相似。我們上面得出了四條結(jié)論,而natcheck網(wǎng)站則把他歸結(jié)為一條:只要兩側(cè)NAT都屬于Cone NAT(含F(xiàn)ull Cone、Restricted Cone和Port Restricted Cone三者),即可雙向通信。而且natcheck網(wǎng)站還建議盡量使用Port Restricted Cone,以充分利用其端口受限的屬性確保安全性。目前,國內(nèi)充分利用了上述思路的具有代表性的P2P軟件是“E話通”(www.et66.com)。
在對natcheck提供的思路進行詳細(xì)分析后,開始探討本文主題:iptables與natcheck。
Natcheck脫胎于Stun協(xié)議,由拙作“iptables與stun”一文可知,其對iptables進行的穿越NAT兼容性測試結(jié)果必然是GOOD。此外,我在該文中還提到一句,如果在每個NAT后面僅有一個客戶端這種特殊情況下,iptables就是一個標(biāo)準(zhǔn)的Port restricted Cone。根據(jù)前面natcheck的結(jié)論,這樣兩個iptables后面的客戶端應(yīng)該可以互相穿越對方的NAT。讓我們來看一下實際情況(例2)呢?
仍然參考前例,只是兩側(cè)都使用iptables來進行地址轉(zhuǎn)換。(因為采用了iptables,故此處和前例稍有點區(qū)別,即轉(zhuǎn)換后源端口不變)
A與B通過C交換對方地址的初始化環(huán)節(jié)此處略去,我們從A(192.168.0.4:5000)向B(210.15.27.140:5000)(注意因使用iptables而導(dǎo)致端口和前例不一樣)發(fā)包開始分析,因為在本例中,兩側(cè)均只有一個客戶端,我們姑且把iptables簡化成Port restricted Cone看待。
如前例一樣,從A(192.168.0.4:5000)到B(210.15.27.140: 5000)的第一個包必不能到達B,但其會在A側(cè)iptables上留下記錄,在這條記錄沒有超時之前(iptables下默認(rèn)30秒),如果B也向A (210.21.12.140:5000)發(fā)包,如前所述,按理該包應(yīng)該能夠到達A,但事實上卻是永遠(yuǎn)到不了。
難道是natcheck的結(jié)論錯了,或者是特殊情況下iptables并不是Port restricted Cone(即仍然是Symmetric NAT),我們還是別忙著再下結(jié)論,先來看看來兩側(cè)iptables上留下的記錄吧:
A側(cè):cat /proc/net/ip_conntrack | grep 192.168.0.4 | grep udp
udp 17 18 src=192.168.0.4 dst=210.15.27.140 sport=5000 dport=5000 [UNREPLIED] src=210.15.27.140 dst=210.21.12.140 sport=5000 dport=5000 use=1
B側(cè):cat /proc/net/ip_conntrack | grep 192.168.0.5 | grep udp
udp 17 26 src=192.168.0.5 dst=210.21.12.140 sport=5000 dport=5000 [UNREPLIED] src=210.21.12.140 dst=210.15.27.140 sport=5000 dport=1026 use=1
把兩條記錄翻譯如下:(關(guān)于ip_conntrack文件的分析,請見
http://www.sns.ias.edu/~jns/security/iptables/iptables_conntrack.html) A(192.168.0.4:5000)-> A側(cè)NAT(轉(zhuǎn)換后210.21.12.140:5000)-> B(210.15.27.140:5000)
B(192.168.0.5:5000)-> B側(cè)NAT(轉(zhuǎn)換后210.15.27.140:1026)-> A(210.21.12.140:5000)
奇怪,B到A的包在映射后源端口號怎么變了呢,按理不應(yīng)該呀?因為按照iptables轉(zhuǎn)換原則(詳見“iptables與stun”),要求盡量保持源端口號不變,除非socket有重復(fù)。難道B側(cè)NAT上還有重復(fù)記錄,再cat一下呢?
B側(cè):cat /proc/net/ip_conntrack | grep 210.21.12.140 | grep udp
udp 17 10 src=210.21.12.140 dst=210.15.27.140 sport=5000 dport=5000 [UNREPLIED] src=210.15.27.140 dst=210.21.12.140 sport=5000 dport=5000 use=1
udp 17 16 src=192.168.0.5 dst=210.21.12.140 sport=5000 dport=5000 [UNREPLIED] src=210.21.12.140 dst=210.15.27.140 sport=5000 dport=1026 use=1
操!還果真有兩條差不多的記錄,第一條與NAT無關(guān),是A到B的包在B側(cè)iptables上留下的記錄,產(chǎn)生時間上略早于第二條記錄,其構(gòu)成的 socket是(210.21.12.140:5000,210.15.27.140:5000)。第二條即B到A的包產(chǎn)生的記錄,其構(gòu)成的socket 是(210.15.27.140:1026,210.21.12.140:5000),如果其源端口不改動,即是(210.15.27.140: 5000,210.21.12.140:5000),還真和第一條記錄重復(fù)了呢,怪不得轉(zhuǎn)換后需要修改源端口,也怪不得B發(fā)包到不了A。
為什么是這樣的結(jié)果呢?我們知道,iptables是一個有狀態(tài)的防火墻,他通過連接跟蹤模塊來實現(xiàn)狀態(tài)檢測的功能,該模塊檢查所有到來的數(shù)據(jù)包,也就是說,該模塊不僅對NAT起作用,而且對普通的包過濾也起作用。顯然,在上述例子里,A到B的包就是作為普通的包過濾而被記載在B側(cè) iptables的連接跟蹤表里,導(dǎo)致后來B到A的包為避免socket重復(fù)而不得不改換端口號,從而導(dǎo)致無法實現(xiàn)雙向通信??磥?,natcheck的結(jié)論并沒有錯,只是由于iptables具有狀態(tài)檢測的新特性導(dǎo)致即使在特殊情況下iptables又從Port restricted Cone變成了Symmetric NAT而已。
那么,有辦法解決這一問題嗎?根據(jù)連接跟蹤的特性,在iptables下,只要啟用了NAT,就肯定要啟用連接跟蹤功能,而只要啟用了連接跟蹤功能,就必然順帶跟蹤普通包過濾(啟用連接跟蹤后,似乎無法控制不讓跟蹤普通包過濾),也就是說,只要用NAT,就無法避免上述情況,真殘酷!然而,這卻是事實,即只要兩端都采用了iptables作為NAT,則盡管兩側(cè)都通過了natcheck的兼容性測試,但iptables兩側(cè)永遠(yuǎn)也不能互相穿越。
在“iptables與stun”一文中曾經(jīng)附帶提到,Win2000下的ics或nat在Stun協(xié)議下的表現(xiàn)和iptables是完全一樣的。那么,在natcheck下,表現(xiàn)是否還一致呢?答案是否定的,雖然Win2000下的ics或nat也具有狀態(tài)檢測的功能,但該狀態(tài)檢測,僅對 NAT起作用,不對普通包過濾起作用。所以在兩側(cè)都是Win2000下的ics或nat可以作為Port restricted Cone的特殊情況下,是允許被穿越的。另外,在一側(cè)使用iptables,另一側(cè)使用Win2000下的ics或nat,但兩者都表現(xiàn)為Port restricted Cone的特殊情況下,從某個方向發(fā)起,最終是允許互相穿越的,但是這種穿越不具有對稱性,即從另一個方向發(fā)起,則永遠(yuǎn)無法穿越,具體原理,讀者可以參考例2自行分析。