1. 程式人生 > >nf_conntrack: table full, dropping packet (by joshua)

nf_conntrack: table full, dropping packet (by joshua)

版權宣告:可以任意轉載,轉載時請務必以超連結形式標明文章原始出處和作者資訊及本版權宣告 (作者:張華 發表於:2018-02-08)

conntrack遇到了’nf_conntrack: table full, dropping packet’怎麼辦?

Ubuntu上和conntrack相關的命令如下:

sudo apt install conntrack
sudo conntrack -L
sudo find /proc/ -name '*conntrack*'
sudo sysctl -a | grep conntrack

[email protected]:~# grep nf_conntrack /proc/slabinfo
nf_conntrack_expect 0 0 224 36 2 : tunables 0 0 0 : slabdata 0 0 0 nf_conntrack 425 425 320 25 2 : tunables 0 0 0 : slabdata 17 17 0

Ubuntu上的預設值如下:

[email protected]:~# sudo sysctl net.netfilter.nf_conntrack_count net.netfilter.nf_conntrack_max net.netfilter.nf_conntrack_tcp_timeout_established net.netfilter.nf_conntrack_buckets 
net.netfilter.nf_conntrack_count = 77 net.netfilter.nf_conntrack_max = 262144 net.netfilter.nf_conntrack_tcp_timeout_established = 432000 net.netfilter.nf_conntrack_buckets = 65536
  1. net.netfilter.nf_conntrack_count為已建立連線,當net.netfilter.nf_conntrack_count > net.netfilter.nf_conntrack_max時會報錯”ip_conntrack table full dropping packet”
  2. net.netfilter.nf_conntrack_tcp_timeout_established為ESTABLISHED的時間,預設為5天。
  3. net.netfilter.nf_conntrack_max可由公式(CONNTRACK_MAX = RAMSIZE (in bytes) / 16384 / (ARCH / 32))計算得到,以16G的64位作業系統為例,CONNTRACK_MAX = 16*1024*1024*1024/16384/2 = 524288
  4. net.netfilter.nf_conntrack_buckets雜湊表大小通常為總表的1/8,最大為1/2。CONNTRACK_BUCKETS = CONNTRACK_MAX / 8, 同樣64G的64位作業系統,雜湊最佳範圍是 262144 ~ 1048576。正常地除以4即可(hashsize = nf_conntrack_max / 4), hashsize = 524288 / 4 = 131072

所以可使用下列配置:

sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=524288
sysctl -w net.netfilter.nf_conntrack_buckets=131072
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established = 86400

如果這些配置還不能解決問題,可以從業務上將不需要跟蹤的網絡卡排除,或者增大硬體配置:

iptables -t raw -A PREROUTING ! –I NIC -j NOTRACK

下面做了一個失敗的試驗,記錄一下,本來理論上理解的nf_conntrack_tcp_timeout_established這個值應該是建立 establish連線之後的超時時間,如果客戶端與服務端均不發訊息,經過nf_conntrack_tcp_timeout_established這個時間後,conntrack表項就會被刪除,然後伺服器再主動給客戶端發訊息就會失敗。但實際我測試的結果是我無論將nf_conntrack_tcp_timeout_established配置多大,過一兩分鐘conntrack表項都會被刪除,並且伺服器也能主動給客戶端發訊息時這個表項又會被重建。暫不清楚什麼原因,有記錄這裡,有時間再弄。

該實驗將證明nf_conntrack_tcp_timeout_established這個值不能低於業務中長連線的最長時間。但實際實驗結果失敗,表項被刪除之後服務端還能往客戶端發包。
在物理機(192.168.99.137)上啟動一虛機(192.168.122.48), 物理機預設有狀態防火牆配置。
hua@t440p:~$ sudo iptables-save |grep 122 |grep FORWARD
-A FORWARD -d 192.168.122.0/24 -o virbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -s 192.168.122.0/24 -i virbr0 -j ACCEPT

物理機上為方便實驗做如下設定將ESTABLISHED的超時時間從5天改成4分鐘:
root@t440p:~# sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=240
net.netfilter.nf_conntrack_tcp_timeout_established = 240
root@t440p:~# sysctl -p

1, 在物理機上啟動Server, 
hua@t440p:~$ python
Python 2.7.12 (default, Nov 20 2017, 18:23:56) 
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
import socket
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.bind(("192.168.99.137",8888))
serversocket.listen(5) 
(clientsocket, address) = serversocket.accept()
#clientsocket.recv(1000)
#clientsocket.send("respond",100)

2, 在虛機裡啟動Client, 並向伺服器傳送資料,但不關閉連線。
hua@xenial:~$ python
Python 2.7.12 (default, Nov 19 2016, 06:48:10) 
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("0.0.0.0",22222)) 
s.connect(("192.168.99.137", 8888))
s.send("request", 100)
#s.recv(1000)

我們看到了conntrack中有相關記錄項,它為ESTABLISHED狀態。
root@t440p:~# netstat -tn |grep 8888
tcp       14      0 192.168.99.137:8888     192.168.122.48:22222    ESTABLISHED
root@t440p:~# conntrack -L |grep 8888
tcp      6 431884 ESTABLISHED src=192.168.122.48 dst=192.168.99.137 sport=22222 dport=8888 src=192.168.99.137 dst=192.168.122.48 sport=8888 dport=22222 [ASSURED] mark=0 use=1

3, 等4分鐘(nf_conntrack_tcp_timeout_established=240)不發包, conntrack表項超時被清空,理論上應該此時無法再從服務端往客戶端發包。但實際測試結果是還能發,conntrack表項又會被重建。與理論不符啊,糾結中。

root@t440p:~# conntrack -L |grep 8888
conntrack v1.4.3 (conntrack-tools): 46 flow entries have been shown.
root@t440p:~# netstat -tn |grep 8888
tcp        7      0 192.168.99.137:8888     192.168.122.48:22222    ESTABLISHED