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