[Apache] 非VPCのELBでX-Forwarded-Forを利用したアクセス制限
はじめに
こんにちは植木和樹です。本日は過去にこのサイトでも取り上げられている内容を組み合わせ、Apacheのアクセス制限設定しました。
解決したい問題
非VPC環境で、ELB配下のWebサーバがインターネットからのDoS攻撃にさらされた場合に、特定のIPアドレスからのアクセスを拒否(403)します。
VPC環境であればNetworkACLやSecurityGroupで制限をかけることができますが、非VPCではELBへのアクセスを制限することができません。この場合httpdレベルで制限する必要があります。
参考にした記事
解決方法
ELBにアクセスしてくる端末のIPアドレスはX-Forwarded-Forリクエストヘッダーに格納されています。X-Forwarded-Forが特定のIPアドレスの場合にアクセスを拒否(DENY)します。なおhttpdサーバにはApache httpd(2.2)を使用しています。
AmazonLinux(というか一般的にrpmでインストールしたapache)の場合、DocumentRootが /var/www/html になっていますので、Directoryコンテキストでアクセス制限の設定を行います。下記に設定例を示します。非VPCなのでELBを介さず直接PublicDNSへアクセスされることも想定しています。
Order alllow,denyは、まずすべてのアクセスを許可(Allow from all)してから、条件に該当するアクセスは拒否する(Deny from env=deny_ip)という動きになります。当初「DENYして、残りはALLOW」のつもりでOrder deny,allowしたら、うまくいかずにハマりました。【参考】Apache モジュール mod_authz_host
httpd.conf
$ sudo vi /etc/httpd/conf/httpd.conf
<Directory "/var/www/html"> Options Indexes FollowSymLinks AllowOverride None SetEnvIf X-Forwarded-For "11\.22\.33\.44" deny_ip SetEnvIf REMOTE_ADDR "11\.22\.33\.44" deny_ip Order allow,deny Allow from all Deny from env=deny_ip </Directory>
設定したら設定ファイルを再読み込みします。
$ sudo service httpd reload
DENYしたログは出力しない
URLに非常に長い文字列を指定してGETされた場合、大量のアクセスログに記録されてしまいます。アクセスを拒否したIPアドレスについては、ログ出力も止めてしまいましょう。
SetEnvIf X-Forwarded-For "11\.22\.33\.44" nolog SetEnvIf REMOTE_ADDR "11\.22\.33\.44" nolog CustomLog logs/access_log combined env=!nolog
結論
本来は環境をVPCに移行してNetworkACL等で制限するのが良いのでしょうが、いろいろな事情でVPCへ移行できないサーバもあります。Apacheを使っているのであれば数行設定を追加して、設定を再読み込みするだけでサービスを止めずに対応することが可能です。