2026年9月15日
2026年9月15日
Squid でSSLターミネーションする方法|https_port の設定・証明書更新・WordPress 側の対応
Squid をリバースプロキシ(アクセラレーター)として使い、HTTPS の暗号化・復号を Squid で終わらせてバックエンドの WordPress には HTTP で渡す構成は、https_port に accel と証明書を指定するだけで組めます。ただし、OpenSSL 対応でビルドされた Squid が必要なこと、証明書更新後の再読み込み、WordPress に HTTPS であることを伝える設定の3点でつまずきやすいのが実情です。この記事では、その3点を中心に、設定から動作確認までを順に説明します。
なお、ここで扱うのは「自分のサイトの前段で HTTPS を受ける」リバースプロキシの構成です。社内の利用者の通信を復号して検査する SSL Bump(フォワードプロキシでの TLS 傍受)は、仕組みも注意点も別物なので扱いません。HTTP のままのリバースプロキシ設定とキャッシュの考え方は、別記事「Squid のリバースプロキシ設定方法」で解説しています。
SSLターミネーション構成の全体像
構成は次のとおりです。
- クライアント → Squid(443番ポートで HTTPS を受け、ここで TLS を終端)
- Squid → WordPress のバックエンド(同じサーバーの 8080 番や、内部ネットワークの別サーバーに HTTP で接続)
TLS 処理を Squid に集めると、証明書の管理場所が1か所になり、バックエンドのサーバーを増やしても証明書を配る必要がありません。一方で、Squid とバックエンド間は暗号化されないため、この区間は同一ホスト内か、外部から到達できない内部ネットワークに限定するのが前提です。
手順1:Squid が TLS に対応しているか確認する
https_port は、Squid が OpenSSL(または GnuTLS)を有効にしてビルドされていないと使えません。対応していないビルドで設定すると、起動時や構文チェックでエラーになります。まずビルドオプションを確認します。
squid -v | tr ' ' '\n' | grep -iE 'openssl|gnutls'
--with-openssl などが表示されれば対応しています。何も出ない場合は、TLS 対応版のパッケージに入れ替える必要があります。Debian や Ubuntu では TLS 対応版が squid-openssl という別パッケージで提供されている場合があります。パッケージ名や既定のビルド内容はディストリビューションとバージョンで異なるため(2026年10月現在)、利用中の OS のパッケージ情報で確認してください。
手順2:証明書と秘密鍵を配置する
Let's Encrypt などで取得した証明書を、Squid の実行ユーザーが読める場所に置きます。証明書ファイルには中間証明書を含めたフルチェーンを使うのが基本です。中間証明書が欠けていると、ブラウザによっては表示できても、スマートフォンや API クライアントで検証エラーになることがあります。
sudo mkdir -p /etc/squid/certs
sudo cp fullchain.pem /etc/squid/certs/example.com.fullchain.pem
sudo cp privkey.pem /etc/squid/certs/example.com.key
# 実行ユーザーは環境により proxy や squid など
sudo chown root:proxy /etc/squid/certs/example.com.key
sudo chmod 640 /etc/squid/certs/example.com.key
秘密鍵は実行ユーザー以外が読めないようにします。権限が緩すぎても厳しすぎても問題になるので、起動に失敗したら cache.log でファイルの読み込みエラーが出ていないかを確認してください。
手順3:squid.conf に https_port と転送先を書く
設定ファイルを変更する前に、既存の squid.conf をバックアップしておきます。
sudo cp /etc/squid/squid.conf /etc/squid/squid.conf.bak.$(date +%Y%m%d)
最小構成の例です。
# 443番でHTTPSを受け、アクセラレーターとして動作させる
https_port 443 accel defaultsite=example.com vhost tls-cert=/etc/squid/certs/example.com.fullchain.pem tls-key=/etc/squid/certs/example.com.key tls-min-version=1.2
# 転送先(オリジン)のWordPress
cache_peer 127.0.0.1 parent 8080 0 no-query originserver login=PASSTHRU name=wp_origin
# 受け付けるドメインを限定する
acl our_sites dstdomain example.com www.example.com
http_access allow our_sites
cache_peer_access wp_origin allow our_sites
cache_peer_access wp_origin deny all
http_access deny all
# WordPressにHTTPS経由であることを伝える
request_header_add X-Forwarded-Proto https all
設定の意味を補足します。
accelは、このポートをリバースプロキシ用として扱う指定です。defaultsiteは Host ヘッダーがない場合の既定のサイト名、vhostは Host ヘッダーを見て転送先を判断させる指定です。tls-certとtls-keyは Squid 4 以降の書式です。古い解説で見かけるcert=とkey=は旧書式で、バージョンによっては非推奨の扱いになっています。tls-min-version=1.2で TLS 1.1 以下の古いプロトコルを拒否します。オプション名や指定できる値はバージョンで変わることがあるため、利用中の Squid の設定リファレンスで確認してください。login=PASSTHRUは、Basic 認証などの認証ヘッダーをそのままオリジンに渡す指定です。WordPress 側で認証を使っていなければ省略しても構いません。http_access deny allを最後に置くことで、許可したドメイン以外への中継を防ぎます。この行がないと、意図せず踏み台として使われるおそれがあります。
1つの https_port には基本的に1つの証明書を指定します。複数のドメインをまとめて扱いたい場合は、SAN(サブジェクト代替名)に全ドメインを含めた証明書を用意するのが扱いやすい方法です。
構文チェックと反映
sudo squid -k parse
sudo systemctl restart squid
squid -k parse で警告やエラーが出ないことを確かめてから再起動します。ポートを新しく追加した場合は、squid -k reconfigure ではなく再起動が必要になることがあります。
手順4:WordPress 側を HTTPS 前提にする
Squid で TLS を終端すると、WordPress には HTTP でリクエストが届きます。そのままだと WordPress は HTTP でアクセスされていると判断し、管理画面へのリダイレクトがループしたり、画像や CSS の URL が http:// で出力されたりします。
上の設定で付けた X-Forwarded-Proto を使い、wp-config.php の require_once ABSPATH . 'wp-settings.php'; より前に次を追加します。
// バックエンドにSquid以外から到達できない構成に限って使う
if ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && 'https' === $_SERVER['HTTP_X_FORWARDED_PROTO'] ) {
$_SERVER['HTTPS'] = 'on';
}
あわせて、管理画面の「設定」→「一般」で WordPress アドレスとサイトアドレスが https:// になっているか確認します。バックエンドの 8080 番ポートが外部から直接開けると、ヘッダーを偽装される余地が生まれるため、Web サーバーを 127.0.0.1 で待ち受けるか、ファイアウォールで接続元を Squid に限定してください。
手順5:動作を確認する
外部の端末から TLS の状態を確認します。
# 証明書チェーンとネゴシエートされたプロトコルを確認
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | grep -E 'subject=|issuer=|Protocol|Verify return code'
# レスポンスヘッダーを確認
curl -sI https://example.com/
Verify return code: 0 (ok) と表示されれば、チェーンの検証は通っています。curl でステータスが 200 または想定どおりのリダイレクトになっているか、Location ヘッダーが https:// になっているかも見ておきます。
うまくいかない場合は、次の順に確認すると原因を絞り込みやすくなります。
sudo ss -tlnp | grep ':443'で Squid が 443 番を待ち受けているか/var/log/squid/cache.logに証明書や秘密鍵の読み込みエラーがないか/var/log/squid/access.logにリクエストが記録され、どのステータスで返しているか- バックエンドに直接
curl -I http://127.0.0.1:8080/ -H 'Host: example.com'を送って正常に応答するか
ログのパスはディストリビューションによって異なることがあります。
証明書の更新を自動化する
Let's Encrypt の証明書は有効期間が短いため、更新の自動化が欠かせません。証明書を取得・更新するサーバーと、それを使う Squid の場所が同じとは限らない点に注意します。HTTP-01 認証は 80 番ポートへのアクセスで検証されるため、80 番を Squid で受けていないなら certbot の standalone 方式が使えます。80 番も Squid で受けている場合は、検証用のパス(/.well-known/acme-challenge/)がオリジンの webroot まで届くかを確認するか、DNS-01 認証を使います。
更新後は証明書をコピーし直し、Squid に再読み込みさせます。certbot の deploy フックを使うと、更新に成功したときだけ処理を走らせられます。
#!/bin/sh
# /etc/letsencrypt/renewal-hooks/deploy/squid.sh
cp /etc/letsencrypt/live/example.com/fullchain.pem /etc/squid/certs/example.com.fullchain.pem
cp /etc/letsencrypt/live/example.com/privkey.pem /etc/squid/certs/example.com.key
chown root:proxy /etc/squid/certs/example.com.key
chmod 640 /etc/squid/certs/example.com.key
squid -k reconfigure
certbot renew --dry-run で更新処理の流れを事前に試せます。再読み込みで新しい証明書が使われているかは、前述の openssl コマンドで有効期限を確認してください。期限切れを防ぐには、外部から証明書の残り日数を監視する仕組みも併用すると安心です。
まとめ
- Squid の SSLターミネーションは
https_portにaccelとtls-cert・tls-keyを指定して組む - OpenSSL 対応でビルドされた Squid が必要。
squid -vで事前に確認する - 証明書はフルチェーンを使い、秘密鍵の権限は実行ユーザーだけが読める状態にする
- WordPress には X-Forwarded-Proto で HTTPS を伝え、バックエンドへの直接アクセスは塞ぐ
- 証明書の更新後は
squid -k reconfigureで再読み込みし、openssl で反映を確認する