再看nf_conntrack: table full問題

轉載自:http://www.361way.com/%E5%86%8D%E7%9C%8Bnf_conntrack-table-full%E9%97%AE%E9%A2%98/2404.htmlphp

一年前,我寫過一篇博文叫 ————  ip_conntrack: table full問題 ,當時是在squid應用主機上最早發現了該問題,也於當時,深入瞭解到iptables的這個報錯,會形成拒絕服務的問題。其後iptables重啓 (重啓會將該hash表存的值清空)、proc參數優化,臨時解決了該問題 。並未進行細一步的研究 。隨着centos 由5.X升級到6.X ,該模塊的名字也由ip_conntrack變成了nf_conntrack 。二者的區別是,前者只支持ipv4,然後者增長了對ipv6的支持。html

因爲公司自身的推廣到位,流量出現了倍增 。因而公司決定另選了兩個機房,每一個機房各放置一臺主機作squid cache加速 。而運行過程當中一直有一個小問題,就是偶爾會出現丟包的問題。當於覺得是IDC的問題,一直讓IDC去查緣由,IDC那邊並未查到緣由 。這個問題就暫時擱置了。linux

同於又因爲受近期金價暴跌的影響,網站流量由平時的80M/s 直接上升到250M/s ,這個ping丟包的問題變的尤其明顯。而將加速應用指到數據機房的squid上時。同現出現了ping丟包的問題,這個不得不從自身找緣由了。經過/var/log/message查看,發現老面孔 ———— ip_conntrack: table full 。看到該錯誤,首先關閉了iptables 。過了一兩分鐘後,神奇的丟包問題沒了。汗 ……ios

至此開始真正開始關注此問題。總結了下網上對該問題的處理方式有三種。nginx

方法一:修改參數法web

這個方法我在一年前就已經用過。以下:apache

vim /etc/sysctl.conf#加大 ip_conntrack_max 值net.ipv4.ip_conntrack_max = 393216net.ipv4.netfilter.ip_conntrack_max = 393216#下降 ip_conntrack timeout時間net.ipv4.netfilter.ip_conntrack_tcp_timeout_established = 300net.ipv4.netfilter.ip_conntrack_tcp_timeout_time_wait = 120net.ipv4.netfilter.ip_conntrack_tcp_timeout_close_wait = 60net.ipv4.netfilter.ip_conntrack_tcp_timeout_fin_wait = 120


增長完以上內容後,經過sysctl -p 使配置生效 。不過該方法有兩個缺點:一是重啓iptables後,ip_conntrack_max值又會變成65535默認值,須要從新sysctl -p ;另外一個是該法治標不治本,在高併發時,很快又會悲劇重演。vim

方法二:使用RAW表,跳過記錄法centos

首先先認識下什麼是raw表?作什麼用的? 服務器

iptables有5個鏈:PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING,4個表:filter,nat,mangle,raw 。 

4個表的優先級由高到低的順序爲:raw-->mangle-->nat-->filter 

舉例來講:若是PRROUTING鏈上,即有mangle表,也有nat表,那麼先由mangle處理,而後由nat表處理 。

RAW表只使用在PREROUTING鏈和OUTPUT鏈上,由於優先級最高,從而能夠對收到的數據包在鏈接跟蹤前進行處理。一但用戶使用了RAW表,在某個鏈上,RAW表處理完後,將跳過NAT表和 ip_conntrack處理,即再也不作地址轉換和數據包的連接跟蹤處理了。
RAW表能夠 style="color:#E53333;">應用在那些不須要作nat的狀況下,以提升性能。如大量訪問的web服務器,可讓80端口再也不讓iptables作數據包的連接跟蹤處理,以提升用戶的訪問速度 。

具體操做方法以下:

一、修改/etc/sysconfig/iptables 文件中的-A RH-Firewall-1-INPUT -m state --state RELATED,ESTABLISHED, UNTRACKED -j ACCEPT 行。增長紅色字體中的部分,保存並restart iptables 。

二、運行下面的語句:

iptables -t raw -A PREROUTING -p tcp -m multiport --dports 80,3128 -j NOTRACK
iptables -t raw -A PREROUTING -p tcp -m multiport --sports 80,3128 -j NOTRACK
iptables -t raw -A OUTPUT -p tcp -m multiport --dports 80,3128 -j NOTRACK
iptables -t raw -A OUTPUT -p tcp -m multiport --sports 80,3128 -j NOTRACK

若是隻是一個端口,改成下面的語句:

iptables -t raw -A PREROUTING -p tcp -m tcp --dport 80 -j NOTRACK
iptables -t raw -A OUTPUT -p tcp -m tcp --sport 80 -j NOTRACK
iptables -t raw -A PREROUTING -p tcp -m tcp --sport 80 -j NOTRACK
iptables -t raw -A OUTPUT -p tcp -m tcp --dport 80 -j NOTRACK

注:第1步很重要,若是第1處沒改,執行後面的語句會形成相應的端口不能訪問。我使用該方法時,就由於沒有執行第一步的操做,形成web訪問不能使用。

方法三:移除模塊法

[root@localhost log]# /sbin/lsmod | egrep 'ip_tables|conntrack'nf_conntrack_ipv6       8748  2nf_defrag_ipv6         12182  1 nf_conntrack_ipv6
nf_conntrack           79453  2 nf_conntrack_ipv6,xt_state
ipv6                  322541  209 ip6t_REJECT,nf_conntrack_ipv6,nf_defrag_ipv6

執行上面的語句,不難發現state模塊和nf_conntrack之間是有依賴關係的。因此想要卸載nf_conntrack模塊的話,必須也要把state模塊移除,否則,其會自動啓用nf_conntrack模塊。

操做方法以下:

一、先將/etc/sysconfig/iptables 中包含state的語句移除,並restart iptables 。

二、執行語句

modprobe -r xt_NOTRACK nf_conntrack_netbios_ns nf_conntrack_ipv4 xt_state
modprobe -r nf_conntrack

執行完查看/proc/net/ 下面若是沒用了 nf_conntrack ,就證實模塊移除成功了。

總結:

以上三種方法種,若是像web這樣的操做訪問量併發不大的狀況下,建議經過第一種方法實現。由於nf_conntrack模塊的做用不只僅只用於記錄狀態,iptables還能夠經過對該模塊的使有達到動態過濾的做用。如我在用ab動測試的一臺服務器上進行併發模擬時,在/var/log/message裏發現以下的日誌:

Apr 22 15:21:46 localhost kernel: possible SYN flooding on port 80. Sending cookies.Apr 22 15:22:46 localhost kernel: possible SYN flooding on port 80. Sending cookies.

而此時iptables會智能的將發動SYN flood***的IP暫時拒絕掉:

[root@localhost ~]# ab -c 500 -n 5000 "http://192.168.10.177/"This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/Copyright 2006 The Apache Software Foundation, http://www.apache.org/Benchmarking 192.168.10.177 (be patient)apr_socket_recv: Connection reset by peer (104)Total of 68 requests completed

如上因此,我用ab操做時,其就會收到apr_socket_recv 的錯誤提示 。我在網上查詢到其具體實現的原理以下:

傳統的防火牆只能進行靜態過濾,而 iptables 除了這個基本的功能以外還能夠進行動態過濾,便可以對鏈接狀態進行跟蹤,一般稱爲 conntrack 。 但這不意味着它只能對 TCP 這樣的面向鏈接的協議有效,它還能夠對 UDP, ICMP 這種無鏈接的協議進行跟蹤,咱們下面立刻就會看到。

iptables 中的鏈接跟蹤是經過 state 模塊來實現的,是在PREROUTING 鏈中完成的,除了本地主機產生的數據包,它們是在 OUTPUT 鏈中完成。 它把「鏈接」劃分爲四種狀態:NEW, ESTABLISHED, RELATED 和 INVALID。鏈接跟蹤當前的全部鏈接狀態能夠經過 /proc/net/nf_conntrack 來查看(注意,在一些稍微舊的 Linux 系統上是 /proc/net/ip_conntrack)。 

當 conntrack 第一次看到相關的數據包時,就會把狀態標記爲 NEW ,好比 TCP 協議中收到第一個 SYN 數據包。當鏈接的雙方都有數據包收發而且還將繼續匹配到這些數據包時,鏈接狀態就會變爲 ESTABLISHED 。而 RELATED 狀態是指一個新的鏈接,但這個鏈接和某個已知的鏈接有關係,好比 FTP 協議中的數據傳輸鏈接。INVALID 狀態是說數據包和已知的任何鏈接都不匹配。

固然,僅僅利用iptables conntrack自動實現syn flood 等DDOS***時很弱的。而現成的動態過濾和DDOS防禦的方法是不少的。好比netstat腳本實現,iptalbes限制每秒進行鏈接數,nginx/apache的鏈接數限制模塊及fail2ban日誌分析法………… ,因此在具備以上防禦的狀況下,很是推薦將web 、squid/varnish等應用所在的服務器配置爲RAW方式 。我在現網一臺150M/S 的cache server上將80和3128兩個端口所有NOTRACK以後,conntrack hash表由瞬滿直線降低到只有幾百條。

最後,最不推薦使用的第三種方法,由於第三種方法會將state模塊也一起移除掉。


參考頁面:

http://jaseywang.me/2012/08/16/%E8%A7%A3%E5%86%B3-nf_conntrack-table-full-dropping-packet-%E7%9A%84%E5%87%A0%E7%A7%8D%E6%80%9D%E8%B7%AF/

http://wiki.khnet.info/index.php/Conntrack_tuning

http://blog.zol.com.cn/2608/article_2607945.html

http://wangcong.org/articles/learning-iptables.cn.html

http://pc-freak.net/blog/resolving-nf_conntrack-table-full-dropping-packet-flood-message-in-dmesg-linux-kernel-log/

http://blog.csdn.net/dog250/article/details/7262619

相關文章
相關標籤/搜索