最初にまとめ
-
apache2.4
のSSL対応に数日かかった - phpでサイトを作っている場合、一工夫必要でした
ってことを書いてます。証明書取得して設置して終了!で済まなかった...
無料でSSL対応にする
単純にSSL化するにはopenssl
で証明書を発行し、apache2.conf
とか000-default.conf
に証明書の場所を記載してrestart
すれば良い。しかし自分で作成した証明書を設置してもOSから信頼されていないのでブラウザがエラー画面を出力する。そこらへんを解決するためにLet's Encrypt
なる無料の証明書があったので、これを使う。
学習に苦労したSSL
「SSL 仕組み」とか「SSL 証明書」とかでググると、多くは暗号化(公開鍵と秘密鍵がうんたらかんたら...)を解説するサイトにヒットする。が、知りたいのはそこじゃない・・・。いろいろ調べた結果、ざっくり理解したSSLの仕組みは以下の通り。
- 王様が信用した部下に証明書を与える。王様は自分の証明書と部下の証明書を作る。
- 一般人が部下に面接を申し込んで証明書作成を申請する。
- 部下は一般人と面接をして合格すれば一般人の証明書を作る。
- 各OSに証明書ライブラリがあり、王様は現実世界でOS開発者に信用してもらってライブラリに自分の証明書を実装してもらう必要がある。
ブラウザ等で接続サイトの証明書の詳細を見ると、上記のような3段構えになっているのが確認できる。カスペルスキーの証明書は中間認証局の無い2段構え。王様、部下、一般人の情報はそれぞれ暗号化されて証明書の中に記載されている。「誰が」「何を」証明する証明書なのか、王様により異なる。
王様を「root認証局」、部下を「中間認証局」という。Let's Encrypt
は「対象とするウェブサイト運営者はそのドメインが記載されているDNSサーバーの該当するドメインレコード編集権限を持っている(つまり、ドメイン保有者以外の第三者によって偽造されたウェブサイトである可能性は低い)」ことを証明する証明書を発行している中間認証局であり、「信用」そのものを発行しているroot認証局は「Internet Security Research Group」、となんとなく理解した(厳密には違っているかも)。
証明する内容が具体的(実際に事務所が存在して人が勤めている企業ですよ証明など)になればなるほど、証明書の値段も上がり電話確認とか面接、登記の記載事項証明書とかが必要になってくるらしい。中間認証局の運営って大変そうだなぁ。
一部のブラウザやメールクライアントはOSの証明書ライブラリを使わずに、独自のライブラリを使うものがあるらしい。
昨今のSSL
どうやらSSLはいろいろ不具合とかセキュリティホールが見つかって、今(2023年3月)はSSLは全滅、SSLからTLSに進化したけどTLSの1.1
も危殆化しており、1.2
ももうすぐ危険レベル、今は1.3
に対応するのが一般的らしい。なんで「TLS」とは言わずに「SSL」って言われてるのか謎。暗号化のアルゴリズムも128bitはもう少しで危殆化しそうだから非推奨とかいろいろあるみたい。webサーバーではcipherなんとかって設定項目で対応するアルゴリズムを指定する。
Explicit TLS と Implicit TLS
平文通信後にTLSに切り替えるExplicit TLS
(別名STARTTLS
)と、最初から暗号化して通信するImplicit TLS
の2種類があるらしい。ウェブサーバー(ポート443:https)はImplicit
のみで、設定とかは特に必要ないらしい。
電子証明書の申請と設置
無料のLet's Encrypt
を利用。手順は良い記事がたくさんあるので別記事におまかせ(という名の丸投げ!)。
電子証明書の更新
期限が短いので更新は自動化したい。昔はcron
に自動更新のスクリプトを書く必要があったらしいけど、certbot
をインストールすると自動更新も有効になっているとのこと。
ちゃんと更新されるかどうかは以下のコマンドでテストできる。
certbot renew --dry-run
おそらく証明書を設置しただけではテストはパスしないことが多いんじゃないかと思う。自分がテストパスのために通った手順は以下の通り。
① webサーバーのドキュメントルート配下に、.well-known/acme-challange
ディレクトリを作成。
mkdir /var/www/html/.well-known
mkdir /var/www/html/.well-known/acme-challange
パーミッション設定を忘れずに。
chmod 755 /var/www/html/.well-known
chmod 755 mkdir /var/www/html/.well-known/acme-challange
② ポート80への米国からのアクセスを許可する。
iptables
の設定とhtaccess
の記述を確認する。
念のため、well-known
ディレクトリへのアクセスはhtaccess
で制限している。ここを狙った攻撃も存在するらしい。
証明書を設置するだけで済まなかった
証明書設置後SSLで接続されるようになったが、サイトの表示が超~~~遅くなった。今までは3秒かからなかったのに、100秒以上かかってしまう。これはいくらなんでも異常だ。
apacheの動作モードがpreforkだと遅い
原因を探ること、数日・・・。以下のことが判明した。
-
mpm_prefork
だとhttp2
に対応していないから遅い。 -
mpm_event
にすれば解決するけど、phpはprefork
に依存して動作している。 - phpの動作を
fastCGI
へ切り替えることで解決可能(mod_fcgi
とphp-fpm
)。
ということで切り替えていきます。
# インストール。
apt install php8.0-fpm
# fast cgiの有効化。
a2enmod proxy_fcgi setenvif
# php-fpmの有効化とprefork依存のphp無効化。
a2enconf php-8.0-fpm
a2dismod php8.0
# 設定ファイルの文法チェック。無反応であることを確認。
apache2ctl configtest
# prefork無効化、event有効化。
a2dismod mpm_prefork
a2enmod mpm_event
# システム再起動。
systemctl restart php8.0-fpm apache2
これだけで既存のページが高速に・・・!・・・なりませんでした。なんとアクセス不可能に!
サイトにアクセスしようとすると、なんかファイルをダウンロードするダイアログが出たり、Forbidden
だったりブラウザによって挙動が違う。なんじゃこれ???
php-fpmだとサイトにアクセスできない
さらに原因と対応を探ること、数日・・・
どうやらphp-fpm
の標準設定では、x-application
をhtaccess
とかに書いてもhtml
拡張子のファイルをphpで実行してくれないらしい。ので設定を変更する。
vi /etc/php/8.0/fpm/pool.d/www.conf
# 以下の項目を編集
security.limit_ = .php .html .htmls
vi /etc/apache2/mods-available/php8.0-fpm.conf
<FilesMatch "\.ph(ar|p|tml)$">
↓に変更
<FilesMatch "\.(phar|php|phtml|html)">
これでようやくまともに表示されるようになった。ちょっと速くなったけど、SSL非対応に比べると遅い・・・。SSLサイトの表示はNginX
の方が得意らしい。
Android版Firefoxなど一部のブラウザでLet's Encrypt
の証明書では「このサイトは危険です」みたいな警告が出ることがあるらしい。これはどうしようもないのでブラウザの対応を待つしかない様子。
ログにエラーが・・・
apache
をリスタートした直後から/var/log/apache2/error.log
を見ると大量のエラーが・・・。
Options FollowSymLinks and SymLinksIfOwnerMatch are both off...(略
mod-rewrite
を使う場合はFollowSymLinks
かSymLinksIfOwnerMatch
は有効化しないといけないらしい。
<Directory /var/www/html>
Options SymLinksIfOwnerMatch
</Directory>
その他
証明書はwwwありなし
をハッキリさせてリダイレクトするように記載する必要がある。高級な証明書(ワイルドカード証明書:超高価)なら両方いけるのかな。証明書ってめんどくさい・・・。
ServerName www.mydomain.com ←wwwを抜くとブラウザに怒られる
RewriteCond
メールサーバーその他でも同じ証明書を使いたかったので、設定は以下のようにした。
ServerName www.mydomain.com
ServerAlias mydomain.com
参考にしたサイト