今や必須のSSL! Let's Encryptを使って無料で実現

 自分専用のホームページだったり、身内だけで公開する会員的なホームページであればオレオレ認証局でも問題ない。
 しかし接続の度にセキュリティ警告画面が表示されてしまうので不特定多数の人に見てもらう為のホームページでオレオレ認証局だと、誰もアクセスしてくれないページになってしまうでしょう。

 そこで無料SSLのLet’s Encryptを使って証明書を発行してもらえば、無料なのにSSL通信で警告も出ないホームページになります。

目次
 ・チャレンジタイプ
 ・certbotのインストール
 ・証明書の発行
 ・DNSの設定
 ・証明書発行の続き
 ・Apacheの設定

チャレンジタイプ

 Let’s Encrypt から証明書を取得するには「チャレンジ」というものを利用して、証明書を申請しようとしているドメインが申請者の制御下にあることを検証する為の仕組みの様です。
 なのでまずどんなチャレンジタイプがあるのかを理解してから設定を始めましょう。

HTTP-01 challenge
 2020年12月時点で最も一般的なチャレンジタイプ。(らしいです)
 大まかにアタイなりに理解した内容を記載すると、証明書発行したいドメインを使用しているWebサーバにアカウントキーなどが含まれたファイルを設置し、80番ポートを開放しておくことでLet's Encryptからそのファイル取得を試みてWebサーバが正常な応答を返せば証明書の発行処理を進めることができるようです。

DNS-01 challenge
 HTTP-01チャレンジよりも難しい構成だがHTTP-01ではできない事もできるようです。その一つがワイルドカード(*)を使って複数ホスト名を1つの証明書で補うことができます。
 DNS-01であれば80番ポートも開放する必要がなくなりますが、DNSサーバでTXTレコードの追加作業などが発生します。(DNSの設定が必要という点がHTTP-01よりも難しいと説明されている理由かな?)


 主な2つのチャレンジタイプを記載しましたが、そもそもセキュリティーを考えてSSLを使いたいのにその承認の為に80番ポートを開放しなくてはいけないHTTP-01チャレンジは本末転倒な気がする。
まぁ~申請時だけ80番ポートを開放すればいいのかもしれないが、本当にそれで問題が発生しないかどうかもわからない。
というかそこまで深く理解する前に、ワイルドカードを使えるDNS-01チャレンジしか選択肢がないと考えた為調べることもしなかったのだが・・・

 という事で以下はDNS-01チャレンジでワイルドカードを使った申請方法を記載していきます。

certbotのインストール

 まずはcertbotのインストールから。
 dnfコマンドでインストールすれば certbotコマンドに依存するものもインストールされます。

dnf -y install certbot
依存関係が解決しました。
-----------------------------
 パッケージ
-----------------------------
インストール:
 certbot
依存関係のインストール:
 python3-acme
 python3-certbot
 python3-configargparse
 python3-configobj
 python3-josepy
 python3-parsedatetime
 python3-pyasn1
 python3-pyrfc3339
 python3-pytz
 python3-requests-toolbelt
 python3-zope-component
 python3-zope-event
 python3-zope-interface
弱い依存関係のインストール:
 python-josepy-doc

証明書の発行

Let's Encryptの証明書の発行には「certbot」コマンドを使って証明書を発行します。
具体的には


certbot certonly --manual --preferred-challenges dns -m [管理者のメールアドレス] -d "[SSL通信を使いたいホスト名無しのドメイン]" -d "*.[SSL通信を使いたいホスト名無しのドメイン]"

となるのですが、まずコマンドオプションの解説です。

オプション解説

certonly
証明書のインストールはせず、SSL/TLS サーバ証明書の取得のみを行います。
--manual
ドメイン名の認証を手動で行い、SSL/TLS サーバ証明書を取得を行います。
--preferred-challenges
ワイルドカードを使用する場合は
dns-01チャレンジとやらを行わないといけないらしく「dns-01」を指定します。
2021年8月5日修正
「dns」を指定します。
-m
管理者メールアドレスを指定します。
-d
SSLを使うドメインを指定します。
  ホスト毎に証明書を発行するのは面倒なのでワイルドカードを使って、
  以後ホスト名を増やしても問題ないようにします。
  とはいえ、「*.caramelsauce.info」だけだとホスト名なしのURLに対して
  SSL通信ができなくなってしまうので更にホスト名なしのものも追加します。

 自分なりに解釈した解説なのでホラを吹いている可能性もあるかと・・・(^^;

では実際にコマンドを実行してみます。


certbot certonly --manual --preferred-challenges dns -m root@caramelsauce.info -d "caramelsauce.info" -d "*.caramelsauce.info"
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server. Do you agree?
// 「ACMEサーバに登録するには同意する必要があります。同意しますか?」という設問です。
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: y        // 「y」で同意します。

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing, once your first certificate is successfully issued, to
share your email address with the Electronic Frontier Foundation, a founding
partner of the Let's Encrypt project and the non-profit organization that
develops Certbot? We'd like to send you email about our work encrypting the web,
EFF news, campaigns, and ways to support digital freedom.
// アバウトに言うと「ニュースやキャンペーンのメールを送っていいですか?」という設問です。
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: n       /" 特にニュースなど英語で送られてきてもわからないので「n」で。 */

Account registered.
Requesting a certificate for caramelsauce.info and *.caramelsauce.info
Performing the following challenges:
dns-01 challenge for caramelsauce.info
dns-01 challenge for caramelsauce.info

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name
_acme-challenge.caramelsauce.info with the following value:

xxxxxxxxXXXXXXXXXXXXxxxxxxXXXXxXXXxxxxXXXXxxXXXxxXXXX

Before continuing, verify the record is deployed.
// Enterを押す前に ハイライト下部分の文字列をDNSに反映させなさい。と。
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue

 ここの36行目でEnterを押す前にDNSの設定に入ります。

DNSの設定

 下記の画面キャプチャはinterlinkの無料DNSサービスのZONE設定画面です。
 ・ホスト名:_acme-challenge
 ・タイプ:TXT
 ・データ:ハイライト部分の文字列

 DNSの設定をしてしばらくしたら「Press Enter to Continue」で止まっているターミナルでEnterを押します。
(私のDNSサービスでは1分もあれば反映されました。)

証明書発行の続き

 ターミナルに戻って「Enter」を押すと続きがあります。

 さっきと違う文字列が表示されました。
 『さっき設定した1つめのDNS設定「_acme-challenge」の設定は削除も変更もするな。
さらに、DNS標準で許可されてるから「ホスト名」欄に2つ目の「_acme-challenge」を追加して登録しろ!』と、
言っているようです。


- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name
_acme-challenge.caramelsauce.info with the following value:

xxxXXXXXXXxxXxXXXXxXXxxxxxxxXXxxXxXXXxXXxXx

Before continuing, verify the record is deployed.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue

ということなので、さっきと同じようにDNSサービスで2つ目の「_acme-challenge」を設定します。


DNSの設定が完了して、しばらくしたらターミナルでEnterを押します。

Waiting for verification...
Cleaning up challenges
Some challenges have failed.

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/caramelsauce.info/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/caramelsauce.info/privkey.pem
   Your certificate will expire on 2021-xx-xx. To obtain a new or
   tweaked version of this certificate in the future, simply run
   certbot again. To non-interactively renew *all* of your
   certificates, run "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

  『証明書と中間証明書を連結したファイルを「fullchain.pem
 秘密鍵ファイルを「privkey.pem」として保存したよ。』と。

更に注意事項が続きます。
 『証明書の有効期限は(90日後)に切れるからこの証明書の新しいバージョンを取得するにはシンプルに「certbot」を再実行。
もし、非対話的に更新するには「certbot renew」コマンドを実行してください。』と。

『ふむ。フム。了解!!』という事で更新方法はこちらします。

Apacheの設定

 私のApache設定では、バーチャルホストの設定で記載した通り、ホスト名毎にVirtualHostディレクティブのファイルを分けて作っています。
例としては
 ・vf-schedule.caramelsauce.info.conf
 ・vf-blog.caramelsauce.info.conf
 というような感じでファイルを分けて設定しています。

 以上のことを踏まえて
 今回の証明書の発行には「*」を使ってすべてのホスト名で使えるような証明書にしました。
 よって、全てのVirtualHostディレクティブのファイルに同じ行を追記します。
 (そんなことはないと思うが、このホスト名だけはSSL通信したくない!というホスト名があれば設定する必要はないですが・・・)

 発行された証明書は場所を変えず、発行された場所をそのままコンフィグファイルに指定しました。
 理由は、場所を変えてしまうと更新の際にいちいちファイルの移動をしないといけなくなるかもしれないからです。
(まだ更新してないので分からないですが・・・)

<VirtualHost *:443>
        ServerName schedule.caramelsauce.info
	      DocumentRoot /var/www/schedule
	      ErrorLog logs/schedule-error_log
	      CustomLog logs/schedule-access_log combined env=!no_log
        SSLCertificateKeyFile /etc/letsencrypt/live/caramelsauce.info/privkey.pem
        SSLCertificateFile /etc/letsencrypt/live/caramelsauce.info/cert.pem
        SSLCertificateChainFile /etc/letsencrypt/live/caramelsauce.info/chain.pem
</VirtualHost>

変更点は
 ・1行目のポートを80から443に変更します。
あと、バーチャルホストの設定時は「CustomLog」の行までしか記載していないので、
 ・SSLCertificateKeyFile : 秘密鍵
 ・SSLCertificateFile : 証明書
 ・SSLCertificateChainFile : 中間CA証明書
 これらの行を追加しました。
コンフィグの設定を保存したらApacheを再起動します。
あっ!一応コンフィグファイルの整合性も確認しておきますか!

apachectl configtest
Syntax OK
systemctl restart httpd

 Apacheの再起動が完了したら
ブラウザで「http://」ではなく「https://」に変えてアクセスしてみましょう。警告も出ずページが表示されたら完了です。