はじめに
AWSのNLBでPrivate subnetにあるEC2へアクセスする方法を書いた記事です。
Web3層アーキテクチャをEC2単体で全部賄っているけど、EC2自体はPublic subnetではなくPrivate subnetに置いておきたいなといった場合に便利です。
ところで、なぜALBではなくNLBを採用するのか?というと、今回は以下の条件があったからです。
- 複数AZで冗長化する予定がない。
- 多量のデータをやり取りする可能性がある。
- 相互 TLS 認証(サーバー認証+クライアント認証)を使いたい。ALBは今のところ相互 TLS 認証がサポートされていません。
公式資料はここら辺を参考にしました。
Network Load Balancer の作成
https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/network/create-network-load-balancer.html
プライベート IP アドレスを持つバックエンドインスタンスを ELB のインターネット向けロードバランサーにアタッチするにはどうすればよいですか?
https://aws.amazon.com/jp/premiumsupport/knowledge-center/public-load-balancer-private-ec2/
Application Load Balancer 用の HTTPS リスナーを作成する←相互 TLS 認証はALBじゃないよという記載
https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/create-https-listener.html
NLB→Public subnet→Private subnetでアクセスする
公式資料にも記載されていますが、NLBからはPublic subnetを経由してPrivate subnetへアクセスします。ただし、ただ経由すればいいという訳ではなくPublic subnetとPrivate subnetは同一のAvailability Zoneに配置する必要があります。
なお、相対TLS認証の終端はEC2に載っているWebサーバーとなります。NLBは暗号化された通信をそのまま転送します。WAFは暗号化された通信を評価できまないため、今回のケースではAWS WAFを利用できません。
EC2のセキュリティグループ設定
Privet subnetにおいたEC2のセキュリティグループにPublicsubentのIPv4 CIDR(VPC CIDR)からの接続を許可しておきます。
嘘です。NLBはクライアントのIPでEC2へ到達するため、EC2のセキュリティグループは対象のポートをソース0.0.0.0/0で開けます。
解放するポートは、EC2で提供するサービスのプロトコルとNLBの設定によって変わります。今回、HTTPSでの接続はNLBのPreserve client IP addressesをoffにして、セキュリティグループはPublicsubentのIPv4 CIDR(VPC CIDR)からの接続を許可しました。また、FTPSはPreserve client IP addressesをonにして、ソース0.0.0.0/0で開けました。
解放するポートは、EC2で提供するサービスのプロトコルとNLBの設定によって変わります。
今回は、HTTPSとFTPSでの接続があります。HTTPS接続についてはNLBのプライベート IPv4 アドレスのみの許可としました。FTPSも同様の設定にしたかったのですが、FTPサーバー側の問題で上手くいかなかったので0.0.0.0/0を許可しました。
なお、クライアントの固定IPが分かっている場合は、NLBのPreserve client IP addressesをONにすればクライアントの固定IPのみを許可することもできます。Preserve client IP addresses→ONにすると、EC2からはクライアントの固定IPが接続してきたように見えて、Preserve client IP addresses→OFFにすると、EC2からはNLBが接続してきたように見えるというわけです。
ターゲットグループとリスナーの関係
リスナーはポートごとに作成します。ターゲットはリスナーと同一のポートで作成します。例えば、80番ポートと443番ポートのリスナーを設定している場合は、80番ポートと443番ポートのターゲットをそれぞれ作成して、それぞれのリスナーに紐づけます。80番ポートと443番ポートを単一のターゲットで作成してリスナー80番ポートに紐づけたりすると、ターゲットの80番ポートに転送されることもあれば443番ポートに転送されることもあるというふるまいをしてしまいます。
なお、複数台のEC2をNLBに紐づける場合はターゲットとして複数のEC2インスタンスの同一ポートを登録し、いずれかのEC2へ転送されるように設定します。
ターゲットグループの作成
NLBを作成する際にターゲットグループの設定が必要になるので、NLBより先にターゲットグループを作成しておきます。
EC2サービスにあるターゲットグループを選択して「Create target group」をクリックします。
Specify group detailsの画面が表示されたら、今回は以下で設定します。
target typeは、Instancesを選択。
Targetgroup nameには、適切なターゲットグループの名前を入力。
ProtocolはTCPでPortは443を設定。これで暗号化通信をパススルーするわけですね。
Health checksのHealth checks protocolはTCPだったのでそのまま何もせず、「Next」をクリックします。
ターゲットとするPrivate subnetにあるインスタンスにチェックをつけます。
Ports for the selected instancesに443を入力して、「Include as pending below」をクリックします。
Targetsに反映した内容を確認して、「Create target group」をクリックします。
Target groupsに表示されたら成功です。
NLBの作成
EC2サービスにあるロードバランサーを選択して「ロードバランサーの作成」をクリックします。
Network Load BalancerのCreateをクリック。
Basic configurationを今回は以下で設定します。
Load balancer nameに適切なNLBの名前を入力します。
インターネットに向けるのでInternet-facingです。
IP address typeはIP4なのでそのまま変更しません。
同じページにあるNetwork mappinngを設定します。
Mappingsで使用するAZにチェックを付けてPublic subnetを選択します。
よく見ると「選択したsubnetはInternetGatewayに繋がってないとダメだからな!」って注意喚起してくれてますね。
同じページにあるListeners and routingを設定します。
Protocol はTCPを選択、Portには443を入力。
Default actionは作成したターゲットグループを選択します。
ここまで設定したらページの一番下にある「Create load balancer」をクリックします。
View load balancerをクリックして…
無事出来上がっていることを確認します。初めは状態がプロビジョニングなのでActiveになるのを待ちましょう。
続いてHealth statusがhealtyyになっていることを確認します。
無事、Httpsで接続できたら完成です。
おわりに
しっかし、NLBは簡単に作れるものの奥が深く、調べれば調べるほど分からないことが出てきますね…。