今回はLinuxを用いて、
実際にSYN Flood攻撃をやって、
その対策に一つである、
SYN cookiesについて説明します。
まずはSYN Flood攻撃を
やってみましょう。
実践するにあたって私は、
次の環境を用いました。
Virtual Box上で動作するLinux2台 ・Kali Linux2018.04 (Webサーバ:Apache) ・Ubuntu18.04 (クライアント側) |
まずはSYN Flood攻撃について、
簡単に確認していきましょう。
TCP通信を始める前に、
クライアントとサーバは
3wayハンドシェークを行います。
3wayハンドシェークの手順は、
まずクライアントがSYNフラグを
セットしたTCPパケットを送ります。
それを受け取ったサーバは、
SYNとAckフラグをセットした
TCPパケットを送り返します。
クライアントはサーバから
それが送られてくると、
Ackフラグをセットして返信します。
図で表すと次のようになります。

サーバはクライアントから
SYNパケットを受け取ると、
syn_backlogキュー(バッファ)に
その情報を一時的に確保します。
この状態はコネクションがまだ
未確立の状態でハーフオープンと
呼ばれれる状態に該当します。
そしてこの状態から
コネクション確立まで遷移すると、
SYN_Backlogキューにあった
コネクション情報はBacklogキューと
呼ばれるバッファに移されます。
ソケットプログラムで扱ったことが
ある方はご存知の通り、
listen()の引数で指定する値です。
listen()の引数で指定した値が、
バックログキューの長さに該当します。
ちなみにaccept()される直前では、
TCPコネクションが確立している状態です。
話しを戻しまして、SYN Flood攻撃は、
このSYN_Backlogというバッファを
攻撃者の手によって埋め尽くすことで、
正規クライアントがコネクション確立を
出来なくするDoS攻撃の一種です。
サーバはクライアントから
SYNパケットが送られてきたら、
Half-openの状態になり、
syn_backlogキューの情報を一時確保します。
攻撃者はこの仕組みを利用して、
多数のランダムIPアドレスからサーバへ
SYNパケットを乱打します。
これがSYN Flood攻撃です。
ではどのように対策すれば
良いのでしょうか。
今回はその一つである、
SYN cookiesについて説明します。
SYN cookiesは、
SYN_Backlogがいっぱいになったら、
Half-openのコネクションを順に
解放してバッファを空ける仕組みです。
このSYN cookiesが有効であれば、
新しいコネクションの確立要求が来ても、
未確立のコネクションを削除することで、
対応できるようになります。
この値が無効であれば、普通、
SYN + Ack パケット対する
Ack パケットの返信がタイムアウトするまで
サーバはHalf-openを維持します。
つまりSYN Backlogキューを持ったままです。
SYN cookiesが有効であるか否かは、
次の場所で設定されています。
/proc/sys/net/ipv4/tcp_syncookies 1なら有効、0なら無効 |
それではこのsyn cookiesが
ONのときとOFFのときとで、
サーバにSYN Flood攻撃を
仕掛けてみましょう。
LinuxでSYN Flood攻撃をやる方法
まずSYNパケットを送信するのに、
hping3 というツールを使用します。
まずはhping3をインストールしましょう。
apt-get install hping3 |
---|
インストールが出来たら、
例えば次のように打って
SYNパケットを送信します。
hping3 -c 1500 -d 120 -w 64 -p 80 --flood --rand-source X.X.X.X |
---|
-c:パケットカウント数
-d:データ長
-w:ウインドウサイズ
-p:送信先ポート番号
--flood:最高レートで送信する
--rand-source:送信元IPアドレスを偽造
x.x.x.x:送信先IPアドレス
サーバ側は listen() のポートを用意します。
私の場合は、Apacheを用いた
Webサーバを用意しました。
Apacheの場合は、
apt-get install apache2で
インストールして、
service apache2 startで
簡単にWebサーバを動かすことが出来ます。
未確立状態のコネクションは
次のコマンドで確認出来ます。
netstat -n | grep SYN_RECV |
---|
クライアント側で上述したhping3を
タイプしてSYNパケットを
送信し続ける状態にしておきます。
こんな感じです。

この状態でサーバ側で接続を確認した
画像がこちらになります。
netstat -n | grep 80 をうちました。

実はLinuxではデフォルト状態では、
SYN cookiesが有効になっています。
なのでどれだけSYNパケットを
送信してもSYN_Backlogキューは
いっぱいになりません。
なのでSYN Flood攻撃をしている中で、
正規クライアントが接続を試みても
コネクションの確立に成功します。
もしSYN Flood攻撃によって、
正規クライアントが接続できない
という状態を体験したい場合は、
syn cookiesを無効にする必要があります。
vimでもなんでもよいので、
/proc/sys/net/ipv4/tcp_syncookies
ここにある値を1から0にしてやります。
実際にこれを0にして、
正規クライアントがWebサーバに
アクセスすると、タイムアウトします。
これ以降はもう少し深堀します。
syn_cookiesの確認 cat /proc/sys/net/ipv4/tcp_syncookies SYN_Backlogキューの確認 cat /proc/sys/net/ipv4/tsp_max_syn_backlog listenに指定できる最大バックログキューの確認 cat /proc/sys/core/somaxconn |
カーネル側でsys_backlogキューの
最大サイズが決められています。
これはあくまでカーネルが決めた
最大値に過ぎず、実はsyn_backlogには
実効値が存在します。
この実効値の計算には、
確立済みのコネクション用の
バッファであるバックログキューが
関係してきます。
このバックログキューの値は、
サーバを実装したプログラム中にある
listen()の引数に指定した値です。
サーバであればSOMAXCONNという
定義された値が入ることが多く、
これはカーネルによって決められた値です。
デフォルトでは↓の画像のように
128 (Debianの場合)がセットされています。

最後の行に、
netstat -n | grep SYN_RECV | wc -l
の出力として 97 が表示されています。
これはコネクション未確立の数を示します。
上の画像ではSYN Flood攻撃を仕掛けて、
数秒経過した後の数です。
この 97 という値は、
実験を行った環境において
Half-openのコネクションを
確保できる最大数を意味しています。
実はこの値は計算によっても
求めることが出来ます。
詳しい計算方法は下記のサイトに
大変分かりやすく記載されています。
参考:
・https://wiki.bit-hive.com/linuxkernelmemo/pg/listen%20backlog%20%E3%80%903.6%E3%80%91
・http://intrajp-computer.hatenadiary.jp/entry/2017/09/22/055158
今回は以上です。
最後まで読んでいただきありがとうございました。