ゲートウェイルートテーブルのターゲットにEC2インスタンス以外のENIを指定してみる

VPC Ingress Routingのために用いるゲートウェイルートテーブルですが、EC2インスタンス以外にルーティングできるのか?と思って調べました。

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

コンバンハ、千葉(幸)です。

みなさん、ゲートウェイルートテーブル使ってますか? 私は使っていません。

でも、いろいろいじって、変な使い方ができないかは考えてみたりします。

ゲートウェイルートテーブルは、ターゲットが VPC 内の local(デフォルトのローカルルート)または Elastic Network Interface(ネットワークインターフェイス)の場合、ルートをサポートします。

https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/VPC_Route_Tables.html#gateway-route-table

ENIであればよくて、必ずしもEC2インスタンス用である必要はなかったりするのか? とすると、ELBをターゲットに指定できたりするのか?と思うなどして、いろいろ試してみました。

目次

先に結論

  • ゲートウェイルートテーブルのターゲットにEC2インスタンス用ではないENIを指定すると、エラーが出る場合と出ない場合がある。
  • エラーが出なかったとしても、EC2インスタンス以外を指定しても使い道がないので、そもそもやる意味はない。

前段:アプライアンスの可用性を考える

ELBを指定できないのか?と考えたのには一応前置きがあります。

ゲートウェイルートテーブルを使う場面として想定されるのは、ミドルボックスのアプライアンス製品を使用して、トラフィックをインターセプトする構成です。例えばパブリックサブネット上のAWSリソースへのアクセスをインターセプトする場合の構成例は以下です。ここではインバウンドの部分しか表現していませんが、通常は戻りの通信やアウトバウンドの通信もアプライアンス製品を経由させることになるでしょう。

ゲートウェイルートテーブルは、ターゲットとしてENIを指定します。対象のENIを持つアプライアンス製品に障害が発生した場合、そこを経由する通信が成り立たなくなります。つまり、アプライアンス製品がSPOFになります。

SPOFを避けるためにELBどう?

無邪気に前段にELBとか配置してみたらいいんじゃないか?とまずは思いました。

しかしすぐにそれがNGなことに気がつきます。ツッコミどころは色々とありますが、ALBとCLBはそもそも「送信元/送信先チェック」に引っかかる時点でNGです。「宛先IPが自分自身でない」通信を受け取れるのは、「送信元/送信先チェック」が無効になっているENIだけであり、そのパラメータを明示的に無効にできるのは、EC2インスタンスにアタッチされている(もしくはされる前の)ENIだけです。

その他のNGな点

仮に「送信元/送信先チェック」がクリアになったとしても、前段にELBを配置する構成は考えられません。IPヘッダを書き換えないまま後段のアプライアンス製品に向けてIPフォワードする、というのは、ELBができることとマッチしていないためです。乱暴に書いた各ELBの働きは以下の通りで、そもそもの動作するレイヤが異なります。

  • レイヤ4のリバースプロキシ(CLB)
  • レイヤ7のリバースプロキシ(CLB、ALB)
  • レイヤ4のNATロードバランサ(NLB)

おまけで言えば、CLB、ALBに関してはENIが可変であるため、特定のENIをゲートウェイルートテーブルのターゲットに指定できても嬉しくありません。

EC2インスタンス用以外のENIをターゲットとして指定する意味

ELBのみならず、他のコンポーネントが持つENIも、ターゲットとして指定して機能することは期待できません。VPCへのインバウンドの通信において、「宛先IPが自身でない通信を受け取る」「それを正しい宛先に向けてフォワードする」という挙動ができるのは、EC2インスタンス以外には無いからです。

なので、この話はもうおしまいと言えばおしまいです。

それでも僕は試したい

無意味であることを理解した上で、試したくなるのが いきもののサガ というものです。

こちらに、たくさんのENIを用意しました。せっかくなのでELB以外のENIでも試してみることにします。

※完全に試すタイミングを間違えたので、以降の画像も含め載っていないですが、#7のENIでも試しています。

# 用途 セキュリティグループ 送信元/送信先チェック
1 CLB用 あり TRUE
2 ALB用 あり TRUE
3 NLB用 なし FALSE
4 RDS用 あり TRUE
5 NAT Gateway用 なし FALSE
6 未アタッチ あり FALSE(手動で変更)
7 インタフェース型VPCエンドポイント あり TRUE

#6の未アタッチのENI以外は、すべて各サービスにより自動的に作成されたものです。未アタッチのものは、明示的に送信元/送信先チェックを無効化してあります。セキュリティグループのアタッチ可否や、デフォルトで送信元/送信先チェックがどうなっているのかを見てみると気づきがありますね。

NLBはFALSEだったことに、ここで初めて気がつきました。

サービスにより作成されるENIの送信元/送信先チェックの変更

例えば#1の送信元/送信先チェックをFALSEにできないかな、と一応試しますが、もちろんできませんでした。 You do not have permission to access the specified resource.

先にサブネットルートテーブルで試す

ゲートウェイルートテーブルとの比較のために、サブネットルートテーブルで設定した場合を先に確認します。

結果、すべてのENIで、ターゲットに指定することができました。

特記事項としては以下のあたりです。

  • NAT Gatewayは、紐づくENI(eni-xxxxx)を指定しても自動的にNAT Gatewayそのもの(nat-xxxxx)に変換される
  • 未アタッチのENIを指定すると、blackholeのステータスになる

設定中の画面はこのような感じです。ENIをターゲットとする際には、「送信先」をVPCより狭い範囲で指定するとエラーが発生するため、適当なCIDRを指定しています。

エラーが発生した時のメッセージは以下のようなもの。VPCのローカルCIDRよりロンゲストマッチするCIDRは指定するな、といったところでしょうか。

This route table is used by a subnet, and doesn't support route destination which are more specific than VPC local CIDR.

ゲートウェイルートテーブルで試す

サブネットルートテーブル において、各種のENIをターゲットにすることが問題ないことが確認できましたので、同じENIをゲートウェイルートテーブルのターゲットに指定してみます。今回はIGWにエッジアソシエーションしたゲートウェイルートテーブルで試します。

ゲートウェイルートテーブルのAPIエラーに引っかかってみる

いろいろENIの指定を試してみる前に、そもそも守らなくてはならない事項があることに気付きました。試行する中で引っかかったAPIエラーメッセージを記します。

ターゲットにENI以外のコンポーネントを指定した場合のエラー

Route table contains routes that do not target a network interface

ターゲットにエッジアソシエーション先のGWを指定した場合のエラー

Route table has a conflicting association with the gateway igw-25bxxxxx

送信先のCIDRがVPCに収まっていない場合のエラー

Route table contains unsupported route destination. The unsupported route destination is less specific or non-overlapping than VPC local CIDR.

送信先のCIDRにマッチするサブネットが存在しない場合のエラー

Route destination doesn't match any subnet CIDR

これらを回避した上で、ENIをターゲットにルートを登録していきます。

ゲートウェイルートテーブルで試行した結果

以下のようになりました。

# 用途 セキュリティグループ 送信元/送信先チェック ターゲット指定可否
1 CLB用 あり TRUE できた
2 ALB用 あり TRUE できた
3 NLB用 なし FALSE できなかった
4 RDS用 あり TRUE できた
5 NAT Gateway用 なし FALSE できなかった
6 未アタッチ あり FALSE(手動で変更) できた(TRUEに変えてもできた)
7 インタフェース型VPCエンドポイント あり TRUE できなかった

#3、#5、#7では、ルートの追加を試行した際に以下のようなエラーが出ます。

Route table contains routes targeting unsupported network interface eni-00c211fxxxxxxxxxx

ENIのタイプを見て判断してくれているようです。何が基準なのか、そしてサブネットルートテーブルの場合とターゲット指定可否に違いがあるのは何故なのかは、さっぱり分かりません。とは言え、いくつかの「何かそれっぽい設定できそう!」というENIを、設定の段階で弾いてくれるのは嬉しいですね。

ひとまず結果が得られたので、ただ単に満足しました。

終わりに

というわけで、そもそも使い道のない構成に対する操作を実施する、という非常にやりがいのある内容をお送りしました。同じことを思いついてしまった皆さんの、無益な時間を削減できれば何よりです。

冒頭のアプライアンス製品の障害にどう対応するかについては、障害を検知して、自動的に経路を変更するような仕組みが現実的かと思います。 Lambda等と連携させることで、以下のような挙動を自動的に実現するパターンがあるかと考えています。

  • ゲートウェイルートテーブルのターゲットであるENIを別インスタンスにスワップするパターン
    • ※スワップ可能なようにセカンダリENIとしておく必要あり
  • ゲートウェイルートテーブルのターゲットを、別インスタンスにアタッチされているENIに書き換えるパターン

以上、以上でした。