April 26, 2020 | 20:50

Cloudflare の SSL/TLS を Full (strict) で運用する

これから Web サーバを立ち上げるなら常時SSLにしたいところです。

Let’sencrpt で証明書を自動更新したい場合、Nginx単体だと $ sudo certbot --nginx で完了しますが Cloudflare で常時SSL設定をすると上手くいきません。certbot は http で acme-challenge を行うため origin までリクエストが届かないからです。

このような環境で origin 側の証明書を作成/更新するには2つの方法があります

  1. Cloudflare の Origin Certificates 機能を使用する

    Cloudflare の SSL/TLS ページ Origin Server タブで origin サーバのための証明書を発行できます。 しかしこの証明書は Cloudflare が発行するオレオレ証明書のため origin サーバに直接アクセスする場合に難があります

  2. certbot-dns-cloudflare を利用する

    Cloudflare DNS API を使用して http を利用せずに Let’sencrypt のドメインの認証をします。 origin サーバに直接アクセスできた方が良いので今回は2番目の方法を採用します。

想定環境

  • OS: Ubuntu 19.10 or Ubuntu 20.04
  • Web サーバ: Nginx

certbot の導入

最近の Ubuntu だと apt で OK なので便利です。その他の環境の場合は 公式手順を参照してください。

1
sudo apt install certbot python-certbot-nginx python3-certbot-dns-cloudflare

Cloudflare API token の発行

アカウントの登録やドメインの登録は Cloudflare が指示するフロー通りで大丈夫です。

  • Overview ページ右下のAPIのところに Get your API token へのリンクがあります
  • Create API Token を押して Edit zone DNS の template を使用して使用するドメインを指定して Create Token を押します。Edit zone DNS 以外の権限は不要です。

~/.secrets/certbot/cloudflare.ini に token を書く

1
2
mkdir -p ~/.secrets/certbot
echo "dns_cloudflare_api_token = 入手したトークン" > ~/.secrets/certbot/cloudflare.ini

certbot を叩いて証明書を発行する

1
sudo certbot certonly --dns-cloudflare --dns-cloudflare-credentials ~/.secrets/certbot/cloudflare.ini -d ドメイン名

成功すると /etc/letsencrypt/live/ドメイン名/ 以下に証明書が格納されます

Nginx の設定

$ sudo certbot --nginx だと自動的に行ってくれますが今回は certonly (証明書発行のみ)なので自分で行う必要があります。

/etc/nginx/sites-enabled/default
server {
    # SSL configuration
    #
    listen 443 ssl default_server;
    listen [::]:443 ssl default_server;

    ssl_protocols TLSv1.3 TLSv1.2;
    ssl_certificate /etc/letsencrypt/live/ドメイン名/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/ドメイン名/privkey.pem;

    # Other configurations
}

自動更新

$ sudo certbot --nginx だとこちらも自動的設定ですが今回は自分で行う必要があります。 /etc/cron.d/ 以下に certbot というファイルを作成して定期的に実行されるようにします。 証明書を更新後に Nginx をリロードしています。

/etc/cron.d/certbot
0 */12 * * * root test -x /usr/bin/certbot -a \! -d /run/systemd/system && perl -e 'sleep int(rand(43200))' && certbot -q renew && /bin/systemctl reload nginx