ALBとEC2間をHTTPS通信させてApacheのアクセスログから接続元のクライアントIPを取得する
こんにちは、岩城です。
ALBとEC2間をHTTPS通信させるかどうかの議論は置いておき、下図のような環境でEC2上のApacheのアクセスログから接続元のクライアントIPを取得する機会がありましたので紹介します。
やってみた
/etc/httpd/conf.d/ssl.conf
に以下のようなX-Forwarded-For
を含めたLogFormatを追記します。
LogFormat "%{X-Forwarded-For}i %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\""
Apacheが停止している場合は起動します。
systemctl start httpd.service
既にApacheが起動している場合は設定ファイルを再読み込みします。
systemctl reload httpd.service
/var/log/httpd/ssl_access_log
に記録されたアクセスログを確認します。
sudo tail -f /var/log/httpd/ssl_access_log - 172.31.47.129 - - [23/Jun/2021:05:47:17 +0000] "GET / HTTP/1.1" 200 34 "-" "ELB-HealthChecker/2.0" - 172.31.40.253 - - [23/Jun/2021:05:47:19 +0000] "GET / HTTP/1.1" 200 34 "-" "ELB-HealthChecker/2.0" - 172.31.22.6 - - [23/Jun/2021:05:47:21 +0000] "GET / HTTP/1.1" 200 34 "-" "ELB-HealthChecker/2.0" 219.xxx.xxx.xxx 172.31.40.253 - - [23/Jun/2021:05:47:41 +0000] "GET / HTTP/1.1" 304 - "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.106 Safari/537.36"
最終行のログを見てください。172.31.xxx.xxx
はALBのIPであり、219.xxx.xxx.xxx
はクライアントIPです。
クライアントがALBを経由してEC2に到達したことを示すログですが、LogFormatにX-Forwarded-For
を含めることでクライアントIPを記録できたことを示しています。
これだけでは寂しいので検証環境の構築方法を以下に記載します。
検証環境の構築
前提
- VPC、サブネット、インターネットゲートウェイ、ルートテーブルなど、ネットワークリソースが作成されていること
- WebサーバーとなるEC2インスタンスがAmazon Linux2で作成されていること
無料ドメインの取得
Freenomで無料ドメインを取得します。サインインが必要なのでユーザー登録してください。本エントリではiwaki.tk
ドメインを取得できるかチェックし、問題なければ取得手続きを進めます。
Use DNS
は後で設定するため、この時点では設定不要です。また、ドメインの有効期限はデフォルトの3ヶ月としています。12ヶ月までは無料なので必要に応じて変更してください。
無料で取得できることを確認した上でドメインを取得します。
取得したドメインはMy Domains
ページで確認できます。後でこのページからNameserverを設定します。
取得したドメインをRoute53に委任する
Route53のホストゾーンを作成します。
ドメイン名はFreenomで取得したドメインを指定します。後はデフォルトのままで構いません。
ホストゾーンが作成されるとNSレコードが登録されます。このNSレコードをFreenomに設定するので控えておきます。
先程のFreenomのコンソールに戻り、Manage Domain
>Management Tools
>Namesevers
を選択します。
控えておいたNSレコードをすべてコピペします。
ACMでSSL証明書を発行する
クライアントとALB間の通信をHTTPS化するには、ALBにSSL/TLS証明書をアタッチする必要があり、本エントリではACMで発行したSSL/TLS証明書を利用します。
パブリック証明書のリクエスト
のまま、証明書をリクエストします
SSL/TLS証明書で保護するドメイン名を指定します。*.iwaki.tk
のようにワイルドカード証明書をリクエストします。
証明書リクエストの検証方法を選択します。今回はDNSの検証
を選択します。
リクエストすると検証保留中
のステータスになるので、コンソールに表示されているままCNAMEレコードをRoute53に作成します。
作成されると検証が済むのでステータスが発行済み
となれば完了です。
EC2のセットアップ
EC2に接続してApacheに関する設定を行います。
mod_ssl
をインストールすると、Apacheもインストールされ、自己証明書も自動的に作成されます(参照元)。
sudo yum install mod_ssl -y
ALBからのヘルスチェック先となるIndex.htmlを作成します。
sudo vi /var/www/html/index.html <HTML> テスト </HTML>
EC2でSSL終端しても、アクセスログにクライアントIPが記録されるようにssl.conf
にLogFormat
を追記します。
sudo vim /etc/httpd/conf.d/ssl.conf LogFormat "%{X-Forwarded-For}i %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\""
Apacheに設定ファイルを再読み込みさせるか、停止していれば起動します。
sudo systemctl reload httpd.service sudo systemctl start httpd.service
ALBを作成する
ALBを作成します。リスナーのプロトコルでHTTPS
を選択します。
証明書タイプはACMから証明書を選択する
、証明書の名前は先程発行した証明書を選択します。ちなみに、HTTPSリスナーを設定する場合、事前に証明書を用意しておく必要があるので注意してください。
セキュリティグループの設定では、インバウンドルールにHTTPSからの通信を許可するルールを追加します。
ルーティングの設定では、ターゲットグループとヘルスチェックのプロトコルをHTTPS
にします。
ターゲットの登録では、EC2を選択して登録済みに追加
します。
ALBが作成できましたら、最後にEC2のセキュリティグループを変更します。インバウンドルールにALBにアタッチしたセキュリティグループからのHTTPSを許可するルールを追加しておきます。
ALBのエイリアスレコードをRoute53に追加する
ALBのエイリアスレコードをRoute53に追加し、https://alb.iwaki.tk
でアクセスできるようにします。作成したホステッドゾーンからレコードを作成
します。
レコード名にalb
を指定、エイリアス
をクリックし、東京リージョンにあるALBを選択し完了です。
dig
コマンドでANSWER SECTION
の問合せ結果が返ってくることを確認しておきます。
[ec2-user@ip-172-31-47-123 ~]$ dig alb.iwaki.tk ; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.amzn2.5 <<>> alb.iwaki.tk ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 47733 ;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;alb.iwaki.tk. IN A ;; ANSWER SECTION: alb.iwaki.tk. 42 IN A 54.64.218.182 alb.iwaki.tk. 42 IN A 54.199.12.24 ;; Query time: 0 msec ;; SERVER: 172.31.0.2#53(172.31.0.2) ;; WHEN: 水 6月 30 06:38:05 UTC 2021 ;; MSG SIZE rcvd: 73
検証
ブラウザからhttps://alb.iwaki.tk
にアクセスして、Index.htmlの内容が表示されることを確認します。
クライアント->ALB->EC2間をすべてHTTPS化させても、ApacheのアクセスログにクライアントIPが記録されることを確認できました。
sudo tail -f /var/log/httpd/ssl_access_log - 172.31.47.129 - - [23/Jun/2021:05:47:17 +0000] "GET / HTTP/1.1" 200 34 "-" "ELB-HealthChecker/2.0" - 172.31.40.253 - - [23/Jun/2021:05:47:19 +0000] "GET / HTTP/1.1" 200 34 "-" "ELB-HealthChecker/2.0" - 172.31.22.6 - - [23/Jun/2021:05:47:21 +0000] "GET / HTTP/1.1" 200 34 "-" "ELB-HealthChecker/2.0" 219.xxx.xxx.xxx 172.31.40.253 - - [23/Jun/2021:05:47:41 +0000] "GET / HTTP/1.1" 304 - "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.106 Safari/537.36"
おわりに
これまでALBまでHTTPS化させ、ALB以降はHTTPとする構成しか構築したことがなかったので試してみました。 Apacheのデフォルト設定では設定ファイルやアクセスログが異なることを知りました。 異なる点は以下のとおりです。
- Apacheの設定は
httpd.conf
ではなくssl.conf
- アクセスログは
access_log
ではなくssl_access_log
本エントリがどなたかのお役に立てれば幸いです。