nagane
3/14/2013 - 4:04 PM

netfilterチューニング

netfilterチューニング

ip_conntrack: table full, dropping packet.
 
この一行のログに悩まされた方は多いのではないでしょうか。
自分もその一人です。
 
多くのブログには echo '500000' > /proc/sys/net/ipv4/netfilter/ip_conntrack_max で解決。みたいなことが書いてあると思います。
では、この数字について根拠はなんでしょうか。そもそも何のためにconntrack tableというものがあるのか考えたことはありますか?
闇雲に最大値をあげることにたいして抵抗がある方もいると思います。
 
このテキストは、転職後2日目にGWとして使っているLinux NAT BOXが爆発したことを起因とした、netfilterのチューニングについてまとめようと思います。
ある程度前提の知識があるのが前提ですので、用語はもちろん調べればすぐ分かるような説明はすべて省きます。
 
1:最初に結論
netfilterは使わないにこしたことはありません。不用ならモジュール自体をアンロードすることをお勧めします。
 
しかし、LVS-DSRやFWやip masquaredeなどどうしても使用しなければいけない状況が多数です。
使わないわけにはいかないものなので、がんばってチューニングしましょう。
パラメータの数値にはすべて根拠に基づいたものですし、ソースを読めば簡単に適切な値を導くこともできます。
がんばって自信をもって使える数値を計算してください。あきらめなければかならずできます。
 
2:conntrack tableってなんぞ?
TCPのセッション管理に直接結びついてると考えてる方もいるかもしれませんが、通信とは直接関係ありません。
conntackの数だけ実際のセッションが開いていません。
 
リモートホストとの通信状態を記録するための記憶領域がconntrack tableになります。
FWで1秒間にn回以上pingがきたらDROPするなど細かいruleを適用する場合は有効です。
 
つまりコネクションをトラッキングしても利用しないAPサーバなどの場合役に立つことがありません。
むしろ、conntrack tableを生成→スキャン→破棄するまでのタイマーなど、CPUとメモリを無駄に消費するでしょう。
 
したがって、サーバの用途によってチューニングのアプローチが違ってきます。
FW機は処理を高速にするために、conntrack tableは大きめに。APサーバなどは不用なので小さめにして貯めないようにします。
 
3:conntrack_tableの実態
conntrack_maxをいくら増やしてもDROPが止まらない、という経験をした方もいるとおもいます。
増やしていくうちにメモリの上限に到達してしまい、無駄にスケールしたりnetfilterをあきらめたりしていませんか?
これもやはり数字の根拠を知ることで解決策にたどり着くことができます。
 
/proc/net/conntrack を参照してみてください。
conntrack_tableのリストが沢山見えます。
 
見るところは[ASSURED]と[UNREPLIED]の二種類です。
UNREPLIEDは破棄されますが、ASSUREDは破棄されないとドキュメントにあるため、ASSURDの本数がconntraxk_maxに到達した時点でDROPが出るという感じです。
 
 
4:FW機向けチューニング
conntrack_tableをフルに利用するのがiptablesによるFWです。
しかし、ただconntrack_maxを大きくすればいいというわけではありません。
 
conntrack 1本あたりにスワップできない物理メモリを数百バイト必要とします。
また、conntrack_tableのスキャンを高速化するためにハッシュ化領域であるconntrack_bucketsを適切に設定しないとパフォーマンスが低下します。
 
公式は以下のサイトにあります。
http://wiki.khnet.info/index.php/Conntrack_tuning
 
OS_BIT = 64 or 32 (OSのbit)
HASHSIZE = CONNTRACK_MAX / 8 = RAMSIZE (in bytes) / 131072 / (OS_BIT / 32)  
 
12Gメモリを使うとして計算してみます。
 
RAMSIZE = 12884901888 / 131072 / 2 = 49152
CONNTRACK_MAX = 49152 * 8 = 393216
HASHSIZE = 393216 / 8 = 49152
 
設定値 nf_conntrack_max = 393216 HASHSIZE = 49152
となります。
 
物理メモリの量がnetfilterの限界ですが、トータルバランスで考えなければいけません。
CPUの割り込み処理、物理メモリ、NICのFPS(Frame Per Sec)、OSの使用できるポート数、すべてを考慮すべきです。
 
5:APサーバ向けチューニング
FW機はメモリの限界まで使い切れますが、APサーバはそうもいきません。conntrack_maxはローカルホスト同士でリバースプロクシをしてる場合を除いてデフォルト値で問題ないと思います。
 
ではどうすればconntrack_maxを増やさずに対処するのか。先ほどのconntrackの実体を思い出してみてください。
 
---
tcp      6 128 TIME_WAIT src=10.x.x.xx dst=1xx.xx.xx.xx sport=43860 dport=80 packets=6 bytes=698 src=1xx.xx.xx.xx dst=1x.x.x.xx sport=80 dport=43860 packets=4 bytes=419 [ASSURED] mark=0 secmark=0 use=2
tcp      6 88 TIME_WAIT src=10.x.x.xx dst=1x.x.x.xx3 sport=28869 dport=4011 packets=7 bytes=2023 src=1x.x.x.xx dst=1x.x.x.xx sport=4011 dport=28869 packets=7 bytes=2317 [ASSURED] mark=0 secmark=0 use=2
tcp      6 23 TIME_WAIT src=10.x.x.xx dst=1xx.xx.xx.xx sport=43708 dport=80 packets=6 bytes=663 src=1xx.xx.xx.xx dst=1x.x.x.xx sport=80 dport=43708 packets=4 bytes=542 [ASSURED] mark=0 secmark=0 use=2
---
 
TIME_WAIT状態のASSUREDが大量に見えると思います。netfilterのDROPの原因は大半はこれです。
ローカルホスト同士でリバースプロクシをしていたり、DBやKVSなど大量にセッションを張るサーバにはこの症状に陥りがちです。
 
デフォルトは180ですが、極端な数値にしてしまっても通信できなくなることはありません。
 
echo 1 > /proc/sys/net/ipv4/netfilter/ip_conntrack_tcp_timeout_time_wait
 
6:監視
こちらのcactiテンプレートが便利です。
netfilter自体メモリにのってしまっているので、全レコードをなめてもコストにはならないと思います。

http://forums.cacti.net/about36629.html

7:まとめ
FWするなら専用機にして、ハイスペック。そして数値を適切に計算して設定する。
APはconntrack_tableを保持するだけ無駄なのでさっさと破棄。
 
という感じです。
 
@SatchanP