Debian8でLet'sEncryptを使用してNginxを保護する方法

提供:Dev Guides
移動先:案内検索

序章

Let's Encryptは、無料のTLS / SSL証明書を簡単に取得してインストールできる新しい認証局(CA)であり、Webサーバーで暗号化されたHTTPSを有効にします。 必要な手順のほとんど(すべてではないにしても)を自動化しようとするソフトウェアクライアントcertbot(以前はletsencryptと呼ばれていました)を提供することにより、プロセスを簡素化します。 現在、証明書の取得とインストールのプロセス全体は、ApacheWebサーバーでのみ完全に自動化されています。 ただし、Let's Encryptを使用すると、無料のSSL証明書を簡単に取得できます。この証明書は、選択したWebサーバーソフトウェアに関係なく、手動でインストールできます。

このチュートリアルでは、Let's Encryptを使用して無料のSSL証明書を取得し、Debian8のNginxで使用する方法を示します。 また、SSL証明書を自動的に更新する方法についても説明します。 別のWebサーバーを実行している場合は、Webサーバーのドキュメントに従って、セットアップで証明書を使用する方法を学習してください。

前提条件

このチュートリアルに従う前に、いくつかのことが必要になります。

sudo権限を持つroot以外のユーザーがいるDebian8サーバーが必要です。 このようなユーザーアカウントを設定する方法は、Debian8チュートリアル初期サーバー設定に従うことで学ぶことができます。

サーバーにNginxをまだインストールしていない場合は、このガイドに従ってインストールしてください。

証明書を使用する登録済みドメイン名を所有または管理する必要があります。 まだドメイン名を登録していない場合は、そこにある多くのドメイン名レジストラの1つに登録できます(例: Namecheap、GoDaddyなど)。

まだ作成していない場合は、ドメインがサーバーのパブリックIPアドレスを指す Aレコードを作成してください(DigitalOceanのDNSを使用している場合は、このガイドに従うことができます])。 これが必要なのは、Let's Encryptが、証明書を発行しているドメインを所有していることを検証する方法のためです。 たとえば、example.comの証明書を取得する場合、検証プロセスを機能させるには、そのドメインをサーバーに解決する必要があります。 この設定では、ドメイン名としてexample.comwww.example.comを使用するため、両方のDNSレコードが必要です

すべての前提条件が整ったら、Let'sEncryptクライアントソフトウェアのインストールに進みましょう。

ステップ1:Let'sEncryptクライアントであるCertbotをインストールする

Let's Encryptを使用してSSL証明書を取得するための最初のステップは、サーバーにcertbotLet'sEncryptクライアントをインストールすることです。

certbotパッケージは、Debian8がリリースされたときには利用できませんでした。 certbotパッケージにアクセスするには、サーバーでJessieバックポートリポジトリを有効にする必要があります。 このリポジトリを使用して、安定したリポジトリに含まれているものよりも新しいバージョンのソフトウェアをインストールできます。

次のように入力して、バックポートリポジトリをサーバーに追加します。

echo 'deb http://ftp.debian.org/debian jessie-backports main' | sudo tee /etc/apt/sources.list.d/backports.list

新しいリポジトリを追加した後、aptパッケージインデックスを更新して、新しいパッケージに関する情報をダウンロードします。

sudo apt-get update

リポジトリが更新されたら、バックポートリポジトリをターゲットにしてcertbotパッケージをインストールできます。

注:バックポートを使用する場合は、一般的な更新にリポジトリを使用するのではなく、必要な特定のパッケージのみをインストールすることをお勧めします。 バックポートパッケージは、メインリポジトリよりも互換性の保証が少なくなっています。

このリポジトリを使用して誤ってパッケージをインストールまたは更新しないようにするには、リポジトリ名とともに-tフラグを明示的に渡して、バックポートからパッケージをインストールする必要があります。


sudo apt-get install certbot -t jessie-backports

これで、certbotクライアントを使用する準備が整いました。

ステップ2:SSL証明書を取得する

Let's Encryptは、さまざまなプラグインを介してSSL証明書を取得するためのさまざまな方法を提供します。 別のチュートリアルで説明されているApacheプラグインとは異なり、ほとんどのプラグインは、使用するWebサーバーを手動で構成する必要がある証明書の取得にのみ役立ちます。 証明書のみを取得し、それらをインストールしないプラグインは、サーバーに証明書を発行する必要があるかどうかを認証するために使用されるため、「認証者」と呼ばれます。

Webrootプラグインを使用してSSL証明書を取得する方法を説明します。

Webrootプラグインの使用方法

Webrootプラグインは、ドキュメントルート内の/.well-knownディレクトリに特別なファイルを配置することで機能します。このファイルは、検証のためにLet's Encryptサービスによって(Webサーバーを介して)開くことができます。 構成によっては、/.well-knownディレクトリへのアクセスを明示的に許可する必要がある場合があります。

Nginxをまだインストールしていない場合は、このチュートリアルに従ってインストールしてください。 終了したら、以下に進みます。

検証のためにLet'sEncryptがディレクトリにアクセスできることを確認するために、Nginx構成に簡単な変更を加えましょう。 デフォルトでは、/etc/nginx/sites-available/defaultにあります。 nanoを使用して編集します。

sudo nano /etc/nginx/sites-available/default

サーバーブロック内に、次のロケーションブロックを追加します。

SSLサーバーブロックに追加

        location ~ /.well-known {
                allow all;
        }

また、Webrootプラグインを使用するにはパスが必要であるため、rootディレクティブを検索して、ドキュメントルートが何に設定されているかを調べることもできます。 デフォルトの設定ファイルを使用している場合、ルートは/var/www/htmlになります。

保存して終了。

構文エラーがないか構成を確認してください。

sudo nginx -t
Outputnginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

エラーが見つからない場合は、次のコマンドでNginxを再起動します。

sudo systemctl restart nginx

webroot-pathがわかったので、Webrootプラグインを使用して、これらのコマンドでSSL証明書を要求できます。 ここでは、-dオプションを使用してドメイン名も指定しています。 単一の証明書を複数のドメイン名で機能させる場合(例: example.comおよびwww.example.com)、必ずすべてを含めてください。 また、強調表示された部分を適切なWebルートパスとドメイン名に置き換えてください。

sudo certbot certonly -a webroot --webroot-path=/var/www/html -d example.com -d www.example.com

certbotが初期化されると、メールアドレスを入力してLet'sEncryptの利用規約に同意するよう求められます。 その後、チャレンジが実行されます。 すべてが成功した場合は、次のような出力メッセージが表示されます。

Output:IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/example.com/fullchain.pem. Your cert
   will expire on 2017-09-05. To obtain a new or tweaked version of
   this certificate in the future, simply run certbot again. To
   non-interactively renew *all* of your certificates, run "certbot
   renew"
 - If you lose your account credentials, you can recover through
   e-mails sent to [email protected].
 - Your account credentials have been saved in your Certbot
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Certbot so
   making regular backups of this folder is ideal.
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

出力例で強調表示されている証明書のパスと有効期限をメモしておく必要があります。

ファイアウォール注: Failed to connect to host for DVSNI challengeのようなエラーが発生した場合は、ポート80および443でTCPトラフィックを許可するようにサーバーのファイアウォールを構成する必要があります。

注:ドメインがCloudFlareなどのDNSサービスを介してルーティングされている場合は、証明書を取得するまで一時的に無効にする必要があります。


証明書ファイル

証明書を取得すると、次のPEMエンコードファイルが作成されます。

  • cert.pem:ドメインの証明書
  • chain.pem:Let'sEncryptチェーン証明書
  • fullchain.pem: cert.pem and chain.pem combined
  • privkey.pem:証明書の秘密鍵

作成したばかりの証明書ファイルの場所を知っておくことが重要です。これにより、Webサーバー構成でそれらを使用できるようになります。 ファイル自体は、/etc/letsencrypt/archiveのサブディレクトリに配置されます。 ただし、Let's Encryptは、/etc/letsencrypt/live/your_domain_nameディレクトリ内の最新の証明書ファイルへのシンボリックリンクを作成します。 リンクは常に最新の証明書ファイルを指すため、これは証明書ファイルを参照するために使用する必要があるパスです。

次のコマンドを実行して、ファイルが存在することを確認できます(ドメイン名に置き換えてください)。

sudo ls -l /etc/letsencrypt/live/your_domain_name

出力は、前述の4つの証明書ファイルである必要があります。 すぐに、fullchain.pemを証明書ファイルとして使用し、privkey.pemを証明書キーファイルとして使用するようにWebサーバーを構成します。

強力なDiffie-Hellmanグループを生成する

セキュリティをさらに強化するには、強力なDiffie-Hellmanグループも生成する必要があります。 2048ビットのグループを生成するには、次のコマンドを使用します。

sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

これには数分かかる場合がありますが、完了すると、/etc/ssl/certs/dhparam.pemに強力なDHグループが作成されます。

手順3:Webサーバー(Nginx)でTLS/SSLを構成する

SSL証明書を取得したので、それを使用するようにNginxWebサーバーを構成する必要があります。

構成にいくつかの調整を加えます。

  1. SSLキーと証明書ファイルの場所を含む構成スニペットを作成します。
  2. 将来的に任意の証明書で使用できる強力なSSL設定を含む構成スニペットを作成します。
  3. Nginxサーバーブロックを調整してSSLリクエストを処理し、上記の2つのスニペットを使用します。

Nginxを構成するこの方法により、サーバーブロックをクリーンに保ち、共通の構成セグメントを再利用可能なモジュールに配置できます。

SSLキーと証明書を指す構成スニペットを作成する

まず、/etc/nginx/snippetsディレクトリに新しいNginx構成スニペットを作成しましょう。

このファイルの目的を正しく区別するために、ssl-、ドメイン名、最後に.confという名前を付けます。

sudo nano /etc/nginx/snippets/ssl-example.com.conf

このファイル内で、ssl_certificateディレクティブを証明書ファイルに設定し、ssl_certificate_keyを関連するキーに設定する必要があります。 私たちの場合、これは次のようになります。

/etc/nginx/snippets/ssl-example.com.conf

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

これらの行を追加したら、ファイルを保存して閉じます。

強力な暗号化設定を使用して構成スニペットを作成する

次に、いくつかのSSL設定を定義する別のスニペットを作成します。 これにより、Nginxに強力なSSL暗号スイートが設定され、サーバーの安全性を維持するのに役立ついくつかの高度な機能が有効になります。

設定するパラメーターは、将来のNginx構成で再利用できるため、ファイルに一般的な名前を付けます。

sudo nano /etc/nginx/snippets/ssl-params.conf

Nginx SSLを安全にセットアップするために、Cipherli.stサイトのRemyvanElstによる推奨事項を使用します。 このサイトは、人気のあるソフトウェアの使いやすい暗号化設定を提供するように設計されています。 Nginxの選択に関する彼の決定について詳しくは、こちらをご覧ください。

注: Cipherli.st のデフォルトの推奨設定は、強力なセキュリティを提供します。 場合によっては、これにはクライアントの互換性が向上するという犠牲が伴います。 古いクライアントをサポートする必要がある場合は、「はい、レガシー/古いソフトウェアで動作する暗号スイートを教えてください」というラベルの付いたリンクのリンクをクリックしてアクセスできる代替リストがあります。

以下の構成では、デフォルトの提案の代わりに互換性リストを使用できます。 使用する構成の選択は、サポートする必要があるものに大きく依存します。


私たちの目的のために、提供された設定全体をコピーすることができます。 いくつかの小さな変更を加える必要があります。

まず、アップストリームリクエスト用に優先DNSリゾルバーを追加します。 このガイドではGoogleを使用します。 また、先に生成したDiffie-Hellmanファイルを指すようにssl_dhparam設定を設定します。

最後に、 HTTP Strict Transport Security(HSTS )、特に「プリロード」機能についてお読みください。 HSTSをプリロードするとセキュリティが向上しますが、誤って有効にした場合や誤って有効にした場合は、広範囲に及ぶ結果が生じる可能性があります。 このガイドでは、設定をプリロードしませんが、影響を確実に理解している場合は、設定を変更できます。

/etc/nginx/snippets/ssl-params.conf

# from https://cipherli.st/
# and https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# Disable preloading HSTS for now.  You can use the commented out header line that includes
# the "preload" directive if you understand the implications.
#add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;

ssl_dhparam /etc/ssl/certs/dhparam.pem;

終了したら、ファイルを保存して閉じます。

SSLを使用するようにNginx構成を調整する

スニペットができたので、Nginx構成を調整してSSLを有効にすることができます。

このガイドでは、/etc/nginx/sites-availableディレクトリにあるdefaultサーバーブロックファイルを使用していることを前提としています。 別のサーバーブロックファイルを使用している場合は、以下のコマンドでその名前に置き換えてください。

先に進む前に、現在のサーバーブロックファイルをバックアップしましょう。

sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/default.bak

次に、サーバーブロックファイルを開いて調整します。

sudo nano /etc/nginx/sites-available/default

内部では、サーバーブロックはおそらく次のように始まります。

/ etc / nginx / sites-available / default

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    # SSL configuration

    # listen 443 ssl default_server;
    # listen [::]:443 ssl default_server;

    . . .

暗号化されていないHTTPリクエストが暗号化されたHTTPSに自動的にリダイレクトされるように、この構成を変更します。 これは私たちのサイトに最高のセキュリティを提供します。 HTTPトラフィックとHTTPSトラフィックの両方を許可する場合は、次の代替構成を使用します。

構成を2つの別々のブロックに分割します。 最初の2つのlistenディレクティブの後に、サーバーのドメイン名に設定されたserver_nameディレクティブを追加します。 次に、作成する2番目のサーバーブロックへのリダイレクトを設定します。 その後、この短いブロックを閉じます。

/ etc / nginx / sites-available / default

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name example.com www.example.com;
    return 301 https://$server_name$request_uri;
}

    # SSL configuration

    # listen 443 ssl default_server;
    # listen [::]:443 ssl default_server;

    . . .

次に、残りの構成を含めるために、すぐ下に新しいサーバーブロックを開始する必要があります。 ポート443を使用する2つのlistenディレクティブのコメントを解除できます。 その後、設定した2つのスニペットファイルを含める必要があります。

注:IPバージョンとポートの組み合わせごとにdefault_server修飾子を含むone listenディレクティブのみを使用できます。 default_serverが設定されているこれらのポートに対して他のサーバーブロックを有効にしている場合は、ブロックの1つから修飾子を削除する必要があります。


/ etc / nginx / sites-available / default

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name example.com www.example.com;
    return 301 https://$server_name$request_uri;
}

server {

    # SSL configuration

    listen 443 ssl default_server;
    listen [::]:443 ssl default_server;
    include snippets/ssl-example.com.conf;
    include snippets/ssl-params.conf;

    . . .

終了したら、ファイルを保存して閉じます。

(代替構成)HTTPトラフィックとHTTPSトラフィックの両方を許可する

暗号化されたコンテンツと暗号化されていないコンテンツの両方を許可する必要がある場合は、Nginxを少し異なる方法で構成する必要があります。 これは、回避できる場合は一般的に推奨されませんが、状況によっては必要になる場合があります。 基本的に、2つの別々のサーバーブロックを1つのブロックに圧縮し、リダイレクトを削除します。

/ etc / nginx / sites-available / default

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

    server_name example.com www.example.com;
    include snippets/ssl-example.com.conf;
    include snippets/ssl-params.conf;

    . . .

終了したら、ファイルを保存して閉じます。

ステップ4:ファイアウォールを調整する

ファイアウォールを有効にしている場合は、SSLトラフィックを許可するように設定を調整する必要があります。 必要な手順は、使用しているファイアウォールソフトウェアによって異なります。 現在ファイアウォールが構成されていない場合は、スキップしてください。

UFW

ufw を使用している場合は、次のように入力すると現在の設定を確認できます。

sudo ufw status

おそらく次のようになります。つまり、WebサーバーへのHTTPトラフィックのみが許可されます。

OutputStatus: active

To                         Action      From
--                         ------      ----
SSH                        ALLOW       Anywhere
WWW                        ALLOW       Anywhere
SSH (v6)                   ALLOW       Anywhere (v6)
WWW (v6)                   ALLOW       Anywhere (v6)

さらにHTTPSトラフィックを取り込むために、「WWWフル」プロファイルを許可してから、冗長な「WWW」プロファイルの許容値を削除できます。

sudo ufw allow 'WWW Full'
sudo ufw delete allow 'WWW'

ステータスは次のようになります。

sudo ufw status
OutputStatus: active

To                         Action      From
--                         ------      ----
SSH                        ALLOW       Anywhere
WWW Full                   ALLOW       Anywhere
SSH (v6)                   ALLOW       Anywhere (v6)
WWW Full (v6)              ALLOW       Anywhere (v6)

これで、HTTPSリクエストがサーバーで受け入れられるはずです。

IPTables

iptablesを使用している場合は、次のように入力すると現在のルールを確認できます。

sudo iptables -S

ルールを有効にしている場合は、それらが表示されます。 構成例は次のようになります。

Output-P INPUT DROP
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT

SSLトラフィックを開くために必要なコマンドは、現在のルールによって異なります。 上記のような基本的なルールセットの場合、次のように入力してSSLアクセスを追加できます。

sudo iptables -I INPUT -p tcp -m tcp --dport 443 -j ACCEPT

ファイアウォールルールをもう一度見ると、新しいルールが表示されます。

sudo iptables -S
Output-P INPUT DROP
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT

プログラムを使用して起動時にiptablesルールを自動的に適用する場合は、必ず新しいルールで構成を更新する必要があります。

ステップ5:Nginxでの変更を有効にする

変更を加えてファイアウォールを調整したので、Nginxを再起動して新しい変更を実装できます。

まず、ファイルに構文エラーがないことを確認する必要があります。 これを行うには、次のように入力します。

sudo nginx -t

すべてが成功すると、次のような結果が得られます。

Outputnginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

出力が上記と一致する場合、構成ファイルに構文エラーはありません。 Nginxを安全に再起動して、変更を実装できます。

sudo systemctl restart nginx

Let's Encrypt TLS / SSL証明書が配置され、ファイアウォールがポート80および443へのトラフィックを許可するようになりました。 この時点で、WebブラウザでHTTPS経由でドメインにアクセスして、TLS/SSL証明書が機能することをテストする必要があります。

Qualys SSL Labsレポートを使用して、サーバー構成のスコアを確認できます。

In a web browser:https://www.ssllabs.com/ssltest/analyze.html?d=example.com

これが完了するまでに数分かかる場合があります。 このガイドのSSL設定では、少なくともAの評価を報告する必要があります。

ステップ6:自動更新を設定する

Let's Encryptの証明書は90日間有効ですが、エラーの許容範囲を確保するために、60日ごとに証明書を更新することをお勧めします。 この記事の執筆時点では、クライアント自体の機能として自動更新はまだ利用できませんが、renewオプションを指定してLet'sEncryptクライアントを実行することにより、証明書を手動で更新できます。

インストールされているすべてのドメインの更新プロセスをトリガーするには、次のコマンドを実行します。

sudo certbot renew

最近証明書をインストールしたため、コマンドは有効期限のみを確認し、証明書がまだ更新されていないことを通知するメッセージを出力します。 出力は次のようになります。

Output:Saving debug log to /var/log/letsencrypt/example.com.log

-------------------------------------------------------------------------------
Processing /etc/letsencrypt/renewal/example.com.conf
-------------------------------------------------------------------------------
Cert not yet due for renewal

The following certs are not due for renewal yet:
  /etc/letsencrypt/live/example.com/fullchain.pem (skipped)
No renewals were attempted.

複数のドメインでバンドルされた証明書を作成した場合、ベースドメイン名のみが出力に表示されますが、更新はこの証明書に含まれるすべてのドメインに対して有効である必要があることに注意してください。

証明書が古くならないようにするための実用的な方法は、自動更新コマンドを定期的に実行するcronジョブを作成することです。 更新は最初に有効期限をチェックし、証明書の有効期限が30日以内の場合にのみ更新を実行するため、たとえば、毎週または毎日実行するcronジョブを作成しても安全です。

crontabを編集して、毎週renewalコマンドを実行する新しいジョブを作成しましょう。 rootユーザーのcrontabを編集するには、次のコマンドを実行します。

sudo crontab -e

crontabを初めて使用する場合は、お好みのテキストエディタを選択するように求められることがあります。 強い好みがない場合は、nanoが簡単な選択です。

次の行を追加します。

crontab entry30 2 * * * /usr/bin/certbot renew --noninteractive --renew-hook "/bin/systemctl reload nginx" >> /var/log/le-renew.log

保存して終了。 これにより、毎日午前2時30分にcertbot renewコマンドを実行する新しいcronジョブが作成され、証明書が更新された場合はNginxがリロードされます。 コマンドによって生成された出力は、/var/log/le-renewal.logにあるログファイルにパイプされます。

注: cronジョブを作成およびスケジュールする方法の詳細については、VPSガイドでCronを使用してタスクを自動化する方法を確認してください。


結論

それでおしまい! Webサーバーは、無料のLet's Encrypt TLS / SSL証明書を使用して、HTTPSコンテンツを安全に提供しています。