SSL/TLS – Let’s Encryptの証明書を更新

具体的には、Let’s Encryptで取得した証明書の暗号化方式がTLS1.0だったため、1.2にアップデートしたんだけど、いろいろスッタモンダしたので備忘録として書いておきます。

事の発端

おっちゃんはメインで使ってるブラウザがFireFoxなのですよ。理由は単純で、Googleが好きじゃないのと、Chromeはもはや最速でもなんでもないから。もちろん開発に便利なときもあるので使ってはいるけど、あくまでメインはFireFoxってだけね。Mozilla製だから辺に利害関係とか無さげなのが良いね。

FireFoxで複数タブを開いた状態のウィンドウが複数ある時、最後じゃないウィンドウを閉じると、そのウィンドウのセッションが消滅してしまうらしく、タブの復元でもとに戻せなくなる。Chromeだとウィンドウまたいでも履歴を復活させてくれて順番に復元可能なので、FireFoxでも同じ機能を実装してほしいね。機能拡張でそういうのあるらしいけど、あんまりゴタゴタ入れるの好きじゃないので本体の対応待ち。

で、FireFoxで自分のブログ見てみたら、なんと最新版(v68.0)だとURLのロケーションバーに警告がでてるじゃないですかンガポゴ!

みっともないし恥ずかしいので、とにかく時間を無理やり作って対策することにしたのです。

Webに携わってる人なら知ってるとは思うけど(IT関連やっててしらんとか情弱にも程があるぞ)、SSLってのはもう殆ど流通してなくて、今みんなが使ってるのはTLSなんだよ。でもSSLって名前で普及しちゃってるのにいきなりTLSに変えましょう!ったって変わらないから、苦肉の策でSSL/TLSって名前にしてるんだよね。詳しくは自分でググればいいと思う。

ちなみにFireFoxの開発ツールのコンソールにはこんなメッセージが山盛り。

準備

まずはFireFox情で証明書の概要を確認してみます。

TLSのECDHE_RSA_WITH_AES_256_CBC_SHAとか、ちょっとよくわからないんだけど、とにかくTLSが1.0であることがわかったので、これはまずいです。せめて1.1でしょ。

早速Let’s Encrypt界隈をごちゃごちゃいじってみることにします。

既存の旧Certbotを削除

以前はyumコマンドでインストールしていたので同じくyumコマンドで削除します。なんでyumで入れたのかと言うと、当時はyum派とgitでclone派があって、cloneが面倒くさかったのでyumでインストールしました。

でも今考えると、yumだとパッケージが古い可能性もあるし、リポジトリから消える可能性もあるので、今回を機にgithubからcloneすることにします。いろいろぐぐってみるとその方法で証明書のインストールしてる人のほうが圧倒的に多いので。

で、サクサクっと既存のcertbotを消しましょう。

  • $ sudo -s ← rootユーザになる
  • # yum remove certbot ← yumで入れたのでyumで消す
  • # yum install git ← git入ってなかったのでインストール
  • # exit

商用サーバにgit入れるとかやや抵抗があるのですが、まぁデプロイツールとかでも普通に使われているので、とりあえず良しとします。

こういう意識が大事。何でもかんでも入れればいいってもんじゃない。ITゆとりにはそれがわからんのですよ。

certbotは証明書をインストールするためのツールなので、別にcertbotを削除しても証明書が削除されるわけではないです。当然消してもWebサイト側は特に問題ないです。

改めて最新版のCertbotをgitでcloneする

さて、certbotをgitでcloneする時、rootユーザではなく一般ユーザで行います。理由は、そのほうが楽だから。というわけで、一般ユーザのホームディレクトリにcloneしておきます。

  • $ cd ← ホームディレクトリに移動
  • $ git clone https://github.com/certbot/certbot

いちおうcertbotの動作確認をしておきましょう。certbotはいわばLet’s Encryptの本体と言ってもいいです。

  • $ cd certbot ← cloneしたディレクトリ内に移動
  • $ ./certbot-auto --help ← とりあえずヘルプを表示させてみる

こんな感じでターミナルに表示されたと思います。

1行目にメッセージがありますね。これは一般ユーザじゃなくてrootユーザで実行してくれよな!という警告です。証明書発行するときはrootユーザになって実行するので無視していいです。

certbot実行

さて、それでは既存の証明書がまだインストールされているとは思いますが、NginxとかApacheを再起動しない限り影響がないので、いきなり証明書をインストールしてみましょう。

StandaloneとWebroot

certbotで証明書をインストールする際のモードが2つあります。Standalone方式はNginxやApacheなどのHTTPdが動いているとエラーが出ます。Webroot方式では出ません。

  • standalone方式
    • certbot自体が持っているWebサーバ機能を使って証明書をインストール
    • 80番ポートを使用するので稼働中のHTTPdは止めておく必要がある
    • --standaloneオプションを使用
  • webroot方式
    • 可動しているhttpdを使用して証明書をインストールする方式
    • --webrootオプションを使用

上記を見れば一目瞭然ですね。すでに証明書が入っているし、HTTPdも稼働中なので、今回はwebroot方式でインストールすることにします。

Webroot方式で実行

ここでは仮に、ブログが/var/www/htmlにインストールされているとします。いわゆるドキュメントルートのことです。

$ sudo -s
# ./certbot-auto certonly --webroot -w /var/www/html -d blog.ogaaaan.com

簡単に説明します。certonlyで証明書をインストールします。--webrootでWebroot方式を指定します。-wでドキュメントルートの場所を指定します。-dでドメインを指定します。簡単ですね。

で、依存関係なんかを先にインストールしてくれます。yumで入れたcertbotを消した時、依存関係も消えてるってことですね。神経質でいい感じです。

というわけで依存パッケージのインストールが開始しました。

インストールしてもいいですかね?と聞かれるので、当然yをタイプしてEnterします。しなければ何も始まりません。そしてそのまま待っていると、勝手にcertbotが実行されて証明書がインストールされます。

が、以前インストールした設定が残っているので、どうするのか聞かれました。そんなの関係ねぇ!バリに実行を続けるか聞かれますので、実行させました。そんなの関係ねぇから。

証明書がインストールされる場所は、

  • /etc/letsencrypt/renewal/ + ドメイン名 + fullchain.pem
    • サーバ証明書と中間証明書の合体した証明書
  • /etc/letsencrypt/renewal/ + ドメイン名 + privkey.pem
    • 秘密鍵

になりました。

ここで2を選択して証明書を最新のものと入れ替えます。

で、後はこの2つのファイルをHTTPd側の設定ファイルで指定するだけです。

ちなみに設定ファイルを見る限り、以前と同じ場所に同じファイル名で作られたことがわかったので、特に変更せずに再起動だけで済むようです。楽ですね。

Nginxの再起動と確認

このブログはNginxで動いています。

現在読み込まれている証明書はサーバのメモリ上に展開されているため、Nginxを再起動して最新の証明書に読み込み直す必要があります。

# systemctl restart nginx

ブラウザ上で確認するも以前と変わらず警告が出てしまました。うーむ。なにかやるべきこと忘れたのかな?

証明書の発行日は本日、有効期限は3ヶ月後になっているため、更新されたことは確認できたので、とりあえずブログがぶっ壊れたとか証明書がぶっ壊れたと買ってことにはなってないわけで、少し時間をかけて調べることにしました。

ツールでスコア判定

Qualys SSL LABSのSSL Server Testをってスコアを判定してみます。ここは判定したいサイトのドメイン名のみを入力して実行すればスコアが表示されます。便利です。

以下がその結果になります。

現状

  • ランクC
    • Certificate: 100
    • Protocol Support: 50
    • Key Exchange: 70
    • Cipher Strength: 70

SSLv2/v3の無効化

とりあえずTLSとして明示的に指定したいので、SSLの設定を無効化してみたいと思います。

現状のNginxのSSLの設定は以下。思いっきりSSLv2とか書いちゃってますし、TSLも1になってます。

これを以下のように、SSLv2とSSLv3以外 が有効になるように編集します。

Nginxを再起動後、ブラウザで警告は出なくなったので、再度スコアを見てみました。

  • ランクC
    • Certificate: 100
    • Protocol Support: 50
    • Key Exchange: 70
    • Cipher Strength: 70

特に変わらずランクCなので、とりあえず最終的によくわからなくなったらこれにしておこうと思います。

しかしもう少し調べておきたいので、更に調査してもっと編集してみることにしました。

匿名認証方式の無効化

以下のように、aNULLeNULLも無効化しました。

Nginx再起動後スコアを見てみます。

  • ランクF
    • Certificate: 100
    • Protocol Support: 100
    • Key Exchange: 0
    • Cipher Strength: 90

なんと一気にFまで落ちてしまったという。なんで?

強度の弱い暗号化方式の無効化

更に以下のように、DHも無効化しました。

  • ランクF
    • Certificate: 100
    • Protocol Support: 100
    • Key Exchange: 0
    • Cipher Strength: 90

残念ながらこちらもランクF。ついでなのでもう少しいろいろ試してみましょう。

Forward Security対応

鍵交換方式をALLからECDH固定にし、DHは有効に戻してみます。

  • ランクF
    • Certificate: 100
    • Protocol Support: 100
    • Key Exchange: 0
    • Cipher Strength: 90

速攻で結果が表示された。残念ながらこちらもランクFでした。
うーむ。ここらへん得意じゃないのでよくわかってないのが痛い。

Strict-Transport-Securityヘッダ対応

サイファは以下のように設定し直して、ヘッダを付与するように設定してみます。

  • ランクF
    • Certificate: 100
    • Protocol Support: 100
    • Key Exchange: 0
    • Cipher Strength: 90

こちらもランクF。

いろいろ調整

最終的に以下にしておきました。

ランクはCです。

個人的にここらへんの知識が足りず、勉強不足なので一旦ここまでにしておきました。
BやAにする方法はまた後日考えます。

おわり

セキュリティ大事。