今日は、backlog の実験をしてみます。
CentOS6.9 で、メモリ4Gbyte の仮想マシン上で実験しました。
よく使われるアプリケーションとして、Apache を上げてみます。
前提知識です。
syn backlog:接続確立中キューの最大値(不完全なソケットのキューの最大長)
backlog:接続待ちキューの最大値(完全に確立されたソケットのキューの最大長)
tcp_syncookies:
有効(値 1):一定の基準を越えた場合、syncookies を送信する。
syn backlog と backlog の小さいほうの値を、付近の 2の累乗の値に
切り上げた数値を超えると、syncookie を送信します(注)。
その際、ソケット蓄積の概念は放棄されるため、syn backlogの最大値の概念
は無視されます。
無効(値 0): 一定の基準を越えた場合、新たな要求を無視する。
接続確立中キューに syn backlog の 75 % + 1 を超えるソケットが溜まる
と、新しい要求を無視します。
(注)
syncookies は、TCP プロトコルにしたがっていない点があり、攻撃に対する
対処用法として存在し、予備的な機能(fallback functionality)でしか
ないため、SYN flood を起こさせるようなDOS 攻撃を受けていると考えられる
場合のみに発動されるべきです。
(参考)
Documentation/networking/ip-sysctl.txt
次に、それぞれの値の設定ヶ所の説明です。
- syn backlog の設定ヶ所
OS の設定か所:/proc/sys/net/ipv4/tcp_max_syn_backlog
Apache の設定ヶ所:なし
- backlog の設定ヶ所
OSの設定箇所: /proc/sys/net/core/somaxconn
Apache の設定か所: ListenBackLog ディレクティブの設定値
backlog の値について、OS および Apache で設定が可能ですが、以下の条件にしたがいます。
Apache の設定値 ≦ OS の設定値ならば、
Apache の設定値が有効
Apache の設定値 > OS の設定値ならば、
OS の設定値が有効
- tcp_syncookies の設定ヶ所
OS の設定か所:/proc/sys/net/ipv4/tcp_syncookies
Apache の設定ヶ所:なし
backlog の値は、実際は 1 から 65535 まで設定可能です。
例えば、OS および Apache の設定値を 4096 にすると、backlog の設定値は、
Apache の値、4096 となります。
syn backlog の値を増やすかどうかは、そのマシンの通常の通信状況によります。
OS のデフォルト設定では、syncookies が有効になっていますので、
接続確立中の要求が syn backlog の値と、backlog 値の小さいほうの値を、
付近の 2 の累乗の値を切り上げた数値を超えた場合、syncookie が送信されます。
通常のトラフィックにおいて、接続確立中の要求が多くならいようであれば、
syn backlog の値を増やす必要はなく、通常の通信環境においても、
接続確立中の要求が多くなるようであれば、多くする必要があるかもしれませんね。
いずれにしても、設定の際は、通常のアプリケーションの通信状況を把握した上で、
各上限値を設定する必要があるといえます。
TCP ソケットを listen している情報は、以下のコマンドの結果が表示する、
Recv-Q,Send-Q により確認できます。ここで、Send-Q の値が、Apache の
backlog になります。
# ss -lti '( sport = :http )'
接続確立中の要求数の確認は、以下のコマンドで確認できます。
# netstat -antp | grep SYN_RECV | wc -l
(一例:syncookies=0 で syn backlog が 2048 の時、上限値に達した場合)
1537
私が行った設定で実験したら、このようになりました。
・デフォルトの設定
128 /proc/sys/net/core/somaxconn
2048 /proc/sys/net/ipv4/tcp_max_syn_backlog
511 Apache の ListenBackLog ディレクティブ
backlog の最大値 128
tcp_syncookies=1 の場合
接続確立中の要求数の上限値 256(backlog の付近の2の累乗の値)
tcp_syncookies=0 の場合
接続確立中の要求数の上限値 1537(syn backlog * 0.75 + 1 の値)
・OS、Apache の設定値を上げる
2048 /proc/sys/net/core/somaxconn
2048 /proc/sys/net/ipv4/tcp_max_syn_backlog
2048 Apache の ListenBackLog ディレクティブ
backlog の最大値 2048
tcp_syncookies=1 の場合
接続確立中キューの最大値 4096(backlog の付近の2の累乗の値)
tcp_syncookies=0 の場合
接続確立中キューの最大値 1537(syn backlog * 0.75 + 1 の値)
・syn backlog 変化させず、さらにOS、Apacheの設定値を上げる
4096 /proc/sys/net/core/somaxconn
2048 /proc/sys/net/ipv4/tcp_max_syn_backlog
4096 Apache の ListenBackLog ディレクティブ
backlog の最大値 4096
tcp_syncookies=1 の場合
接続確立中キューの最大値 4096(syn backlog の付近の 2 の累乗の値)
tcp_syncookies=0 の場合
接続確立中キューの最大値 1537(syn backlog * 0.75 + 1 の値)
・syn backlog を、4096 に上げる
4096 /proc/sys/net/core/somaxconn
4096 /proc/sys/net/ipv4/tcp_max_syn_backlog
4096 Apache の ListenBackLog ディレクティブ
backlog の最大値 4096
tcp_syncookies=1 の場合
接続確立中キューの最大値 8192(backlog の付近の2の累乗の値)
tcp_syncookies=0 の場合
接続確立中キューの最大値 3073(syn backlog * 0.75 + 1 の値)
また、この実験の場合ですが、接続確立中の要求が syn backlog の値と、
backlog 値の小さいほうの値を、付近の 2 の累乗の値を切り上げた数値を超えた
場合、syncookie が送信されることになります。
そのとき、/va/log/messages には、以下のログが 60秒に 1回記録されます。
kernel: possible SYN flooding on port <PORT>. Sending cookies.
tcp_syncookies は OS で有効に設定されています。
tcp_syncookies が有効な場合、上述のとおり syn backlog の値を
変化させることにより、接続確立中キューの最大値は変化するので、
適宜設定したらいいと思います。
具体的にどうやって実験したかというと、次のようにやりましたよ。
以下のスクリプトを実行します。これを確認します。
#!/bin/bash
while :
do
netstat -antp | grep SYN_RECV | wc -l
sleep 1
done
下記のとおり、SYN FLOOD 攻撃を実行して、上記の表示を観察する(実際のシステムにやってはいけませんよ)。
# hping3 -c 10000 -d 120 -S -w 64 -p 21 --flood --rand-source <TARGET_IP>
おいしいもの食べたいなぁ。
(参考:用語解説等)
mpm_common - Apache HTTP サーバ バージョン 2.4