自サイトをHTTPS化してみた

はてなブログでホストしていただいている等ブログの他に、勉強のために自ドメインでサイトを構築しております。 (内容はあまりありません。日記的ブログだった残骸があるだけです…)

Noisy Spot | 個人的まとめ

で、なんか最近調子が良くなかったので、OSごと再構築しまして、ついでに Let's Encrypt のDV証明書を利用してHTTPS化してみました。

letsencrypt.org

以下は手順メモです。

作成時の環境

  • Ubuntu 16
  • Nginx 1.10.0
  • OpenSSL 1.0.2g

クライアントツールの取得と申請~証明書発行

Let's Encrypt への申請、認証、証明書発行の一連の流れを自動化してくれるクライアントツールは、対象の環境や実装手段によりいくつか開発されているようです。Let's Encrypt推奨の方法としては、以下のCertbotというサイトでWebサーバとOSを選択して、表示された手順に従うというものでした。今回はそれに従いました。

certbot.eff.org

まずは apt でクライアントツールを導入します。

$ sudo apt-get update
$ sudo apt-get install letsencrypt

で、nginxを起動した状態で、letsencrypt コマンドを打ちます。

$ letsencrypt certonly --webroot -w [[Webサーバのドキュメントルートのパス]] -d [[申請するドメイン名]]

すると、CUIが立ち上がり、メールアドレスを要求してくるので入力します。申請失敗時などはここで入力したアドレスに連絡が飛んで来るようなので、使えるアドレスを入力する必要があります。

メールアドレスを入力し、利用規約などをAgreeすると、申請・認証が開始します。以下の様な流れで動作するようです。

  1. メールアドレスとドメイン名をLet's Encryptに送付して発行申請する。戻り値としてシグネチャが返される。
  2. Webサーバのドキュメントルートに .well-known/acmechallenge/ ディレクトリを作成し、返されたシグネチャを格納
  3. Let's Encryptのサーバから、http://[[申請したドメイン]]/.well-known/acmechallenge/ のリクエストを飛ばし、取得したシグネチャと発行したものが同一となればドメイン所有者認証の完了
  4. 証明書と鍵がLet's Encryptから発行され、クライアントツールはそれらを所定の場所に格納する。

以上がコマンド実行から2分くらい放置で完了。簡単!

上記コマンド完了後 /etc/letsencrypt に下記のファイルが格納されます。

.
|-- accounts
|   `-- acme-v01.api.letsencrypt.org
|       `-- directory
|           `-- [[ハッシュコード]]
|               |-- meta.json
|               |-- private_key.json
|               `-- regr.json
|-- archive
|   `-- [[ドメイン名]]
|       |-- cert1.pem
|       |-- chain1.pem
|       |-- fullchain1.pem
|       `-- privkey1.pem
|-- csr
|   `-- 0000_csr-certbot.pem
|-- keys
|   `-- 0000_key-certbot.pem
|-- live
|   `-- [[ドメイン名]]
|       |-- cert.pem -> ../../archive/[[ドメイン名]]/cert1.pem
|       |-- chain.pem -> ../../archive/[[ドメイン名]]/chain1.pem
|       |-- fullchain.pem -> ../../archive/[[ドメイン名]]/fullchain1.pem
|       `-- privkey.pem -> ../../archive/[[ドメイン名]]/privkey1.pem
`-- renewal
    `-- [[ドメイン名]].conf

Nginxから参照するのは以下の2ファイルです。(再発行時にそなえ、ファイル実体を直接参照するより、live以下のシンボリックリンクを参照するほうがよいでしょう)

  • サーバ証明書 /etc/letsencrypt/live/[[ドメイン名]]/fullchain.pem
  • 秘密鍵 /etc/letsencrypt/live/[[ドメイン名]]/privkey.pem

この時点で、ドキュメントルートの .well-known ディレクトリは削除しておきます。

ちなみに、WebサーバがApache2等の場合、letsencryptのサブコマンド(上記の certonly)を run とすると、上記の証明書発行に加え、Webサーバの設定ファイルの更新までやってくれるようなのですが、現時点ではNginxはそこまでサポートされていないようです。

なので、以下はNginxへの個別設定となります。通常のhttpsサイト構築とあまり変わらないと思いますので、その辺ご存じの方は、サーバ証明書秘密鍵の格納場所がわかれば十分でしょう。

DHパラメータファイルの作成

TLSの暗号化アルゴリズムの一つ、Diffie-Hellman暗号で使用するDHパラメータファイルを作成します。

$ sudo openssl dhparam 2048 -out /etc/nginx/dhparam.pem

`2048' は生成するビット長です。数値が大きいほど生成に時間がかかりますが、小さいと脆弱になるので、とりあえずLogjam Attack対策での推奨値である2048を設定しました。うちの環境(2CPUのVPS)で1分くらいで生成完了。 ファイルパーミッションは600にしておきます。

Nginxの設定

/etc/nginx/sites-available/ 以下に任意の名前でファイルを作成し、サイト設定を記入します。

server {
       listen 80;
       server_name www.noisyspot.jp;
       return 301 https://$server_name$request_uri;   # httpにリクエストが来たらpermanent redirectでhttpsに飛ばす
}

server {
        listen 443 ssl default_server;
        listen [::]:443 ssl default_server;

        ssl_certificate /etc/letsencrypt/live/[[ドメイン名]]/fullchain.pem;    # サーバ証明書
        ssl_certificate_key /etc/letsencrypt/live/[[ドメイン名]]/privkey.pem;  # 秘密鍵
        ssl_session_tickets on;

        ssl_dhparam /etc/nginx/dhparam.pem;

        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers 'ECDHE+RSAGCM:ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:!aNULL!eNull:!EXPORT:!DES:!3DES:!MD5:!DSS';
        ssl_prefer_server_ciphers on;


(以下略)

ssl_protocolsssl_ciphers は、暗号化仕様の使用制限に関する設定です。今回は以下のサイトを参考にしました。

qiita.com

このへん、脆弱性が見つかっては新しい物が策定されが繰り返し、またWebサーバやブラウザ側のサポート状況にもよりますので、世間に注意しつつ定期的に更新していく必要があるでしょう。

あとは、/etc/nginx/sites-enabled/ から、上記で作成したサイト設定ファイルへのシンボリックリンクを張り、defaultのシンボリックリンクを削除すれば、設定は以上です。念のため nginx -t で設定ファイルのバリデーションをした後、 systemctl restart nginx サービスを再起動すればOK。