AWS WAFで簡単にDoS攻撃を防いでみよう
DoS攻撃流行ってますね。もぐら叩きになりがちなDoS攻撃対応ですが、IPアドレスでのブロックだけなら、AWS WAFに実装された [rate-based limit] を使って割とお手軽に対応が出来そうです。
という事で、ちょっと試してみました。
今回の環境
こんな感じで簡単に構築。
EC2はそれぞれBaseAMIから作成。
攻撃は単純にApacheBenchで代用してみます。
ですので、攻撃元・攻撃先それぞれにapacheを入れておきます。
攻撃先には上流にALBを設定しておきます。
ALBでないとAWS WAFを活用出来ないので、ここは必須です。
CloudFrontを被せる手もありますが、今回はお手軽にこっち。
AWS WAF を設定する
- まずruleを作ります
AWS WAF & Shield のダッシュボードから、[Rules] > [Create rule]
できました。
閾値(Rate limit)は、一旦最低値の2,000にしておきます。
この値は、5min間にこの値のリクエストが来た場合、自動でブロックしてくれます。
※逆に言うとこの閾値以下は全部許可
- 次にweb ACLを作ります
AWS WAF & Shield のダッシュボードから、[Web ACLs] > [Create web ACL]
画面に従ってリソース指定していきます。
できました。
- 作成したweb ACLに、作成したruleを紐づけます
作成した web ACL を指定して Edit
ルールにマッチしたときに、リクエストをブロックします。
※何もマッチしない時は全リクエスト許可です
できました。
- 通知用CloudWatchアラームを作ります
AWS WAFの設定が済むと、メトリクスが見つかるはずです。
ただこのままでは攻撃を受けている時にしか通知が来ないので、攻撃予兆を見られるように準備しておきます。さっきまでの手順と同じように、rate-basedのruleを作っておきます。
同じく web ACL に紐づけますが、今度は Action を Count として、Blockより上位のOrderに設定します。
できました。
これをベースに、CloudWatchアラームを設定します。
今回は一回でも引っかかったらアラートメールが飛ぶようにしておきます。
できました。
ちなみに、欠落データの処理方法は、初期値の[見つかりません(missing)]のままだと、攻撃を検知していない間ずっと「データ不足」になってしまって気持ち悪いので、[適正(good)]にしておきます。
攻撃してみる
準備が整ったので、実際にどんな感じになるか試してみます。
シナリオとしては、攻撃元からApacheBenchで3,000リクエストを投げて、EC2からはアクセスが出来なくなり、
オフィスからのアクセスは何もない、という事を確認します。
- 攻撃前の、攻撃元EC2ホストのログ
[root@ip-192-169-20-183 ~]# curl http://alb-nm-test-003.ap-northeast-1.elb.amazonaws.com/ <title>Test Page for the Apache HTTP Server on Amazon Linux AMI</title> /*.content-column-left, .content-columns>.content-column-right { /* Non-IE/Win */ } img { border: 2px solid #fff; padding: 2px; margin: 2px; } a:hover img { border: 2px solid #f50; } /*]]>*/ <h1>Amazon Linux AMI <strong>Test Page</strong></h1> <div class="content"> <div class="content-middle"> <p>This page is used to test the proper operation of the Apache HTTP server after it has been installed. If you can read this page, it means that the Apache HTTP server installed at this site is working properly.</p> </div> <hr /> <div class="content-columns"> <div class="content-column-left"> <h2>If you are a member of the general public:</h2> <p>The fact that you are seeing this page indicates that the website you just visited is either experiencing problems, or is undergoing routine maintenance.</p> <p>If you would like to let the administrators of this website know that you've seen this page instead of the page you expected, you should send them e-mail. In general, mail sent to the name "webmaster" and directed to the website's domain should reach the appropriate person.</p> <p>For example, if you experienced problems while visiting www.example.com, you should send e-mail to "webmaster@example.com".</p> <p>For information on Amazon Linux AMI , please visit the <a href="http://aws.amazon.com/">Amazon AWS website</a>.</p> <hr /> </div> <div class="content-column-right"> <h2>If you are the website administrator:</h2> <p>You may now add content to the directory <tt>/var/www/html/</tt>. Note that until you do so, people visiting your website will see this page, and not your content. To prevent this page from ever being used, follow the instructions in the file <tt>/etc/httpd/conf.d/welcome.conf</tt>.</p> <p>You are free to use the image below on web sites powered by the Apache HTTP Server:</p> <p align="center"><a href="http://httpd.apache.org/"><img src="/icons/apache_pb2.gif" alt="[ Powered by Apache ]" /></a></p> </div> </div> </div> [root@ip-192-169-20-183 ~]# |
Let’s Attack!!
[root@ip-192-169-20-183 ~]# ab -n 3000 -c 1 http://alb-nm-test-003.ap-northeast-1.elb.amazonaws.com/ This is ApacheBench, Version 2.3 Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking alb-nm-test-003.ap-northeast-1.elb.amazonaws.com (be patient) Completed 300 requests Completed 600 requests Completed 900 requests Completed 1200 requests Completed 1500 requests Completed 1800 requests Completed 2100 requests Completed 2400 requests Completed 2700 requests Completed 3000 requests Finished 3000 requests Server Software: Apache/2.2.34 Server Hostname: alb-nm-test-003.ap-northeast-1.elb.amazonaws.com Server Port: 80 Document Path: / Document Length: 3839 bytes Concurrency Level: 1 Time taken for tests: 21.649 seconds Complete requests: 3000 Failed requests: 0 Write errors: 0 Non-2xx responses: 3000 Total transferred: 12111000 bytes HTML transferred: 11517000 bytes Requests per second: 138.57 [#/sec] (mean) Time per request: 7.216 [ms] (mean) Time per request: 7.216 [ms] (mean, across all concurrent requests) Transfer rate: 546.31 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 0.1 0 2 Processing: 6 7 0.3 7 12 Waiting: 6 7 0.3 7 12 Total: 7 7 0.3 7 13 Percentage of the requests served within a certain time (ms) 50% 7 66% 7 75% 7 80% 7 90% 7 95% 8 98% 8 99% 8 100% 13 (longest request) |
攻撃された方は……と
tail -f /var/log/httpd/access_log 100.100.10.10 192.169.20.10 - - [13/Nov/2017:21:16:48 +0900] "GET / HTTP/1.1" 403 3839 "-" "ApacheBench/2.3" 100.100.10.10 192.169.20.10 - - [13/Nov/2017:21:16:48 +0900] "GET / HTTP/1.1" 403 3839 "-" "ApacheBench/2.3" 100.100.10.10 192.169.20.10 - - [13/Nov/2017:21:16:48 +0900] "GET / HTTP/1.1" 403 3839 "-" "ApacheBench/2.3" 100.100.10.10 192.169.20.10 - - [13/Nov/2017:21:16:48 +0900] "GET / HTTP/1.1" 403 3839 "-" "ApacheBench/2.3" 100.100.10.10 192.169.20.10 - - [13/Nov/2017:21:16:48 +0900] "GET / HTTP/1.1" 403 3839 "-" "ApacheBench/2.3" 100.100.10.10 192.169.20.10 - - [13/Nov/2017:21:16:48 +0900] "GET / HTTP/1.1" 403 3839 "-" "ApacheBench/2.3" 100.100.10.10 192.169.20.10 - - [13/Nov/2017:21:16:48 +0900] "GET / HTTP/1.1" 403 3839 "-" "ApacheBench/2.3" 100.100.10.10 192.169.20.10 - - [13/Nov/2017:21:16:48 +0900] "GET / HTTP/1.1" 403 3839 "-" "ApacheBench/2.3" 100.100.10.10 192.169.20.10 - - [13/Nov/2017:21:16:48 +0900] "GET / HTTP/1.1" 403 3839 "-" "ApacheBench/2.3" 100.100.10.10 192.169.20.10 - - [13/Nov/2017:21:16:48 +0900] "GET / HTTP/1.1" 403 3839 "-" "ApacheBench/2.3" 100.100.10.10 192.169.20.10 - - [13/Nov/2017:21:16:48 +0900] "GET / HTTP/1.1" 403 3839 "-" "ApacheBench/2.3" 100.100.10.10 192.169.20.10 - - [13/Nov/2017:21:16:48 +0900] "GET / HTTP/1.1" 403 3839 "-" "ApacheBench/2.3" 100.100.10.10 192.169.20.10 - - [13/Nov/2017:21:16:48 +0900] "GET / HTTP/1.1" 403 3839 "-" "ApacheBench/2.3" 100.100.10.10 192.169.20.10 - - [13/Nov/2017:21:16:48 +0900] "GET / HTTP/1.1" 403 3839 "-" "ApacheBench/2.3" 100.100.10.10 192.169.20.10 - - [13/Nov/2017:21:16:48 +0900] "GET / HTTP/1.1" 403 3839 "-" "ApacheBench/2.3" 100.100.10.10 192.169.20.10 - - [13/Nov/2017:21:16:48 +0900] "GET / HTTP/1.1" 403 3839 "-" "ApacheBench/2.3" 100.100.10.10 192.169.20.10 - - [13/Nov/2017:21:16:48 +0900] "GET / HTTP/1.1" 403 3839 "-" "ApacheBench/2.3" 100.100.10.10 192.169.20.10 - - [13/Nov/2017:21:16:48 +0900] "GET / HTTP/1.1" 403 3839 "-" "ApacheBench/2.3" 100.100.10.10 192.169.20.10 - - [13/Nov/2017:21:16:48 +0900] "GET / HTTP/1.1" 403 3839 "-" "ApacheBench/2.3" 100.100.10.10 192.169.20.10 - - [13/Nov/2017:21:16:48 +0900] "GET / HTTP/1.1" 403 3839 "-" "ApacheBench/2.3" (以下略) |
するとものの数分で……。
攻撃元からは
2017年 11月 13日 月曜日 21:18:01 JST [root@ip-192-169-20-183 ~]# curl http://alb-nm-test-003.ap-northeast-1.elb.amazonaws.com/ && date <title>403 Forbidden</title> <h1>403 Forbidden</h1> 2017年 11月 13日 月曜日 21:18:33 JST [root@ip-192-169-20-183 ~]# curl http://alb-nm-test-003.ap-northeast-1.elb.amazonaws.com/ && date <title>403 Forbidden</title> <h1>403 Forbidden</h1> 2017年 11月 13日 月曜日 21:18:42 JST [root@ip-192.169.20-183 ~]# curl http://alb-nm-test-003.ap-northeast-1.elb.amazonaws.com/ && date <title>403 Forbidden</title> <h1>403 Forbidden</h1> 2017年 11月 13日 月曜日 21:18:46 JST |
403返されてますね。
一方そのころ攻撃された側のアクセスログは……。
192.169.20.67 - - [13/Nov/2017:21:17:52 +0900] "GET / HTTP/1.1" 403 3839 "-" "ELB-HealthChecker/2.0" - 192.169.10.235 - - [13/Nov/2017:21:17:59 +0900] "GET / HTTP/1.1" 403 3839 "-" "ELB-HealthChecker/2.0" - 192.169.20.10 - - [13/Nov/2017:21:18:06 +0900] "GET / HTTP/1.1" 403 3839 "-" "ELB-HealthChecker/2.0" - 192.169.10.242 - - [13/Nov/2017:21:18:13 +0900] "GET / HTTP/1.1" 403 3839 "-" "ELB-HealthChecker/2.0" - 192.169.20.67 - - [13/Nov/2017:21:18:22 +0900] "GET / HTTP/1.1" 403 3839 "-" "ELB-HealthChecker/2.0" 192.168.1.1 192.169.10.242 - - [13/Nov/2017:21:18:22 +0900] "GET / HTTP/1.1" 403 3839 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0" 192.168.1.1 192.169.10.242 - - [13/Nov/2017:21:18:22 +0900] "GET /icons/apache_pb2.gif HTTP/1.1" 304 - "http://alb-nm-test-003-963952958.ap-northeast-1.elb.amazonaws.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0" - 192.169.10.235 - - [13/Nov/2017:21:18:29 +0900] "GET / HTTP/1.1" 403 3839 "-" "ELB-HealthChecker/2.0" 192.168.1.1 192.169.10.242 - - [13/Nov/2017:21:18:30 +0900] "GET / HTTP/1.1" 403 3839 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0" 192.168.1.1 192.169.10.242 - - [13/Nov/2017:21:18:30 +0900] "GET /icons/apache_pb2.gif HTTP/1.1" 304 - "http://alb-nm-test-003-963952958.ap-northeast-1.elb.amazonaws.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0" 192.168.1.1 192.169.10.242 - - [13/Nov/2017:21:18:35 +0900] "GET / HTTP/1.1" 403 3839 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0" 192.168.1.1 192.169.10.242 - - [13/Nov/2017:21:18:35 +0900] "GET /icons/apache_pb2.gif HTTP/1.1" 304 - "http://alb-nm-test-003-963952958.ap-northeast-1.elb.amazonaws.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0" |
オフィスからはアクセス出来ましたが、攻撃元からは403に見えているタイミングではアクセスが来ていません。
AWS WAF側で見ても、ブロック対象になっているのが確認出来ます。
仕込んでいたCloudWatchアラームも飛んでくれました。
まとめ
DDoS攻撃と違って、攻撃元IPアドレスがコロコロ変わるDoS攻撃の場合、都度都度対応が必要になってしまうため、対応工数がどうしても跳ね上ってしまいます。
今回検証したAWS WAFの rate-based limit を使うと、このタイプの攻撃に関しては自動で防いでくれます。
閾値の設定はちょっと悩むところではありますが、快適なホスト運用ライフのために検討頂ければ。
注意
今回リクエスト数が多いテストを行いましたが、AWS環境へ負荷をかける場合はちゃんと一報入れてからやりましょう。
この記事を書いた人
-
ネットワークとセキュリティメインでやっています。
L4/L3以下が好きです。
最近書いた記事
- 2021.12.03えを描こう
- 2018.03.22AWS Certificate Manager (ACM) がCT対応するぞ!
- 2018.01.29【AWSロードバランサー】CLBからALBに移行したくなる機能が追加された件
- 2018.01.15AWS WAFにマネージドルールが!