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