Let's EncryptとnginxでHTTP/2サーバを立てる
この記事は ピクシブ株式会社 Advent Calendar 2015 10日目の記事です。
こんにちは。Androidアプリエンジニアのいとおちゃんです。
高校生の頃からアルバイトとしてピクシブに入社してから4年目になりました。昨年は若手アルバイトと名乗っていましたが、気づいたらもう大学生です。最近はpixivマンガアプリの開発をしています。
今回はAndroidアプリ開発の話ではなく、個人的に最もアツいと感じているLet's Encryptを使ってnginxでHTTP/2サーバを立てる話をします。
Let’s Encryptを使おう
Let's Encryptを利用すると、無料で認証されたSSL証明書を簡単に発行することができ、ここ最近話題を集めています。今月、Let's EncryptはようやくPublic Betaになりました。そこで、まさに今が旬ともいえるLet's Encryptを使って、HTTP/2サーバを立ててみました。 以下の手順はUbuntu 14.04 LTS上でサーバにnginxを使ったときのものです。
HTTP/2は実質HTTPSが必要
HTTP/2はその仕様上、暗号化が必須ではありません。しかし、ChromeやFirefoxではHTTPSでのみHTTP/2に対応しています。そのため、HTTP/2に対応するにはHTTPSにする必要があるのです*1。
そこでLet's Encryptを使えば、コマンドをたった4回くらい叩くだけで恐ろしく便利かつ簡単に自己証明書を使うことなくブラウザのエラーが出ないHTTPS通信を実現することができます。最高のHTTPS通信はもう目の前です!
Let's Encryptで証明書を発行する
letsencrypt-auto のインストール
今回はこちらを参考にしました。
無料SSL証明書の Let’s Encrypt が公開されたので実際に試してみた | Webセキュリティの小部屋
まず、Let's Encryptで証明書を発行してみましょう。以下の手順はLet's Encryptで証明書を使いたいサーバ上で実行します。
letsencrypt-auto
コマンドを使うため、GitHubのリポジトリから適当なディレクトリにcloneしてきます。
git clone https://github.com/letsencrypt/letsencrypt
cd letsencrypt
リポジトリの中に移動すると、 letsencrypt-auto
というコマンドがあります。このコマンドの恐ろしいのは、なんと実行するだけで勝手にディストリビューションのパッケージをインストールしてしまいます。Debian系なら apt-get
が実行されます。怖すぎ!
./letsencrypt-auto --help
HTTPサーバにApacheを使っているとApacheプラグインがあり、自動でconfの設定をしてくれるようです。しかしnginxは実験的なサポートに限られるため、今回は証明書の発行のみ行います*2。Let's Encryptの証明書は有効期間が3か月なので、その頃には便利になっていると信じましょう。
証明書今すぐ取得
いよいよ証明書を取得します。--webroot
オプションを使いHTTPサーバを動かしたままACMEプロトコルの通信します。
${DOMAIN}
の部分は証明書を取得したいドメインに変更してください。 -d
オプションを複数つけるとマルチドメイン証明書となり、1枚の証明書で無限に複数のドメインに対応できます(例: example.com と www.example.com など)。${WEBROOT}
はnginxで設定しているドメインのルートディレクトリに設定します。
./letsencrypt-auto certonly --webroot -d ${DOMAIN} --webroot-path ${WEBROOT}
すると Enter email address という画面が表示されるので、メールアドレスを入力します。 私の環境ではTUIが若干崩れた状態で表示されましたが、気にせずさくさく進めていきます。
次に、規約に同意します。
うまくいくと、以下のような表示になります。
IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at /etc/letsencrypt/live/itochan.jp/fullchain.pem. Your cert will expire on 2016-03-08. To obtain a new version of the certificate in the future, simply run Let's Encrypt again. - If like Let's Encrypt, please consider supporting our work by: Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate Donating to EFF: https://eff.org/donate-le
最新のnginxをインストール
nginxはmainlineとstableがありますが、HTTP/2に対応しているのはmainlineで提供されている1.9.5以降のものです。よって、nginxでHTTP/2を使うにはnginx 1.9.5以降をインストールしましょう。
UbuntuならPPAでインストールするのがお手軽です。その他の環境ではnginxのドキュメントを参照してください。たとえば、RHEL/CentOSであればパッケージが提供されています。
sudo add-apt-repository ppa:nginx/development
sudo apt-get update
sudo apt-get install nginx
nginxのHTTPSとHTTP/2を使う設定
今回Let's Encryptの証明書を発行したドメインでHTTPSとHTTP/2を使える設定をします。以下は設定例です。
server { listen 80; listen [::]:80; listen 443 ssl http2; listen [::]:443 ssl http2; server_name itochan.jp; ssl_certificate /etc/letsencrypt/live/itochan.jp/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/itochan.jp/privkey.pem; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA; root /var/www/itochan.jp; }
nginxの設定を service nginx reload
などで再読み込みすると、HTTPSが使えるようになっているはずです。
HTTPSとHTTP/2通信を確認してみる
やっとHTTPSとHTTP/2が使えるようになりました。手元のブラウザから確認してみると、HTTPSになっていればChromeではアドレスバーから接続に関する情報が見れます。
ChromeであればデベロッパーツールのNetworkタブでProtocolの項目を入れると、プロトコルがh2かどうかわかります。
また、HTTP/2 and SPDY indicatorというエクステンションをインストールすることによりHTTP/2であればアドレスバーにイケてる青いイナズマのアイコンを表示させることができ、HTTP/2であるかどうか確認するのに便利です。ビリビリ。
もっとセキュアにしたい
今回nginxのデフォルト設定でHTTPSを提供しましたが、この状態でサーバを公開すると脆弱な部分があります。この記事では、安全なHTTPS通信を提供する手順を省略しています。安全にHTTPSを使うにはさまざまな対策を行います。具体的には2048bit以上のDH鍵を使用するなどの対策が必要です。
実際にサーバを外部に公開する場合、安全にHTTPS通信を提供するには弊社の id:harukasan によるQiitaがわかりやすくまとめられているのでおすすめです。 qiita.com
すでにお気づきの方もいらっしゃるかもしれませんが、上記のスクリーンショットでは 証明書の透明性に関する有効な情報がサーバーから提供されました。
と表示されています。これはSSL/TLSのCertificate Transparency(透かし入り証明書)、略してCTの設定をするとブラウザに表示されるものです。
nginxでCTを使うには現状 nginx-ct というモジュールをインストールする必要があるため手間がかかります。でも、 証明書の透明性に関する情報がサーバーから提供されませんでした。
より 提供されました。
のほうがかっこいいじゃないですか。
証明書の透明性に関する情報を提供したい!私はそう思うのですが、余力がある人はnginxをビルドしてnginx-ctを組み込むとよいでしょう。
まとめ
いかがでしょうか。Let's Encryptを使えば手軽にHTTPS通信を実現できます。nginxのHTTP/2サポートも実用的なものになっています。
ピクシブではエンジニアを募集しています!
- [PR] ピクシブではAndroidアプリエンジニアを募集しています。
- [PR] ピクシブではHTTP/2に強いエンジニアを募集しています。
- [PR] ピクシブで働く大学生の仲間がほしい!ピクシブではアルバイトを募集しています。
一発エントリーボタン
次回は @uchienneo による素敵な作品に出会えるメディア、pixiv Spotlightのお話です。楽しみですね!
*1:参考: HTTP/2 Frequently Asked Questions | HTTP/2 Japan Local Activity
*2:letsencrypt-auto なのに全然autoじゃないと思われるかもしれませんが、GitHubを見る限り活発に開発されているようなので対応を待ちましょう。