HTTPSはWebの通信を暗号化するために使われていると一般的には思われています。しかし実際には暗号化だけでなく、Webサイトを運営する会社・組織の身元を保証するためにも使われています。
そのため身元を保証してもらいたい会社・組織は審査を受ける必要が有り、時間とそれなりのお金をかけて証明書を発行してもらっていました。その結果としてユーザは安心してオンラインで買い物をしたり預金を確認できます。
一方、身元の保証は必要なく単純に安全な通信のためにHTTPSを使いたいという場合には、これまでのやり方は非常に手間がかかりハードルが高いものです。そこで誰でもHTTPSの暗号化機能を手軽に使えるようにするためLet’ Encryptプロジェクトが、Webサイトの身元は保証しないけど暗号化に使用できる証明書を機械的かつ無料で発行する実験が開始されました。
会社・組織の身元保証が無いので商業利用向きではありませんが、個人のWebサーバでも簡単にHTTPSを使って安全な通信を行えるようになりました。
ここではHTTPSに必要な証明書の取得方法からサーバの設定、証明書の更新方法について説明します。
証明書の取得
HTTPSの証明書は、専用のプログラムletsencrypt
を使用して取得します。
letsencrypt
をインストール
letsencrypt
は、Debianなどパッケージとして配布されている場合も有りますが、Ubuntuではまだパッケージになっていなのでgit
コマンドを使ってプログラムを取得します。
$ sudo apt-get install git # gitをまずインストールする。
$ git clone https://github.com/letsencrypt/letsencrypt
$ cd letsencrypt
HTTPSの証明書を取得
letsencrypt-auto
コマンドを実行してHTTPSの証明書を取得します。
WebサーバにApacheを使用している場合は、次のコマンドを実行します。
ただしこのコマンドを実行するとサーバが一時的に停止します。ダウンタイムを最小にするには、--apache
の代わりに--webroot
オプション(webroot mode)を使用します。
$ ./letsencrypt-auto --apache
実行すると必要なパッケージがインストールされ、証明書を取得するために必要な質問をいくつかされます。質問に答えてしばらく(1分程度)待つとHTTPS証明書が/etc/letsencrupt/live/
に保存されます。
もしかすると、証明書を取得するときにHTTPSポートが開いている必要があったかもしれません。その場合は、次の「HTTPSポート(443)を公開」を参照してください。
証明書を取得するときに質問される項目は次の3つです。
- 現在のApacheがホストしているドメインの内で証明書に含めるドメイン名。
- 連絡先のメールアドレス。
- Let’s Encryptを使用するための決まりに同意するか。
1.で選択したドメイン名は、全て同じ証明書を使ってHTTPS通信が行えます(SAN Certificate?)。また-d
オプションで事前に対象のドメイン名を指定しておくことができます。
複数のサーバ名を指定すると「複数のサーバ名はサポートしていない」というようなエラーが表示されますが、問題なく使えています。
2.と3.の質問は、それぞれ--email
と--agree-tos
オプションで事前に指定しておけます。
オプションの詳しい説明は、
$ ./letsencrypt-auto --help all
で取得できます。説明が表示されるのが遅いので、次のようにリダイレクトを使って説明を保存しておくと後で参照しやすくなって便利だと思います。
$ ./letsencrypt-auto --help all > help.txt
--apache
オプションは、証明書の取得の他にインストールもするということですが、具体的に何をしているのか私には分かりませんでした。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を削除して単に//
と変更します。
証明書の自動更新
Let’s Encryptが発行する証明書の有効期間は90日なので、最低三ヶ月に一度証明書を更新する必要が有ります。もちろんここも人が介在すること無く証明書の更新を自動化できます。
更新処理の自動化にはcronサービスを使用するのが簡単です。例えば次のようなエントリーをrootのcrontabに登録すると、奇数月の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
参照と脚注