gokigenmaruのブログ

40から始めるクラウドエンジニア

AWSのIPv6通信(NLB-EC2)

AWSIPv6通信を実施する要件がありました。
その際に調べたこととか、考えたことをメモ程度で記載します。

IPv6通信構成

いつもの構成図を。

構成図1

Clientからの接続をNLBで受けて裏側のオートスケーリンググループを組んでいるEC2(Apache)に流します。
当初はこのNLBをIPv4からDualStackに変更すればいけるだろうと思っていましたが、なかなか想定通りにはいかなかったですね。

基本設定

VPC

VPCは新規でIPv6の割り当てをしました。アドレスはAmazon提供のもの。
SubnetにもIPv6を割り当て、NLBのSubnetとEC2のサブネットにそれぞれIPv6アドレスを設定します。
EgressOnlyインターネットゲートウェイを新規構築、これはIPv4でいうNATGatewayになります。注意点はインターネットゲートウェイIPv4/IPv6ともにOKなので、Publicサブネットはインターネットゲートウェイ、PrivateサブネットはEgress Onlyインターネットゲートウェイを使うということです。
ルートテーブルの更新、Publicサブネットは::/0をインターネットゲートウェイに向けるルーティングの追加、Privateサブネットは::/0をEgress Onlyインターネットゲートウェイに向けるルーティングの追加。
セキュリティグループで、今回はNLB構成なので裏にあるEC2にアタッチされているセキュリティグループのインバウンドで::/0の443を追加。またアウトバウンドで::/0をAnyで追加。

EC2(Apache)

ApacheはVirtualHostで*:443で受ける設定にしていたので、Apache側は特にIPv6にするために必要となる設定はなかったです。
OS側は意図的にIPv6を拒否(sysctl.conf)していたので、IPv6を許可する設定に変更。

/etc/sysctl.conf

net.ipv6.conf.all.disable_ipv6 = 0
net.ipv6.conf.default.disable_ipv6 = 0
net.ipv6.conf.eth0.disable_ipv6 = 0
net.ipv6.conf.lo.disable_ipv6 = 0

RAと止める設定は入れませんでした。
今回、SubnetにIPv6アドレスを割り当てて、EC2はSubnetに割り当てられたIPを動的に貰う形にしようと思ったので、RA止めてしまうとそのあたりで不具合ありそうな気がしたからです。
でもせっかくなので一応検証しておけばよかったなとこのブログ書いてて思いました。(後の祭り

NLBをDualStack化

上記基本設定を実施した後にNLBをDualStack化。
結果は想定通りIPv6で通信を受けることが出来ました。
めでたしめでたしなのですが、念のため通信の確認を実施。
ここでいくつか不審点がありました。

前提

curl -vvv -6 https://example.com/testコマンドを実行し、IPv6でNLBあてに通信はできている。
NLB設定のクライアント IP アドレスの保持は「オン」

確認結果

Apacheのログには「IPv4」アドレスでIPv6の通信が来ているように見える
 →このIPv4アドレスを調べると、NLB用のSubnetで設定しているIPv4アドレスであることから、NLBから通信が来ているようにログ上は出ている。
・EC2側でtcpdumpを使用しパケットレベルで確認すると、Apacheのログと同じようにIPv4アドレスになっている。
 →L7レベルではなく、L3レベルでもEC2側にはIPv4で通信が来ている。

つまり、想定では
Client -- (IPv6) -- NLB -- (IPv6) -- EC2=Apache
の通信となるはずが、実際には
Client -- (IPv6) -- NLB -- (IPv4) -- EC2=Apache
となっていた。

となると、基本設定で実施したEC2のIPv6化って意味がないのではないかと考えて、EC2のsysctl.confでIPv6をDisableに変更。
DualStackにしているNLBにcurl -vvv -6 https://example.com/testコマンドを実行した結果、通信が出来た。
つまり、Client-NLBはIPv6だけれどもNLB-EC2はIPv4となることが確定。

EC2側にIPv6で通信をさせてみようと考え、DualStackにしたNLBのターゲットグループをインスタンスにしているが、これをIPアドレス(IPv6)にして通信を試したところ、うまくIPv6Apacheのログが出るように。
であれば、NLBを2つにし、1つをIPv4、1つをDualStackにしてDualStack側をIPv6で名前解決させるようにしたらいいのではないかと考え実施してみたところ、オートスケーリンググループのロードバランシングにNLB(IPv6)を登録するところでターゲットグループのアタッチに失敗しましたとエラー。
内容としては[Provided Target Group xxx has invalid tareget type.Please ensure all provided Target Groups have target tyep of instance.]
つまり、IPタイプのターゲットグループはオートスケーリンググループでは設定できないということでした。
オートスケールしたときに、IPv4はNLBでEC2のLaunchやTerminateを補足して自動的にNLBのバックエンドを更新してくれますが、DualStack側はEC2のLaunchやTerminateを補足出来ないため、オートスケールするとNLBのバックエンドからEC2が消えてしまうことに…。

困ったこと

この結果で2点困ったことが発生。
・通信はセキュリティグループで制限を実施しているが、NLBではセキュリティグループがかけられず(AWSの仕様)、EC2側でセキュリティグループをかける必要があるが、NLB-EC2間がIPv4(SrcはNLBのIP)となると、IPv6アドレスで通信制御が実施できない。
ApacheアクセスログにはIPv6通信はIPv6で出力されること(Client側のIPv6アドレスが識別できること)が望ましい。(調査の観点から)

暫定解決策

・セキュリティグループによるIP制限ではなく、NACLによるIP制限にすればNACLはSubnetにかかることから設定はIPv6で制限はかけられる。
Apache側でログを出すのではなく、NLB側でログを出せばIPv6アドレスが記録される。
ただ、内部で検討した結果、NACL制御はこのNLB以外にも影響が出てしまうこと、NLBログではなくApacheログで確認をしたいという要望のため、却下に。。。

解決策検討

上記検証内容をAWSのサポートの方に連絡、方針についてやり取りをした結果、対応としては以下3点が取りうる対応となりました。

 (A) 1台の NLB でターゲットグループのタイプを「instance」にし Proxy Protocol v2 を使用する
 (B) 2台の NLB でターゲットグループのタイプを「IPアドレス」にし NLB-for-IPv6 では ASG を使用しない
 (C) 2台の NLB でターゲットグループのタイプを「IPアドレス」にし ASG でノード入れ替えを検出する仕組みを実装いただく

(A)Proxy Protocol v2 を使用する

結論は採用せずでした。

(A)設定

NLBをDualStack構成とし、クライアント IP アドレスの保持はオフ、Proxy Protocol v2をオンとする。(EC2(Apache)のVhostでProxyProtocol Onを設定する)
オートスケーリンググループでは、インスタンスで設定したターゲットグループをロードバランサーに設定し、スケールイン・スケールアウトでEC2を捕捉出来るようにする。

(A)結果

・Proxy Protocol v2をオンとしIPv6で接続した場合、クライアントのIPはTCPヘッダ(L4)に入る。TCPレベルではNLB<->EC2間はIPv4となる。
・ClientからIPv6で通信した場合、NLB から EC2 は IPv4 で通信。クライアント IP アドレスは「保持されない」。
Apache側のログはIPv4/IPv6共に接続元のIPが表示される。
・NLBへのアクセスは出来るが、EC2への直接接続が出来なくなる。(ApacheのProxy Protocol v2の仕様?)
上記からセキュリティグループによる制限、直接接続不可となるため、この対応はあきらめることに。

(B)NLB-for-IPv6 では ASG を使用しない

オートスケールの観点から、ASGはどうしても使用したいため、この対応はあきらめることに。

(C)ASG でノード入れ替えを検出する仕組みを実装

結論としてはこれを採用しました。
IPv4のNLBは今まで通りの設定でターゲットグループをインスタンスに設定しオートスケーリンググループに組み込む。
DualStackのNLBはEC2のLaunchやTerminate発生時に自動でターゲットグループを更新するような仕組みを検討して入れることとしました。

終わり

ということで、AWSのDualStack化はなかなか想定通りにはいかなかったですが、なんとかなりました。
続きはまた次回に。