Let’s Encrypt は無料でサーバー証明書を発行してくれる認証局です。2016 年のサービス開始以来、 急速に普及しています。
Let’s Encrypt の証明書発行には ACME プロトコルに対応したクライアントソフトウェアを使います。主要な ACME クライアントソフトウェアは ACME Client Implementations で紹介されています。Let’s Encrypt のサイトでは certbot というツールが推奨されているのですが、 このツールは Windows には対応していません。Windows 環境では win-acme (旧名 letsencrypt-win-simple) というツールが良く使われているようです。
私も、 これまで win-acme を使ってきたのですが、 先日、 ふとしたことで mod_md という Apache モジュールの存在を知りました。mod_md は win-acme よりもずっと簡単に使えます。ただし、 mod_md は Apache モジュールであるため Apache 環境でしか使えません。IIS など他のウェブサーバーに Let’s Encrypt を導入するのであれば、 引き続き win-acme が有力な選択肢になります。
Apache 2.4.30 以降で利用可能になった mod_md モジュールを使って Let’s Encrypt 証明書を導入する手順を紹介していきます。
ドメイン認証
Let’s Encrypt では、 ドメイン認証 (Domain Validation:DV) 証明書を発行することができます。企業認証 (Organization Validation:OV) 証明書、 EV (Extended Validation) 証明書は発行できません。
ドメイン認証について少し説明しておきましょう。OV や EV では電話確認や登記確認によって組織の実在性を確認しますが、 DV ではドメインの所有者であることを間接的に確認します。
方法は主に 3 つあります。
- メール認証
- あなたが example.com ドメインの管理者なら postmaster@example.com 宛のメールを受け取れるはずです。メールで認証コードを送るので、 その認証コードを入力してください。それができたら example.com を所有していると認めます。
- DNS認証(dns-01)
- あなたが www.example.com ドメインの管理者であるなら DNS を変更できるはずです。私が指定する値を example.com の TXT レコードに設定してください。私がそれを確認できたら www.example.com を所有していると認めます。
- HTTP認証(http-01)
- あなたが www.example.com ドメインの管理者であるならウェブサイトを変更できるはずです。私が指定するファイルを http://wwww.example.com/.well-known/~で参照できるように配置してください。私がそれを確認できたら www.example.com を所有していると認めます。
大体こんな感じです。ドメインを所有していればできることを課題として出され、 それを達成すればドメイン所有者として認められるということですね。
Let’s Encrypt はメール認証には対応していないので、 DNS 認証か HTTP 認証を使うことになります。HTTP 認証のほうが扱いやすい人が多いかな? 私の場合は、 お名前.com を使っているので DNS の変更には Web インターフェース (ブラウザー) を使う必要があります。Apache の設定で条件をクリアできる HTTP 認証のほうがやりやすいと考えました。
win-acmeで面倒だったところ
HTTP 認証をするためには指定されたファイルを /.well-known/
に配置してインターネット側から参照できるようにしなければなりません。これが Apache では少し手間がかかりました。
Apache では httpd.conf
の SSLCertificateFile
ディレクティブにサーバー証明書のファイルパスを指定するのが一般的ですが、 ここに存在しないファイルパスが指定されていると Apache 自体が起動できなくなります。そのため、 サーバー証明書を発行する前は SSLCertificateFile
や SSLEngine on
をコメントアウトして、 HTTP のみが有効な状態で Apache を起動する必要がありました。
/.well-known/
が参照できるように HTTP のみの構成で Apache を起動して認証を通す、 その後、 取得したサーバー証明書を SSLCertificateFile
に指定して HTTPS 構成の Apache を起動する、 という 2 ステップが必要だったわけです。
途中で httpd.conf
を書き換えるのがなんとなく億劫でした。これが mod_md を使うことで改善できます。
mod_mdの設定
mod_md では SSLCertificateFile
ディレクティブを使いません。サーバー証明書のファイルパスを明示的に指定する必要がないのです。
mod_md の設定手順を説明していきましょう。
mod_md の使用には mod_md.so
だけでなく mod_watchdog.so
もロードする必要があります。SSL/TLS を使うのが目的ですから mod_ssl.so
、 mod_socache_shmcb.so
もロードしておきます。
必要なモジュール(httpd.conf)LoadModule ssl_module modules/mod_ssl.so
LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
LoadModule watchdog_module modules/mod_watchdog.so
LoadModule md_module modules/mod_md.so
次に mod_md の共通設定です。
共通設定(httpd.conf)MDBaseServer on
MDCertificateProtocol ACME
MDCAChallenges http-01
MDDriveMode auto
MDPrivateKeys RSA 2048
MDRenewWindow 33%
MDStoreDir md
MDCertificateAuthority https://acme-v01.api.letsencrypt.org/directory
MDCertificateAgreement https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf
基本的には上記の設定のままで大丈夫です。それぞれのディレクティブの設定の意味は下記サイトで確認できます。
いくつかのディレクティブについて説明します。
- MDStoreDir
- 管理対象ドメインのデータを格納するローカルファイルシステム上のパスを指定します。既定値は
md
です。既定値md
のままなら${SRVROOT}/md
になります。実際はC:\Apache24/md
などのパスに展開されるでしょう。
- MDRenewWindow
- 証明書を更新するしきい値を指定します。既定値は
33%
です。Let’s Encrypt の証明書の有効期間は 90 日です。既定値33%
のままなら残りの有効期間が 30 日になった時点で証明書が更新されます。割合ではなく日数を指定する場合は%
の代わりにd
を使用します。21d
と指定すれば、 残り 21 日で証明書が更新されます。
- MDCertificateAuthority
- 認証局の証明書発行サービスの URL を指定します。既定値は
https://acme-v01.api.letsencrypt.org/directory
です。Let’s Encrypt は 1 日に証明書発行リクエストを出せる回数に上限があります。DNS やサーバーの設定に誤りがあって何度も証明書発行に失敗してしまうと、 しばらく証明書が発行できなくなってしまいます。そうならないように、 最初はテスト用の URLhttps://acme-staging.api.letsencrypt.org/directory
を指定して確認をしましょう。テスト用の URL なら何度失敗しても大丈夫です。ただし、 テスト用の URL では正規の証明書は発行されません。代わりにFake LE Intermediate X1
という偽物の証明書が発行されます。この証明書が発行されれば、 DNS やhttpd.conf
の設定に誤りはないはずです。それを確認してから正規の URLhttps://acme-v01.api.letsencrypt.org/directory
を設定するのが良いでしょう。
- MDCertificateAgreement
- Let’s Encrypt には利用規約があります。規約に同意せずに利用することはできません。とはいえ、 画面に規約を表示して同意ボタンを押させるようなインターフェースでは自動化の妨げになってしまいます。利用者は、 利用規約に同意したことを示すために、 読んで同意した利用規約の URL を
MDCertificateAgreement
に指定します。
最後にホスト固有の設定です。
ホスト固有の設定(httpd.conf)MDomain www.example.com
<VirtualHost *:443>
SSLEngine on
ServerName www.example.com
DocumentRoot "${SRVROOT}/htdocs"
# 本来ならここで SSLCertificateFile を指定しますが mod_md では必要ありません。
# MDStoreDir で指定した場所にサーバー証明書が作成され、それが自動的に使用されます。
</VirtualHost>
<VirtualHost *:80>
ServerName www.example.com
DocumentRoot "${SRVROOT}/htdocs"
</VirtualHost>
MDomain
ディレクティブに証明書を発行するドメイン名 (Common Name:CN) を指定します。あとは VirtualHost
ディレクティブ内の ServerName
に同じドメイン名を指定するだけです。
Apacheを起動してみる(1回目)
まずは練習ということで、 httpd.conf
の MDCertificateAuthority
にテスト用の URL https://acme-staging.api.letsencrypt.org/directory
を指定しておきます。
# MDCertificateAuthority https://acme-v01.api.letsencrypt.org/directory
# ↓
MDCertificateAuthority https://acme-staging.api.letsencrypt.org/directory
Apache を起動すると error.log
に気になる出力が記録されます。
error.log[Sun Jun 16 21:20:06.222610 2019] [ssl:warn] [pid 3528:tid 564] AH10085: Init: www.example.com:443 will respond with '503 Service Unavailable' for now. This host is part of a Managed Domain, but no SSL certificate is available (yet). [Sun Jun 16 21:20:15.727703 2019] [md:notice] [pid 3528:tid 528] AH10059: The Managed Domain www.example.com has been setup and changes will be activated on next (graceful) server restart.
読みやすいように改行を入れました。日本語に訳すとこんな感じでしょうか。
error.log(日本語訳)初期化: 今のところ www.example.com:443 は '503 Service Unavailable' を応答します。 このホストは管理ドメインの一部ですが、利用可能なSSL証明書が(まだ)ありません。 管理ドメイン www.example.com がセットアップされました。 変更は次回のサーバー再起動時に有効になります。
ちなみに、 利用可能な SSL 証明書がありませんという警告は 4 行出力されていました。
ふむぅ。1 回の起動ではダメなようです。おそらく、 Let’s Encrypt の証明書発行プロセス完了前に Apache を起動させるためにこのようになっているのでしょう。
ブラウザーで https://www.example.com
にアクセスしてみても、 やはりエラーが表示されます。
証明書を表示してみると、 Apache Managed Domain Fallback
という証明書になっています。これは Let’s Encrypt が発行した証明書ではなく Apache 内部で生成されたダミー証明書です。ダミー証明書で代替することで、 ひとまず、 Apache が起動できる仕掛けのようです。(従来の SSLCertificateFile
ディレクティブを使う方法では、 サーバー証明書なしで HTTPS 構成の Apache を起動させることはできなかったはずです。)
Apacheを起動してみる(2回目)
次回のサーバー再起動時に有効になるとログに出ていたのですから、 素直に Apache を再起動してみましょう。
error.log[Sun Jun 16 21:23:47.907378 2019] [ssl:warn] [pid 11084:tid 536] AH10085: Init: www.example.com:443 will respond with '503 Service Unavailable' for now. This host is part of a Managed Domain, but no SSL certificate is available (yet). [Sun Jun 16 21:23:48.032424 2019] [mpm_winnt:notice] [pid 11084:tid 536] AH00455: Apache/2.4.39 (Win64) OpenSSL/1.1.1c SVN/1.12.0 configured -- resuming normal operations [Sun Jun 16 21:23:48.032424 2019] [mpm_winnt:notice] [pid 11084:tid 536] AH00456: Server built: May 29 2019 21:57:40
no SSL certificate is available (yet).
(利用可能な SSL 証明書がありません) という警告がまだ出ていますね。初回は 4 行出ていたのですが、 今回は 1 行しか出ていないので起動シーケンスの途中で問題が解決したのかもしれません。
ブラウザーで https://www.example.com/
を開いてみましょう。
やはりダメなのかな? 一応、 証明書も確認しておきましょうか。
おおっ。さっきとは証明書が違います。発行者が Fake LE Intermediate X1
になっています。LE
というのは Let's Encrypt
の略ですね。これは Let’s Encrypt が発行してくれた証明書 (のフェイク) です。
証明書がフェイクになっているのは MDCertificateAuthority
にテスト用の URL https://acme-staging.api.letsencrypt.org/directory
を指定していたからです。想定通りです。
フェイクとはいえ Let’s Encrypt から証明書を取得できたわけですから、 DNS や Apache の設定には問題なさそうです。自信が出てきました。
Apacheを起動してみる(3回目)
フェイク証明書の発行が成功したので正規の証明書発行に進みましょう。
httpd.conf
の MDCertificateAuthority
ディレクティブの値を正規のサービス URL https://acme-v01.api.letsencrypt.org/directory
にします。
httpd.confMDCertificateAuthority https://acme-v01.api.letsencrypt.org/directory
それと、 フェイク証明書一式が ${SRVROOT}/md
(たとえば C:\Apache24\md
など) に残っているので削除しておきましょう。md
フォルダーをまるごと削除してしまって大丈夫です。必要に応じて md
フォルダーは再作成されます。
それでは、 3 回目の Apache を起動して error.log
を確認します。
error.log[Sun Jun 16 21:40:08.529514 2019] [ssl:warn] [pid 6824:tid 564] AH10085: Init: www.example.com:443 will respond with '503 Service Unavailable' for now. This host is part of a Managed Domain, but no SSL certificate is available (yet). [Sun Jun 16 21:40:17.415908 2019] [md:notice] [pid 6824:tid 612] AH10059: The Managed Domain www.example.com has been setup and changes will be activated on next (graceful) server restart.
初回と同じで、 サーバー再起動で有効になる旨のメッセージが出力されています。md
フォルダーをまるごと削除して証明書が存在しない状態に戻したの当然ですね。
Apacheを起動してみる(4回目)
もう一度、 Apache の起動して、 ブラウザーで https://www.example.com/
にアクセスします。
うまくいきました! 「この接続は保護されています」 と表示されています。
証明書の発行者は Let's Encrypt Authority X3
となっています。Fake
の表示はありません。
今回は、 テスト用の URL を指定してフェイク証明書を発行して練習しましたが、 DNS などネットワーク構成に問題ないことが分かっているなら、 初回から正規の URL https://acme-v01.api.letsencrypt.org/directory
を指定しても構いません。
Apache を再起動しないと有効にならないというのは少しモヤっとしますが、 単純に再起動すればいいだけなので大した手間ではありません。win-acme のときよりもずっとシンプルになりました。嬉しいです。