「Hub &Spoke 環境でのネットワークルーティングを分解してみる」というタイトルでLTしました
はじめに
こんにちは。コンサルティング部の津谷です。
8/28にAWSコミュニティイベント「品川会」のLTで登壇してきましたので、内容をブログにもまとめます。
登壇資料
「Hub&Spoke環境でのネットワークルーティングを分解してみる」というタイトルでLTさせていただきました。
そもそもHub&Spokeとは
そもそもHub&Spoke構成とは、中心となる拠点(Hub環境)を1つ置き、各拠点(Spoke環境)はHub環境を介して通信をする構成になります。
Organizationなどで複数のAWSアカウントを管理しているような環境では、アカウントごとにVPCが作られていきます。この時、通信要件をアカウント単位・VPC単位で個別に考えていくとどうでしょうか。
「AチームのVPCからオンプレミスのDBにつなぎたい」「BチームのVPCからインターネットに出たい」といった要件が出てきます。要件そのものは単純です。しかしこれらを個別に対応すると、VPCごとにNAT Gatewayが必要になる、VPCごとにDirect Connectの経路を引く必要がある、VPC間の通信が必要になればPeeringを1本ずつ張る必要がある、といった形で構成が膨らんでいきます。VPCが少ないうちは何とかなりますが、数十を超えたあたりから全体像を把握することが難しくなってきます。
そこで、共有すべきネットワーク機能をHub側に集約し、SpokeはHubとだけ接続する形をとります。これがHub&Spoke構成で、具体的には以下のような環境で採用されることが多いです。
- Organizationで複数アカウントを運用しており、今後もアカウントが増えていく
- オンプレミス環境とDirect Connectなどで閉域接続している
- インターネットへの通信を1か所に集約して検査・記録したいという要件がある
- ネットワーク/セキュリティの管理主体と、アプリケーションの開発主体が分かれている
LTで取り上げた構成
今回のLTでは一般的なHub&Spoke構成を題材にしました。

Hubアカウントに以下を集約しています。
- Transit Gateway — 全体の中継点。RAM共有でSpokeアカウントからもアタッチメントを作成できるようにしています
- Internet Gateway / NAT Gateway — インターネットへの出口
- Network Firewall(TGW統合) — インターネット向け通信の検査
- Direct Connect Gateway — オンプレミス環境との閉域接続
SpokeアカウントにはPrivate Subnetにそれぞれ、疎通確認用のEC2とTransit GatewayのVPCアタッチメントのみ配置しています。東京⇔大阪のTransit Gateway Peeringも本構成では取り上げているので、マルチリージョン構成になっています。
アクセス構成については、以下の3つになります。
- インターネットアクセス
- SpokeアカウントのEC2からTransit Gateway経由でHubアカウントに接続
- HubアカウントのNetwork Firewall(TGW統合)でInspection(検査)を実施
- 検査完了後にNAT Gateway ⇒ Internet Gateway経由でインターネットに接続
- オンプレミスアクセス
- SpokeアカウントのEC2からTransit Gateway経由でHubアカウントに接続
- HubアカウントのDirect Connect Gatewayを経由し、オンプレミス環境に接続
- 東阪Peeringアクセス
- 東京リージョンのSpokeアカウントEC2からTransit Gateway経由でHubアカウントに接続
- 東阪のTransit Gateway間でPeering接続を実施
- 大阪リージョンのTransit Gateway経由で、HubアカウントのEC2に疎通
構成図としては見慣れた形だと思います。ただ、この図には描かれていないものがあります。ルートテーブルです。なんとなくの通信経路は目で追えるけど、実際にコンポーネント間でどういうルート設定をいれて通信を可能にしているのか可視化できないと実際の構築では結構きついなと感じやすいです。
どのルートテーブルを参照して/どの宛先CIDRに対して/どのターゲット(ネクストホップ)に飛ばしているのかを明確にするために、以下の工夫をすることにしました。
- ルーティングの層を分解する
AWSのルーティングには、VPCルートテーブルとTGWルートテーブルという2つの層があります。この2つは役割も引く主体も違うのに、構成図上では整理して描かれることは少ないです。そこで本記事では、TGWルートテーブルを赤、VPCルートテーブルを青で色分けして図に載せています。どちらの層の設定なのかが一目で分かるようにするためです。
【補足:VPCルートテーブルとTGWルートテーブル】
VPCルートテーブルは文字通りVPC内のルーティングを主に行います。そのため、VPCをまたいだルーティングはできません。今回のケースで行くと、VPCルートはRAM共有したTransit Gatewayをネクストホップにしますので、経路としてはTransit Gatewayまでしか届きません。そのあとのルートはTransit Gatewayルートテーブルが引き継ぐことになります。Transit GatewayはTransit Gatewayアタッチメント間のルーティングなので、ネクストホップはアタッチメントを指定する形になります。そのため、マルチアカウント構成(別VPC)の通信では、通信元VPCルートテーブル⇒Transit Gatewayルートテーブル(通信を仲介するHub)⇒送信先VPCルートテーブルのように参照させていきます。
- アクセスパターンごとに図を切り出す
全体構成図には、インターネット向け・オンプレミス向け・東阪Peering向けの3つの経路が同時に描かれています。同時に追おうとすると混乱するので、パターンごとに図を分けます。1枚の図に1つの経路だけを描くと、必要なルート設定が数行に収まり、見通しが良くなります。
- 往路(行き)と復路(戻り)に分解する
セキュリティグループを例に挙げますが、こちらはステートフルなのでインバウンドを許可すれば戻りの通信は自動的に許可されます。しかしルーティングにその仕組みはありません。行きと戻りで参照するルートテーブルは別物で、それぞれに設定が必要です。往路だけを設計して「通信が通らない」と悩むケースは、この復路の設定漏れであることが多いです。そのため、往路と復路を必ず別の図として分けて確認します。
各アクセスパターンごとのルーティング詳解
インターネットアクセス(往路)

SpokeアカウントのEC2からインターネットへ抜ける経路です。Transit Gatewayで一度受けてNetwork Firewallに検査させ、そこからEgress VPCのNAT Gateway・Internet Gatewayを経由して外に出ます。
①EC2を配置したサブネットのVPCルートテーブル
| 送信先 | ターゲット |
|---|---|
| 0.0.0.0/0 | Transit Gateway |
すべての外向き通信をTransit Gatewayに渡すだけの行です。ここで決まるのは「TGWまで渡す」ところだけで、その先どう転送されるかはこのテーブルには一切書かれていません。Spoke VPCにはInternet Gatewayを置かない前提なので、この行が無いとEC2はVPCの外に出る手段そのものを持ちません。
②SpokeVPC用TGWアタッチメントのTGWルートテーブル
| 送信先 | ターゲット |
|---|---|
| 0.0.0.0/0 | Network Function Attachment |
Transit Gatewayに届いた通信を、まずNetwork Firewallへ向けます。Spoke VPCアタッチメントが関連付けられているTGWルートテーブルを引いています。ここを直接Egress VPCに向けてしまうと検査を飛ばして外に出られてしまうため、インターネット向け通信を必ず検査させるという要件を担保しているのがこの1行になります。
なお、Network Firewallアタッチメント宛てのルートはルート伝搬に対応していないため、静的ルートとして明示的に追加する必要があるのがポイントになります。
③NetworkFirewall用TGWアタッチメントのTGWルートテーブル
| 送信先 | ターゲット |
|---|---|
| 0.0.0.0/0 | Egress VPC Attachment |
検査を終えた通信の行き先を決めます。Network Firewallのアタッチメントが関連付けられているTGWルートテーブルです。
この行が無いと、検査までは成功しているのにTransit Gateway上で行き先を失って破棄されます。Firewallのログには通過記録が残るのに疎通しない、という分かりにくい状態になるので注意が必要です。
④EgressVPC用TGWアタッチメントを配置したサブネットのVPCルートテーブル
| 送信先 | ターゲット |
|---|---|
| 0.0.0.0/0 | NAT Gateway |
Egress VPCに入った通信を、TGWアタッチメント用サブネットからNAT Gatewayへ渡します。ここからは再びVPCルートテーブルの世界です。Spoke VPCのEC2はプライベートIPを持っているため、インターネットに出るにはNAT GatewayでのIPアドレス変換が必要です。この行を忘れると、Egress VPCまでは到達しているのにインターネットに出られません。
⑤PublicサブネットのVPCルートテーブル
| 送信先 | ターゲット |
|---|---|
| 0.0.0.0/0 | Internet Gateway |
NAT Gatewayが配置されているPublicサブネットのルートテーブルです。ここでようやくInternet Gatewayに渡り、インターネットへ出ていきます。
インターネットアクセス(復路)

インターネットからの戻りの通信です。往路でルーティング設定したので終わりではありません。行きと戻りで参照するルートテーブルは別物で、それぞれに設定が必要です。
そして往路と決定的に違う点があります。宛先が 0.0.0.0/0 ではなく、Spoke VPCのCIDRになることです。
①PublicサブネットのVPCルートテーブル
| 送信先 | ターゲット |
|---|---|
| Spoke VPCのCIDR | Transit Gateway |
Internet GatewayからNAT Gatewayに戻ってきた通信を、Transit Gatewayへ向けます。NAT GatewayがアドレスをEC2のプライベートIPに戻すため、その宛先に対する経路が必要になります。
ここが往路の 0.0.0.0/0 と対照的な部分です。戻り先は「どこでもいい」わけではなく、特定のSpoke VPCを名指しする必要があります。IPAM(アナログですが台帳などで管理してもOK)などで管理したSpokeアカウント用のVPC CIDRをまとめて入れておくと、都度運用でルートを追加していく手間が省けます。
②EgressVPC用TGWアタッチメントのTGWルートテーブル
| 送信先 | ターゲット |
|---|---|
| Spoke VPCのCIDR | Network Function Attachment |
Transit Gatewayに戻った通信を、再びNetwork Firewallへ向けます。Network Firewallはステートフルなアプライアンスなので、往路と復路で同じFirewallを通す必要があります。片方向しか通らないとセッション情報が引き継げず、通信が成立しません。この行はそのための経路です。
③NetworkFirewall用TGWアタッチメントのTGWルートテーブル
| 送信先 | ターゲット |
|---|---|
| Spoke VPCのCIDR | Spoke VPC Attachment |
検査を終えた戻りの通信を、元のSpoke VPCへ返します。Spoke VPCが増えるたびに、このテーブルに行が増えていきます。往路は 0.0.0.0/0 の1行で全Spokeを賄えたのに対し、復路はSpokeごとにCIDRを書く必要があるためです。CIDR設計の段階で集約可能な採番にしておくと、この運用負荷を抑えられるかと思います。
④SpokeVPC用TGWアタッチメントを配置したサブネットのVPCルートテーブル
| 送信先 | ターゲット |
|---|---|
| SpokeアカウントVPCのCIDR | local |
Spoke VPCに戻ってきた通信を、EC2が配置されているサブネットへ届けます。この local ルートはVPC作成時に自動生成されるため、設定作業は不要です。ただし「ここでも1回テーブルを引いている」という点は押さえておきたいので、あえて分解に含めています。
閉域アクセス(往路)

SpokeアカウントのEC2からDirect Connect経由でオンプレミス環境に接続する経路です。インターネットアクセスと比べるとコンポーネントが少なく見やすいです。Network Firewallによる検査を挟まず、NAT Gatewayも経由しないためです。
①EC2を配置したサブネットのVPCルートテーブル
| 送信先 | ターゲット |
|---|---|
| 閉域網CIDR | Transit Gateway |
オンプレミス宛ての通信をTransit Gatewayへ渡します。インターネット向けの 0.0.0.0/0 と異なり、宛先を具体的なCIDRで指定します。ここを 0.0.0.0/0 にまとめてしまうと、インターネット向け通信までDirect Connectに吸い込まれてしまいます。NetworkFirewallへ向けるインターネット接続の経路とCIDR競合を起こしてしまうので、オンプレ側のCIDR設計をあらかじめ把握しておく必要があります。
②SpokeVPC用TGWアタッチメントのTGWルートテーブル
| 送信先 | ターゲット |
|---|---|
| オンプレCIDR | Direct Connect Gateway Attachment |
Transit Gatewayに届いた通信を、Direct Connect Gatewayへ向けます。
ここは静的ルートを書くこともできますが、オンプレ側のルータからBGPで広報された経路を伝搬(propagation)させる運用が一般的です。伝搬を有効にしておけば、オンプレ側でCIDRが追加されたときにAWS側の設定変更が不要になります。
なお、Transit Gatewayでは、この伝搬されたルートと静的ルートが競合した場合、静的ルートが優先されます。運用でどちらに寄せるかは事前に決めておくべきポイントです。
閉域アクセス(復路)

オンプレミス環境からSpokeアカウントのEC2へ戻る経路です。
⓪Direct Connect Gatewayのallowed prefixes(AWS ⇒ オンプレへの広報)
Transit GatewayアソシエーションのDirect Connect Gatewayでは、allowed prefixesに入力したプレフィックスだけがオンプレミスに広報されます。ここにAWS側のCIDRを入れ忘れると、そもそもオンプレ側がAWSへの戻り経路を学習できません。
ルートテーブルはすべて正しいのに疎通しない、という場合はこの部分を注意してみると良いです。
補足として、Virtual Private Gatewayアソシエーションの場合はallowed prefixesが「VPC CIDRに対するフィルタ」として動作するのに対し、Transit Gatewayアソシエーションでは入力値がそのままDirect Connect GatewayのASN発として広報されます。挙動が異なるので混同しないよう注意が必要です。
また、allowed prefixesは1アソシエーションあたり20プレフィックスが上限です。CIDRを個別に列挙するのではなく、集約レンジで設計しておく必要があります。
①Direct Connect Gateway用TGWアタッチメントのTGWルートテーブル
| 送信先 | ターゲット |
|---|---|
| Spoke VPCのCIDR | Spoke VPC Attachment |
オンプレミスから戻ってきた通信を、対象のSpoke VPCへ振り分けます。このルートは、Spoke VPCアタッチメントからの伝搬で自動的に載せることができます。Spoke VPCが増えるたびに手動で追加する運用にはしないほうが無難です。
②SpokeVPC用TGWアタッチメントを配置したサブネットのVPCルートテーブル
| 送信先 | ターゲット |
|---|---|
| Spoke VPCのCIDR | local |
Spoke VPC内で目的のEC2まで届けます。インターネットアクセスの復路と同じく、自動生成される local ルートです。
東阪Peering(往路)

東京リージョンのSpoke EC2から、大阪リージョンのSpoke EC2へ接続する経路です。リージョンをまたぐため、Transit Gateway同士のPeering接続を経由します。
①EC2を配置したサブネットのVPCルートテーブル
| 送信先 | ターゲット |
|---|---|
| Spoke VPC CIDR(大阪) | Transit Gateway(東京) |
大阪リージョン宛ての通信を、東京リージョンのTransit Gatewayへ渡します。
②SpokeVPC用TGWアタッチメントのTGWルートテーブル(東京)
| 送信先 | ターゲット |
|---|---|
| Spoke VPC CIDR(大阪) | Peering Attachment(東京) |
東京のTransit Gatewayに届いた通信を、Peeringアタッチメントへ向けます。
Transit Gateway Peeringではルート伝搬がサポートされていないため、この行は静的ルートで追加する必要があります。リージョンをまたぐ経路が自動で載ってこないのは、Peering特有の注意点です。
③Peering用TGWアタッチメントのTGWルートテーブル(大阪)
| 送信先 | ターゲット |
|---|---|
| Spoke VPC CIDR(大阪) | Spoke VPC Attachment(大阪) |
大阪リージョンのTransit Gatewayに届いた通信を、大阪のSpoke VPCへ渡します。ここで注目したいのが、送信元側(東京)のPeeringアタッチメントには、関連付けるTGWルートテーブルが不要という点です。Peeringアタッチメントは通信を対向リージョンへ受け渡すだけで、経路の判断は受け側のTGWルートテーブルが行います。
「Peeringを張ったのに両側にルートテーブルを用意すべきか」で迷いやすいポイントなので、往路・復路それぞれでどちら側のテーブルが判断しているのかを意識すると整理しやすいです。
④SpokeVPC用TGWアタッチメントを配置したサブネットのVPCルートテーブル(大阪)
| 送信先 | ターゲット |
|---|---|
| Spoke VPC CIDR(大阪) | local |
大阪のSpoke VPC内で目的のEC2に届けます。
東阪Peering(復路)

大阪から東京へ戻る経路です。往路と完全に対称な形になります。
①EC2を配置したサブネットのVPCルートテーブル(大阪)
| 送信先 | ターゲット |
|---|---|
| Spoke VPC CIDR(東京) | Transit Gateway(大阪) |
②SpokeVPC用TGWアタッチメントのTGWルートテーブル(大阪)
| 送信先 | ターゲット |
|---|---|
| Spoke VPC CIDR(東京) | Peering Attachment |
③Peering用TGWアタッチメントのTGWルートテーブル(東京)
| 送信先 | ターゲット |
|---|---|
| Spoke VPC CIDR(東京) | Spoke VPC Attachment(東京) |
④SpokeVPC用TGWアタッチメントを配置したサブネットのVPCルートテーブル(東京)
| 送信先 | ターゲット |
|---|---|
| Spoke VPC CIDR(東京) | local |
さいごに
いかがでしたでしょうか。ルーティングを分解してみるとマルチアカウント構成の複雑なネットワーク設計も捗るのではないでしょうか。全体を俯瞰する記事はあまり見当たらなかったので、参考にしていただけると良いかと思います。






