SSL終了を使用したNginxロードバランシングのセットアップ方法

前書き

この記事では、ロードバランサー上でSSL証明書を1つだけ使用して、SSL終了でNginxロードバランシングを設定する方法を示します。 これにより、OpenSSLの更新とキーと証明書をロードバランサー自体から管理できるようになるため、SSL管理のオーバーヘッドが削減されます。

SSL終了について

Nginxは、複数のバックエンドサーバーに着信トラフィックを分散するロードバランサーとして構成できます。 SSL終了とは、ロードバランサーとバックエンドサーバー間のトラフィックがHTTPになるようにSSL暗号化/復号化を処理するロードバランサーで発生するプロセスです。 バックエンドは、ロードバランサーのIPへのアクセスを制限することで保護する必要があります。これについては、この記事で後述します。

SSL Termination Diagram

前提条件

このチュートリアルでは、コマンドはrootユーザーまたはsudo特権を持つユーザーとして実行する必要があります。 Users Tutorialでそれを設定する方法を見ることができます。

次のガイドを参照として使用できます。

LAMPサーバーは必須ではありませんが、このチュートリアルでは例として使用します。

セットアップ

このチュートリアルでは、次の3つのドロップレットを使用します。

ドロップレット1(フロントエンド)

  • 画像:Ubuntu 14.04

  • ホスト名:loadbalancer

  • プライベートIP:10.130.227.33

ドロップレット2(バックエンド)

  • 画像:Ubuntu 14.04

  • ホスト名:web1

  • プライベートIP:10.130.227.11

ドロップレット3(バックエンド)

  • 画像:Ubuntu 14.04

  • ホスト名:web2

  • プライベートIP:10.130.227.22

Domain name-example.com

これらのすべてのドロップレットでは、private networkingを有効にする必要があります。

3つのサーバーすべてでソフトウェアを更新およびアップグレードします。

apt-get update && apt-get upgrade -y

Reboot each server to apply the upgrades. OpenSSLは安全であるために最新バージョンである必要があるため、これは重要です。

アップストリームモジュールがバックエンドの負荷分散を行うドメイン名の新しいNginx仮想ホストをセットアップします。

Nginxの負荷分散を設定する前に、VPSにNginxをインストールする必要があります。 apt-getを使用してすばやくインストールできます。

apt-get install nginx

2つのバックエンドサーバーで、リポジトリを更新し、Apacheをインストールします。

apt-get install apache2

両方のバックエンドサーバーにPHPをインストールします。

apt-get install php5 libapache2-mod-php5 php5-mcrypt

詳細については、this articleを参照してください。

キーを生成してSSL証明書を作成する

このセクションでは、SSL証明書の作成に必要な手順を実行します。 This articleは、NginxのSSL証明書について詳しく説明しています。

SSL証明書ディレクトリを作成して、切り替えます。

mkdir -p /etc/nginx/ssl/example.com
cd /etc/nginx/ssl/example.com

秘密鍵を作成します。

openssl genrsa -des3 -out server.key 2048

パスフレーズを削除します。

openssl rsa -in server.key -out server.key

CSR(証明書署名要求)を作成します。

openssl req -new -key server.key -out server.csr

このCSRを使用して、a certificate authorityから有効な証明書を取得するか、次のコマンドで自己署名証明書を生成します。

openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

これが完了すると、このディレクトリには次のファイルが含まれます。

  • server.key - The private key

  • ca-certs.pem - A collection of your CA’s root and intermediate certificates. CAから有効な証明書を取得した場合にのみ存在します。

  • server.crt - The SSL certificate for your domain name

仮想ホストファイルとアップストリームモジュール

Nginxディレクトリ内に仮想ホストファイルを作成します

nano /etc/nginx/sites-available/example.com

バックエンドサーバーのプライベートIPアドレスを含むアップストリームモジュールを追加します

upstream mywebapp1 {
    server 10.130.227.11;
    server 10.130.227.22;
}

この行でサーバーブロックafterを開始します。 このブロックには、ドメイン名、上流サーバーへの参照、およびバックエンドに渡す必要のあるヘッダーが含まれています。

server {
    listen 80;
    server_name example.com www.example.com;

    location / {
        proxy_pass http://mywebapp1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

proxy_set_headerディレクティブは、要求に関する重要な情報をアップストリームサーバーに渡すために使用されます。

このファイルを保存し、sites-enabledディレクトリへのシンボリックリンクを作成します。

ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com

構成テストを実行して、エラーを確認します。

service nginx configtest

エラーが表示されない場合は、nginxサービスをリロードします。

service nginx reload

ロードバランシングがHTTP用に設定されました。

SSLを有効にする

server {}ブロック内の仮想ホストファイル(/etc/nginx/sites-available/example.com)に次のディレクティブを追加します。 これらの行は、次の例でコンテキストで表示されます。

listen 443 ssl;
ssl on;
ssl_certificate         /etc/nginx/ssl/example.com/server.crt;
ssl_certificate_key     /etc/nginx/ssl/example.com/server.key;
ssl_trusted_certificate /etc/nginx/ssl/example.com/ca-certs.pem;

自己署名証明書を使用している場合は、ssl_trusted_certificateディレクティブを無視してください。 これで、serverブロックは次のようになります。

server {
    listen 80;
    listen 443 ssl;
    server_name example.com www.example.com;

    ssl on;
    ssl_certificate         /etc/nginx/ssl/example.com/server.crt;
    ssl_certificate_key     /etc/nginx/ssl/example.com/server.key;
    ssl_trusted_certificate /etc/nginx/ssl/example.com/ca-certs.pem;

    location / {
        proxy_pass http://mywebapp1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

構成エラーを確認し、Nginxサービスをリロードします。

service nginx configtest && service nginx reload

バックエンドサーバーのセキュリティ保護

現在、バックエンドサーバーでホストされているWebサイトには、パブリックIPアドレスを知っている人なら誰でも直接アクセスできます。 これは、プライベートインターフェイスでのみリッスンするようにバックエンドのWebサーバーを構成することで防止できます。 Apacheでこれを行う手順は次のとおりです。

ports.confファイルを編集します。

nano /etc/apache2/ports.conf

次の行を見つけます。

Listen 80

backend server’s自身のプライベートIPアドレスに置き換えます。

Listen 10.130.227.22:80

すべてのバックエンドサーバーでこれを行い、Apacheを再起動します。

service apache2 restart

次のステップは、load balancer’sのプライベートIPへのHTTPアクセスを制限することです。 次のファイアウォールルールはこれを実現します。

iptables -I INPUT -m state --state NEW -p tcp --dport 80 ! -s 10.130.227.33 -j DROP

例をロードバランサーのプライベートIPアドレスに置き換え、すべてのバックエンドサーバーでこのルールを実行します。

セットアップのテスト

すべてのバックエンドサーバー(この例ではweb1とweb2)でPHPファイルを作成します。 これはテスト用であり、セットアップが完了したら削除できます。

nano /var/www/html/test.php

アクセスしたドメイン名、サーバーのIPアドレス、ユーザーのIPアドレス、アクセスしたポートを印刷する必要があります。

ブラウザまたはcurlを使用して、このファイルに数回アクセスします。 自己署名証明書の設定でcurl -kを使用して、curlがSSLエラーを無視するようにします。

curl https://example.com/test.php https://example.com/test.php https://example.com/test.php

出力は次のようになります。

   Host: example.com
   Remote Address: 10.130.245.116
   X-Forwarded-For: 117.193.105.174
   X-Forwarded-Proto: https
   Server Address: 10.130.227.11
   Server Port: 80

   Host: example.com
   Remote Address: 10.130.245.116
   X-Forwarded-For: 117.193.105.174
   X-Forwarded-Proto: https
   Server Address: 10.130.227.22
   Server Port: 80

   Host: example.com
   Remote Address: 10.130.245.116
   X-Forwarded-For: 117.193.105.174
   X-Forwarded-Proto: https
   Server Address: 10.130.227.11
   Server Port: 80

Server Addressはリクエストごとに変化することに注意してください。これは、異なるサーバーが各リクエストに応答していることを示しています。

SSL設定の強化

このセクションでは、古い暗号とプロトコルの脆弱性を排除するためのベストプラクティスに従ってSSLを構成する方法について説明します。 このセクションには個々の行が示されており、このチュートリアルの最後のセクションに完全な構成ファイルが示されています。

SSLセッションキャッシュを有効にすると、HTTPS Webサイトのパフォーマンスが向上します。 次のディレクティブは、afterssl_trusted_certificateに配置する必要があります。 これらは、10 minutesのキャッシュライフタイムでサイズ20MBの共有キャッシュを有効にします。

ssl_session_cache shared:SSL:20m;
ssl_session_timeout 10m;

SSL接続で使用されるプロトコルと暗号を指定します。 ここでは、SSLv2を省略し、MD5やDSSなどの安全でない暗号を無効にしました。

ssl_prefer_server_ciphers       on;
ssl_protocols                   TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers                     ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS;

Strict Transport Securityは、サポートするすべてのWebブラウザーにHTTPSのみを使用するように指示します。 add_headerディレクティブで有効にします。

add_header Strict-Transport-Security "max-age=31536000";

構成エラーを確認し、Nginxサービスをリロードします。

service nginx configtest && service nginx reload

完全な構成

SSLターミネーションを構成して強化すると、完全な構成ファイルは次のようになります。

/etc/nginx/sites-available/example.com

upstream mywebapp1 {
    server 10.130.227.11;
    server 10.130.227.22;
}

server {
    listen 80;
    listen 443 ssl;
    server_name example.com www.emxaple.com;

    ssl on;
    ssl_certificate         /etc/nginx/ssl/example.com/server.crt;
    ssl_certificate_key     /etc/nginx/ssl/example.com/server.key;
    ssl_trusted_certificate /etc/nginx/ssl/example.com/ca-certs.pem;

    ssl_session_cache shared:SSL:20m;
    ssl_session_timeout 10m;

    ssl_prefer_server_ciphers       on;
    ssl_protocols                   TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers                     ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS;

    add_header Strict-Transport-Security "max-age=31536000";

    location / {
        proxy_pass http://mywebapp1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

SSL Server Testを実行すると、このセットアップはA +グレードを取得するはずです。 カールテストを再度実行して、すべてが正常に機能しているかどうかを確認します。

curl https://example.com/test.php https://example.com/test.php https://example.com/test.php

参考文献

負荷分散アルゴリズムの詳細については、this articleをお読みください。

Related