[AWS] CloudFrontからのリクエスト以外をオリジンで拒否する

  • このエントリーをはてなブックマークに追加
  • LINEで送る

このブログはCloudFrontからLightsailで作成したオリジンを参照する構成になっているのですが、最近オリジンに直接リクエストが来ることが増えました。間違えてオリジンのURLを返している可能性もあったのでログを解析してたのですが、大方の予想通りセキュリティホールを探っている物ばかりでした。

めちゃめちゃ気持ち悪い(´・ω・`) オリジンへのリクエストはCloudFrontからしか来ないと割り切って、80/443番へ直接来るリクエストはすべて拒否することにしました。

ここではApacheの設定を掲載しますが、同様の手法でnginxなど他のWebサーバーでも利用できると思います。

- Sponsored Link -

原理

動作原理は非常にシンプルです。

CloudFrontからオリジンへリクエストを投げる際に、秘密の独自HTTPヘッダーを付与します。オリジン側ではこの独自HTTPヘッダーが付いていればCloudFrontからのリクエストと判断。もし付いていなければ403を返して拒否します。

CloudFrontでは「Origin Custom Headers」という設定項目で自由にヘッダーを付けることができるのでこれを利用します。

CloudFront側の設定

Origin Custom Headersには今回X-Cdn-Secretという独自のHTTPヘッダーを追加し、値にはランダムな文字列を16桁指定しました。ヘッダー名も値も推測されにくければ何でもかまいません。これで設定を反映したらステータスがDeployedになるまで待ちます。

ちなみに独自ヘッダーの先頭にX-を付けるやり方は10年ほど前までは頻繁に利用されていましたが、最近では推奨されないようです。

独自のヘッダーは、以前は X- 接頭辞を使用していましたが、この慣習は 2012 年 6 月に非推奨になりました。これは、 RFC 6648 で非標準のフィールドが標準になったときに発生した不便さのためです。
※MDN – HTTPヘッダーより

……ですが、私が勝手に命名したこのフィールドが標準仕様になることは考えにくいのでこのまま行きます。

オリジン側の設定

運用中のサーバの場合、いきなりオリジン側で拒否するのではなくCloudFrontから値が渡ってきているか検証してから拒否する設定を入れます。

Webサーバのログに出力

httpd.confを開きLogFormatを新たに追加します。ここではcombined2という名前で定義しました。安直w

$ sudo vi /etc/httpd/conf/httpd.conf
<IfModule log_config_module>
  # 中略
  LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" \"%{X-Cdn-Secret}i\"" combined2

今回はVirtualHostで管理していたサーバでしたので、CustomLogに先ほど新規に追加したLogFormatを指定します。

$ sudo vi /etc/httpd/conf.d/vhost.conf
<VirtualHost *:80>
  ServerName   origin.example.com
  CustomLog    logs/origin.example.com-access_log combined2

あとはApacheを再起動などして設定を反映します。

$ sudo systemctl restart httpd

しばらくしてApacheのログを確認し、CloudFrontからトークンが渡ってきていれば次のステップへ進みます。

$ sudo grep 'BIIklPy5qQmgE7ol' /var/log/httpd/origin.example.com-access_log
64.252.110.127 - - [04/Nov/2020:18:17:21 +0900] "GET / HTTP/1.1" 200 113612 "-" "Amazon CloudFront" "BIIklPy5qQmgE7ol"

Webサーバで拒否設定

拒否設定は非常に簡単で、以下の例で言う10〜13行目がそれにあたります。

<VirtualHost *:80>
  ServerName   origin.example.com
  DocumentRoot /web/public
  CustomLog    logs/origin.example.com-access_log combined2
  ErrorLog     logs/origin.example.com-error_log
  <Directory /web/public>
    Require all granted
    AllowOverride All

    SetEnvIf X-Cdn-Secret "^BIIklPy5qQmgE7ol" CDNValid
    Order deny,allow
    Deny from all
    Allow from env=CDNValid
  </Directory>
</VirtualHost>

あとは再起動などして設定を反映します。

$ sudo systemctl restart httpd

効果検証

半日〜1日程度経過したら、アクセスログからトークンが含まれていないログを抽出し、403で正常に拒否できているか確認してみます。

$ sudo grep -v 'BIIklPy5qQmgE7ol' /var/log/httpd/origin.example.com-access_log
159.203.128.47 - - [04/Nov/2020:14:05:28 +0900] "GET / HTTP/1.0" 403 4890 "-" "masscan/1.0 (https://github.com/robertdavidgraham/masscan)" "-"
114.222.156.160 - - [04/Nov/2020:15:03:42 +0900] "GET /phpmyadmin/ HTTP/1.1" 403 199 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, li

バッチリですね👍

コメント

感想やご質問などお気軽にどうぞ。広告が表示されている場合は下にスクロールしてください。投稿にはSNSへのログインが必要です。

このブログを応援する

お寄せいただいたお気持ちは全額サーバ代や次の記事を執筆するための原資として活用させていただいております。この記事が参考になった場合などぜひご検討ください。

PayPal(ペイパル)
PayPalで300円支払う
※金額は任意で変更できます。
※100円でも泣いて喜びますw
※住所の入力欄が現れた場合は「no needed」を選択ください
これまでのご協力者さま
- Sponsored Link -