相変わらずblogの記事がメモ代わりになっていますが・・・。それは置いておきまして。
自己署名ではないSSLの証明書を確保するためにいろいろと調べましてLet’s Encryptより証明書を取得しまして導入する準備をする、というところです。
SSLでの通信がかなり必須になってきている
今回の作業の第一目的がこれです。というのも、非暗号通信でのメールのやりとりなどはしないようにしていることから自己署名でのSSLはすでに設定してあったのですが、Googleが「常時SSL」を推していることもあることやSEOでの優遇もありますが、GoogleChromeがとうとう非暗号通信であるHTTPを使用した場合に「ブラウザに」マークをつけ始めたことからちょっといじらしく感じるようになってSSLを再導入する必要に迫られたわけです。ここで問題になるのは「常時SSL化を行う場合、証明書が自己署名だとブラウザ上ではHTTPよりたちが悪い状態となるため何らかの方法でちゃんとした署名がされているSSLの証明書を取得する必要がある」というところです。このため、できる限りやすい費用で手間がかからずになんとかならないかな~というわけでいろいろと探しましまして・・・
Let’s Encryptから証明書を取得することに
無料の証明書としては以前から「StartSSL」があることは知っていましたが、ユーザー登録や管理の手順などから微妙に避けていたのでさらにないかと探していたところちょうどいいところに2016年4月12日から正式サービスとなった無料で証明書が取得できるLet’s Encryptがあることがわかりましてそちらを導入することにしました。こちらの方はCUIからコマンドを入力するだけでさらに管理もcronだけで済むので面倒だと思う人はこちらを一度導入してみるといいかもしれません。導入の説明なども日本語のポータルサイトがありますのでそちらを参考にすれば以下を見なくても比較的簡単に導入できます。(以下の手順もポータルサイトを参考にしています)
CentOS6系でのLet’s Encryptからの証明書の導入手順
ポータル側でも書かれていますがCentOS6系だと処理で使用するスクリプト言語のPythonのバージョンが合わないために警告が出るのが難点です。そのため、CentOS6系のパッケージ処理だけで処理する場合はいくつか特殊な手順が必要になります。自前でPythonを導入している場合は必要ないかもしれません。以下基本的にコマンドはrootで実行するものとします。rootになれない場合はsudoにより管理者権限で実行してください。また取得する前に
- ちゃんと受信できる連絡先のメールアドレス
- どのドメイン名をSSLの証明書に対応させるか
- 登録の代表となるDNSの正引きでDNSがIPに変換され自身のサーバーのPort80およびPort443にアクセスできるか
を確認しておく必要があります。これが抜けると後の手順でいろいろと問題になります。
手順1 gitによりLet’s Encryptから証明書を取得するためのスクリプトを取得する
基本的にスクリプトはrootでアクセスすることになるのでユーザーのホームディレクトリにダウンロードするのは微妙なので/usr/local以下に適当にディレクトリを作って取得するのがいいと思います。もしくは/var以下ですかね。コマンドは
# git clone https://github.com/certbot/certbot
となります。昔はletsencryptとそのままの名前だったのですがこの記事を書いている段階ではcertbotという名前になっているようです。以下/usr/local/certbotに各種ファイルがあるものとして書いていきます。
手順2 Python環境のためにSCLを導入する
Python2.7以降を導入していないときには実行時に警告やら何やらで大変なことになってしまうのですが、CentOS6系でのPythonはパッケージによりインストールした場合は2.6系となってしまうので一時的にでもPython2.7が有効となる環境で動かす必要があります。そのためにSCLを導入します。コマンドは
# yum -y install centos-release-scl
となります。
手順3 Python2.7を導入する
これは普通に
# yum install python27 python27-python-tools
でOKです。
手順4 Port80およびPort443をListenしているサービスを一時的に停止させる
初回起動後にエラーが出てからやってもいいのですが今回の手順では先にやってしまいます。
Let’s Encryptから証明書を取得する場合、取得用のスクリプトが一時的にPort80およびPort443をListenして証明書を作成するときに必要となるやりとりを代行する、という動作を行います。そのため、対象ポートをListenしているサービスは一時的に停止させないと証明書が作れません。もちろん初回導入後にプラグインを導入することで一部のWebサーバーではサービス停止が必要なくなるのですが今回は停止させてから行います。このやり方はちょっとダウンタイムが長くなるのが難点ですね。例としてApacheをパッケージから導入しているのであれば
# service httpd stop
nginxをパッケージとして別に導入している場合は
# service nginx stop
をしておきましょう。CentOS7系などではsystemctlから行う処理ですがCentOS6系を例にしているのでserviceのままですね…。
手順5 certbot-autoの初回の起動を行う
ここで初めてLet’s Encryptから証明書を取得するためのコマンドを発行します。初回に限り不足しているパッケージの取得処理や取得対象となるスクリプトによる初期設定が行われますのでここからは特に注意して行います。コマンドは
# scl enable python27 "/bin/bash /usr/local/certbot/certbot-auto"
で行えます。もちろん、二段階にして
# scl enable python27 bash # /usr/local/certbot/certbot-auto
とした方がよいのですが、1行で呼び出す方法がこの後とある事情から現れますのでこの時点で紹介しておきます。
まず初回起動時には必要となるパッケージの取得処理が発行します。これについては各OSに合わせた取得処理が行われるようです。ちなみにこのときにpython2.6側のパッケージがいくつかダウンロードされますが2.7導入時にすでに必要なパッケージはダウンロードされていますので慌てる必要は全くありません。2.6側もとりあえず導入しておけばよいと思います。
次にCUIからTUIに切り替わります。ここでは利用規約の同意および必要な情報を入力します。必要な情報は
- 管理者のメールアドレス
- SSL証明書を作成する対象のドメイン名(複数あり、ワイルドカードなし)
になります。このあたりの説明はポータルの方が詳しいのでそちらを見ながらやってみるといいと思います。なお、ワイルドカードが利用できないので使っているドメイン名はすべて入力しておくといいです。このサイトの場合は「timbreofprogram.info」が本来のドメイン名で、その前にいくつか役割に応じて名前をつけて後で何かあったときに対応できるようにしています。そのため、今回の場合だとメインは「timbreofprogram.info」をメインとして先頭に記述して後ろに使っているサブのドメイン名を書いています。処理が完了すれば/etc/letsencryptが作成され証明書が作成されます。基本的には/etc/letsencrypt/live/[ドメイン名]/以下にある証明書ファイルを使用することになると思います。
手順6 Port80およびPort443をListenしているサービスを復帰させる
完了した後は証明書を利用するように設定を書き換えてサービスを復帰させます。ついでにそのほかSSLを利用している各種サービスの設定も書き換えてしまうといいでしょう。メールサービスなどですかね。
手順7 証明書の自動更新スクリプトを作成する
Let’s Encryptで作成される証明書は期間が短く3ヶ月で設定されています。もちろん、設定で記述したメールアドレスに期限切れになる前に警告メールが届くようになっているのですが毎回手動でやるのも面倒だと思いますので自動更新用のスクリプトを作ってしまうといいと思います。私が使っているスクリプトのひな形がこちら。
#!/bin/sh # Stop HTTP(Port 80) and HTTPS(Port 443) services. # /sbin/service httpd stop # Renew certificate. /usr/bin/scl enable python27 "/bin/bash /usr/local/certbot/certbot-auto renew" # Start HTTP(Port 80) and HTTPS(Port 443) services. # /sbin/service httpd start # Reload other services which use certificate.
スクリプト内の英語コメントが正しくないかもしれませんが…。必要に応じてSSLの証明書が更新されたときのために必要なサービスの停止および復帰を書いておくと便利です。で、これをcronにより定期的に実行するとよいでしょう。3ヶ月で期限切れを起こすので1~2週間に1度くらいがよいのではないでしょうか。このスクリプトの難点は証明書が更新されなくてもサービスを一旦停止してしまうことなんですよね…。そこまでダウンタイムは長くないはずですが。
ちなみに、certbot-autoにはいくつか引数をつけることができます。たとえば「–rsa-key-size 4096」をつけると鍵長が4096bitのものを作成できる、などがあります。
あとはこれをWebサービスに反映させるだけ
証明書をWebサーバーに読み込ませるとともにHTTPで通信が要求されたときにHTTPS側にリダイレクトさせる処理、検索エンジンにHTTPS側のURLを登録するなどが必要です。このサイトの場合は実はそれ以外にもいくつか面倒なことがあるので今現在は「まだ」対応していません。今月中には常時SSL化ができるかな、というところですね。