序章

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

SSLターミネーションについて

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

前提条件

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

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

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

設定

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

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

  • 画像:Ubuntu 14.04
  • ホスト名:ロードバランサー
  • プライベート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

ドメイン名example.com

これらすべてのドロップレットでは、プライベートネットワーキングを有効にする必要があります。

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

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

各サーバーを再起動してアップグレードを適用します。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

詳細については、この記事を参照してください。

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

このセクションでは、SSL証明書を作成するために必要な手順を実行します。 この記事では、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を使用して、認証局から有効な証明書を取得するか、次のコマンドで自己署名証明書を生成します。

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

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

  • server.key-秘密鍵
  • ca-certs.pem-CAのルート証明書と中間証明書のコレクション。 CAから有効な証明書を取得した場合にのみ存在します。
  • server.crt-ドメイン名のSSL証明書

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

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

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

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

upstream mywebapp1 {
    server 10.130.227.11;
    server 10.130.227.22;
}

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

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;
    }
}

The 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を有効にする

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

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

バックエンドサーバーの独自のプライベートIPアドレスに置き換えます。

Listen 10.130.227.22:80

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

service apache2 restart

次のステップは、ロードバランサーのプライベート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アドレス、およびアクセスされたポートを出力する必要があります。

<?php
    header( 'Content-Type: text/plain' );
    echo 'Host: ' . $_SERVER['HTTP_HOST'] . "\n";
    echo 'Remote Address: ' . $_SERVER['REMOTE_ADDR'] . "\n";
    echo 'X-Forwarded-For: ' . $_SERVER['HTTP_X_FORWARDED_FOR'] . "\n";
    echo 'X-Forwarded-Proto: ' . $_SERVER['HTTP_X_FORWARDED_PROTO'] . "\n";
    echo 'Server Address: ' . $_SERVER['SERVER_ADDR'] . "\n";
    echo 'Server Port: ' . $_SERVER['SERVER_PORT'] . "\n\n";
?>

ブラウザまたはを使用してこのファイルに数回アクセスします 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

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

SSL構成の強化

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

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

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サーバーテストを実行すると、このセットアップはA+グレードを取得するはずです。 カールテストを再度実行して、すべてが正しく機能しているかどうかを確認します。

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

参考文献

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