SSLターミネーションを使用してNginxロードバランシングを設定する方法
序章
この記事では、ロードバランサーで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
参考文献
負荷分散アルゴリズムの詳細については、この記事をお読みください。