[ubuntu] apacheのSSL化（TLS1.3）に超苦労した [apache 2.4]

# 最初にまとめ
* `apache2.4`のSSL対応に数日かかった
* phpでサイトを作っている場合、一工夫必要でした
ってことを書いてます。証明書取得して設置して終了！で済まなかった...

# 無料でSSL対応にする
　単純にSSL化するには`openssl`で証明書を発行し、`apache2.conf`とか`000-default.conf`に証明書の場所を記載して`restart`すれば良い。しかし自分で作成した証明書を設置してもOSから信頼されていないのでブラウザがエラー画面を出力する。そこらへんを解決するために`Let's Encrypt`なる無料の証明書があったので、これを使う。

# 学習に苦労したSSL
　「SSL 仕組み」とか「SSL 証明書」とかでググると、多くは暗号化（公開鍵と秘密鍵がうんたらかんたら...）を解説するサイトにヒットする。が、知りたいのはそこじゃない・・・。いろいろ調べた結果、ざっくり理解したSSLの仕組みは以下の通り。

1. 王様が信用した部下に証明書を与える。王様は自分の証明書と部下の証明書を作る。
2. 一般人が部下に面接を申し込んで証明書作成を申請する。
3. 部下は一般人と面接をして合格すれば一般人の証明書を作る。
0. 各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だと遅い
　原因を探ること、数日・・・。以下のことが判明した。

1. `mpm_prefork`だと`http2`に対応していないから遅い。
2. `mpm_event`にすれば解決するけど、phpは`prefork`に依存して動作している。
3. 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`を見ると大量のエラーが・・・。

```:/var/log/apache2/error.log
 Options FollowSymLinks and SymLinksIfOwnerMatch are both off...（略
```

　`mod-rewrite`を使う場合は`FollowSymLinks`か`SymLinksIfOwnerMatch`は有効化しないといけないらしい。

```:apacheの設定ファイル
<Directory /var/www/html>
    Options SymLinksIfOwnerMatch
</Directory>
```

# その他
　証明書は`wwwありなし`をハッキリさせてリダイレクトするように記載する必要がある。高級な証明書（ワイルドカード証明書：超高価）なら両方いけるのかな。証明書ってめんどくさい・・・。

```:/etc/apache2/site-available/000-default.conf

 ServerName www.mydomain.com　　←wwwを抜くとブラウザに怒られる
 RewriteCond 
```

　メールサーバーその他でも同じ証明書を使いたかったので、設定は以下のようにした。

```
 ServerName www.mydomain.com
 ServerAlias mydomain.com
```

# 参考にしたサイト
https://tecadmin.net/setup-apache-php-fpm-ubuntu-20-04/

https://qiita.com/mindwood/items/fa30f91f9379592eea1e

https://kzhishu.hatenablog.jp/entry/2016/11/22/100000

https://appw.jp/20200113-58.html

https://qiita.com/gotohiro55/items/7daa988db23a5a8355c1