SquidのSSL Bump機能を使いHTTPS通信のリクエストヘッダーをログに出力してみる

# 目的
プロキシサーバを利用して、HTTPS 通信時のリクエストヘッダーに特定の項目を追加する方法を調査しました。​その結果、Squid の「SSL Bump」機能を使用することで実現可能であることがわかりました。​この機能を実践してみたいと思います。​

ただし、SSL Bump の仕組み上、プロキシサーバはクライアントと Web サーバ間の通信内容を復号化して確認するため、プロキシサーバに対する通信の秘匿性は失われる点に注意が必要です。

当初は、プロキシサーバでリクエストヘッダーを追加する方法について実践する予定でしたが、記載内容が多くなったため、別の記事としてまとめることにしました。

# SSL Bump有無によるHTTPS通信接続の違いについて
SSL Bump を使用する場合と使用しない場合で、HTTPS 通信の構成に以下のような違いがあります。

```less:SSL Bump 未使用の場合
[ クライアント ]
      |
      | HTTPS通信
      v
[ プロキシサーバ (Squid without SSL Bump) ]
      |
      | HTTPS通信
      v
[ Webサーバ ]
```

- クライアントと Web サーバ間で直接 HTTPS 通信が行われます。​
- プロキシサーバは通信内容を復号化できないため、リクエストやレスポンスのヘッダー情報を確認・変更することはできません。​

```less:SSL Bump 使用の場合
[ クライアント ]
      |
      | HTTPS通信1
      v
[ プロキシサーバ (Squid with SSL Bump) ]
      |
      | HTTPS通信2
      v
[ Webサーバ ]
```

- プロキシサーバがクライアントと Web サーバの間に介在し、それぞれと個別に HTTPS 通信を確立します。​
- プロキシサーバは通信内容を復号化できるため、リクエストやレスポンスのヘッダー情報を確認・変更することが可能です。​

このように、SSL Bump を使用することで、HTTPS 通信の内容をプロキシサーバで確認・操作することが可能になります。ただし、通信の秘匿性が失われるため、使用する際は慎重に検討する必要があります。​

# 実験環境
|構成要素|備考|
|-------|---|
|OS|CentOS Steram 9|
|SELinux|Dsiabled|
|squid|IP 192.168.11.551,ポート 31281|

# Squid access_log へのリクエストヘッダー出力
デフォルトでインストールされた Squid の access_log フォーマットでは、HTTP ヘッダー情報がログに出力されません。​そのため、特定のヘッダー（例：TEST ヘッダー）をログに記録するには、squid.conf にカスタムのログフォーマットを定義する必要があります。

以下は、TEST ヘッダーを含むカスタムログフォーマットの例です。
```:/etc/squid/squid.conf
# 参照および操作するヘッダー変数TESTが出力されるように定義変更
logformat custom_with_headers %ts.%03tu %6tr %>a %rm %ru %>Hs %<st %{TEST}>h

access_log /var/log/squid/access_with_headers.log custom_with_headers
```
この設定により、TEST ヘッダーの値がアクセスログに出力されるようになります。​設定を反映させるために、Squid サービスを再起動してください。

# SSL Bump有効化前のアクセスログ
squidをSSL Dump化する前のログ出力を確認する。

```bash
# クライアント側(例：IP 192.168.11.54)
$ export HTTPS_PROXY=http://192.168.11.55:3128
$ curl -H "TEST: TEST_HTTP" http://example.com
$ curl -H "TEST: TEST_HTTPS" https://example.com

# サーバ側(例：IP 192.168.11.55)
$ tail -f /var/log/squid/access_with_headers.log
1744514982.911      0 192.168.11.54 GET http://example.com/ 200 1630 TEST_HTTP
1744515005.304    358 192.168.11.54 CONNECT example.com:443 200 4896 -
```

ログの出力結果から、現在の構成や設定では、HTTPS 通信のヘッダー情報をプロキシサーバで確認できないことがわかります。​これは、HTTPS 通信が暗号化されており、プロキシサーバが通信内容を復号できないためです。​

実際に、HTTP と HTTPS のリクエストで動作を確認してみます。​HTTP リクエストでは、リクエストヘッダーに指定した TEST 変数の値がログに出力されます。​一方、HTTPS リクエストでは、同じ TEST 変数を指定しても、ログには出力されません。​これは、HTTPS 通信が暗号化されており、プロキシサーバが通信内容を確認できないためです。​

このように、HTTPS 通信ではプロキシサーバが通信内容を確認できないため、通信内容の検査や制御が困難です。​そこで、次に Squid に SSL Bump 機能を追加し、HTTPS 通信の内容を確認できるように設定を行います。

# SquidへのSSL Bump機能追加

## サーバ証明書の作成

クライアントとプロキシサーバ間でHTTPS通信接続するために必要なサーバ証明書を作成していきます。

```bash
$ cd /etc/squid/
$ sudo mkdir ssl_cert
$ sudo openssl genrsa -out myCA.key 4096
$ sudo openssl req -new -x509 -days 3650 -key myCA.key -out myCA.pem -subj "/C=JP/ST=Tokyo/L=Chuo/O=MyOrg/OU=Dev/CN=MySquidCA"
$ sudo openssl x509 -in myCA.pem -outform DER -out myCA.der
```

## SquidへのSSL Bump有効化機能追加
```bash:/etc/squid/squid.conf
$ sudo vi /etc/squid/squid.conf
# Squid normally listens to port 3128
#http_port 3128
http_port 3128 ssl-bump \
    cert=/etc/squid/ssl_cert/myCA.pem \
    key=/etc/squid/ssl_cert/myCA.key \
    generate-host-certificates=on dynamic_cert_mem_cache_size=4MB

acl step1 at_step SslBump1
ssl_bump peek step1
ssl_bump bump all
```

Squid は、特別な設定を行わなくても動作しますが、証明書が保存されているディレクトリに対して最低限のアクセス制御を設定することが推奨されます。​これにより、証明書ファイルのセキュリティを強化し、不正なアクセスから保護することができます。​

たとえば、証明書ファイルが /etc/squid/ ディレクトリに保存されている場合、以下のコマンドを実行して適切なアクセス権を設定します。
```bash
$ sudo chown -R squid:squid /etc/squid/ssl_cert
$ sudo chmod 700 /etc/squid/ssl_cert
# $ sudo setsebool -P squid_connect_any 1
$ sudo systemctl restart squid
```
この設定により、squid ユーザーのみが証明書ファイルにアクセスできるようになります。セキュリティ上のベストプラクティスとして、証明書ファイルのアクセス権を適切に設定することをお勧めします。​

# 定義修正後のSquid起動時エラー
定義修正後、squidを起動してみましたがエラーが発生していました。
```
$ sudo systemctl status squid
x squid.service - Squid caching proxy
     Loaded: loaded (/usr/lib/systemd/system/squid.service; enabled; preset: disabled)
     Active: failed (Result: exit-code) since Sun 2025-04-13 13:21:19 JST; 18min ago
〜省略〜
Apr 13 13:21:19 rhel88v04 squid[1837412]: Squid Parent: (squid-1) process 1837436 started
Apr 13 13:21:19 rhel88v04 (squid-1)[1837436]: FATAL: The sslcrtd_program helpers are crashing too rapidly, need help!
 ```

SSL Bump を利用する場合、Squid はクライアントとサーバ間の HTTPS 通信を中継し、通信内容を検査するために、動的に証明書を生成する必要があります。​この動作には、squid.conf で sslcrtd_program に指定されたヘルパープログラム（通常は ssl_crtd または security_file_certgen）が関与し、クライアントとプロキシサーバ間の通信で使用する証明書の生成を担当します。​

今回、必要な設定が漏れていたことが原因で、証明書の動的生成が正しく行われていなかったようです。​適切な設定を行うことで、SSL Bump 機能が正常に動作するようになります。

# SSL Dumpに利用する証明書管理用DBの初期化および定義
```bash
# -c が初期化オプション
$ sudo /usr/lib64/squid/security_file_certgen -c -s /var/lib/ssl_db -M 4MB
Initialization SSL db...
Done
$ sudo vi /etc/squid/squid.conf
sslcrtd_program /usr/lib64/squid/security_file_certgen -s /var/lib/ssl_db -M 4MB
sslcrtd_children 5
$ sudo chown -R squid:squid /var/lib/ssl_db
$ sudo systemctl restart squid
```

# 再度の動作確認
```
$ curl -H "TEST: TEST_HTTP" http://example.com
$ curl -H "TEST: TEST_HTTPS" https://example.com
curl: (60) SSL certificate problem: self signed certificate in certificate chain
More details here: https://curl.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

# プロキシサーバ
$ tail -f /var/log/squid/access_with_headers.log 
1744521741.617      0 192.168.11.54 GET http://example.com/ 200 1630 TEST_HTTP
1744521747.444    325 192.168.11.54 CONNECT example.com:443 200 0 -
```
作成した証明書は自己署名であるため、HTTPS通信時に証明書の検証エラーが発生しています。​この証明書はプロキシサーバでルート証明書として使用され、security_file_certgen は、そのルート証明書を用いて、各リクエストに対応するサーバ証明書を動的に生成し、署名しています。​

動作確認には curl -k オプション（証明書の検証をスキップ）を使用しています。​なお、クライアントにルート証明書をインストールすることで、検証エラーを回避することも可能ですが、今回はその手順については扱いません。

```
# クライアント
$ curl -k -H "TEST: TEST_HTTP" http://example.com
$ curl -k -H "TEST: TEST_HTTPS" https://example.com

# プロキシサーバ
$ tail -f /var/log/squid/access_with_headers.log 
1744521430.033    226 192.168.11.54 GET http://example.com/ 200 1622 TEST_HTTP
1744521447.873    292 192.168.11.54 CONNECT example.com:443 200 0 -
1744521447.874      0 192.168.11.54 GET https://example.com/ 200 1713 TEST_HTTPS
```

# 最後に
プロキシサーバのログにクライアントからのHTTPSリクエストヘッダーを出力することができました。​次回は、この環境を活用して、リクエストヘッダーに新たな項目を追加する方法を実践してみたいと思います。