- 論壇徽章:
- 0
|
在網(wǎng)易看到相關(guān)的介紹
http://uh1.gz.163.com/cgi/readelite?i=462547
主題:iptables和qq
發(fā)信人: shixudong(5270)
整理人: qiaoqian(2002-05-13 06:53:32), 站內(nèi)信件
一、提出問題
在用iptables作nat時(shí),qq間通信經(jīng)常需要通過服務(wù)器中轉(zhuǎn),而且有些時(shí)候發(fā)送速度很慢。具體表現(xiàn)為以下幾種情形:
1、隱身用戶或在線用戶發(fā)送信息給nat后面的隱身用戶、離線用戶時(shí),總需要經(jīng)過服務(wù)器中轉(zhuǎn),但此時(shí)發(fā)送速度并不慢。
2、隱身用戶發(fā)送信息給nat后面的在線用戶時(shí),不管這個(gè)隱身用戶是不是也在nat后面,總需要經(jīng)過服務(wù)器中轉(zhuǎn),而且此時(shí)發(fā)送速度很慢。
3、在線用戶a發(fā)送信息給nat后面的在線用戶b時(shí),又分三種情況:
(1)、在線用戶a不在nat后面,當(dāng)a向b發(fā)送信息時(shí),只要b不回答a,那么a發(fā)給b的信息總需要經(jīng)過服務(wù)器中轉(zhuǎn),而且此時(shí)發(fā)送速度很慢;一旦b答復(fù)了a(由于a不在nat后面,所以b答復(fù)a很正常),那么此后a發(fā)給b的信息將恢復(fù)正常(即不需要中轉(zhuǎn),發(fā)送速度也很快)。
(2)、在線用戶a也在nat后面,那么不論是a向b發(fā)送信息,還是b回答a的信息,有時(shí)候經(jīng)過服務(wù)器中轉(zhuǎn),此時(shí)發(fā)送速度很慢;有時(shí)候又不必中轉(zhuǎn),此時(shí)發(fā)送速度很快。
(3)、是(2)的一個(gè)特例,在線用戶a和在線用戶b在同一個(gè)nat后面,他們之間互發(fā)信息,總是需要經(jīng)過服務(wù)器中轉(zhuǎn),而且發(fā)送速度很慢。
二、分析問題
解鈴還需系鈴人,既然是在用iptables作nat時(shí)出現(xiàn)的問題,那我們還是通過分析iptables的工作原理來分析qq的問題。netfilter/iptables是基于linux2.4內(nèi)核的具有狀態(tài)檢測(cè)功能的新一代包過濾防火墻,它的狀態(tài)檢測(cè)功能是通過連接跟蹤模塊實(shí)現(xiàn)的。iptables的連接跟蹤模塊不僅可以跟蹤tcp,還可以跟蹤無連接的udp。udp跟蹤的實(shí)現(xiàn)原理如下:
當(dāng)一個(gè)"初始"udp包從內(nèi)網(wǎng)到達(dá)nat時(shí),iptables會(huì)在/proc/net/ip_conntrack文件里記錄該udp"連接"的一些信息:源地址/端口、目標(biāo)地址/端口、期待的應(yīng)答包的源地址/端口(對(duì)應(yīng)于發(fā)送包的目標(biāo)地址/端口)、期待的應(yīng)答包的目標(biāo)地址/端口(對(duì)應(yīng)于發(fā)送包的masqed后的源地址/端口,即nat的外部地址/端口)。當(dāng)該udp的應(yīng)答包從外網(wǎng)到達(dá)nat時(shí),在目標(biāo)地址/端口符合的前提下,iptables還將用應(yīng)答包的源地址/端口去匹配先前iptables保存的期待的應(yīng)答包的源地址/端口。如果源地址/端口匹配,則iptables對(duì)其demasq并轉(zhuǎn)交給nat后面的原始發(fā)送者;如果源地址/端口不匹配,則由于應(yīng)答包的目標(biāo)地址/端口是nat本身,iptables將該包放入INPUT鏈。一般情況下,INPUT鏈的默認(rèn)策略為ACCEPT,則該udp應(yīng)答包將被轉(zhuǎn)交給nat的本地進(jìn)程處理,但事實(shí)上由于不存在這樣的本地進(jìn)程,結(jié)果是nat向產(chǎn)生udp應(yīng)答包的機(jī)器發(fā)回一個(gè)icmp-port-unreachable包(注意,這個(gè)包是linux系統(tǒng)產(chǎn)生的,不是iptables的REJECT目標(biāo)產(chǎn)生的)。如果INPUT鏈的策略為DROP,則該udp應(yīng)答包被DROP。
qq的即時(shí)通訊使用了udp,當(dāng)nat后面的qq用戶在登陸注冊(cè)時(shí),它必須向qq服務(wù)器的8000(udp)端口發(fā)送登陸請(qǐng)求,這是iptables看到的該udp的初始包,所以iptables記下了它的相關(guān)信息,當(dāng)qq服務(wù)器的udp應(yīng)答包到達(dá)nat時(shí),能夠匹配源地址/端口,所以iptables將其轉(zhuǎn)交給nat后面的原qq用戶。當(dāng)該qq用戶在qq服務(wù)器上登陸的同時(shí),也注冊(cè)了它的地址(發(fā)送包的masqed后的源地址/端口,即nat的外部地址/端口)。
如果用戶a向nat后面的用戶b發(fā)送信息,分兩種情況:
1、b隱身,則a向qq服務(wù)器發(fā)送信息,然后再由b登陸時(shí)對(duì)應(yīng)的qq服務(wù)器中轉(zhuǎn),由于這個(gè)中轉(zhuǎn)包總是能夠匹配源地址/端口,于是iptables將其轉(zhuǎn)交給nat后面的b,所以此時(shí)雖然需要中轉(zhuǎn),但發(fā)送速度并不慢。
2、b在線,則a向b發(fā)送信息,實(shí)際上就是向b注冊(cè)的地址發(fā)送udp包。然而,iptables在處理這個(gè)從外網(wǎng)來的udp包時(shí),由于無法匹配該包的源地址/端口。如前所述,一般情況下,nat會(huì)向a發(fā)回一個(gè)icmp-port-unreachable包(用戶a如果使用sniffer,應(yīng)該能夠捕獲到這個(gè)icmp包)。然后,a會(huì)重復(fù)這個(gè)過程若干次,都無法發(fā)送成功。最后只能通過服務(wù)器中轉(zhuǎn),所以發(fā)送速度很慢。其實(shí)在這種情況下,還可細(xì)分:
(1)、a在線且不在nat后面,則只要b答復(fù)a,由于這個(gè)答復(fù)包在iptables看來是一個(gè)udp初始包,所以,iptables記下它的相關(guān)信息。當(dāng)以后a再向b發(fā)送信息時(shí),就能夠匹配源地址/端口,從而a與b之間的通信不必再由服務(wù)器中轉(zhuǎn)。
(2)、a在線但也在nat后面,當(dāng)a第一次向b發(fā)送信息時(shí),在a的nat處的iptables也會(huì)記錄該udp包(aàb)的相關(guān)信息,但如前所述,這個(gè)包無法直接發(fā)送到b,必須經(jīng)由服務(wù)器中轉(zhuǎn)。當(dāng)b答復(fù)a時(shí),可分為兩種情況:
如果b一收到a發(fā)來的信息(由服務(wù)器中轉(zhuǎn)),就立即答復(fù)a。由于這個(gè)答復(fù)包在iptables看來是一個(gè)udp初始包,所以,iptables記下它的相關(guān)信息。當(dāng)這個(gè)答復(fù)包到達(dá)a處的nat時(shí),由于a處nat的iptables先前記下的相關(guān)信息尚未超時(shí),能夠匹配源地址/端口,所以該答復(fù)包(bàa)能夠直接發(fā)送到a,此后a到b也能直接發(fā)送信息。
如果b收到a發(fā)來的信息(由服務(wù)器中轉(zhuǎn))后,過了一段時(shí)間才答復(fù)a。由于這個(gè)答復(fù)包在iptables看來是一個(gè)udp初始包,所以,iptables記下它的相關(guān)信息。當(dāng)這個(gè)答復(fù)包到達(dá)a處的nat時(shí),由于a處nat的iptables先前記下的相關(guān)信息已因超時(shí)而刪除,因而無法匹配源地址/端口,所以該答復(fù)包(bàa)也只能夠經(jīng)由服務(wù)器中轉(zhuǎn)發(fā)送到a。
作為(2)的一個(gè)特例,當(dāng)a與b在同一個(gè)nat后面,無論如何,總是需要經(jīng)過服務(wù)器中轉(zhuǎn),而且發(fā)送速度很慢。
在(1)和(2)兩種情況下,即使a和b之間已經(jīng)能夠直接互發(fā)信息,但如果a與b之間長時(shí)間不聯(lián)絡(luò),則由于udp"連接"的超時(shí),iptables會(huì)刪除超時(shí)的相關(guān)信息。從而a與b之間的通信將重復(fù)上述過程,所以會(huì)出現(xiàn)有時(shí)需要中轉(zhuǎn)、有時(shí)不必中轉(zhuǎn)的現(xiàn)象。
(3)、a隱身,則b答復(fù)a總是通過服務(wù)器中轉(zhuǎn),當(dāng)以后a再向b發(fā)送信息時(shí),仍然無法匹配源地址/端口,所以a與b之間的通信始終只能通過服務(wù)器中轉(zhuǎn) 。雖然雙方都需要中轉(zhuǎn),但是a向b發(fā)送消息很慢,而b向a發(fā)送消息很快。
由上面的分析可知,qq間通信經(jīng)常需要通過服務(wù)器中轉(zhuǎn),"罪魁禍?zhǔn)?quot;不是nat,而是iptables的連接跟蹤。在iptables中,連接跟蹤已經(jīng)作為一個(gè)單獨(dú)的模塊被實(shí)現(xiàn),對(duì)于nat來說,該模塊自動(dòng)且必須被啟用,而在用iptables實(shí)現(xiàn)包過濾時(shí),也可以使用連接跟蹤功能。換句話說,不僅是nat,即使是包過濾(即和internet直接相連),只要使用了連接跟蹤模塊,同樣無法避免qq間通信時(shí)產(chǎn)生服務(wù)器中轉(zhuǎn)的現(xiàn)象。
如果使用ipchains取代iptables,盡管它沒有連接跟蹤功能,但在用ipchains作nat時(shí),ipchains會(huì)記錄一個(gè)masq表,該表的功能有些類似于iptables的連接狀態(tài)表。所以,用ipchains作nat,一般情況下,qq間通信也會(huì)出現(xiàn)通過服務(wù)器中轉(zhuǎn)的現(xiàn)象。但由于ipchains是基于linux2.2內(nèi)核,而從linux2.2.3內(nèi)核開始,另有一個(gè)參數(shù)專門用于控制udp,即/proc/sys/net/ipv4/ip_masq_udp_dloose。如果ip_masq_udp_dloose為0,則ipchains處理從外網(wǎng)到來的udp時(shí),必須去匹配源地址/端口。如果ip_masq_udp_dloose為1,則ipchains處理從外網(wǎng)到來的udp時(shí),不去匹配源地址/端口,任何目標(biāo)地址/端口符合的udp包,都將被ipchains轉(zhuǎn)交給nat后面的原qq用戶,從而也就不會(huì)出現(xiàn)qq間通信通過服務(wù)器中轉(zhuǎn)的現(xiàn)象。從linux2.2.16內(nèi)核開始,ip_masq_udp_dloose默認(rèn)為0,而在此之前,ip_masq_udp_dloose默認(rèn)為1。也就是說,如果使用linux2.2.3內(nèi)核以后、linux2.2.16內(nèi)核以前的ipchains,默認(rèn)情況下,qq間通信是不會(huì)出現(xiàn)通過服務(wù)器中轉(zhuǎn)現(xiàn)象的。
三、解決問題
前文提到,qq間通信經(jīng)常需要通過服務(wù)器中轉(zhuǎn),是由iptables的連接跟蹤功能造成的。事實(shí)上,不僅是qq,只要是基于udp的即時(shí)通訊軟件,在使用iptables的連接跟蹤功能時(shí)都有這個(gè)問題;還有我們常用的tftp客戶端,由于tftp服務(wù)端返回的udp包使用的源端口不同于客戶端發(fā)出的udp包的目標(biāo)端口,所以也無法和iptables的連接跟蹤功能一道使用。
為了使這些軟件能和iptables的連接跟蹤功能協(xié)同工作,需要加載附加的連接跟蹤模塊,如ip_conntrack_qq.o、ip_conntrack_tftp.o。此外,為了使這些軟件在nat后面也能正常工作,考慮到nat總是和iptables的連接跟蹤捆綁在一起,所以,在nat環(huán)境下,不僅需要加載這些軟件的連接跟蹤模塊,還需要加載它們的nat模塊,如ip_nat_qq.o、ip_nat_tftp.o。然而,到目前為止,netfilter/iptables的標(biāo)準(zhǔn)發(fā)布只提供ftp和irc的相關(guān)模塊。至于其他軟件的相關(guān)模塊,則需要自行編寫。有關(guān)編寫這些連接跟蹤和nat相關(guān)模塊的資料可以參見如下網(wǎng)址:http://www.gnumonks.org/ftp/pub/doc/conntrack+nat.html。下面這個(gè)網(wǎng)址列出了一些常用軟件(如tftp客戶端)的已經(jīng)可用的連接跟蹤和nat相關(guān)模塊的一些資料:http://netfilter.samba.org/documentation/HOWTO//netfilter-extensions-HOWTO-5.html,具體的模塊則可以通過google搜索得到。
對(duì)于qq軟件,編寫這個(gè)模塊的大致思路如下,在qq用戶登陸注冊(cè)時(shí),它必須向qq服務(wù)器的8000(udp)端口發(fā)送登陸請(qǐng)求,所以這個(gè)模塊只要監(jiān)控向外的8000(udp)端口的初始連接,一旦發(fā)現(xiàn)這個(gè)初始連接,該模塊就可記住初始udp包對(duì)應(yīng)的masqed后的源地址/端口,即nat的外部地址/端口。以后,當(dāng)有其他qq用戶向這個(gè)nat后面的qq用戶發(fā)送信息時(shí),實(shí)際上就是向該模塊記住的nat的外部地址/端口發(fā)送udp包,只要這些udp包的目標(biāo)地址/端口符合該模塊記住的nat的外部地址/端口,該模塊就不去匹配源地址/端口,直接將這些udp包轉(zhuǎn)交給nat后面的原qq用戶,從而也就不會(huì)出現(xiàn)qq間通信通過服務(wù)器中轉(zhuǎn)的現(xiàn)象。這就是ip_conntrack_qq/ip_nat_qq模塊的簡單實(shí)現(xiàn),至于復(fù)雜的實(shí)現(xiàn),還可以讓不同nat后面的qq用戶進(jìn)行文件傳輸。
事實(shí)上,qq的連接跟蹤和nat相關(guān)模塊的編寫者,最理想的莫過于騰訊公司了。希望老馬能看到這篇文章,并希望老馬在看到這篇文章后,不是從經(jīng)濟(jì)利益出發(fā),而是本著GNU的精神,為廣大linux/iptables后面的qq迷們帶來福音。 |
|