listen backlog 【3.6】
Rev.9を表示中。最新版はこちら。
1. 概要
listen()時に指定するbacklogに関するメモ。
2. backlogとsyn table
listen()システムコールでLISTEN状態にあるソケットはbacklogというキューを持つ。backlogにはクライアントからのTCP接続要求が確立(ESTABLISH状態)し、まだaccept()されていない接続が並ぶ。
Listenソケットはbacklog以外にもTCP接続中(SYN_RECV状態)の接続を格納しておくキューがある。各種ドキュメントではキューと読んでいるが、実際にはハッシュテーブルで実装されている。ここではsyn tableと呼ぶ。
backlogのキューはinet_csk(sk)->icsk_accept_queueの.rskq_accept_headと.rskq_accept_tailで管理され、syn tableのハッシュはinet_csk(sk)->icsk_accept_queue.listen_opt->syn_tableで管理される(図1)。
図1 Listenソケットとbacklog
backlogのキュー長はlisten()時に指定されるbacklog引数の値に設定される。ただし、指定値がsysctlのnet.core.somaxconnより大きかった場合は、net.core.somaxconnの値に切り詰められる。
syn tableの最大サイズはbacklog値を8〜net.ipv4.tcp_max_syn_backlogの範囲に収めた後、一つ上の2の階乗の値に切り上げた値になる。例えば、backlog長が200ならsyn tableサイズは256、backlog長が256ならsyn tableサイズは512となる(syn tableの初期化処理はreqsk_queue_alloc()で行っている)。
3. SYN Flood攻撃の検出とSYN cookies
SYN Flood攻撃を受けるとSYN_RECV状態の接続が大量にできる。SYN RECVがsyn tableからあふれた場合の動作はnet.ipv4.tcp_syncookiesの設定により異なる。
(1) net.ipv4.tcp_syncookies = 0の場合
SYN_RECVの数がsyn tableの最大サイズの3/4を越えると、新たにSYN_RECVは登録せず廃棄する。このため、新たにTCP接続を確立できない。
(2) net.ipv4.tcp_syncookies = 1の場合
SYN_RECVの数がsyn tableの最大サイズを越えると、SYN Flood攻撃と判断しSYN cookiesの動作が始まる。
SYN Flood攻撃への耐性をあげようとsyn tableのサイズを大きくしようとする場合は、以下の点に注意する。
(a) net.ipv4.tcp_max_syn_backlogを大きくする
(b) listen()で指定するbacklog値を大きくする(apacheならListenBackLogディレクティブで指定できる)
(c) backlogの値自体はnet.core.somaxconnに切り詰められるため、net.core.somaxconnの方も大きくしておく。
syn tableの最大サイズはbacklogサイズに基づいて決まるため(2. backlogとsyn table を参照)、net.ipv4.tcp_max_syn_backlogを大きくするだけでなく、backlog自体が大きくなるように(b),(c)も行う必要がある。