Let’s Encryptをnginx + dehydratedで使う

前回は海外通販でのお買い物を紹介しましたが、今回は話題をちょっと変えてサーバ運用についてです。

かなり昔にLet’s Encryptの無料のSSL証明書を導入したことを紹介しました。

今回はLet's Encryptの提供する正式なサーバ証明書を取得する方法を紹介します。これでオレオレ証明書を使うことなくSSLを使ったサーバを構築することができます。Webサイトを完全HTTPS化をするにはほかにもいろいろ作業が必要なのですが、第一歩としてサーバ証明書を入手しておくことをお勧めします。

今回はLet’s Encryptを利用するためのクライアントプログラムをdehydratedに変更したことを紹介します。

Let’s Encryptクライアント

Let’s EncryptはSSL証明書の発行・更新にクライアントプログラム(Let’s Encryptクライアント)が必要になります。

Let’s Encryptとの通信方法はACMEプロトコルとして規格化されているの様々なLet’s Encryptクライアントが開発されています。

ざっと調べてみたところ次のようなLet’s Encryptクライアントが見つかりました。

  • acmetool: automatic certificate acquisition tool for Let’s Encrypt
  • dehydrated: ACME client implemented in Bash
  • certbot (letsencrypt): automatically configure HTTPS using Let’s Encrypt
  • acme-tiny: letsencrypt tiny Python client

私は「letsencrypt」というスクリプトを使っていて、そのあとは「certbot」というクライアントを使ってきました。

certbotが使えなくなる!?

certbotで問題なく運用できていたのですが、先日Let’s encryptoから次のようなメールが送られきました。

Subject: Action required: Let’s Encrypt certificate renewals

Hello,

**Action is required to prevent your Let’s Encrypt certificate renewals from breaking.**

Your Let’s Encrypt client used ACME TLS-SNI-01 domain validation to issue a certificate in the past 60 days.

TLS-SNI-01 validation is reaching end-of-life and will stop working on **February 13th, 2019.**

You need to update your ACME client to use an alternative validation method (HTTP-01, DNS-01 or TLS-ALPN-01) before this date or your certificate renewals will break and existing certificates will start to expire.

If you need help updating your ACME client, please open a new topic in the Help category of the Let’s Encrypt community forum:

https://community.letsencrypt.org/c/help

Please answer all of the questions in the topic template so we can help you.

For more information about the TLS-SNI-01 end-of-life please see our API announcement:

Let’s Encrypt allows subscribers to validate domain control using any one of a few different validation methods. For much of the time Let’s Encrypt has been ope...

Thank you,
  Let’s Encrypt Staff

どうも私が使っているLet’s Encryptクライアント(certbot)は2019/02/13に使えなくなってしまうようです。理由は「TLS-SNI-01 domain validation」という認証方法が無効になるからのようです

もう少し調べてみるとcertbotの0.28.0以降であればTLS-SNI-01 domain validationを停止して別の認証方法が使えるようです。

Let’s Encrypt is removing support for domain validation with TLS-SNI-01. If you’re using Certbot and received an email titled “Action required: Let’s Encrypt ce...

しかし、私がサーバに使っているDebian 9.6 (stretch)に入っているcertbotは0.10.2で駄目そうです。

あとから調べるてみるとstretch-backportsを使うと certbot 0.28.0を導入できるようです。

そこでLet’s Encryptクライアントを dehydrated に変更してみることにしました。

準備

Let’s Encryptを使った作業を行う前に、まず自分の環境を確認しておきましょう。

  • サーバ証明書を取りたい(HTTPSを使いたい)ドメインはどれか
    今回の例では「example.com」と「example.net」の二つとします
  • 使用しているWebサーバは何か
    私の場合はNginxです
  • HTTPでアクセスするためのWebサーバの設定ファイルはどれか
    サーバがNginxの場合は設定ファイルは/etc/nginx/sites-availableに置かれていて、その設定を有効にする場合は /etc/nginx/sites-enabledにシンボリックリンクが貼られているはずです。

Webサーバの設定ファイルを把握する必要があるので、dehydratedが制したファイルを外部から取得できるようにする必要があるからです。

dehydratedはドメインの所有者であることを証明するファイルを作成し、それをLet’s Encrypt側がHTTPで取得することでドメインの持ち主であると認証します。

設定ファイルはHTTPS用ではなくHTTP用であることに注意してください。

dehydratedのインストールと設定

まずdehydratedをインストールしていきます。dehydratedはDebianのパッケージとして含まれているので簡単にインストールすることができます。

$ sudo apt-get update
$ sudo apt-get instal dehydrated

バージョンが「0.3.1」とちょっと古いですが、そのまま使ってみます。

dehydratedの設定ファイルは/etc/dehydrated以下に格納されます。デフォルトの設定ファイル(/etc/dehydrated/config)の中身は次のようになっています。

#############################################################
# This is the main config file for dehydrated               #
#                                                           #
# This is the default configuration for the Debian package. #
# To see a more comprehensive example, see                  #
# /usr/share/doc/dehydrated/examples/config                 #
#                                                           #
# For details please read:                                  #
# /usr/share/doc/dehydrated/README.Debian                   #
#############################################################

CONFIG_D=/etc/dehydrated/conf.d
BASEDIR=/var/lib/dehydrated
WELLKNOWN="${BASEDIR}/acme-challenges"
DOMAINS_TXT="/etc/dehydrated/domains.txt"

基本的にこのフィルは変更する必要がありません。

もし設定の変更が必要な場合は /etc/dehydrated.dディレクトリに拡張子.shのファイルを置くことで設定を上書きすることができます。

設定をする必要があるのは証明書を取得するドメインです。今回は次のような内容のファイルを/etc/dehydrated/domains.txtとして作成します。

example.com
example.net

もし一つの証明書で複数のサブドメインをサポートする場合は1行にまとめて書きます。例えばexample.comとwww.example.comの両方に対応する証明書を管理したい場合は

example.com www.example.com

のようにスペース区切りでリストアップします。

nginxの設定の変更

dehydratedは/var/lib/dehydrated/.well-known以下にドメイン認証のファイルを生成します。

nginxの設定ファイルを変更してこのディレクトリを外部からアクセスできるようにします。

まずは共通の設定ファイルを作ります。下記の内容ファイルを/etc/ngins/snippets/dehydrated.confとして作成します。

location ^~ /.well-known/acme-challenge {
    alias /var/lib/dehydrated/acme-challenges;
    break;
}

そしてこのファイルをHTTP(ポート80)でのアクセス処理を設定するファイルで取り込みます。例えば、http://example.com/を処理するためのファイルが/etc/nginx/sites-available/example.com.confというファイルがあればそのファイルの中で次のように記述します。

server {
    listen 80;
    server_name example.com;
    ...
    include snippets/dehydrated.conf;
    ...
}

設定ファイルの編集が終わったらnginxの設定ファイルにエラーがないかどうかチェックしましょう。

$ sudo service nginx testconfig
[ ok ] Testing nginx configuration:.

このように「ok」と表示されれば設定ファイルに以上はありません。

次のコマンドで変更した設定を有効にします。

$ sudo service nginx reload

SSL証明書の取得!

新しいバージョンのdehydratedを使う場合はアカウントのセットアップが必要なようです。

$ sudo dehydrated --register --accept-terms
# INFO: Using main config file /etc/dehydrated/config
+ Generating account key...
+ Registering account key with ACME server...
+ Done!

ここまでできたらdehydratedを使ってSSL証明書を取得します。下記のコマンドをルートで実行するだけです。

$ sudo dehydrated -c
# INFO: Using main config file /etc/dehydrated/config
# !! WARNING !! Extra configuration directory /etc/dehydrated/conf.d exists, but no configuration found in it.
Processing example.com
 + Signing domains...
 + Creating new directory /var/lib/dehydrated/certs/example.com ...
 + Generating private key...
 + Generating signing request...
 + Requesting challenge for example.com...
 + Responding to challenge for example.com...
 + Challenge is valid!
 + Requesting certificate...
 + Checking certificate...
 + Done!
 + Creating fullchain.pem...
 + Done!
Processing example.het
 + Signing domains...
 + Creating new directory /var/lib/dehydrated/certs/example.net ...
 + Generating private key...
 + Generating signing request...
 + Requesting challenge for example.net...
 + Responding to challenge for bullettraveler.com...
 + Challenge is valid!
 + Requesting certificate...
 + Checking certificate...
 + Done!
 + Creating fullchain.pem...
 + Done!

これで/var/lib/dehydrated/certsの下に証明書が作成されます。

SSL証明書の設定

SSL証明書が取得できたらこの証明書を使用するようにnginxの設定を変更しましょう。

HTTPSを処理する設定フィアルに次のように「ssl_certificate」と「ssl_certificate_key」の行を追加します。

server {
    listen 443 ssl http2;
    server_name example.com;
    ...
    ssl_certificate     /var/lib/dehydrated/certs/example.com/fullchain.pem;
    ssl_certificate_key /var/lib/dehydrated/certs/example.com/privkey.pem;
    ....
}

設定ファイルの変更が完了したら「service nginx testconfig」で間違えがないかどうかチェックし、「service nginx reload」で新しい設定を有効にします。

あとはWebブラウザでSSL証明書をセットしたサイトにアクセスしてみましょう。ブラウザのアドレスバーに鍵マークが出ていればOKです。

鍵マークをクリックして証明書の情報を表示させると、発行元が「Let’ Encrypt Authority X3」で有効期間はSSL証明書を取得した日から90日となっているはずです。

取得した証明書

HTTPSが使えるようになって、HTTPによる接続を全てHTTPSにリダイレクトする場合は、HTTPSのnginxの設定ファイルでも

include snippets/dehydrated.conf;

としておきましょう。証明書を更新するときにドメイン認証で失敗してしまいます。

自動更新の設定

Let’s EncryptのSSL証明書の有効期間は90日です。将来的にはさらに短くなるという話もあります。

そこで月に1回更新をチェックするように次のようなスクリプトファイルをdehydratedという名前で/etc/cron.monthlyに作成します。

#!/bin/sh

/usr/bin/dehydrated -c > /var/log/dehydrated.log 2> /var/log/dehydrated.err && service nginx reload

あとはこのスクリプトファイルに実行権限をつければ毎月更新をチェックします。

$ sudo chmod +x /etc/cron.monthly/dehydrated

更新をチェックして残り有効期限が30日を切っていると自動的に証明書を更新してくれます。

まとめ

今回はLet’s Encrypt用のクライアントをcertbotからdehydratedに変更してnginxでSSLが使えるようにしました。

dehydratedは実行時に引数としてパラメータを与える必要がないので、certbotよりも簡単に管理できるのではないかと思います。

certbotがうまくいかない場合はdehydratedに乗り換えることをお勧めします。

次回はまた海外通販の話題に戻ります。