【アップデート】暖機不要で固定IPの Network Load Balancer ( NLB ) がSNIで複数の証明書をサポートしました

大栗です。

Network Load Balancer(NLB)でSNIをサポートして、複数の証明書を設定できるようになりました。

Elastic Load Balancing: Network Load Balancers now support multiple TLS certificates using Server Name Indication (SNI)

SNI(Server Name Indication)とは

SNI(Server Name Indication)とはRFC 6066に記述されている仕様です。「Server Name Indication」つまりサーバ名表示のことです。SNI以前の仕様ではIPアドレス/ポートに対して一つのSSL/TLS証明書しか設定が行なえませんでした。SNIによりサーバ名ごとにSSL/TLS証明書を設定できるようになり、リクエストから証明書を適用するサーバ名が判断して適用するようになります。

HTTPSリクエストのホストヘッダーを見れば判断できるだろうと思われるかもしれませんが、HTTPSで暗号化されるため証明書を適用する前にはホスト名を判断できません。そこで、SSL/TLSハンドシェイクのプロセス中でホスト名を送信することで解決しています。クライアントからサーバへ初回アクセスする時のClient Helloの中にserver_nameと言う型のExtensionsを含めてアクセス先のホスト名(host_name)を通知します。サーバ側ではClient Hello(とクライアントへ返すServer Hello)の内容を元にSSL/TLSで通信するための暗号形式などを決定するので、SSL/TLSで暗号化する前にアクセス先のホスト名が判断でき適切な証明書を適用します。

(この章の内容はALBでSNIが対応したときの記事をそのまま持ってきました。。。)

試してみる

下図のような環境を考えてみます。

NLBにsni-1.example.comsni-2.example.comの2個のドメインを設定します。同様にACMで各々の証明書をNLBに設定します。EC2側はPHPのphpinfo()でアクセス内容を表示します。

証明書の取得

ここでは証明書はACMで取得します。以下のエントリを参考に2つのドメインの証明書を発行してください。

Certificate Manager (ACM) がDNSの検証をサポートしました

EC2の設定

ここでは以下を前提とします。

  • リージョン: 東京リージョン
  • OS: Amazon Linux 2 AMI (HVM), SSD Volume Type - ami-0ff21806645c5e492 (64 ビット x86)
  • インスタンスタイプ: t3.small
  • Webサーバ:Apache HTTP Server 2.4.39
  • PHP: 7.3.8

EC2のUserDataで以下のような内容を記載しておき、ApacheやPHPを導入します。

#!/bin/bash
yum install -y httpd
amazon-linux-extras install -y php7.3
cat <<EOF > /var/www/html/index.php
<?php
phpinfo(INFO_VARIABLES);
EOF
systemctl start php-fpm
systemctl start httpd

NLBの場合はロードバランサーへのアクセス許可はEC2のセキュリティグループの設定になるため、アクセス元からのポート443を許可しておきます。

ターゲットグループの作成

以下の内容でターゲットグループを作成します。

項目名 備考
ターゲットグループ名 php-target
プロトコル TCP
ポート 80
ターゲットの種類 インスタンス
VPC <EC2を設置したVPC>
ヘルスチェックの設定 プロトコル TCP
ヘルスチェックの設定 ポート トラフィックポート

作成したターゲットグループのターゲットとして2台のEC2を設定します。

NLBの作成

NLB(Network Load Balancer)を作成します。

1. ロードバランサーの設定

項目名 備考
名前 sni-nlb
スキーマ インターネット向け
ロードバランサーのプロトコル TLS(セキュア TCP)
ロードバランサーのポート 443
アベイラビリティゾーン <対象VPCのパブリックなサブネット>

2. セキュリティ設定の構成

項目名 備考
証明書タイプ ACM から証明書を選択する
証明書の名前 sni-1.example.com デフォルトの証明書です
セキュリティポリシー ELBSecurityPolicy-TLS-1-2-2017-01 安全なプロトコルのみを許可します

3. ルーティングの設定

項目名 備考
ターゲットグループ 既存のターゲットグループ
名前 sni-target
ターゲットの種類 インスタンス
プロトコル TCP
ポート 80
ヘルスチェック プロトコル TCP
ヘルスチェックの設定 ポート トラフィックポート

4. ターゲットの登録

先程設定したEC2が設定されていることを確認して作成します。

5. 確認

設定内容を確認して、作成をクリックします。

SNIの設定

作成したNLBのリスナーで証明書の表示/編集をクリックします。

記号をクリックします。

sni-2.example.comの証明書を選択して追加をクリックします。

DNSの設定

ここではRoute 53で登録します。

このような形で、Alias Targetをsni-1.example.comsni-2.example.comで登録します。エイリアス先でNLBの登録する場合はNLBのDNS名を入力します。

アクセスしてみる

まずはhttps://sni-1.example.com/index.phpにアクセスしてみます。するとsni-1の内容が表示されます。

証明書も確認してみるとsni-1.example.comの証明書でアクセスしています。sni-1の内容が表示されます。

次にhttps://sni-2.example.com/index.phpにアクセスしてみます。するとsni-2の内容が表示されます。

証明書も確認してみるとsni-2.example.comの証明書でアクセスしています。

特殊なパターンとしてIPアドレスでアクセスする場合を試してみます。

証明書を確認してみるとsni-1.example.comの証明書でアクセスしています。これはNLBのリスナーでメインの証明書をsni-1.example.comにしているためです。

このようにホスト名によって別の証明書でアクセスしていることが確認できました。

さいごに

NLBでもSNIに対応して複数の証明書を設定できるようになりました。複数のエンドポイントをまとめる時に有効かと思います。個人的にはエンドポイントごとに別のロードバランサーを設定したいのですが、選択肢が増えたため構成の自由度が上がったと思います。