AWS Lambda IPv6 と APIエンドポイントと NAT G/W

AWS Lambda in VPC から、IPv6 で Egress-only internet gateway を通って外に出ていけるようになりました。

それに関連して、APIエンドポイントと NAT G/W を絡めて確認したことをまとめておきます。よくわからないタイトルになりましたが、雑学用の材料ということで:-)



リリース

公式情報はこちら。

内容的に、確認したいことはすぐ成功して終わるだろうと Twitter でボヤいてたら、想定外に調べることが出てきて最終的に願いは叶わずでした。



目的

過去記事 AWSのPublic IPv4構成をIPv6に切り替える | 外道父の匠 にて、IPv6 構成にしたら NAT G/W 無くせるんちゃうん、無理だと思うけど! → やっぱダメでした、をやりました。

PublicIPv4 を持たず、Private で IPv6 にした場合、インターネットへ出ていく際に IPv6 なら Egress-only IGW を通れば出ていけますが、送信先が IPv4 しか持たない場合は Global IPv4 がないため通信できなく、NAT G/W (NAT64) を用意する必要がありました(復習終)。

仮にアプリケーションの外部接続が IPv6 のみだったとしても、Lambda in VPC が外部接続するには、NAT G/W が必要という仕様のために、NAT G/W を撤去することは叶わぬ夢となっていました。

しかし、ここに本件リリースがきて、Lambda in VPC から AWS API を叩く程度なら、NAT G/W 不要で Egress-only IGW だけで済ませられるんちゃうか、と思って試したところ見事に撃沈した流れになります。


IPv6 通信は可能

とりあえずリリースどおりに NAT G/W 無しの Lambda in VPC → EIGW → Internet IPv6 がイケるのか?を試します。

Lambda 関数の設定 → VPC で、サブネット『IPv6 トラフィックを許可』という項目が増えているので、true にして下記を実行すると、


問題なく IPv6 で名前解決できて、レスポンスも正常に返ってきました。google.com にしたのは、www.amazon.com だと 503 が返るからで、そんなことはどうでもいいです。

これで道が見えた!かというと、そんな甘いものではなく。


AWS API は通らない

では、勢いで同環境(IN 東京)で AWS API を叩いてみると


タイムアウトします。これは Lambda だからとか Python3 boto3 だからではなく、Private Subnet の IPv6 環境かつ NAT G/W 不在だからで、EC2 で AWS CLI を叩いても同じ状況になります。

理由は簡単で、API を叩く時は EC2 の場合 ec2.ap-northeast-1.amazonaws.com にリクエストされるのですが、この宛先は IPv4 にしか対応していないことがドキュメントにかかれています。


そして肝心の Dual-stack (IPv4 and IPv6) endpoints が、ap-northeast-1 (東京) で対応されていない、というオチもあります。


リージョン格差を確認する

ドキュメントの例題通り、us-west-2 に投げると通り、ap-northeast-1 に投げると失敗します。


なまじ、IPv4 用エンドポイントが IPv6 も返してくるので期待しちゃいますが、IPv4 でアクセスしないと返事してくれません。一応、リダイレクト用のWEBサイトとしても機能している URL なので、IPv6 にも対応しているだけって感じでしょうか。

……AWS大先生はなぜ IPv4 エンドポイントをそのまま IPv6 に対応しなかったんでしょうね。まぁ普通に考えて、技術的負債とまでは言わなくとも、過去の気に食わない設計を *.api.aws に分けたほうが都合が良かった、とかありそうですけど。いつかは Dual-stack Endpoint の方がデフォルトに変更されたりするのかな?


IPv6 化の注意点

デフォルトの IPv4 用エンドポイントは IPv6 も返してくるので、IPv4 のみと判断して NAT64 を通すような挙動にはならないはずで、常に IPv6 優先でアクセスすることになります。

また、接続情報のエンドポイントに Dual-stack エンドポイントを明示的に指定しても、東京はそもそも未対応ということもあります。

EIGW や NAT G/W の有無が、自分たちの扱う外部接続にどう影響するのか、は正しく認識しておくべきでしょう。

とはいえ、NAT G/W があれば基本は大丈夫です。IPv6環境+NAT G/W 無しの場合、以下のような結果になります。


しかし、IPv6環境+NAT G/W 有りにすると、以下のようになります。


curl の結果が最もわかりやすいですが、他も tcpdump で処理を追うと、最初に IPv6 で接続を試みて、ダメなら IPv4 でリトライするようになっています。

要はクライアントがちゃんとしていれば、NAT G/W を置いてあげれば AWS API のエンドポイントはそのままでも動くということです。よかったですね。

おまけ

ただこの件は AWS API に限った話ではないので、やはりよく扱うアプリケーション環境・よくアクセスする外部API があれば、NAT G/W 無し/有りで接続がどうなるかってのは、軽く確認して挙動を把握しておく方が無難と言えそうです。

あと、今回ので知れたこととして、送信先の挙動には以下のパターンが考えられるということです。
  • IPv4 しか返さない
  • IPv6 しか返さない
  • IPv4 & IPv6 を返し、両方とも応答する
  • IPv4 & IPv6 を返すが、IPv4 だけ応答する
  • IPv4 & IPv6 を返すが、IPv6 だけ応答する
それはナイでしょってパターンもありますが、可能性として認識しているかどうかで、いつかトラブルシューティングに役立つかもしれないのでってところです。


まとめ

東京リージョンで Dual-stack Endpoint が対応されたら、API接続情報に明示的に新 Endpoint URL を指定すれば、NAT G/W を撤去する第一歩となるだろう。

俺たちは今しばらく、NAT G/W と命運をともにすることになる;-)