單位的一臺(tái)Linux服務(wù)器為外網(wǎng)提供Web服務(wù),最近當(dāng)客戶進(jìn)行訪問(wèn)時(shí),經(jīng)常出現(xiàn)連接失敗或者端口訪問(wèn)超時(shí)等問(wèn)題,給公司業(yè)務(wù)造成不利影響。在內(nèi)網(wǎng)對(duì)該服務(wù)器進(jìn)行大量連接檢測(cè)時(shí),發(fā)現(xiàn)頻頻丟包。使用“vi”工 具 查 看“/var/log/messages”日志文件,發(fā)現(xiàn)“Kernel:nf_conntrack:table full,dropping packet”,kernel: printk:1 messages suppressed之類(lèi)的錯(cuò)誤信息,這些信息說(shuō)明,該故障與Linux的連接追蹤機(jī)制相關(guān)。
我們知道,在Linux中內(nèi)置了NetFilter防火墻模塊,使用IPtables工具可以對(duì)其進(jìn)行靈活調(diào)整。IPtables允許管理員使用連接跟蹤(connection tracking) 功能來(lái)檢查和限制到內(nèi)部網(wǎng)絡(luò)中可用服務(wù)的連接,并在一個(gè)內(nèi)存數(shù)據(jù)結(jié)構(gòu)中記錄了連接狀態(tài)。因?yàn)镹etfilter防火墻使用了nf_conntrack內(nèi)核模塊實(shí)現(xiàn)連接跟蹤功能,而上述Linux服務(wù)器不僅開(kāi)啟了防火墻功能,而且在網(wǎng)站流量非常高的時(shí)候最容易會(huì)出現(xiàn)上述問(wèn)題。
其原因就在于,該Linux服務(wù)器收到了大量的連接,IPtables會(huì)把所有連接信息都做連接跟蹤處理,其中包括源 IP、目的 IP、源端口、目的端口、協(xié)議類(lèi)型、協(xié)議狀態(tài)和超時(shí)等。這樣,IPtables就會(huì)有一個(gè)鏈接跟蹤表,利用這些信息,可以讓管理員更加靈活地設(shè)置過(guò)濾策略。
執(zhí) 行“cat /proc/net/nf_conntrack命令,可以查看當(dāng)前連接追蹤信息。對(duì)該表中的內(nèi)容進(jìn)行分析,可以看到實(shí)際上使用了IPtables的state模塊進(jìn)行匹配,并執(zhí)行了特定的過(guò)濾規(guī)則,Iptables支 持 基 于INVALID(無(wú)效的報(bào)文請(qǐng)求),ESTABLISHED(已建立的連接),NEW(新連接發(fā)送的第一個(gè)包)和RELATED(數(shù)據(jù)連接和命令連接之間的關(guān)系)等狀態(tài)的過(guò)濾規(guī)則。但是,一旦該連接跟蹤表被填滿以后,就會(huì)發(fā)生丟包,導(dǎo)致網(wǎng)絡(luò)不穩(wěn)定。執(zhí)行“sysctl net.netfilter.nf_conntrack_max” 和“sysctl net.netfilter.nf_conntrack_count”命令,對(duì)比預(yù)設(shè)的最大追蹤數(shù)和已存在的追蹤條目,可以發(fā)現(xiàn)兩者幾乎相等。
為了解決該問(wèn)題,可以 執(zhí) 行“vi /etc/sysctl.conf” 命 令,在 目 標(biāo) 配置文件中將輸入“net.nf_conntrack_max =65000”,“net.netfilter.nf_conntrack_max =65000”行,增大連接追蹤表的容量,當(dāng)然具體數(shù)值可以根據(jù)實(shí)際情況更改。
經(jīng)過(guò)這樣的調(diào)整,雖然暫時(shí)解決了上述故障,但是經(jīng)過(guò)一段時(shí)間,尤其是訪問(wèn)量加大后,又會(huì)導(dǎo)致追蹤表被填滿,進(jìn)而重新出現(xiàn)上述故障。
為 此 執(zhí) 行“vi /etc/sysctl.conf” 命 令, 輸入“net.nf_conntrack_max = 855360”,“net.netfilter.nf_conntrack_max = 855360”,“net.netfilter.np_conntrack_tcp_timeout_established= 1000”等內(nèi)容,進(jìn)一步增大追蹤表容量,并調(diào)整追蹤表超時(shí)時(shí)間。執(zhí)行“vi /etc/modprobed/netfilter.conf”命令,在其中輸入“options nf_conntrack hashsize=855360”行,調(diào)整存儲(chǔ)跟蹤連接條目列表的哈希表的數(shù)量。之后執(zhí)行“/etc/init.d/iptable restart”命令,重新加載跟蹤連接模塊,更新跟蹤連接條目列表的哈西表的數(shù)量。執(zhí)行“sysctl-p”命令,使得上述修改生效。
雖然經(jīng)過(guò)以上修改,可以在一定程度上解決問(wèn)題,但要想徹底解決問(wèn)題,必須關(guān)閉連接追共功能。
在開(kāi)啟了Netfilter防火墻的情況下,如果激活了連接追蹤功能,在應(yīng)對(duì)比較大的訪問(wèn)流量時(shí),就容易出現(xiàn)網(wǎng)絡(luò)訪問(wèn)不暢的問(wèn)題,最好的處理方法是關(guān)閉連接追蹤功能。關(guān)閉的方法有多種,例如重新編譯Linux內(nèi)核,在其中取消“Netfilter connection tracking support”項(xiàng)目。在編寫(xiě)防火墻規(guī)則時(shí),在IPtable語(yǔ)句中禁用“-m state”模塊,并修改“/etc/init.d/iptables”文 件, 在“NF_MODULES_COMMON=”欄中刪除其中的“nf_nat nf_conntrack” 關(guān)鍵字等。不過(guò)最簡(jiǎn)單直接的辦法是在RAW表中使用“NOTRACK”關(guān)鍵字來(lái)禁用連接追蹤功能。我們知道,在Netfilter模塊的RAW表中為IPtable提供了一種不經(jīng)過(guò)狀態(tài)追蹤的機(jī)制,在訪問(wèn)流量較大的服務(wù)器上使用RAW表,可以有效避免連接追蹤功能引發(fā)的問(wèn)題。
例如在本案例中,對(duì)外提供Web服務(wù)的Linux主機(jī)的IP為 xxx.xxx.xxx.xxx,那么在命令行中執(zhí)行“iptable–t raw -A PREROUTING -p tcp -j NOTRACk”,“iptable–t raw -A OUTPUT -p tcp-j NOTRACk”,“iptable –A INPUT -p tcp xxx.xxx.xxx.xxx --sport 80 -j ACCEPT”,“iptable –A OUTPUT -p tcp -j ACCEPT”。
經(jīng)過(guò)測(cè)試,說(shuō)明如果在OUTPUT鏈中進(jìn)行了相關(guān)設(shè)置,那么在PREROUTING鏈中也必須針對(duì)特定端口配置規(guī)則,否則數(shù)據(jù)封包無(wú)法出去。其原因在于,連接跟蹤的狀態(tài)主要在PREROUTING和OUTPUT兩個(gè)鏈被觸發(fā),分別對(duì)應(yīng)外來(lái)報(bào)文和本級(jí)產(chǎn)生報(bào)文。當(dāng)禁用了連接追蹤工后,執(zhí)行“vi /var/log/messages”命令,在日志中就不再出現(xiàn)上述錯(cuò)誤提示。執(zhí)行“l(fā)smod | gerp nf_conntrack”命令,不會(huì)顯示任何內(nèi)容。
應(yīng)該特別注意的是,當(dāng)使用Netfilter開(kāi)啟了NAT地址轉(zhuǎn)換能后,是不允許禁用連接追蹤功能的,只能采用提高連接追蹤表容量的方法加以應(yīng)對(duì)。