目次

目次

AWS WAFを使って簡単にDoS攻撃を防いでみよう【セキュリティ対策】

アバター画像
野村昌男
アバター画像
野村昌男
最終更新日2025/12/25 投稿日2017/12/04

AWS WAFで簡単にDoS攻撃を防いでみよう

DoS攻撃流行ってますね。もぐら叩きになりがちなDoS攻撃対応ですが、IPアドレスでのブロックだけなら、AWS WAFに実装された [rate-based limit] を使って割とお手軽に対応が出来そうです。

という事で、ちょっと試してみました。

今回の環境

こんな感じで簡単に構築。

AWS WAF環境例

EC2はそれぞれBaseAMIから作成。 攻撃は単純にApacheBenchで代用してみます。 ですので、攻撃元・攻撃先それぞれにapacheを入れておきます。

攻撃先には上流にALBを設定しておきます。 ALBでないとAWS WAFを活用出来ないので、ここは必須です。 CloudFrontを被せる手もありますが、今回はお手軽にこっち。

AWS WAF を設定する

  • まずruleを作ります  AWS WAF & Shield のダッシュボードから、[Rules] > [Create rule]  
    AWS WAF ルール作成

できました。

AWS WAF ルール作成完了

閾値(Rate limit)は、一旦最低値の2,000にしておきます。 この値は、5min間にこの値のリクエストが来た場合、自動でブロックしてくれます。 ※逆に言うとこの閾値以下は全部許可

  • 次にweb ACLを作ります  AWS WAF & Shield のダッシュボードから、[Web ACLs] > [Create web ACL]
AWS WAF ACL設定

画面に従ってリソース指定していきます。

AWS WAF ACL設定完了

できました。

  • 作成したweb ACLに、作成したruleを紐づけます  作成した web ACL を指定して Edit
AWS WAF ルール紐づけ

ルールにマッチしたときに、リクエストをブロックします。 ※何もマッチしない時は全リクエスト許可です

AWS WAF 紐づけ完了

できました。

  • 通知用CloudWatchアラームを作ります AWS WAFの設定が済むと、メトリクスが見つかるはずです。 ただこのままでは攻撃を受けている時にしか通知が来ないので、攻撃予兆を見られるように準備しておきます。 さっきまでの手順と同じように、rate-basedのruleを作っておきます。
AWS WAF Cloudwatchルール

同じく web ACL に紐づけますが、今度は Action を Count として、Blockより上位のOrderに設定します。

AWS WAF Cloudwatchルール設定
AWS WAF Cloudwatch設定完了

できました。

これをベースに、CloudWatchアラームを設定します。 今回は一回でも引っかかったらアラートメールが飛ぶようにしておきます。

AWS WAF アラーム設定

できました。

ちなみに、欠落データの処理方法は、初期値の[見つかりません(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&gt;.content-column-right {
                                /* Non-IE/Win */
                        }
                        img {
                                border: 2px solid #fff;
                                padding: 2px;
                                margin: 2px;
                        }
                        a:hover img {
                                border: 2px solid #f50;
                        }
                        /*]]&gt;*/

                <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/ &amp;&amp; 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/ &amp;&amp; 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/ &amp;&amp; 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側で見ても、ブロック対象になっているのが確認出来ます。

AWS WAF block状況

仕込んでいたCloudWatchアラームも飛んでくれました。

AWS WAF cloudwatch状況

まとめ

DDoS攻撃と違って、攻撃元IPアドレスがコロコロ変わるDoS攻撃の場合、都度都度対応が必要になってしまうため、対応工数がどうしても跳ね上ってしまいます。 今回検証したAWS WAFの rate-based limit を使うと、このタイプの攻撃に関しては自動で防いでくれます。

閾値の設定はちょっと悩むところではありますが、快適なホスト運用ライフのために検討頂ければ。

注意

今回リクエスト数が多いテストを行いましたが、AWS環境へ負荷をかける場合はちゃんと一報入れてからやりましょう。

アバター画像

野村昌男

インフラとセキュリティメインでやっています。
L4/L3以下が好きです。

目次