AWS Cloud WAN series · Part 9 of 17

AWS Cloud WAN: Centralized Egress and Ingress Inspection

Ninth in the AWS Cloud WAN series. The most common security design teams build on Cloud WAN is centralized internet egress: instead of a NAT gateway in every VPC, traffic funnels through a few inspected exit points. Here's the route design that pulls spoke traffic to the central VPC, where to place firewalls when the network is global but NAT isn't, and why ingress refuses to ride the same rails — sourced to AWS docs throughout.

TL;DR

Centralize egress with a send-to action to a Network Function Group: it installs a default route (0.0.0.0/0 and ::/0) into each workload segment pointing at the local egress attachment, so spoke traffic flows VPC → core → egress VPC → firewall → NAT → internet with zero per-VPC static routes. Firewalls and NAT are per region even though Cloud WAN is global, so the real decision is placement — a cost-vs-latency call — and any region without a local stack must be steered with with-edge-overrides, or the default ordering routes it somewhere far. Ingress does not use this machinery at all: a NAT gateway can't accept inbound, and centralized ingress is inspected at the VPC/IGW boundary, not by service insertion.

Design it this way

  • One send-to per workload segment to a shared Egress NFG — let it install the default route.
  • Put inspection before NAT inside the egress VPC; turn on appliance mode for symmetry.
  • Use with-edge-overrides deliberately for every region with no local stack.
  • For ingress, reach for a public ALB + Network Firewall at the boundary — or app-edge controls.

Don't do this

  • Don't scatter a NAT gateway across every VPC and AZ when a few exits will do.
  • Don't assume the default ordering picks the nearest firewall — it isn't geography-aware.
  • Don't reference an empty NFGsend-to deploys fine but blackholes egress.
  • Don't expect a NAT-based egress design to handle ingress — it's outbound only.

Why funnel the whole estate through a handful of exits

In a distributed model every VPC runs its own NAT gateway, usually one per Availability Zone for high availability. NAT gateways bill per hour and per GB, and you multiply that by every VPC times every AZ. The cost is the obvious problem; the quieter one is control. With NAT scattered everywhere there's no single place to filter what's leaving, apply URL or domain filtering, or even answer "what did this account talk to last night?"

Centralizing fixes both at once. Route all outbound traffic from your workload segments through one egress path per region, where you place the NAT gateways and — optionally — a firewall for deep-packet inspection and URL filtering. You collapse dozens or hundreds of NAT gateways into a handful of exits, and you get a single enforcement and visibility point per region. What makes it clean on Cloud WAN is that the steering is automatic: you don't hand-write a default route into every VPC, you declare one action and the policy installs the routes for you. That action is service insertion's send-to, and the next section is how it pulls traffic in.

Figure 1 · Centralized egress topology AWS Region · us-east-1Spoke VPC · prod-aPrivate subnetSpoke VPC · prod-bPrivate subnetSecurity VPC · egressInspection subnetPublic subnet0.0.0.0/00.0.0.0/0egress segmentinspectNATegressApp EC2App EC2Cloud WAN coreEgress NFGNetworkFirewallNAT gatewayInternet gatewayInternet
Spoke VPCs reach one inspected exit: their default route lands on the local egress attachment, traffic crosses the firewall, is NAT'd, and leaves through the internet gateway. Inspection sits before NAT.

How Cloud WAN pulls spoke traffic to the egress VPC

The simplest centralized design has no firewall yet: an egress VPC holding NAT gateways and an internet gateway, attached to a Network Function Group — call it Egress. You apply a send-to action from each workload segment to that NFG. send-to is the north-south half of service insertion (inspect-then-exit, no re-entry into the core), and it installs a default route — both 0.0.0.0/0 and ::/0 — into the source segment's route table, with the local NFG attachment as the next hop. No mode key, no per-VPC static routes: every internet-bound packet now flows VPC → core network → egress VPC → NAT gateway → internet, and return traffic follows the reverse path (Figure 2).

One subtlety keeps egress fast. When send-to is applied, Cloud WAN propagates each workload VPC's CIDR into the NFG route table, and routes propagated within the same region have their next hop redirected to the local NFG attachment. So same-region egress stays in-region by default — exactly what you want for latency. The one trap here is an empty NFG: a send-to that references an NFG with no attachments deploys successfully and then blackholes everything sent to it until you associate an egress attachment. The policy won't warn you; the traffic just disappears.

Figure 2 · The route pull Core network policy action: send-to segment: Prod via: [ Egress NFG ] one action, no per-VPC routes installs Prod segment route table DESTINATION NEXT HOP 10.0.0.0/16 local (segment) 0.0.0.0/0 local Egress NFG attach. ::/0 local Egress NFG attach. green rows are what send-to writes · next hop redirected to the same-region attachment
A single send-to action writes the IPv4 and IPv6 default routes into the workload segment, pointed at the region-local egress attachment — the spoke route table you never have to touch.

Where the firewall slots in — inspection before NAT

To gain visibility and control you insert a firewall ahead of the NAT. The AWS-native choice is AWS Network Firewall, which does stateful rules including URL filtering and deep-packet inspection; a third-party NGFW (Palo Alto, Fortinet, Cisco) slots into the same shape behind a Gateway Load Balancer. You add an inspection subnet to the egress VPC, deploy the firewall endpoint there, and adjust the egress VPC's internal route tables so the path becomes: traffic enters from the core → inspection subnet (firewall) → NAT gateway → internet.

Here's the part worth internalizing: the Cloud WAN side does not change. Whether or not there's a firewall, the policy is still a send-to to the NFG. Inspection is internal plumbing of the egress VPC — the route tables inside the VPC decide the firewall hop, not the core network policy. AWS even packages the two shapes as distinct Terraform central-VPC types in the maintained aws-ia/cloudwan module: egress for NAT-only and egress_with_inspection when you want the firewall auto-created.

Two non-obvious requirements come with inspection. First, appliance mode must be enabled on the inspection VPC's attachment so a flow is pinned to one AZ for its lifetime and the return packets come back through the same firewall — it's enabled on the VPC attachment, supported only on VPC attachments, and is independent of service insertion, so you need both. Second, the NFG itself spends budget: a core network caps at 40 segments, not adjustable, and every NFG quietly consumes one of those 40 internally. One egress NFG is cheap; it's worth knowing the meter exists.

Where to put firewalls when Cloud WAN is global but NAT isn't

This is the key design decision, and it's a cost-vs-latency tradeoff. Cloud WAN is global, but firewalls and NAT are deployed per region (or per geography). The governing principle is regional presence: a region with a local egress attachment controls its own exit point; a region without one inherits a propagated route and exits through some other region. Three patterns fall out of that:

Firewall in every region. Each region has its own egress VPC with firewall and NAT. Lowest latency — every region exits locally — and highest cost, a full security stack everywhere. Right when traffic volume justifies a stack in each region.

Firewall per geography. Deploy stacks for the Americas, EMEA, and APAC, and route each region's egress to its geography's stack. Fewer stacks, still-reasonable latency — the usual middle ground.

Firewall in some regions only. The most cost-sensitive: stacks in high-traffic regions, and low-traffic regions borrow a neighbor's. This is where the latency trap lives, because "borrow a neighbor's" is exactly the case Cloud WAN's default routing gets wrong — the next section.

The cross-country detour you didn't ask for

When a region has no local egress stack, something has to decide which region inspects its traffic — and by default it's Cloud WAN's ordered Region-priority list, which is not geography-aware. The canonical failure: us-west-1 has no local firewall, so its egress gets routed through us-east-1 (higher in the default order) rather than the far closer us-west-2. Your N. California traffic takes a cross-country detour to be inspected before it even reaches the internet — latency you'll hear about as a complaint, plus inter-region data charges you'll see on the bill (Figure 3).

The fix is with-edge-overrides, nested under the action's via block. You override the default so us-west-1's egress uses us-west-2's firewall:

"segment-actions": [
 {
 "action": "send-to",
 "segment": "Prod",
 "via": {
 "network-function-groups": ["InspectionNFG"],
 "with-edge-overrides": [
 { "edge-sets": [["us-west-1"]], "use-edge-location": "us-west-2" }
 ]
 }
 }
]

Now N. California egress is inspected by the nearby Oregon firewall, not the default Virginia one. The general rule is blunt: use an edge-override deliberately for every region that lacks a local stack. Otherwise the default ordering quietly routes egress somewhere suboptimal, and you discover it as a latency ticket rather than an error.

Figure 3 · The ordering trap and the override default ordering (not geography-aware) with-edge-overrides us-west-2 Oregon firewall + NAT local egress stack us-west-1 N. California no local stack must borrow a neighbor us-east-1 N. Virginia firewall + NAT higher in default order default override Default: N. California egress inspected cross-country in Virginia. Override: inspected next door in Oregon instead.
The default Region-priority order isn't geographic, so a region with no local stack can be sent across the country to inspect. with-edge-overrides is how you reclaim the nearby exit.

Why ingress won't ride the same rails

It's tempting to assume centralized ingress — inspecting traffic coming into your network from the internet — is just egress in reverse. It isn't, and the differences are sharp (Figure 4).

A NAT gateway can't do ingress. The whole egress design is outbound only; a NAT gateway will not accept inbound connections from the internet. Ingress needs a different front door.

Ingress isn't service insertion at all. send-to and send-via cover east-west and internet egress — not ingress. Centralized ingress is inspected at the VPC/IGW boundary: the internet gateway's route table steers inbound traffic to a Network Firewall endpoint, then to a public load balancer, and only then is it routed over Cloud WAN to the app VPC. Because Cloud WAN is a Layer-3 network with no load balancer of its own, an internet-facing ALB or NLB is mandatory in front. The maintained module models this as its own central-VPC type, ingress_with_inspection, with the public, endpoint, and core-network subnets it needs.

Symmetry is even more critical. Inbound flows that get NAT'd or load-balanced must return through the same inspection path, so appliance mode on the inspection attachment and consistent routing aren't optional. And mind one footgun: NLB client-IP preservation can't be enabled across Cloud WAN to a different VPC, so if your app needs the real client address you recover it from X-Forwarded-For or Proxy Protocol v2 rather than the packet.

Figure 4 · Egress vs ingress, side by side DIMENSION Egress (north-south) Ingress Steering service insertion: send-to NFG IGW route table, not SI Front door NAT gateway + IGW public ALB/NLB + firewall Inbound? no — outbound only yes — that's the point Cloud WAN role installs default route to exit L3 transport after inspection Symmetry appliance mode appliance mode (more critical) Same centralization instinct, different machinery — ingress never touches send-to.
Egress and ingress share the goal of one inspected chokepoint, but ingress is built at the IGW boundary with a real load balancer — service insertion does not apply.

The design most estates converge on — and when app-edge is enough

Put the egress pieces together for a three-region network — us-east-1, us-west-2, and us-west-1 with no local stack — and you get the pattern enterprises settle on:

The result: us-east-1 and us-west-2 workloads exit through their own local firewall and NAT; us-west-1 exits through the nearby Oregon stack rather than a distant default — all with no per-VPC static routes and a single policy document. That consolidates hundreds of NAT gateways into a handful of inspected exits, applies one filtering policy globally, and keeps latency sane through deliberate placement plus edge-overrides.

One honest caveat before you centralize everything. Service insertion re-routes traffic; it does not shrink your firewall fleet or its licenses — if you run a given number of firewall instances today, you run the same number after, and each inspection hop adds standard Cloud WAN data-processing. And for ingress specifically, plenty of teams never build a central inspection VPC at all: they handle it at the application edge with a public ALB or NLB, CloudFront, and WAF, reserving Cloud WAN service insertion for egress and east-west. Choose based on whether your compliance posture genuinely demands centralized network-layer ingress inspection, or whether application-layer controls already cover you. Egress is the north-south half worth centralizing for almost everyone; the next article takes on the other half — east-west inspection with send-via, where traffic between your segments must cross a firewall without ever leaving AWS.

Sources

  1. AWS — Core network policies (JSON) reference: send-to is north-south service insertion (no mode) and installs default routes 0.0.0.0/0 and ::/0 into the source segment with the local NFG attachment as next hop; Cloud WAN does not propagate blackhole routes. docs.aws.amazon.com/.../cloudwan-policies-json.html
  2. AWS — Service insertion in the core network policy: empty NFG referenced by send-to/send-via deploys but blackholes; the default Region-priority list is not geography-aware; with-edge-overrides remedies it; service insertion adds no extra AWS charge and does not reduce firewall count. docs.aws.amazon.com/.../cloudwan-policy-service-insertion.html
  3. AWS — Simplifying egress inspection with AWS Cloud WAN service insertion (blog): egress VPC layout (inspection before NAT → IGW), placement patterns, and same-region next-hop redirect to the local NFG attachment. aws.amazon.com/blogs/.../simplifying-egress-inspection-with-aws-cloud-wan-service-insertion-for-greenfield-deployments
  4. AWS — Cloud WAN VPC attachment: appliance mode is enabled on the VPC attachment, supported only on VPC attachments, pins a flow to one AZ for its lifetime, and is independent of service insertion (you need both). docs.aws.amazon.com/.../cloudwan-vpc-attachment.html
  5. AWS — Achieve optimal routing with AWS Cloud WAN for multi-Region networks (blog): regional-presence principle — a Region with a local attachment controls its exit point; without one it inherits a propagated route and exits via another Region. aws.amazon.com/blogs/.../achieve-optimal-routing-with-aws-cloud-wan-for-multi-region-networks
  6. AWS — Centralized ingress inspection architecture in AWS Cloud WAN (blog): ingress is not service insertion; it is inspected at the IGW boundary (IGW route table → Network Firewall endpoint → public ALB) then routed over Cloud WAN; NAT gateways can't accept inbound; NLB client-IP preservation can't cross Cloud WAN. aws.amazon.com/blogs/.../centralized-ingress-inspection-architecture-in-aws-cloud-wan
  7. AWS — aws-ia/cloudwan/aws Terraform module: central VPC types include egress, egress_with_inspection, ingress, and ingress_with_inspection (Network Firewall auto-created in the *_with_inspection types). registry.terraform.io/modules/aws-ia/cloudwan/aws/latest
  8. AWS — AWS Cloud WAN quotas: "Segments per core network" = 40, Adjustable = No. docs.aws.amazon.com/.../cloudwan-quotas.html
  9. AWS — Simplify global security inspection with AWS Cloud WAN service insertion (blog): a Network Function Group uses one core network segment internally, so it draws from the 40-segment budget. aws.amazon.com/blogs/.../simplify-global-security-inspection-with-aws-cloud-wan-service-insertion
  10. AWS — Amazon VPC pricing: NAT gateways are billed per hour and per GB processed (the per-VPC, per-AZ multiplication centralized egress avoids). aws.amazon.com/vpc/pricing/