6/10追記です
possible SYN flooding on port 24224. Sending cookies.
が出力される
→backlog最大まであげる
→netstat -sでみたoverflowedは止まったがCLOSE_WAITが多発
→間に挟んでたELBがサージキューを握りつぶす問題を特定
→logサーバ増やしELBに向いてたのを直送に切り替え(backlogは増やさず)
→再送されてればcookie送ってても気にしなくていいのでは説
→monitor-agent監視いれて再送を捕捉
→logサーバ増やす計画を立て中
→td-agent3がでたら色々解決しそうだけどまだでてないし人柱回避できる頃合を見計らいたい
以下のようなログをみかけて、bufferはファイルだしログは受け取れてfluentdが落ちたりしてはいないけどスルーする内容ではない気がして少し調べました。
kernel: possible SYN flooding on port 24224. Sending cookies.
まず、ログサーバのこのポートに接続できる範囲は絞ってあって限られているしいろんなところからログ受けてるせいなだけであからさまにSYN flooding攻撃ではないであろう(確信)という前提があります。
このログでそのままググると、負荷テストだったらnet.ipv4.tcp_syncookies = 1(デフォルト)じゃなくて0にしたほうがいいよという情報がみつかるのですが、ググりつづけてみたところ鵜呑みに設定すると問題ありそうな情報もわりと見つかりました。
http://d.hatena.ne.jp/nyant/20111216/1324043063
http://triplesky.blogspot.jp/2014/07/centos6dmesgpossible-syn-flooding-on.html
https://www.npa.go.jp/cyberpolice/server/rd_env/pdf/DDoS_Inspection_2.pdf
↑のあたりによると、net.ipv4.tcp_syncookiesが0だとパケットがdropされるようなことが書いてあったり、net.ipv4.tcp_syncookiesが1のほうがいっぱい受け取れるらしいと書いてあったり。
netstat -i
でインターフェースの情報をみたかんじ、特にパケットがドロップされている形跡は無さそうで、
netstat -an
をみたところ、TIME_WAITとCLOSE_WAITがとても多くて、あ、そういえばtcp_tw_reuseが0だなー1にしないと、と思いました。(tcp_tw_recycleは内部ELBつかってるので0で)
それから以下を変えようと思いました。(警視庁のpdfの2ページ目の付記が根拠で、まだ提案しただけで反映はしてない 結果は後述してて端的にはbacklogをアプリ側とそろえて広げる以外は焼け石に水)
net.ipv4.tcp_max_syn_backlog = 8192 → 16384
net.ipv4.tcp_syn_retries = 5 → 3
実際にSYNFlood攻撃を受けていないにもかかわらず、システムログにSYNFloodの警告が出力される場合は、正当なコネクションが過負荷状態に陥っている可能性がある。
この様な場合は、syncokies機能を有効にするのではなく、tcp_max_syn_backlog(注5),tcp_synack_retries(注6),tcp_abort_on_overflow(注7)等の値を調整する必要がある。
(注5)tcp_max_syn_backlog・・送信したSYNのステートを記憶する最大数の設定
(注6)tcp_synack_retries・・SYN/ACKの再送回数の設定
(注7)tcp_abort_on_overflow・・listen状態のサービスに新しいコネクションの受け入れが非常に遅い場合、それらをリセットするか否かの設定
ちなみにnet.ipv4.tcp_max_syn_backlogのデフォルト値は1024であらかじめ増やしてたんですが足らなくなった?模様。(logに"possible SYN flooding"がでてるのがそう思う根拠)
相談の結果、まずアプリ側の対応が要るかも?という意見からin_forwardにbacklog指定してみることに。
マニュアルはin_unixにはbacklog指定できるけどin_forwardにそういうディレクティブがないんですが、
実際試験機で設定してconfigtestとかrestartしてtd-agent.logみてもエラーも出ずとまったりもしなかったので2台中のlogサーバのfluentd1024らしいデフォルト値を2048にしてみました。
<source>
type forward
port 24224
bind 0.0.0.0
backlog 2048 #これを追加
</source>
http://docs.fluentd.org/articles/in_unix
https://github.com/fluent/fluentd/blob/v0.10.55/lib/fluent/plugin/in_forward.rb
https://github.com/tarcieri/cool.io/blob/v1.1.1/lib/cool.io/server.rb#L59
とりあえず様子を見中です。
このへんの図と、
http://koseki.hatenablog.com/entries/2007/03/31
このへんの解説から
http://d.hatena.ne.jp/nyant/20111216/1324043063
cookieおくりはじめちゃってるからCLOSE_WAIT増加につながっているのかしらとなんとなく思ったけどSYN_RECVの数は設定増やしたアプリ側のbacklogとtcp_max_syn_backlogには到達してなくていまのところ謎です。
→netstatでみてたら瞬間的なやつはSYN_RECVでいる時間が短すぎて取れないらしく/proc/net/tcpをみるのがいいぽいです。
muninのtcpのプラグインあったなーと思って見てみたら普通に/proc/net/tcpみてました。早く気づけばよかったorz
ほぼ似たような状況の英語のリンクを見かけたので追記。
http://serverfault.com/questions/294209/possible-syn-flooding-in-log-despite-low-number-of-syn-recv-connections
また追記(3/10)、man 7 tcp
でみたtcp_max_syn_backlogのTCP_SYNQ_HSIZE
を修正してカーネル再コンパイル推奨というのは以下リンクによるとカーネル2.6.20から動的になっててTCP_SYNQ_HSIZE
はソースから削除されてるそうです。マニュアル修正漏れらしいです。(3.82でmanが修正される模様)
上記リンク内のTP.とかって何だろうと思ったらmanのマクロでした。
https://linuxjm.osdn.jp/html/LDP_man-pages/man7/man.7.html
man 2 listenの、「この設定は無視される」ってどういうことなんでしょうか。わからないです。
TCP ソケットでの backlog 引き数の振る舞いは Linux 2.2 で変更された。現在ではこの 引
き数は、受け付けられるのを待っている、 完全に確立されたソケットのキューの長さを指定
する。以前は不完全な接続要求の数であったが、これを置き換えた。不完全なソケットの キ
ュ ー の 最 大長は /proc/sys/net/ipv4/tcp_max_syn_backlog を用いて設定できる。 syn-
cookie が有効になっている場合、論理的な最大長は存在せず、この設定は無視される。
backlogふやしたぶんは効いていそうですがパケットキャプチャしてみたところ再送が結構な割合を占めているタイミングがある等々わかりました。
3/18追記:
結果として、わかったことだけ追記を。
・内部ELBを介してログを送ってたわけなんですが、
負荷テスト(hpingとかdummerとかで)したところELBを介した場合、サージキュー頭打ちが継続するとログがロストするケースが。(量が少なければ大丈夫そう)
・fluentdのin_forwardのbacklog(要するに前述しているアプリ側のバックログ)と
net.ipv4.tcp_max_syn_backlogと
net.core.somaxconnを
ELB配下のlogサーバ全部 65535 (最大値)にしたところ、
ELBのサージキュー頭打ち解消し、
かつ"possible SYNFlooding"のログが1時的に消えました(その後は再度でたり出なかったりしている)。
tcp_syncookiesは1でも0でもサージキューに関しては大差ない。
・送る側のheartbeat_interval 1sでそれが数百台分きてるSYNをさばくのにキューがいるという話だったもよう。
(パケットキャプチャではpushがとても少なかった)
http://blog.livedoor.jp/sonots/archives/36895001.html
http://ogibayashi.github.io/blog/2014/12/16/try-fluentd-v0-dot-12-at-least-once/
・/proc/net/tcpでキューを確かめるのがよさげ(muninとかのtcpモニタはそうなってたかと)
https://searchcode.com/codesearch/view/67882452/
http://www.usupi.org/sysad/110.html
このへんとかみると、24224ポートのSYN_RECVを数えたいとかいった場合、
24224をbcとかで16進数になおすと5EA0なので2カラム目の:の後ろが5EA0でSYN_RECVだと4カラム目のst(ステート)が03ぽいのでそれをcatからawkとgrepとかwcでつなげるとカウントできるっぽいですね。
$ cat /proc/net/tcp |awk '{print $4}'|sort|uniq -c|sort -r|grep -v st|sed -e 's/ 01/ established/g' -e 's/ 02/ syn_sent/g' -e 's/ 03/ syn_recv/g' -e 's/ 04/ fin_wait1/g' -e 's/ 05/ fin_wait2/g' -e 's/ 06/ time_wait/g' -e 's/ 07/ close/g' -e 's/ 08/ close_wait/g' -e 's/ 09/ last_ack/g' -e 's/ 0A/ listen/g' -e 's/ 0B/ closing/g'
これでいいのかはよくわかりませんがOSコマンドでがんばるとこんなかんじでしょうか。(24224だけ知りたいときはawkの手前でgrep 5EA0)なんかメモリ食いそうかな。。
backlogの最大値の根拠となる情報はこちらに
Life with open mind: somaxconnの上限値は65535
また公式に接続の使いまわしとポートレンジ広げるカーネルチューニングが載ってました(recycleは負荷分散してるのでつかわないのがよさげ)
Before Installing Fluentd | Fluentd
ほかにも最近のブクマがtcpとかfluentdにまみれたけどとりあえず確実そうなのだけで失礼します。
参考サイト:
LinuxのTCP/IPの実装について調べてみた - nyantの日記
小岩以上アキバ未満~記憶のディザスター~: CentOS6などでdmesgにpossible SYN flooding on port(SYN flooding警告)が出た場合の対策方法を考えてみるテスト
DDoS_Inspection_2.pdf
td-agentでqueue size exceeds limit - Glide Note
2007-03-31 TCP接続が切れるまで - こせきの技術日記
linux - "Possible SYN flooding" in log despite low number of SYN_RECV connections - Server Fault
tcp in sonic-dns-munin | source code search engine
ポートをリッスンしているプロセスを知る - いますぐ実践! Linuxシステム管理 / Vol.110
Fluentd の out_forward プラグインで良く出る warning メッセージとその負荷対策まとめ - sonots:blog
Fluentd v0.12のAt-least-once Semanticsを試す - Tech Notes
Life with open mind: somaxconnの上限値は65535
Before Installing Fluentd | Fluentd
fluent-plugin-multiprocessと戯れた話 - Qiita
Ele-Craft/電子工作日記: syncookiesとListenバックログとパケットロスト
続きをかきました。
http://qiita.com/smallpalace/items/805f41b9bd6d3d404d28