3/2 追記
最大リクエスト数(burst)の設定値が厳しすぎて、
データを受け取り切る前にぶった切られる事が判明したので、制限を緩めました。
location / {
limit_req zone=one burst=100 nodelay;
...
}
先日の深夜にこの WordPress サイトが DoS 攻撃を受け、
一時的にアクセス不可になった模様。あっ…(察し)
59.106.50.252 - - [21/Feb/2017:01:10:44 +0900] "GET / HTTP/1.0" 499 0 "-" "ApacheBench/2.0.40-dev" "-"
59.106.50.252 - - [21/Feb/2017:01:10:44 +0900] "GET / HTTP/1.0" 499 0 "-" "ApacheBench/2.0.40-dev" "-"
59.106.50.252 - - [21/Feb/2017:01:10:44 +0900] "GET / HTTP/1.0" 499 0 "-" "ApacheBench/2.0.40-dev" "-"
59.106.50.252 - - [21/Feb/2017:01:10:44 +0900] "GET / HTTP/1.0" 499 0 "-" "ApacheBench/2.0.40-dev" "-"
59.106.50.252 - - [21/Feb/2017:01:10:44 +0900] "GET / HTTP/1.0" 499 0 "-" "ApacheBench/2.0.40-dev" "-"
59.106.50.252 - - [21/Feb/2017:01:10:44 +0900] "GET / HTTP/1.0" 499 0 "-" "ApacheBench/2.0.40-dev" "-"
59.106.50.252 - - [21/Feb/2017:01:10:44 +0900] "GET / HTTP/1.0" 499 0 "-" "ApacheBench/2.0.40-dev" "-"
~ (省略) ~
59.106.50.252 - - [21/Feb/2017:01:10:44 +0900] "GET / HTTP/1.0" 499 0 "-" "ApacheBench/2.0.40-dev" "-"
59.106.50.252 - - [21/Feb/2017:01:10:44 +0900] "GET / HTTP/1.0" 499 0 "-" "ApacheBench/2.0.40-dev" "-"
59.106.50.252 - - [21/Feb/2017:01:10:44 +0900] "GET / HTTP/1.0" 499 0 "-" "ApacheBench/2.0.40-dev" "-"
59.106.50.252 - - [21/Feb/2017:01:10:44 +0900] "GET / HTTP/1.0" 499 0 "-" "ApacheBench/2.0.40-dev" "-"
59.106.50.252 - - [21/Feb/2017:01:10:44 +0900] "GET / HTTP/1.0" 499 0 "-" "ApacheBench/2.0.40-dev" "-"
59.106.50.252 - - [21/Feb/2017:01:10:44 +0900] "GET / HTTP/1.0" 499 0 "-" "ApacheBench/2.0.40-dev" "-"
122.218.250.122 - - [21/Feb/2017:01:12:34 +0900] "GET / HTTP/1.1" 504 176 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:51.0) Gecko/20100101 Firefox/51.0" "-"
ApacheBench でアクセスして来たようですが、この威力です。(直後のアクセスが 504 エラーを返している)
WEB アクセスを国内のみに制限しているのに、まさかアタックを受けるとは思わんかったので
なにかしら対策をしてみようと思います。
nginxでのDoS攻撃対策
主な対策は以下となります。
- Nginx のモジュール ngx_http_limit_req_module を使用して、単位時間あたりにリクエストできる数に制限をかける
Nginx の limit_req の設定内容
とりあえずこんな感じで設定します。
# vi /etc/nginx/nginx.conf
http {
...
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
...
}
limit_req_zone
上記設定では、limit_req_zone で同一 IP からの
アクセスが 秒間1回 以上あったら制限をかけるゾーンを定義しています。
続けて、location ディレクティブなどに limit_req を設定します。
server {
location / {
limit_req zone=one burst=10 nodelay;
...
}
}
limit_req zone
limit_req zone = name [ burst = number(default 0)] [ nodelay ]
- ゾーン (
zone) とバースト時の最大リクエスト数 (burst) を指定 - 過剰リクエスト数(今回であれば 10)が
burstの数値以内であれば、レスポンスを遅延させる nodelayを設定すると、レスポンスを遅延させなくなる- 過剰リクエスト数が
burstの数値を超過した場合、リクエストはコード503 Service Temporarily Unavailableを返す
したがって、秒間10リクエストを超える、つまり制限を超えると即座に 503 エラーを返す ようになります。
動作確認
今回の DoS で使用された ApacheBench で検証します。
リクエスト回数 100、同時リクエスト数 100 とします。
※間違っても本番に打たないでね……
# ab -n 100 -c 100 http://hdserver.mydns.jp/
結果:
Time taken for tests: 7.881 seconds
Complete requests: 100
Failed requests: 83
100 リクエスト中 83 アクセスが失敗しています。
エラーログ:
2017/02/25 19:51:19 [error] 6958#6958: *155 limiting requests, excess: 10.025 by zone "one", client: 121.116.163.198, server: , request: "GET / HTTP/1.0", host: "150.95.141.227"
エラーログを見ると、秒間アクセスが制限を超えた旨のログが出ています。
アクセスログにも 503 でエラーを返しているのがわかります。
121.116.163.198 - - [25/Feb/2017:19:51:24 +0900] "GET / HTTP/1.0" 503 206 "-" "ApacheBench/2.3" "-"
対策前は攻撃を受けただけで Load が 50 近く跳ね上がっていましたが、
対策後はせいぜい 1~2 程度の負荷で済みました。
しっかり対策しないとこういうことが起こるんだなぁと、身をもって実感した出来事でした。