Let’s EncryptでValidなSSL/TLS証明書を取得する
ども、大瀧です。
無償で利用できるSSL証明書発行サービスであるLet's Encryptがクローズドベータになりました。早速ベータ申請が通ったので、証明書を発行してみた様子をレポートします。
動作確認環境
- 端末 : OS X El Capitan
- Webサーバー : Debian Wheezy
手順
現在はクローズドベータなので、事前にベータにエントリーしていたメールアドレスに招待メールが届くことで利用可能になります。手順自体は以下のページでアナウンスされているものです。
まずはローカルにユーティリティをインストール&実行します。OSXの場合は自動でHomebrewを検出し依存ソフトウェアがインストールされます。環境を汚したくないという方はDockerを利用するのも良いでしょう。プレビュー版のものですが、@sawanobolyさんの以下のQiitaエントリーが詳しいです。
$ git clone https://github.com/letsencrypt/letsencrypt : $ cd letsencrypt/ $ ./letsencrypt-auto --agree-dev-preview --server \ > https://acme-v01.api.letsencrypt.org/directory auth Bootstrapping dependencies for Mac OS X... WARNING: Mac support is very experimental at present... ==> Installing dependencies for augeas: libxml2 ==> Installing augeas dependency: libxml2 ==> Downloading https://homebrew.bintray.com/bottles/libxml2-2.9.2.el_capitan.bo ######################################################################## 100.0% ==> Pouring libxml2-2.9.2.el_capitan.bottle.1.tar.gz ==> Caveats This formula is keg-only, which means it was not symlinked into /usr/local. OS X already provides this software and installing another version in parallel can cause all kinds of trouble. Generally there are no consequences of this for you. If you build your own software and it requires this formula, you'll need to add to your build variables: LDFLAGS: -L/usr/local/opt/libxml2/lib CPPFLAGS: -I/usr/local/opt/libxml2/include ==> Summary ? /usr/local/Cellar/libxml2/2.9.2: 275 files, 10M ==> Installing augeas ==> Downloading http://download.augeas.net/augeas-1.4.0.tar.gz ######################################################################## 100.0% ==> ./configure --prefix=/usr/local/Cellar/augeas/1.4.0 ==> make install ==> Caveats Lenses have been installed to: /usr/local/share/augeas/lenses/dist ==> Summary ? /usr/local/Cellar/augeas/1.4.0: 419 files, 3.9M, built in 111 seconds ==> Downloading https://homebrew.bintray.com/bottles/dialog-1.2-20150528.el_capitan.bottle.tar.gz ######################################################################## 100.0% ==> Pouring dialog-1.2-20150528.el_capitan.bottle.tar.gz ? /usr/local/Cellar/dialog/1.2-20150528: 13 files, 824K Creating virtual environment... -n Updating letsencrypt and virtual environment dependencies... -n . -n . -n .
画面がブルーバックのTUIに切り替わります。[1.Manual Authenticator]にカーソルがあることを確認し、[Enter]を押下します。
ベータリクエストに記載したメールアドレスを入力します。
使用許諾画面では[Agree]にカーソルがあることを確認し、[Enter]を押下します。
証明書を発行するドメインを入力します。
しばらく待つとTUI画面からCUIに切り替わり、以下のメッセージが表示されます。ユーザーがドメインのオーナーであるかを認証するために、ドメイン以下の特定URLへのサーバーレスポンスを自動生成し、Let's Encryptのホストからリクエストを送出、レスポンスを検証します。メッセージの前半が検証要件、If you don't have HTTP server configured, you can run the following command on the target server (as root):
から後ろの後半はPythonで要件を満たす簡易Webサーバー起動するためのコマンド一覧です。メッセージの最後にPress ENTER to continue
とありますが、[Enter]キーを押すと先ほどの検証が実行されるため、サーバーの準備が整うまで放置しておきましょう。
Make sure your web server displays the following content at http://www.takipone.com/.well-known/acme-challenge/91OhqnUB4ct7sdT-4EbhopZk_RS4Qzn_PGp3nKKo4ms before continuing: {"header": {"alg": "RS256", "jwk": {"e": "AQAB", "kty": "RSA", "n": "2zpa2Lk-bfZcjqAaUQZByoQ6n4PhW-BC6wiujAPhLyF1ZNEv704o4PjXuJP3M2RetAHluUpMikFgD302guSbX8BUZSfsGzYZ9xdaSV0S3aGO8iq-kpZLuEZn_ijWv49vx6hu21J838_uriK6kPOo1gWD6LmP5p1cJi-HJ8x08UwWOFdzJrVaydqtPJ8iiHKmkHbltElsLUyXPAib3fPcHgTuZiDyPKRUpVa-KAA-RRTRgQNQhipVAeBZlxuwkz6cI_fRASkjQz7ixx8atseVgCOzmRIr8ExXL0ksWdmwOkKvu4xMGT2hfes-8dX-mTsfTa2ZZNLPLmAMwhrolbvE7Q"}}, "payload": "eyJ0bHMiOiBmYWxzZSwgInRva2VuIjogIjkxT2hxblVCNGN0N3NkVC00RWJob3Baa19SUzRRem5fUEdwM25LS280bXMiLCAidHlwZSI6ICJzaW1wbGVIdHRwIn0", "signature": "wTg-MEog6l3zWrUlc7AXazBCKCi3nt1tJP-o1D5nZzG2OSTALXbG9I-PaalCCf8w_L167NzyD78J-WxhW1jLerVj7XHF2DFaiZNuRkGlvODPpS4oi2oU38tR7wwUpoeGy5xnlzb5VUjECACyG5-22HddAk41-qk2d1JNH8tCo78UrG-uYmS3vMDtL8LKJrT7RuX_nVrXaW4sgogtOTIBmv6RLF2Nd8RqeSFE3kkinok0XvqBVAdS1R4zME6XZUWayCu31TWIsgnu7lH_ZZBKn3hgHIm7hc1P1La9xKLeQb5nROhNfzuHcPUm1AiApu8N-4hzM8Yt-pNEkbbQiJOp4Q"} Content-Type header MUST be set to application/jose+json. If you don't have HTTP server configured, you can run the following command on the target server (as root): mkdir -p /tmp/letsencrypt/public_html/.well-known/acme-challenge cd /tmp/letsencrypt/public_html echo -n '{"header": {"alg": "RS256", "jwk": {"e": "AQAB", "kty": "RSA", "n": "2zpa2Lk-bfZcjqAaUQZByoQ6n4PhW-BC6wiujAPhLyF1ZNEv704o4PjXuJP3M2RetAHluUpMikFgD302guSbX8BUZSfsGzYZ9xdaSV0S3aGO8iq-kpZLuEZn_ijWv49vx6hu21J838_uriK6kPOo1gWD6LmP5p1cJi-HJ8x08UwWOFdzJrVaydqtPJ8iiHKmkHbltElsLUyXPAib3fPcHgTuZiDyPKRUpVa-KAA-RRTRgQNQhipVAeBZlxuwkz6cI_fRASkjQz7ixx8atseVgCOzmRIr8ExXL0ksWdmwOkKvu4xMGT2hfes-8dX-mTsfTa2ZZNLPLmAMwhrolbvE7Q"}}, "payload": "eyJ0bHMiOiBmYWxzZSwgInRva2VuIjogIjkxT2hxblVCNGN0N3NkVC00RWJob3Baa19SUzRRem5fUEdwM25LS280bXMiLCAidHlwZSI6ICJzaW1wbGVIdHRwIn0", "signature": "wTg-MEog6l3zWrUlc7AXazBCKCi3nt1tJP-o1D5nZzG2OSTALXbG9I-PaalCCf8w_L167NzyD78J-WxhW1jLerVj7XHF2DFaiZNuRkGlvODPpS4oi2oU38tR7wwUpoeGy5xnlzb5VUjECACyG5-22HddAk41-qk2d1JNH8tCo78UrG-uYmS3vMDtL8LKJrT7RuX_nVrXaW4sgogtOTIBmv6RLF2Nd8RqeSFE3kkinok0XvqBVAdS1R4zME6XZUWayCu31TWIsgnu7lH_ZZBKn3hgHIm7hc1P1La9xKLeQb5nROhNfzuHcPUm1AiApu8N-4hzM8Yt-pNEkbbQiJOp4Q"}' > .well-known/acme-challenge/91OhqnUB4ct7sdT-4EbhopZk_RS4Qzn_PGp3nKKo4ms # run only once per server: $(command -v python2 || command -v python2.7 || command -v python2.6) -c \ "import BaseHTTPServer, SimpleHTTPServer; \ SimpleHTTPServer.SimpleHTTPRequestHandler.extensions_map = {'': 'application/jose+json'}; \ s = BaseHTTPServer.HTTPServer(('', 80), SimpleHTTPServer.SimpleHTTPRequestHandler); \ s.serve_forever()" Press ENTER to continue
今回はwww.takipone.com
のDNSに登録したマシンでPythonスクリプトを実行します。rootユーザーになってからコピペでOKです。
ryuta@instance-1:~$ sudo -i root@instance-1:~# mkdir -p /tmp/letsencrypt/public_html/.well-known/acme-challenge root@instance-1:~# cd /tmp/letsencrypt/public_html root@instance-1:/tmp/letsencrypt/public_html# echo -n '{"header": {"alg": "RS256", "jwk": {"e": "AQAB", "kty": "RSA", "n": "2zpa2Lk-bfZcjqAaUQZByoQ6n4PhW-BC6wiujAPhLyF1ZNEv704o4PjXuJP3M2RetAHluUpMikFgD302guSbX8BUZSfsGzYZ9xdaSV0S3aGO8iq-kpZLuEZn_ijWv49vx6hu21J838_uriK6kPOo1gWD6LmP5p1cJi-HJ8x08UwWOFdzJrVaydqtPJ8iiHKmkHbltElsLUyXPAib3fPcHgTuZiDyPKRUpVa-KAA-RRTRgQNQhipVAeBZlxuwkz6cI_fRASkjQz7ixx8atseVgCOzmRIr8ExXL0ksWdmwOkKvu4xMGT2hfes-8dX-mTsfTa2ZZNLPLmAMwhrolbvE7Q"}}, "payload": "eyJ0bHMiOiBmYWxzZSwgInRva2VuIjogIk9ubTB5bERiMTlkZU1wdEI0eExhdE9NM0ExcDJWRS1CWXJfSXJ0OU9yLVEiLCAidHlwZSI6ICJzaW1wbGVIdHRwIn0", "signature": "A3qTQ1IsmuqxV_zvNJIARUI4eZ-WrecRZKOEEHoM7gsCRHS8oj27QzbSglhHcx0TKYcCnUbxsCEGSG2g9SGOEqyJih7psMPgNzcZpRI1PwrO_VEZb1MZ2zYJRhsXUPAIrcaNRzAuQnNqhp1IWdGP81zqauqboyds-AdJPlCYNtmMibbKQXEagb5A4tSEGvkKT-CB0zbK_2fk9hGO0BX7hZkwG0-VTavm7GsZieCUSwPtUAuJuIGNLWv9yPDdPbn3Fk_VadAcjDjW5zkY13W0aGvA7eg9HndJfqeCQbuMVqAKb8TNJx9pU8NjmZq1OQUM3_fDHgqiQ6pacBN1SZR56w"}' > .well-known/acme-challenge/Onm0ylDb19deMptB4xLatOM3A1p2VE-BYr_Irt9Or-Q root@instance-1:/tmp/letsencrypt/public_html# # run only once per server: root@instance-1:/tmp/letsencrypt/public_html# $(command -v python2 || command -v python2.7 || command -v python2.6) -c \ > "import BaseHTTPServer, SimpleHTTPServer; \ > SimpleHTTPServer.SimpleHTTPRequestHandler.extensions_map = {'': 'application/jose+json'}; \ > s = BaseHTTPServer.HTTPServer(('', 80), SimpleHTTPServer.SimpleHTTPRequestHandler); \ > s.serve_forever()"
フォアグラウンドで80番ポートをListenし、クライアントからの接続を待ち受けます。 Let's Encryptのユーティリティを実行する端末に戻り、[Enter]を押下すると検証が実行されます。 サーバーの端末にアクセスログが表示され、ユーティリティの端末には検証が成功したことと証明書が保存されたことを示すメッセージが表示されます。
XX.XX.XX.XX - - [26/Oct/2015 15:12:51] "GET /.well-known/acme-challenge/Onm0ylDb19deMptB4xLatOM3A1p2VE-BYr_Irt9Or-Q HTTP/1.1" 200 -
IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at /etc/letsencrypt/live/www.takipone.com/fullchain.pem. Your cert will expire on 2016-01-24. To obtain a new version of the certificate in the future, simply run Let's Encrypt again. $
証明書は/etc/letsencrypt/live/<ドメイン名>/
に配置されます。
$ sudo ls /etc/letsencrypt/live/www.takipone.com Password: cert.pem chain.pem fullchain.pem privkey.pem $
できていますね!
動作検証
今回は、Nginxで試してみました。Let's EncryptのSSL証明書は中間証明書を含むため、中間証明書を指定するディレクティブの無いNginxの場合はfullchain.pem
(サーバー証明書と中間証明書のセット)を使いましょう。
: # HTTPS server # server { listen 443; server_name www.takipone.com; root html; index index.html index.htm; ssl on; ssl_certificate certs/fullchain.pem; ssl_certificate_key certs/privkey.pem; ssl_session_timeout 5m; ssl_protocols SSLv3 TLSv1; ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv3:+EXP; ssl_prefer_server_ciphers on; location / { try_files $uri $uri/ =404; } }
Firefox 41.0.2でアクセスした様子が以下です。証明書エラーなしで正常に接続できています。
証明書ビューアは以下のような感じ。
Chrome 46.0でも正常に接続できました。
まとめ
現在はベータなので証明書の有効期限や発行回数に制限があるため実用するのはまだ早いですが、GAの準備が確実に進んでいる様子がうかがえますね。