AWS Cloud

One guarded door to the internet: an F5 egress proxy in a centralized egress VPC, across regions and accounts

Send every account's outbound traffic through one inspected exit per region — an F5 BIG-IP behind a Gateway Load Balancer — and the whole design lives or dies on flow symmetry.

Deep dive · cloud & network engineers ·

Scope & versions: AWS Transit Gateway / Gateway Load Balancer / Cloud WAN service insertion and F5 BIG-IP (16.1+ for GENEVE) as documented mid-2026. Network Firewall proxy GA’d Nov 2025. GWLB configurable TCP idle timeout since Sep 2024. Re-verify version-sensitive facts (BIG-IP GENEVE minimum, NFW proxy limits, GWLB MTU/timeout numbers) before relying on them.

The exit nobody's guarding — why one door beats sixty

You have 60 AWS accounts, each with its own NAT gateway punching straight out to the internet, and nobody can say what any of them talks to. Security wants URL filtering, TLS inspection, and DLP on every byte that leaves — none of which a NAT gateway will ever do. So you funnel all of it through one inspected exit per region and drop an F5 BIG-IP in the path — and immediately hit the design's real test: the return packet has to come back through the same appliance, or the stateful firewall silently drops it.

TL;DR

  • Centralize egress for control, not for cost. The win is one inspected door per region; on pure dollars, Transit Gateway's ~$0.02/GB processing can make centralization more expensive than per-VPC NAT when a few VPCs push heavy volume.
  • F5 goes in one of two ways. Transparent: BIG-IP as GENEVE targets behind a Gateway Load Balancer (inspects all L3, needs TGW appliance mode and an unchanged 5-tuple, BIG-IP 16.1+). Explicit: apps point at a forward proxy — NLB in front of an APM/SWG autoscale pool (identity-aware, symmetry is inherent). Most enterprises run both.
  • Appliance mode is the load-bearing setting. Without it, Transit Gateway sends the return through a different AZ's appliance, which has no session state, and the flow dies. It is off by default.
  • F5 earns its keep only past native. If you need decrypt-and-chain, DLP, non-HTTP protocols, or per-user policy, F5 wins; if it's just HTTP/HTTPS domain allow-listing, AWS Network Firewall's proxy is the cheaper, managed answer.
  • Keep egress regional and lock the spokes. One egress stack per region (don't backhaul), and an SCP that denies spoke accounts their own internet gateway so the guarded door is the only door.

Cost isn't the reason. Collapsing many low-traffic VPCs saves their per-VPC NAT sets, but TGW data processing (~$0.02/GB) rides on top of everything you centralize: in one illustrative comparison at 100 GB/VPC, centralization ran ~$342 more than per-VPC NAT, which won only in an edge case. Free S3/DynamoDB gateway endpoints in the spokes cut NAT traffic and improve the math. Centralize because you gain one place to inspect and log — not to shrink the bill.

What you're actually building — one door, many tenants, who owns each box

The design is hub-and-spoke, repeated once per region: workload accounts are spokes with no internet path of their own, and a central Network Services account owns each hub — a Transit Gateway plus an egress/inspection VPC holding the F5 fleet, the load balancer fronting it, and the NAT gateway to the internet.

The whole door: multi-region, multi-account centralized egressLegendWorkload accountNetwork Services accountExternalActive traffic pathNot an egress / droppedREGION 1 · us-east-1Workload accounts (spokes)Network Services accountegress-vpc · central egress/inspection VPC— transparent path (GWLB + F5 GENEVE) —— explicit forward-proxy path (NLB + APM/SWG) —spoke-aWorkload VPC · Acct Aspoke-bWorkload VPC · Acct BtgwTransit GW (R1)tgw-attachgwlbegwlbf5BIG-IP GENEVE targetsnlbf5-swgBIG-IP APM/SWG autoscale poolnat-gwigwinternet(external)Reserved L→R corridor: spoke → tgw → egress-vpc (transparent GWLB row · explicit NLB row) → nat-gw → igw → internet.Governance (SCP-deny-IGW, RAM-shared attachments, central logging) are invariants, not data-path boxes.REGION 2 · eu-west-1 — its own egress door (regional egress)Workload accountNetwork Services accountspoke-r2Workload VPC (R2)tgw-r2Transit GW (R2)region2-egress · condensedGWLBe → GWLB → F5 → NATigw-r2internet(R2 local exit)tgw-peerinter-region peeringNOT an egress path
fig-01 · The master canvas. Everything below is a grey-map zoom into this same picture. Account-boundary shading: green = workload spokes (no internet path of their own); blue = the Network Services account that owns the fabric.
ComponentOwnerPurpose
spoke-a / spoke-b — Workload VPC (private subnets only)App teamRuns workloads; default route points at the TGW, never an IGW
tgw — Transit Gateway (one per region)Network teamRegional hub; RAM-shared to spoke accounts; two route tables steer spokes to the egress VPC
egress-vpc — egress/inspection VPCNetwork teamHolds the GWLB/GWLBe, F5 fleet, and NAT gateways; three subnet tiers per AZ (TGW · appliance · NAT)
gwlb + gwlbeNetwork teamTransparent bump-in-the-wire; hands every flow to an F5 over GENEVE and pins it there
f5 / f5-swg — BIG-IP fleetSecurity / NetworkThe actual inspection: URL filtering, TLS decrypt, DLP, logging
nat-gw + igwNetwork teamThe one real exit to the internet, per region
Three subnet tiers per AZ inside the egress VPC — TGW, appliance (GWLB/GWLBe/F5), NAT — each with its own route table. That separation is what makes the flow traceable.

What does the inspecting — F5 vs native, and the two ways to wire it in

A NAT gateway hides source addresses and Network Firewall can allow-list domains — so why run a BIG-IP fleet? Because a full forward proxy does what the AWS-native path still can't: F5 BIG-IP (APM/SWG + SSL Orchestrator) gives real URL categorization (60M+ URLs across 150+ categories), TLS interception with service chaining — decrypt once, fan the cleartext through DLP, AV, and IPS, then re-encrypt — plus non-HTTP protocols and identity-aware per-user policy. Network Firewall's proxy (GA Nov 2025) is useful but narrower: HTTP/HTTPS only, no DLP, no non-HTTP inspection, no client-IP policy behind NAT, IPv4-only in preview.

CapabilityAWS Network Firewall proxyF5 BIG-IP SWG / SSLOVerdict
Domain / URL allow-listingYes (HTTP/HTTPS)Yes, categorized (60M+ URLs)Tie — native is enough
TLS interceptionYes (HTTP/HTTPS)Yes, any TCP + service chainingF5 if you chain inspectors
DLP / AV / IPS chainingNoYes (SSL Orchestrator)F5
Non-HTTP protocolsNoYesF5
Per-user / identity policyNoYes (APM)F5
Ops burdenManaged, lowYou run and license the fleetNative

The honest call: if you need domain allow-listing on web traffic and nothing more, native Network Firewall is the cheaper, lower-ops door. Reach for F5 when you need decrypt-and-chain, DLP, non-HTTP, or identity in the policy. Everything below assumes you've decided you need the F5.

Given F5, two dominant insertions differ only in whether the app knows the proxy exists. Transparent (Model A): the Gateway Load Balancer is a bump-in-the-wire that GENEVE-encapsulates every IP flow (UDP 6081) to a BIG-IP target — the app changes nothing, but inside the inspection zone the packet's 5-tuple must not change, because GWLB uses it to match the return to the same appliance (so any NAT on the F5 breaks it; BIG-IP 16.1+). Explicit (Model B): the app sends HTTP CONNECT to a BIG-IP APM/SWG virtual server behind an NLB, which runs URL and TLS policy per request. Most enterprises run both — transparent as the catch-all, explicit for the fleet that needs user-level web policy.

How a packet actually gets out — the transparent path, and the return that must match

This is the packet a security reviewer cares about most: an instance in a spoke reaching an external API, and its reply coming home. Treat the two directions as one story — because BIG-IP is stateful, the reply has to land on the same appliance that saw the request.

Flow 1 — how a packet gets out (transparent, GWLB + F5 GENEVE)LegendWorkload accountNetwork Services accountExternalActive traffic pathNot an egress / droppedREGION 1 · us-east-1egress-vpcspoke-aWorkload VPC · Acct AtgwTransit GW (R1)tgw-attachgwlbegwlbf5GENEVE inspectnlbf5-swgAPM/SWG autoscalenat-gwigwinternet(external)12345678910① default route 0.0.0.0/0 → tgw② TGW egress route table → egress VPC③ GENEVE encap (UDP 6081) to F5④ 5-tuple preserved (no NAT on F5)⑤ NAT masks source → IGW
fig-02 · The app did nothing special — it default-routed to a TGW and the fabric did the rest, so the F5 saw every byte. Badges ①–⑩ are the hops in the table below.
#Hop (egress)What happens
1spoke-atgwSubnet route sends 0.0.0.0/0 to the Transit Gateway (no IGW exists in this VPC)
2tgw egress RTDefault route → the egress-VPC attachment
3tgw-attachgwlbeTGW-subnet route table points at the GWLB endpoint in the same AZ
4–5gwlbegwlbGWLBe forwards to the Gateway Load Balancer over PrivateLink
6gwlbf5GWLB picks a BIG-IP by flow hash, GENEVE-wraps (UDP 6081); F5 decaps, inspects (URL/TLS/log), re-encaps — 5-tuple unchanged
7f5gwlbeGWLB strips GENEVE; appliance-subnet route defaults to the NAT gateway
8–10nat-gwigwinternetNAT SNATs to its public IP; out the internet gateway

Now the reply has to retrace that path exactly — and this is where appliance mode earns its spot in the verdict.

Flow 2 — the return that must match (why appliance mode exists)LegendWorkload accountNetwork Services accountExternalActive traffic pathNot an egress / droppedREGION 1 · us-east-1egress-vpcspoke-aWorkload VPC · Acct AtgwTransit GW (R1)tgw-attachgwlbegwlbf5GENEVE inspectnlbf5-swgAPM/SWG autoscalenat-gwigwinternet(external)↑ SAME appliance both directions (AZ-A)f5 (AZ-B)no session → dropped12345678⑦ transit RT (spoke CIDR) → spoke attachment → instanceAppliance mode pins the flow to ONE f5 ENI both ways.Without appliance mode, TGW AZ-affinity can send the return to the AZ-B appliance — no session state — and GWLB drops it.
fig-03 · Appliance mode forces TGW to hash each flow to one ENI and use it both directions, so the stateful F5 sees request and reply. It's off by default — turning it on is the whole design.
#Hop (return)What happens
1–2internetigwnat-gwReply arrives at the NAT public IP; NAT un-NATs and routes the spoke-bound packet on
3–4nat-gwgwlbegwlbGWLB uses the preserved 5-tuple to route to the same BIG-IP as the request
5gwlbf5 (same)BIG-IP matches its existing session, inspects, re-encaps
6–7gwlbetgwspoke-aTransit route table (spoke-CIDR route) → the correct spoke attachment → the originating instance

Never NAT on the F5 in the transparent path. Any address/port translation on the appliance changes the 5-tuple and GWLB silently drops the return. Let the AWS NAT gateway do translation; keep the F5 inspection virtual server translation-disabled.

The config that makes it work

Appliance mode — enable on the egress attachment (off by default)
aws ec2 create-transit-gateway-vpc-attachment \
  --transit-gateway-id tgw-0262a0e521EXAMPLE \
  --vpc-id vpc-07e8ffd50f49335df \
  --subnet-id subnet-0752213d59EXAMPLE \
  --options ApplianceModeSupport=enable

# already exists? modify it:
aws ec2 modify-transit-gateway-vpc-attachment \
  --transit-gateway-attachment-id tgw-attach-0253EXAMPLE \
  --options ApplianceModeSupport=enable
The two TGW route tables (conceptually)
# Egress route table  (associated: all spoke attachments)
0.0.0.0/0            -> tgw-attach-<egress-vpc>

# Transit route table (associated: egress VPC attachment)
10.1.0.0/16          -> tgw-attach-<spoke-A>
10.2.0.0/16          -> tgw-attach-<spoke-B>
GWLB + GWLBe — the transparent bump-in-the-wire
# GWLB fronts the F5 fleet as GENEVE (UDP 6081) targets; GWLBe is the
# PrivateLink endpoint the TGW-subnet route table points at, per AZ.
#   TGW subnet RT:        0.0.0.0/0        -> <gwlbe-eni>
#   Appliance subnet RT:  0.0.0.0/0        -> nat-gw
#   NAT subnet RT:        spoke CIDRs      -> <gwlbe-eni>   (return)
# GWLB health-checks the pool and drains a failed appliance;
# existing flows stay pinned to their target through a health blip.
F5 as a GENEVE target (Model A) — tmsh shape · BIG-IP 16.1+, SDN Services license
tmsh create net tunnels tunnel geneve \
  local-address <bigip-private-ip>%1 remote-address any%1 profile geneve

tmsh create ltm virtual inspect_vs \
  destination 0.0.0.0:any ip-protocol any \
  vlans add { geneve } \
  profiles add { fastL4 } \
  translate-address disabled translate-port disabled

Layer the actual inspection (SWG URL policy, SSL Orchestrator topology) on that virtual server. translate-address/translate-port disabled is what keeps the 5-tuple intact.

That's the whole mental model: one regional door, stateful F5 in the middle, symmetric flow. The rest is the explicit-proxy variant, going multi-region, and the ways this bites in production.

When you need identity, not just IPs — the explicit forward proxy

When an app is configured to use a proxy, the path is structurally different: the F5 terminates the connection and opens a fresh one, so there's no 5-tuple to preserve, no GENEVE, and — because the proxy re-originates — no appliance mode needed. The price is coverage: only apps you can configure are inspected, which is why transparent GWLB usually runs alongside as the catch-all.

Flow 3 — the explicit forward proxy (apps that speak proxy)LegendWorkload accountNetwork Services accountExternalActive traffic pathNot an egress / droppedREGION 1 · us-east-1egress-vpcspoke-aWorkload VPC · Acct AtgwTransit GW (R1)tgw-attachgwlbegwlbf5GENEVE inspectnlbf5-swgAPM/SWG autoscalenat-gwigwinternet(external)proxy terminates + re-originates — new 5-tuple (client ≠ server side)1234567① HTTP CONNECT → proxy VIP → nlb③ APM/SWG per-request URL + TLS policy④ symmetry inherent — no appliance mode
fig-04 · Because the proxy re-originates the connection, flow symmetry is free — the price is coverage: only apps you can point at a proxy are inspected.
#HopWhat happens
1app → nlbApp (proxy set via env/PAC/OS policy) opens HTTP CONNECT to the proxy VIP, which resolves to the NLB
2–3nlbf5-swgNLB spreads the connection across the autoscale pool; the explicit-proxy virtual server (HTTP profile → tcp-forward tunnel) runs APM/SWG per-request policy — URL category, allow/deny, optional TLS intercept
4–7f5-swgnat-gwigwinternetBIG-IP originates a fresh connection to the destination; the reply returns to the same BIG-IP (it owns the server-side socket) and back down the client connection
Explicit proxy (Model B) — the moving parts on AWS
# BIG-IP VE autoscale group behind an NLB:
#   NLB  --> ASG of BIG-IP VEs (NLB tracks ASG membership)
#   explicit-proxy virtual server:
#     HTTP profile  --> tunnel (encapsulation: tcp-forward)
#     APM/SWG per-request policy: URL category filter + TLS intercept
#
# F5 ships CloudFormation (v2) for the ASG/NLB/CloudWatch wiring,
# with Lambda lifecycle hooks that push AS3 declarations from S3 as
# instances come up — a scaled-out VE gets its full config automatically.

Why every region keeps its own door — egress stays regional

The instinct that trips people up is "we centralized, so send everything to the one egress VPC." Don't. A workload in Region 2 default-routes to Region 2's TGW, egress VPC, and NAT; the inter-region TGW peering carries cross-region workload traffic and management, never internet egress. Backhauling would add a cross-region hop — latency plus inter-region data charges — to every outbound call and make one region's stack a global single point of failure. AWS's guidance is explicit: one egress/inspection VPC per region (or per geo, e.g. AMER/EMEA); override only when a compliance rule demands a specific egress country, and backhaul that one segment deliberately.

Flow 4 — every region its own door (egress stays regional)LegendWorkload accountNetwork Services accountExternalActive traffic pathNot an egress / droppedREGION 1 · us-east-1 — greyedspoke-atgwgwlbe → gwlb → f5 → nat-gwigwREGION 2 · eu-west-1 — its own egress doorWorkload accountNetwork Services accountregion2-egress · condensedspoke-r2Workload VPC (R2)tgw-r2Transit GW (R2)GWLBe → GWLB → F5 → NATigw-r2internet(R2 local exit)12345tgw-peereast-west onlyno egress backhaul
fig-05 · Region 2 exits through its own door; the inter-region peering carries east-west traffic, never egress backhaul.

Cloud WAN is the modern alternative to hand-maintaining route tables. With service insertion you define a network function group (a segment of inspection attachments whose routes are auto-managed) and use a send-to action to steer north-south egress through it — no per-VPC static routes to babysit as the estate grows (send-via does the same for east-west). It supports Network Firewall, GWLB, and third-party vendors including F5. Appliance mode is still documented as required for stateful inspection: Cloud WAN changes how you express the steering, not the physics of keeping F5's state intact.

Keeping tenants honest — the account guardrails

A central Network Services account owns the fabric — TGW, egress VPC, and F5 fleet — with only network admins in it (separation of duties); TGW attachments are RAM-shared to each workload account, so app teams attach their VPC without owning the hub, and flow/appliance logs centralize there too. But centralized egress is only real if a spoke can't build its own exit. Attach this SCP to every OU except the network account:

SCP — deny every spoke its own path to the internet
{
  "Effect": "Deny",
  "Action": [
    "ec2:AttachInternetGateway",
    "ec2:CreateInternetGateway",
    "ec2:CreateEgressOnlyInternetGateway",
    "ec2:CreateVpcPeeringConnection",
    "ec2:AcceptVpcPeeringConnection",
    "globalaccelerator:Create*",
    "globalaccelerator:Update*"
  ],
  "Resource": "*"
}
That closes the obvious bypasses: a new IGW, an egress-only IGW, a peering shortcut, or a Global Accelerator front door. The guarded door becomes the only door.

Where this bites — pitfalls before you ship

Almost all of these have bitten someone in production. Several field reports below come from a Palo Alto VM-Series GWLB deployment, but the failure modes are properties of GWLB + a stateful appliance + TGW, so they apply to F5 just the same. The cost, MTU, and timeout numbers are illustrative of the pattern's shape, not F5 benchmarks.

PitfallWhy it bitesFix
No appliance mode → asymmetric dropsForward and return land on different AZ appliances; the return has no session and is dropped. Off by default.Enable appliance mode on the egress attachment
Silent fail-openIf every F5 target goes unhealthy (crash, license expiry, CPU spike), GWLB fails open — traffic bypasses inspection with no errorAlert on UnHealthyHostCount; treat "all targets down" as a security incident
NAT on the F5 (transparent path)Any address/port translation on the appliance changes the 5-tuple → GWLB silently drops the returnLet the AWS NAT gateway translate; keep the F5 virtual server translation-disabled
MTU / MSSThe GENEVE header adds 68 bytes. GWLB interfaces handle up to 8,500-byte packets (larger dropped); the F5 interface must support at least 8,568 bytes. (GWLB-doc numbers, illustrative.)MSS clamping, or raise the appliance MTU; large flows hanging is the tell
Idle timeouts kill long-lived flowsGWLB default idle timeout is 350s TCP / 120s non-TCP; since Sep 2024 the TCP value is tunable 60–6000s. (GWLB-doc numbers, illustrative.)Set app/OS TCP keep-alive below the timeout
Failover isn't instantNew flows can take up to ~70s to reroute after an appliance fails (health-check + detection)Size the fleet so losing one instance doesn't overload the rest during that window
Debugging is genuinely hardVPC Flow Logs on the path show only GENEVE on UDP 6081 — you can't see the real 5-tuple thereFlow logs on the GWLBe ENIs, read F5's own logs, Reachability Analyzer; simultaneous tcpdump on client, F5, and destination
TLS interception is a trust projectDecrypting egress means every client must trust the F5's signing CA; pinned-cert and mutual-TLS destinations break when interceptedPlan a bypass list and CA distribution before you flip it on
Cost and sizing are realOne illustrative 3-AZ, 2-firewall GWLB stack ran ~$1,800/mo in infrastructure and ~$9,287/mo once PAYG appliance licenses were added. (Palo Alto VM-Series field report; F5 licensing differs but the shape holds.) Budget TGW data processing (~$0.02/GB), PrivateLink/GWLBe, cross-AZ transfer, and per-instance throughput.Don't undersize the F5 fleet — it becomes the bottleneck for the whole estate
One region is one blast radiusRegional egress is right, but that region's F5 fleet is a hard dependency for all its outbound trafficMulti-AZ within the region, health-based autoscaling, and fleet alarms are not optional

So build it like this: one egress/inspection VPC per region in a central Network Services account; F5 inserted transparently as GENEVE targets behind a GWLB for blanket coverage, plus an explicit APM/SWG proxy behind an NLB for the fleet that needs user-level web policy; TGW (or Cloud WAN service insertion) steering spokes to the door with appliance mode on; and an SCP denying every spoke its own exit. Trace your own Flow 1 and Flow 2 on a whiteboard before you build — if you can't name the appliance the return packet lands on, you're not done designing. And if all you really need is domain allow-listing on web traffic, use Network Firewall's proxy and skip the F5 fleet entirely. The best egress proxy is the smallest one that meets the requirement.

References

  1. AWS — Centralized inspection architecture with Gateway Load Balancer and Transit Gateway. https://aws.amazon.com/blogs/networking-and-content-delivery/centralized-inspection-architecture-with-aws-gateway-load-balancer-and-aws-transit-gateway/
  2. AWS Whitepaper — Building a Scalable and Secure Multi-VPC Network Infrastructure: centralized egress; NAT gateway + GWLB with EC2. https://docs.aws.amazon.com/whitepapers/latest/building-scalable-secure-multi-vpc-network-infrastructure/centralized-egress-to-internet.html ; https://docs.aws.amazon.com/whitepapers/latest/building-scalable-secure-multi-vpc-network-infrastructure/using-nat-gateway-and-gwlb-with-ec2.html
  3. AWS Prescriptive Guidance — Centralized egress. https://docs.aws.amazon.com/prescriptive-guidance/latest/transitioning-to-multiple-aws-accounts/centralized-egress.html
  4. AWS — Best practices for deploying Gateway Load Balancer (idle timeouts, failover, cross-zone). https://aws.amazon.com/blogs/networking-and-content-delivery/best-practices-for-deploying-gateway-load-balancer/
  5. AWS — Gateway Load Balancers (ELB docs): GENEVE, MTU 8,500/8,568, asymmetric-flow limits. https://docs.aws.amazon.com/elasticloadbalancing/latest/gateway/gateway-load-balancers.html
  6. AWS — How Transit Gateways work: appliance mode / flow symmetry. https://docs.aws.amazon.com/vpc/latest/tgw/how-transit-gateways-work.html
  7. AWS — Securing egress architectures with Network Firewall proxy (Nov 2025). https://aws.amazon.com/blogs/networking-and-content-delivery/securing-egress-architectures-with-network-firewall-proxy/
  8. AWS — Centralized outbound inspection architecture in AWS Cloud WAN (regional egress). https://aws.amazon.com/blogs/networking-and-content-delivery/centralized-outbound-inspection-architecture-in-aws-cloud-wan/
  9. AWS — Simplify global security inspection with Cloud WAN service insertion (NFG, send-to/send-via, appliance mode). https://aws.amazon.com/blogs/networking-and-content-delivery/simplify-global-security-inspection-with-aws-cloud-wan-service-insertion/
  10. AWS — Prevent internet access with an SCP; Organizations SCP examples for VPC. https://docs.aws.amazon.com/prescriptive-guidance/latest/patterns/prevent-internet-access-at-the-account-level-by-using-a-service-control-policy.html ; https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps_examples_vpc.html
  11. F5 — BIG-IP integration with AWS Gateway Load Balancer (overview): BIG-IP 16.1+, 5-tuple preservation. https://community.f5.com/kb/technicalarticles/big-ip-integration-with-aws-gateway-load-balancer---overview/290821
  12. F5 — Configuring Network Virtualization (GENEVE) Tunnels; SDN Services license. https://techdocs.f5.com/en-us/bigip-14-1-0/big-ip-tmos-tunneling-and-ipsec-14-1-0/configuring-network-virtualization-tunnels.html
  13. F5 — BIG-IP APM Secure Web Gateway: explicit forward proxy (tcp-forward tunnel), URL categories. https://techdocs.f5.com/kb/en-us/products/big-ip_apm/manuals/product/apm-secure-web-gateway-implementations-11-6-0/5.html ; https://techdocs.f5.com/en-us/bigip-15-1-0/big-ip-access-policy-manager-secure-web-gateway/big-ip-apm-secure-web-gateway-overview.html
  14. F5 — BIG-IP autoscale on AWS (CloudFormation v2, NLB + ASG + AS3 via lifecycle hooks). https://github.com/F5Networks/f5-aws-cloudformation-v2/tree/main/examples/autoscale
  15. F5 DevCentral — f5-tgw-examples: BIG-IP firewall sandwich with TGW (non-GWLB alternative). https://github.com/f5devcentral/f5-tgw-examples
  16. HAIT — 9 production pitfalls: Palo Alto VM-Series on AWS GWLB (asymmetric routing, fail-open, cost, MTU, NAT-breaks-5-tuple). https://haitmg.pl/blog/palo-alto-vm-series-aws-transit-gateway-gwlb/
  17. Charles Sieg / Mantel Group — AWS egress cost analysis: centralized vs per-VPC NAT, TGW $/GB. https://www.charlessieg.com/articles/aws-egress-vpc-transit-gateway-cost-optimization.html ; https://community.mantelgroup.com.au/articles/post/designing-egress-in-aws-nat-gateways-transit-gateways-and-cost-analysis-uExURbgeu5MezIh