【テクニカル・上級編】 AWS VPCにおけるマルチホーム構成(複数ENI接続)のルーティングとポリシーベースルーティング – クラウドインフラと仮想化ネットワーク実践ガイド

マルチホームの迷宮:AWS EC2における複数ENIのルーティングと「非対称パケット」の深淵

クラウドインフラの設計において、冗長化やセキュリティ分離の観点から「1台のインスタンスに複数のENI(Elastic Network Interface)をぶら下げる」というアーキテクチャに遭遇することは珍しくありません。しかし、この設計は往々にして、パケットの往来に関する「ネットワークの迷宮」を招きます。

特に、デフォルトゲートウェイが設定されたプライマリENI以外のセカンダリENIに対して外部からパケットが到達した際、Linuxカーネルが「返信をどこに送るべきか」を見失い、パケットがブラックホールに消える現象は、多くのエンジニアが一度は通る洗練の壁です。今回は、この泥臭いルーティングの挙動を、カーネルの視点から紐解いていきます。

—

なぜパケットは「迷子」になるのか?

Linuxのネットワークスタックは、デフォルトで「宛先ベースのルーティング」を行います。

1. パケットが eth1(セカンダリENI)に届く。
2. カーネルは応答パケットを作成する。
3. カーネルはルーティングテーブルを参照する。
4. 通常、ルーティングテーブルにはデフォルトゲートウェイとして eth0(プライマリENI)が指定されている。
5. 結果、応答パケットは eth0 から出ていく。

これをAWSのインフラ層が検知するとどうなるか。AWSのソース/デスティネーションチェックは、「パケットの送信元IPが、そのインターフェースに割り当てられたIPと一致しない」場合、即座にパケットを破棄します。つまり、eth1 に届いたリクエストの応答が eth0 から出ていこうとすると、AWSのネットワークフィルタによって遮断されるのです。これが「通信が確立しない」という事象の正体です。

—

Policy Based Routing(PBR)による解決:ip ruleの真価

この問題を解決するには、カーネルに対して「どのインターフェースから入ってきたパケットか」を識別させ、それに応じた「専用のルーティングテーブル」を適用させる必要があります。これを実現するのが ip rule です。

まずは、カスタムルーティングテーブルを定義します。

# テーブル番号200に「secondary_net」という名前を付与
echo "200 secondary_net" >> /etc/iproute2/rt_tables

# eth1のサブネットからの通信は、このテーブルを参照するようにルールを追加
# 10.0.1.0/24 は eth1 が属するサブネットの CIDR
ip rule add from 10.0.1.5 table secondary_net

# デフォルトゲートウェイをテーブル200に定義
# 10.0.1.1 は eth1 のサブネットのゲートウェイIP
ip route add default via 10.0.1.1 dev eth1 table secondary_net

この設定により、10.0.1.5 のIPを持つパケットに対する応答は、必ず eth1 のゲートウェイを経由して戻るようになります。これで「非対称ルーティング」という呪縛からは解放されます。

—

パフォーマンスとセキュリティの極致:TCPスタックの最適化

マルチホーム構成において、ルーティングが解決した後に待ち受けているのは「パフォーマンスの最適化」です。特にレイテンシにシビアなマイクロサービス環境では、以下のチューニングが決定打となります。

TCPバッファとウィンドウサイズ

デフォルトのTCPバッファサイズは、現代の高速なクラウドネットワーク環境では小さすぎることがあります。帯域幅遅延積(BDP)を考慮した調整が必要です。

# /etc/sysctl.conf に追記し、カーネルパラメータを最適化
# 大容量通信時のスループット向上
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216

# TCPウィンドウのスケーリングを有効化(必須)
net.ipv4.tcp_window_scaling = 1

RTT削減とTLSハンドシェイク

ネットワークの物理的な制約(光の速さ)を超えられない以上、RTT(Round Trip Time)の削減はアプリケーション層の手腕にかかっています。

  • TLS 1.3の強制: TLS 1.3はハンドシェイクを1回(1-RTT)で完了させます。従来のTLS 1.2の2-RTTと比較して、ハンドシェイク自体のレイテンシを確実に半減させます。
  • TCP Fast Open (TFO): 2回目の接続以降、ハンドシェイク中にデータを送りつける技術ですが、AWSのロードバランサ等で終端する場合は注意が必要です。アプリケーションのエンドツーエンドで有効化することで、体感速度は劇的に向上します。

—

セキュリティの「見えない穴」を塞ぐ

複数ENI構成において、最も恐ろしいのは「誤ったインターフェースからパケットが漏洩すること」です。これを防ぐために、rp_filter(Reverse Path Filtering)の設定を慎重に行う必要があります。

# /etc/sysctl.conf
# 厳密なリバースパスフィルタリング(2は緩い設定、1が推奨)
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.eth0.rp_filter = 1
net.ipv4.conf.eth1.rp_filter = 1

rp_filter を 1 に設定することで、カーネルは「ソースIPアドレスに対して、パケットが到着したインターフェースが最適ルートであるか」をチェックします。これはセキュリティの最後の砦です。IPスプーフィング攻撃への耐性を高め、予期せぬルーティングミスによるパケット漏洩を未然に防ぎます。

結びに代えて:SREとしての矜持

複数ENIを扱うということは、OSレベルのネットワークスタックの深淵を覗き込むことに他なりません。単にクラウドのGUIでボタンをポチポチ押すだけでは、真の可用性は得られないのです。

パケットは嘘をつきません。tcpdump でキャプチャしたパケットが、期待したインターフェースから出ていっているか。あるいは、TCPフラグが正常なシーケンスを描いているか。その一瞬の挙動にこそ、我々エンジニアが追求すべき「信頼性」の真髄が宿っています。

この記事が、あなたの構築するアーキテクチャの堅牢性を、ほんの少しでも高める一助となれば幸いです。

コメント

タイトルとURLをコピーしました