2016-06-15 Let's encrypt使って暗号化してみた
ポートが1つ(https/443)しか使えないワシの場合用メモ。
一般的な場合は、Let’s EncryptでSSL証明書を無料取得&自動更新しよう - D2CSolutions Weblog - デジタル・マーケティングの技術&事例ブログあたりを見ながらやれば良いと思う。letsencrypt-autoは、certbot-autoになってて入手先も違うけど。
対象はCentOS 6系です。他の環境でも一部変更すれば使えると思うよ!
◆ [日記][Linux][Unix] Let's encryptで暗号化
まず前提として、1つしかポートが使えない状態(httpsの443のみ使える状態)です(いやまぁ、開けることはできるんだけど、セキュリティ上開けたくなかったのよ……)
最初はwebrootプラグイン使って認証出来ないかなぁと色々試してみたが、どうやら出来ない模様(将来的には出来るかもしれん)
理想は……
Let's Encrypt側 - インターネット - サーバー(nginx/port443)
だったのだが、webrootプラグインではどうも443にいきなりアクセスして/.well-known/をつついてもらうことは出来ないっぽい(問答無用でhttp/80にアクセスが来た。http/80を開けてるなら、webroot使うと良いかもしれない)
しょうがないので妥協案
Let's Encrypt側 - インターネット - Let's Encryptクライアント(port443/旧名:letsencrypt-auto。使ったのは、cartbot-auto)
にして、Let's Encryptクライアント(以下、certbot)が起動している間は、nginxをシャットダウンさせるという方法。まぁ、こうすれば443ポートが空くので、certbotがstandaloneで使えるようになる。
欠点は、certbotが起動している間(数秒程度だが)httpsのアクセスが出来なくなるところ……。まあこの辺は、ポート空けるか、リロードする間止めるかのトレードオフになりそう。
と言う訳で、前置きが長くなりましたが、方法を。
CentOS 6の場合、どうやらユーザー権限ではなく、rootじゃないと無理っぽいので、全部rootで実行です。
まず、CentOS 6で必要なおまじないをします。
yum install centos-release-scl
yum install python27 python27-python-tools
1行目は、CentOS 6でSCL(CentOSで、複数のバージョンのバイナリを動かすためのツールみたいなもん)をインストールしています。
何故かというと、certbotはpython 2.7系じゃ無いと警告(まれにエラーも)が出るからです。ちなみにCentOS 6系は、python 2.6が入っています。2.7にすることは出来ません(´・ω・`)
で、2行目は、python 2.7(と、ツール)をインストールします。SCLのおかげで、これをインストールしてもOS標準のpythonは書き換わりません。要するに、python依存のツールはそのまま使えます。
んじゃぁ、どうやってpython 2.7を使うかというと、次のコマンドを入力します
scl enable python27 bash
これを使うと、python27(python 2.7)が有効な状態の、bashが起動します(つまり、この端末から元の環境に戻るためには一回exitしないとだめです)
以降はこのbash上から実行することになります。
複数端末を起動している場合は、入力先を間違わないように注意。
ちなみに、pythonが2.6か2.7かは、
python -V
(Vは大文字)とやるとバージョンが分かるので、sclコマンド入力前後で確かめると良いでしょう。
これで準備はOK。以下はCentOS 6以外でも共通です。
まず、certbotをダウンロードするディレクトリを決めましょう。今回は、/usr/local/certbotとします。*1
そのディレクトリを作成して、移動*2します。
mkdir /usr/local/certbot
cd /usr/local/certbot
次に、certbot本体(certbot-auto)をダウンロードして、実行権限をつけます。
wget https://dl.eff.org/certbot-auto
chmod 700 certbot-auto
この状態で、
./certbot-auto --help
とやると、必要なものをモリモリインストールしてくれます。
次に、standaloneモードで起動するため、一度nginxを閉じます。
service nginx stop
これで443ポートが使えるようになります。
あとは、certbotを起動するだけ!
./certbot-auto
現在、最初に「何モードで起動するか」を聞いてきます。
今回はstandaloneモード(certbot自体にサーバーもやらせる)ので、standaloneを選びます。
次に、緊急時のメールアドレスを聞いてきますので、入力します。何かあったときはこのアドレス宛に何かクルらしいです。よく分からないが、英語を読め(笑)
で、その次に利用規約へ同意するかどうかを聞いてきますので、大丈夫ならagreeを選びます。
そうすると、「ドメイン名入れてね」みたいな事を言われますので、httpsサーバーにするドメイン名(=今動かそうとしているサーバーを指しているドメイン名)を入力します。
で、OKを押すと、勝手にドメインに対する証明書を作ってくれます。
証明書自体は、最新のものが
/etc/letsencrypt/live/ドメイン名/fullchain.pem
/etc/letsencrypt/live/ドメイン名/privkey.pem
に置かれます(それぞれ、証明書のフルチェインと鍵です。Apacheに設定するときは、同じディレクトリのcert.pemやらchain.pemを使います)
ちなみにこれらのファイルはシンボリックリンクになっていて、/etc/letsencrypt/archive/ドメイン名/fullchain1.pemとかにリンクされています。全部/etc/letsencrypt以下に出来ますので、そこは安心。
この時点で、今まで入れた設定が/etc/letsencrypt以下にも保存されています。
後は、何らかの方法でwebサーバーにこの証明書を教えてやればOKです。
ちなみに、nginxの場合は、こんな感じ(/etc/nginx/conf.d/ssl.conf)
server {
listen 443;
server_name サーバー名;
(省略)
ssl on;
ssl_certificate /etc/letsencrypt/live/ドメイン名/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/ドメイン名/privkey.pem;
(以下省略)
これで、service nginx startとか入力してやれば、認証済みの証明書を使ったhttpsサーバーが起動します。
ヨカッタネ!
さて、最後に更新の問題です。
Let's encryptは、更新期間が90日と非常に短くなっています。
まぁ、90日後前後に再入力してやれば良いのですが、めんどくさいので、自動化しましょう。
その前に、更新方法を。
今回はstandaloneモードなので、nginxを止めた状態で
./certbot-auto renew
としてやれば、必要ならば勝手に更新されます。
なので、centos6のSCLを有効にしたうえでrenewするには、
scl enable python27 'bash -c "cd /usr/local/certbot && /etc/init.d/nginx stop && ./certbot-auto renew && /etc/init.d/nginx start"'
と書いてやれば良いことになります。
順に、SCLでpython27を有効にする。bashを起動して、以下のコマンドを実行する。/usr/local/certbotへ移動する。nginxを止める。certbotを使って更新する。nginxを起動する。というコマンドです。1行で書いて下さい。
さて、少しだけ改良してログをとるようにしましょう。
scl enable python27 'bash -c "cd /usr/local/certbot && /etc/init.d/nginx stop >> /root/cert-renew.log 2>&1 && ./certbot-auto renew >> /root/cert-renew.log 2>&1 && /etc/init.d/nginx start >> /root/cert-renew.log 2>&1"'
これで、更新ログが/root/cert-renew.logにとられるようになります。
あとはこれをcronあたりで実行してやればいいわけです。
上のサイトを参考にして、rootでcrontab -eを実行し、こんな行を付け足しました。
10 0 1 * * scl enable python27 'bash -c "cd /usr/local/certbot && /etc/init.d/nginx stop >> /root/cert-renew.log 2>&1 && ./certbot-auto renew >> /root/cert-renew.log 2>&1 && /etc/init.d/nginx start >> /root/cert-renew.log 2>&1"'
これで毎月1日、0時10分に証明書を更新しようともくろむようになります。
一応注意なのですが、これだと、証明書が古いままの期間がまれに出ます。
nginxを止めている時間が毎日ある程度確保できているなら、
10 0 * * * scl~
とした方が良いかもしれません。
もしくは、./certbot-auto renewを、
./certbot-auto certonly --renew-by-default --standalone --standalone-supported-challenges tls-sni-01 --domains ドメイン名
として強制更新するのも手ではあります。これはまぁ、お好みで。
とまぁ、こんな感じで某所は更新させています。
本来はwebrootプラグインを使ってやったほうが良いのですが、443しか使えないという制約があったので……(;´Д`)