SSLサーバ証明書の設定確認、中間CAの設定ミスを発見する

SSLサーバ証明書の設定で一番やらかしがちなのは中間CA証明書の設定ミスです。

# PCブラウザでの鍵マーク確認だけじゃダメ！

いまどきのPCブラウザだと証明書に記載されている `Authority Information Access` 拡張フィールドから中間CA証明書を自動DLしてくれたりキャッシュしたりする機能がある為、サーバに中間CA証明書が正しく設定されていなくても問題なく閲覧出来てしまう。
便利だが、それ故に確認ツールとしてブラウザを使ってしまうと中間CA証明書の設定漏れに気が付かずに置かれた結果、中間CA証明書の自動DL機能のない(主には)携帯端末などからアクセスできなくなって初めて設定漏れに気付く。
なんてことがよくあるのでブラウザじゃなくちゃんとした手順で確認することを覚えましょう！

# SSLサーバ証明書チェッカー
認証局がチェッカサイトを提供しているのでこれを使うのが一番簡単で確実だと思います。以下は提供元とロゴが違うだけで基本的には同じアプリによってチェックしているようで、出力もどこ使っても同じようです。ていうか厳密にはサーバはアプリを配布してるだけで実際のチェックはローカル環境のJavaが行ってる模様。

- https://ssltools.websecurity.symantec.com/checker/views/certCheck.jsp
- https://ssltools.geotrust.com/checker/views/certCheck.jsp
- https://ssltools.thawte.com/checker/views/certCheck.jsp

結果は大体一目瞭然で親切。

- 緑なら問題なし
- 赤なら致命的な設定ミスがある
- オレンジなら致命的ではないけど直した方が良い設定がある（中間CAとして余計な証明書が混ざってるとか）

赤かオレンジが出た場合も、問題の詳細や対応方法まで教えてくれるので非常に便利です。

# opensslを使って手動でチェック
の手順を書こうと思ったんだけど上述の証明書チェッカーが結構優秀なのでこれ使えばいいんじゃね？
ということで暇が出来たらマニュアル確認方法も調べて書くかもしれない…。

# 中間CA証明書が複数ある場合の設定方法
例えばある認証局でSSL証明書を発行してもらったら以下の様な証明書チェーンになってたとします。

```text:証明書チェーン
Root CA Certificate - AddTrustExternalCARoot.crt
└Intermediate CA Certificate - COMODORSAAddTrustCA.crt
  └Intermediate CA Certificate - COMODORSADomainValidationSecureServerCA.crt
    └Your PositiveSSL Certificate - example_com.crt
```

この場合、

- example_com.crt は自分用に発行された証明書であり、中間CA証明書ではありません。
- 残りの3つが認証局の証明書ですが、RootCA証明書は各クライアントが持ってるべきもので中間CA証明書ではありません。
- RootCAと自分用の証明書以外の間の2つが中間CA証明書です。
    - 中間CA証明書が無くて、RootCAから直接発行されることもあります。その場合は中間CA証明書の設定は不要です。
- サーバに中間CA証明書として設定するにはこの2つを繋げて１つのファイルにしたものを使います。その際のつなげる順番は自分用証明書から逆順にたどる順番がベター。
    - 上記チェーン例では以下のように作ります。`cat COMODORSADomainValidationSecureServerCA.crt COMODORSAAddTrustCA.crt > example_com.ca_bundle`
    - 出来た example_com.ca_bundle (ファイル名は適当)を中間CA証明書として設定してやればOKです。

# 脆弱性対応チェックもやるといいよ！
これもやろう。
[SSL Server Test (Powered by Qualys SSL Labs)](https://www.ssllabs.com/ssltest/index.html)

# Perfect Forward Security な設定をしておこう
TLSには暗号スイートの選択というのがつきものなんですがその選択自体が素人には難易度高いので、まー難しい話は置いておいて、PFS な設定ジェネレーターとかあるのでこれ設定を使っておくと最低限の安全が保たれて便利です。
https://mozilla.github.io/server-side-tls/ssl-config-generator/

ちなみに PFS とはメッセージ（暗号文）と秘密鍵の両方が漏れても解読できないようにしようっていう概念で、鍵合意において公開可能なランダム値と非決定的なアルゴリズムのみを用いることがPFSの条件となっています。PFSな暗号スイートを使っておけば、万が一部のセッションキーが漏れて一部メッセージが解読されたとしてもそれが他のメッセージに影響することはなく過去＆未来の他の暗号文は解読できません。
PFSで無い例は例えば、AさんとBさんはRSA暗号を使って通信していたとします。第三者のCさんは通信内容は買得できませんがとりあえず全てのメッセージをそのままHDDとかに延々保存し続けておきます、そして将来的に例えばAさんが廃棄したPCのHDDから秘密鍵をCさんが取得出来てしまったとします、すると当時は不明だった過去の通信内容も全てが解読できてしまうことになります。
これがもしPFSであれば盗まれて困るような長期的な秘密鍵はそもそも存在せず、各メッセージの暗号化に用いる共有鍵もメッセージ毎に変わるので例え一部メッセージの解読に成功したとしても、過去や未来の暗号文を解読することも出来ません。Perfect Forward Security の Forward は作成されたメッセージは将来においても安全という意味です。

# 落ち葉拾い： DNS CAA について
DNS CAA とは FQDN に対する証明書を発行可能な CA を明記して限定できるという仕組みです。
CAA レコードで設定可能な値やフォーマットは設定ジェネレータを使うのが楽ちんです。
https://sslmate.com/caa/

たとえば `kawaz.jp` とそのサブドメインの証明書は `Let's Encrypt` か `ACM (Amazon Trust Services)` でしか発行できないようにして、また別のCAで証明書発行しようとしてエラーになった場合は連絡先として `https://twitter.com/kawaz` を表示するようにして欲しい場合は、Route53 なら↓こんなレコードを作れば良いよと教えてくれる。

| Name | Type | Value |
|:--:|:--:|:--|
| kawaz.jp. | CAA | 0 issue "amazon.com"<br>0 issue "letsencrypt.org"<br>0 iodef "https://twitter.com/kawaz" |

ついでに、BIND用ゾーンファイルや tinydns や dnsmasq 用のコピペ可能な設定例までジェネレートしてくれる親切設計。