2017年10月4日水曜日

FreeBSD+ApacheのLet's Encrypt導入が簡単だった件

StartSSLが使い物にならなくなったため、Let's Encryptを導入しようとしたのだが、仕組みがよくわからず、ずっと敬遠していた。
しかしようやく導入してみたところ、全然簡単だったためここに記す。

なお私の場合、Apacheを80番ポートで運用しておらず、尚且つルートディレクトリに既にアクセス制限を行っているため、通法ではLet's Encryptのドメイン認証が行えない。
そのため、スタンドアロンのドメイン認証用サーバープログラムを走らせて認証を行う。
このように書くとややこしく思えるが、行うことは非常に単純である。

まず、Let's Encryptの証明書取得ツールを導入する。
# pkg install py27-certbot

そして、ドメイン認証と証明書取得を行うのだが、この際ポート443で待ち受けしているソフトがある場合終了させる。(ApacheのSSLが443で待ち受けている場合はApacheを終了させる)
# /usr/local/etc/rc.d/apache24 stop

証明書取得を対話モードで行う
# certbot certonly

How would you like to authenticate with the ACME CA?
-------------------------------------------------------------------------------
1: Spin up a temporary webserver (standalone)
2: Place files in webroot directory (webroot)
-------------------------------------------------------------------------------
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 1
↑ここで今回はスタンドアロンサーバーで認証を行うため、1を入力してEnter
Enter email address (used for urgent renewal and security notices) (Enter 'c' to
cancel): hoge@hogehoge.com
連絡用メールアドレスを聞かれるため入力してEnter。(メール認証は特に行われない)

-------------------------------------------------------------------------------
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf. You must agree
in order to register with the ACME server at
https://acme-v01.api.letsencrypt.org/directory
-------------------------------------------------------------------------------
(A)gree/(C)ancel: a
↑利用規約に同意するか聞かれるのでaを入力しEnter

-------------------------------------------------------------------------------
Would you be willing 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 EFF and
our work to encrypt the web, protect its users and defend digital rights.
-------------------------------------------------------------------------------
(Y)es/(N)o: n
EFFにメールアドレスを登録するか聞かれるので、任意で答える。私の場合はnを入力してEnterした。

Please enter in your domain name(s) (comma and/or space separated)  (Enter 'c'
to cancel): hogehoge.com
↑自分のドメイン名を入力

以下、証明書取得に伴うメッセージが表示される。
Obtaining a new certificate
Performing the following challenges:
tls-sni-01 challenge for hogehoge.com
Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /usr/local/etc/letsencrypt/live/hogehoge.com/fullchain.pem. Your
   cert will expire on 20YY-MM-DD. 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
これだけ!!これだけでもう、/usr/local/etc/letsencrypt/live/hogehoge.com/にサーバー証明書、プライベートキー、中間CA証明書ができている!

あとはApacheのSSL設定ファイルでこれらのファイルをそれぞれ指定するだけである。
# vi /usr/local/etc/apache24/extra/httpd-ssl.conf

#   Server Certificate:
#   Point SSLCertificateFile at a PEM encoded certificate.  If
#   the certificate is encrypted, then you will be prompted for a
#   pass phrase.  Note that a kill -HUP will prompt again.  Keep
#   in mind that if you have both an RSA and a DSA certificate you
#   can configure both in parallel (to also allow the use of DSA
#   ciphers, etc.)
#   Some ECC cipher suites (http://www.ietf.org/rfc/rfc4492.txt)
#   require an ECC certificate which can also be configured in
#   parallel.
SSLCertificateFile "/usr/local/etc/letsencrypt/live/hogehoge.com/cert.pem"
#SSLCertificateFile "/usr/local/etc/apache24/server-dsa.crt"
#SSLCertificateFile "/usr/local/etc/apache24/server-ecc.crt"

#   Server Private Key:
#   If the key is not combined with the certificate, use this
#   directive to point at the key file.  Keep in mind that if
#   you've both a RSA and a DSA private key you can configure
#   both in parallel (to also allow the use of DSA ciphers, etc.)
#   ECC keys, when in use, can also be configured in parallel
SSLCertificateKeyFile "/usr/local/etc/letsencrypt/live/hogehoge.com/privkey.pem"
#SSLCertificateKeyFile "/usr/local/etc/apache24/server-dsa.key"
#SSLCertificateKeyFile "/usr/local/etc/apache24/server-ecc.key"

#   Server Certificate Chain:
#   Point SSLCertificateChainFile at a file containing the
#   concatenation of PEM encoded CA certificates which form the
#   certificate chain for the server certificate. Alternatively
#   the referenced file can be the same as SSLCertificateFile
#   when the CA certificates are directly appended to the server
#   certificate for convenience.
SSLCertificateChainFile "/usr/local/etc/letsencrypt/live/hogehoge.com/chain.pem"

これで、Apacheを起動できれば無事導入できている。
# /usr/local/etc/rc.d/apache24 start
Performing sanity check on apache24 configuration:
Syntax OK
Starting apache24.

Let's Encryptの証明書期限は90日しかないため、それ以内に更新する必要があるが、更新するときは下記コマンドを入力するだけである。(この時もスタンドアロンサーバーが起動するため、競合するサーバープログラムがある場合は停止する)
# certbot renew 
これだけで更新される。超簡単!

2017年10月13日追記
証明書更新時にApacheの再起動も行う場合は下記のコマンドを使う。証明書の更新がある場合はApacheを停止し、証明書更新後Apacheを再起動する。私の環境では何故かエラーメッセージが出ますが実用上問題なさそうです。これをCronに登録しておけば多分OK。
certbot renew --pre-hook "service apache24 stop" --post-hook "service apache24 start"

実際に更新はしないが、更新できるかどうか試したい場合、下記のコマンドを入力する。
# certbot renew --dry-run
下記のように出てくれば成功。
Saving debug log to /var/log/letsencrypt/letsencrypt.log

-------------------------------------------------------------------------------
Processing /usr/local/etc/letsencrypt/renewal/hogehoge.com.conf
-------------------------------------------------------------------------------
Cert not due for renewal, but simulating renewal for dry run
Renewing an existing certificate
Performing the following challenges:
tls-sni-01 challenge for hogehoge.com
Waiting for verification...
Cleaning up challenges

-------------------------------------------------------------------------------
new certificate deployed without reload, fullchain is
/usr/local/etc/letsencrypt/live/hogehoge.com/fullchain.pem
-------------------------------------------------------------------------------
** DRY RUN: simulating 'certbot renew' close to cert expiry
**          (The test certificates below have not been saved.)

Congratulations, all renewals succeeded. The following certs have been renewed:
  /usr/local/etc/letsencrypt/live/hogehoge.com/fullchain.pem (success)
** DRY RUN: simulating 'certbot renew' close to cert expiry
**          (The test certificates above have not been saved.)
赤文字で下記のエラーが出た場合は、競合するサーバープログラムがあり、更新に失敗しているのでそれらを停止してから更新を行う。
Attempting to renew cert from 
/usr/local/etc/letsencrypt/renewal/hogehoge.com.conf produced an 
unexpected error: Problem binding to port 443: Could not bind to IPv4 or
 IPv6.. Skipping.

いやはや、あまりの簡単さに愕然とした。最早簡単すぎてセキュリティスペシャリストの勉強にならない次元である。

巷には公式サイトからの引用で、
$ sudo certbot certonly --webroot -w /var/www/example -d example.com -d 
www.example.com -w /var/www/thing -d thing.is -d m.thing.is
とコマンドを入力する導入方法が紹介されているところが多く見られるが、今回のやり方が初心者には一番わかり易いのではないかと思う。
慣れてきたら上記コマンドで導入したいが、次回以降使うのは# certbot renew だけなのである(笑)。

一度導入すると仕組みがわかると思うので、色々とチャレンジしたい場合は非公式解説サイトを読んでみると良いと思う。
https://letsencrypt.jp/faq/


参考:
certbot
https://certbot.eff.org/#freebsd-apache


Let's Encrypt 総合ポータル
https://letsencrypt.jp/

完全に闇に落ちていた StartSSL に ¥3,603 課金してしまったお話
https://masutaka.net/chalow/2017-01-10-1.html