Let’s Encryptから証明書を取得して常時HTTPS化

目次
  • Let’ Encryptから HTTPS(暗号化)通信に必要な証明書を無料で発行してもらいました。

  • HTTPS が有効になるように Apache の設定を変更して、暗号化されていることを示す鍵アイコンが表示されることを確認しました。

  • HTTP でのリクエストを HTTPS に転送して常時 HTTPS 化しました。

  • HTTPS の証明書には有効期限があるので、自動的に更新できるようにしました。

  • 証明書の取得

  • Apache の設定

  • 証明書の自動更新

HTTPS は Web の通信を暗号化するために使われていると一般的には思われています。しかし実際には暗号化だけでなく、Web サイトを運営する会社・組織の身元を保証する(注1)ためにも使われています。

そのため身元を保証してもらいたい会社・組織は審査を受ける必要が有り、時間とそれなりのお金をかけて証明書を発行してもらっていました。その結果としてユーザは安心してオンラインで買い物をしたり預金を確認できます。

一方、身元の保証は必要なく単純に安全な通信のために HTTPS を使いたいという場合には、これまでのやり方は非常に手間がかかりハードルが高いものです。そこで誰でも HTTPS の暗号化機能を手軽に使えるようにするためLet’ Encrypt プロジェクトが、Web サイトの身元は保証しないけど暗号化に使用できる証明書を機械的かつ無料で発行する実験が開始されました。

会社・組織の身元保証が無いので商業利用向きではありませんが、個人の Web サーバでも簡単に HTTPS を使って安全な通信を行えるようになりました。

ここでは HTTPS に必要な証明書の取得方法からサーバの設定、証明書の更新方法について説明します。

証明書の取得

HTTPS の証明書は、専用のプログラムletsencryptを使用して取得します。

letsencryptをインストール

letsencryptは、Debian などパッケージとして配布されている場合も有りますが、Ubuntu ではまだパッケージになっていなのでgitコマンドを使ってプログラムを取得します(注2)。

$ sudo apt-get install git # gitをまずインストールする。
$ git clone https://github.com/letsencrypt/letsencrypt
$ cd letsencrypt

HTTPS の証明書を取得

letsencrypt-autoコマンドを実行して HTTPS の証明書を取得します。

Web サーバに Apache を使用している場合は、次のコマンドを実行します(注3)。

ただしこのコマンドを実行するとサーバが一時的に停止します。ダウンタイムを最小にするには、--apacheの代わりに--webrootオプション(webroot mode)を使用します(注4)。

$ ./letsencrypt-auto --apache

実行すると必要なパッケージがインストールされ、証明書を取得するために必要な質問をいくつかされます。質問に答えてしばらく(1 分程度)待つと HTTPS 証明書が/etc/letsencrupt/live/に保存されます。

もしかすると、証明書を取得するときに HTTPS ポートが開いている必要があったかもしれません。その場合は、次の「HTTPS ポート(443)を公開」を参照してください。

証明書を取得するときに質問される項目は次の 3 つです。

  1. 現在の Apache がホストしているドメインの内で証明書に含めるドメイン名。
  2. 連絡先のメールアドレス。
  3. Let’s Encrypt を使用するための決まりに同意するか。

1.で選択したドメイン名は、全て同じ証明書を使って HTTPS 通信が行えます(SAN Certificate?)。また-dオプションで事前に対象のドメイン名を指定しておくことができます。

複数のサーバ名を指定すると「複数のサーバ名はサポートしていない」というようなエラーが表示されますが、問題なく使えています。

2.と 3.の質問は、それぞれ--email--agree-tosオプションで事前に指定しておけます。

オプションの詳しい説明は、

$ ./letsencrypt-auto --help all

で取得できます。説明が表示されるのが遅いので、次のようにリダイレクトを使って説明を保存しておくと後で参照しやすくなって便利だと思います。

$ ./letsencrypt-auto --help all > help.txt

--apacheオプションは、証明書の取得の他にインストールもするということですが、具体的に何をしているのか私には分かりませんでした(注5)。Apache の設定を変えてくれるということもありませんでしたし、インストール機能がないwebrootでも証明書は同じ場所に保存されました。

またletsencrypt-autoを実行すると、/var/log/letsencrypt/letsencrypt.logにログが記録されます。

HTTPS ポート(443)を公開

HTTPS で通信するには、HTTPS 用のポートに外部からアクセスできる必要が有ります。

HTTPS ポートを開くためには、次のルールを iptables の設定に追加します。既に HTTP 用のルールが書かれていると思うので、その後ろあたりに追加するのが良いと思います。また二番目のようにmultiportモジュールを使って HTTP ポートと HTTPS ポートをまとめてルールにすることもできます。

iptables -A INPUT -p tcp --syn -m state --state NEW --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --syn -m state --state NEW --dport 443 -j ACCEPT

# or

iptables -A INPUT -p tcp --syn -m state --state NEW -m multiport --dports 80,443 -j ACCEPT

iptables の設定はサイトを守る上で非常に重要ですので、十分注意してください。

Apache の設定

HTTPS の証明書を取得できたら、その証明書を使って HTTPS 通信ができるように Apache の設定を変更します。

SSL モジュールを有効化

HTTPS 通信をするには、Apache の SSL モジュールを有効にします。

次のようにして SSL モジュールを有効にしますが、もしかするとletsencrypt-auto --apacheが既にモジュールを有効にしているかもしれません。もちろん既に ssl モジュールが有効になっているときにこのコマンドを実行してしまっても問題はありません。

$ sudo a2enmod ssl
$ sudo a2ensite default-ssl # optional

a2ensite default-ssl/etc/apache2/sites-enabledに SSL 用の雛形default-sslが作成されますが、000-default.confに設定を加えても問題ありません。

Apache の設定変更

実際に HTTPS で通信するにするには、<VirtualHost *:80/>に加えて<VirtualHost *:443/>を加えます。

例えば、私の場合は VirtualHost なので、次のような内容を設定に追加しました。

<VirtualHost *:443>
    # これまでの設定内容をコピーする。

    SSLEngine		on
    SSLProtocol		all -SSLv2 -SSLv3

    # Apache 2.4.7まで
    SSLCertificateFile    /etc/letsencrypt/live/_MY_DOMAIN_NAME_/cert.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/_MY_DOMAIN_NAME_/privkey.pem
    SSLCertificateChainFile /etc/letsencrypt/live/_MY_DOMAIN_NAME_/chain.pem

    # Apache 2.4.8以降
    # SSLCertificateChainFileが廃止になった。
    #SSLCertificateFile    /etc/letsencrypt/live/_MY_DOMAIN_NAME_/fullchain.pem
    #SSLCertificateKeyFile /etc/letsencrypt/live/_MY_DOMAIN_NAME_/privkey.pem

    # 使用したSSLプロトコルと暗号化方式をログに記録することもできます。
    #CustomLog logs/ssl_request_log \ "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
</VirtualHost>

その他の設定オプションは、/etc/apache2/sites-available/default-ssl.confを参照して設定に追加します。

また/etc/letsencrypt/options-ssl-apache.confに書かれているようなグローバル設定は、/etc/apache2/mods-enabled/ssl.confで設定します。

設定を変更したら、次のコマンドで設定の書き方に問題がないか確認しておきます。

$ sudo apachectl configtest

SSL で接続できるか確認

Apache の設定が終わったら、サーバを再起動して HTTPS で接続できるか確認します。

$ sudo service apache2 restart

まず Apache が HTTPS のポートを見ているか確認します。Apache が HTTPS ポートで待っている場合は、次のように表示されます。何も出力がないときはポート番号に間違いがないか設定を再確認してください。

$ ss -lnt | grep 443
LISTEN     0      128                      :::443                     :::*

次に Web ブラウザから Web ページを開いてみます。この時 URL の頭を http:から https:に変更してページにアクセスします。

Web ページを開けない時は、ファイアウォールで HTTPS のポートが閉じられていないか確認してください。

HTTP を転送して常時 HTTPS 化

常時 HTTPS 化するかはサイト毎のポリシーですので必須ではありません。

常時 HTTPS 化するには、HTTP で接続を求めてきたリクエストを全て HTTPS にリダイレクトします。この例ではリダイレクトステータスをR=301で恒久的な移動を示す 301 にしています。

<VirtualHost *:80>
    ServerName www.nosuz.jp
    LogLevel warn
    #LogLevel warn rewrite:trace8
    CustomLog {APACHE_LOG_DIR}/access.log
    ErrorLog {APACHE_LOG_DIR}/error.log
    RewriteEngine On
    RewriteRule . https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</VirtualHost>

アドレスバーの鍵表示

HTTPS でアクセスすると多くの Web ブラウザでは、通信が暗号化されていることを鍵アイコンが表示されます。

しかし HTTPS でアクセスしているのに鍵アイコンが表示されないことが有ります。この時は、画像や JavaScript の読み込みなど一部に HTTP でのアクセスが使われています。

鍵アイコンを表示させるには、ページのソースを開いてhttp://となっている部分を探して、その部分をhttps://または htp を削除して単に//と変更します(注6)。

証明書の自動更新

Let’s Encrypt が発行する証明書の有効期間は 90 日なので、最低三ヶ月に一度証明書を更新する必要が有ります。もちろんここも人が介在すること無く証明書の更新を自動化できます。

更新処理の自動化には cron サービスを使用するのが簡単です。例えば次のようなエントリーを root の crontab に登録すると、奇数月(注7)の 15 日 3 時 21 分に更新処理が行われます。

21 3 15 */2 * /_PATH_/letsencrypt-auto certonly --text --renew-by-default --webroot -w /var/www-root -d www.example.jp > /var/log/letsencrypt/renew-cert.log 2>1 && service apache2 restart

参照と脚注

  1. Webデザイナーなら知っておくべき サーバ知識相談室
  2. Quick Start Guide – Let’s Encrypt
  3. Ngixサーバの場合は、--ngixオプションが将来使えるようになる予定です。しかし現在は、--webrootオプションを使うなど他の方法で証明書を取得する必要が有ります。
  4. webroot modeを使用すると、起動中のWebサーバを使用して証明書を取得します。そのため多少時間がかかる証明書を取得する過程でもサービスを停止しないですみます。ただしHTTPSを有効にするところでWebサーバの再起動が必要になります。
  5. Plugins – Let’s Encrypt
  6. URLがいきなり//で始まる場合は、現在のプロトコールでそのリソースにアクセスします。そのため![](//domain/img.png)を含むページをHTTPで開いた場合はHTTPでimg.pngを取得し、HTTPSで開いた場合はHTTPSでimg.pngを取得します。
  7. crontabの月は時間や分とスタートが異なり1-12なので、*/2は1-12/*と同じ意味です。よって2で割り切れる順番の月、すなわち0番目1月、2番目3月…と奇数月にcrontabエントリーが実行されます。偶数月ならば、21 3 15 2-12/2 * commandとなります。