From eace9971800b116a7fbb03544cd17ede3dceb76c Mon Sep 17 00:00:00 2001 From: kanywst <45947799+kanywst@users.noreply.github.com> Date: Sun, 8 Nov 2026 11:27:31 +0900 Subject: [PATCH 1/7] refactor(cost): read Direct Connect prices from one shared price list --- src/data/asOf.ts | 6 ++ src/data/dxPricing.test.ts | 67 +++++++++++++++++ src/data/dxPricing.ts | 130 +++++++++++++++++++++++++++++++++ src/features/cost/cost.test.ts | 13 ++++ src/features/cost/cost.ts | 21 +++--- 5 files changed, 228 insertions(+), 9 deletions(-) create mode 100644 src/data/dxPricing.test.ts create mode 100644 src/data/dxPricing.ts diff --git a/src/data/asOf.ts b/src/data/asOf.ts index dbfe2b4..48ff811 100644 --- a/src/data/asOf.ts +++ b/src/data/asOf.ts @@ -1,2 +1,8 @@ /** The date every fact and list price on the site was last verified. */ export const AS_OF = "2026-10-10"; + +/** + * The date the Direct Connect deep dive (direct-connect/) and the shared DX + * price list in @/data/dxPricing were last verified. + */ +export const DX_AS_OF = "2026-10-12"; diff --git a/src/data/dxPricing.test.ts b/src/data/dxPricing.test.ts new file mode 100644 index 0000000..42a3766 --- /dev/null +++ b/src/data/dxPricing.test.ts @@ -0,0 +1,67 @@ +import { describe, expect, it } from "vitest"; +import { + DTO_PER_GB, + FLAT_RATE_EXAMPLE, + PORT_HOURLY, + breakEvenGb, + estimate, + portHourly, +} from "./dxPricing"; + +describe("pricing", () => { + // Both examples are the worked scenarios on the AWS pricing page. + it("reproduces AWS's high-resiliency hosted example ($984.08)", () => { + const r = estimate({ + type: "hosted", + mbps: 2000, + count: 2, + dxGeo: "us", + source: "us", + gbOut: 1024, + }); + expect(r).toEqual({ portHourly: 0.66, port: 963.6, dto: 20.48, total: 984.08 }); + }); + + it("reproduces AWS's maximum-resiliency dedicated example ($14,762)", () => { + const r = estimate({ + type: "dedicated", + mbps: 10000, + count: 4, + dxGeo: "us", + source: "us", + gbOut: 409600, + }); + expect(r.port).toBe(6570); + expect(r.dto).toBe(8192); + expect(r.total).toBe(14762); + }); + + it("uses Japan port prices at Japanese locations", () => { + expect(portHourly("dedicated", 1000, "japan")).toBe(0.285); + expect(portHourly("dedicated", 1000, "us")).toBe(0.3); + expect(portHourly("dedicated", 100000, "japan")).toBe(22.5); + }); + + it("rejects speeds that do not exist", () => { + expect(() => portHourly("dedicated", 25000, "us")).toThrow(); + }); + + it("has a DTO rate for every source/location pair", () => { + for (const row of Object.values(DTO_PER_GB)) { + for (const v of Object.values(row)) expect(v).toBeGreaterThan(0); + } + expect(Object.keys(PORT_HOURLY.dedicated)).toEqual([ + "1000", + "10000", + "100000", + "400000", + ]); + }); + + it("matches the ~230 TB break-even for a 10G Tier 1 port-pair", () => { + const f = FLAT_RATE_EXAMPLE; + const gb = breakEvenGb(f.hourly, f.paygPortHourly, f.paygPorts, f.dtoPerGb); + expect(Math.round(gb)).toBe(235790); + expect(breakEvenGb(1, 2.25, 2, 0.02)).toBe(0); + }); +}); diff --git a/src/data/dxPricing.ts b/src/data/dxPricing.ts new file mode 100644 index 0000000..1cea4f8 --- /dev/null +++ b/src/data/dxPricing.ts @@ -0,0 +1,130 @@ +import { DX_AS_OF } from "./asOf"; + +/** + * The one Direct Connect price list on the site. Both the road map's cost lab + * (@/features/cost/cost) and the deep dive's pricing section read DX prices + * from here, and docs/direct-connect/10-pricing.md is the matching research + * note. USD list prices from aws.amazon.com/directconnect/pricing and the AWS + * Price List API. Monthly figures use 730 hours, as AWS's own examples do. + */ + +export const HOURS_PER_MONTH = 730; +export const PRICES_AS_OF = DX_AS_OF; + +export type ConnType = "dedicated" | "hosted"; + +/** Port-hour price by capacity in Mbps: [non-Japan, Japan]. */ +export const PORT_HOURLY: Record> = { + dedicated: { + 1000: [0.3, 0.285], + 10000: [2.25, 2.142], + 100000: [22.5, 22.5], + 400000: [85, 85], + }, + hosted: { + 50: [0.03, 0.029], + 100: [0.06, 0.057], + 200: [0.08, 0.076], + 300: [0.12, 0.114], + 400: [0.16, 0.152], + 500: [0.2, 0.19], + 1000: [0.33, 0.314], + 2000: [0.66, 0.627], + 5000: [1.65, 1.568], + 10000: [2.48, 2.361], + 25000: [6.2, 6.2], + }, +}; + +export const SOURCE_REGIONS = [ + "us", + "europe", + "tokyo-osaka", + "apac-other", + "india", + "australia", + "south-america", +] as const; +export type SourceRegion = (typeof SOURCE_REGIONS)[number]; + +export const DX_GEOS = ["us", "europe", "japan", "apac", "australia"] as const; +export type DxGeo = (typeof DX_GEOS)[number]; + +/** Data transfer out, USD/GB: source Region group → DX location geography. */ +export const DTO_PER_GB: Record> = { + us: { us: 0.02, europe: 0.02, japan: 0.0491, apac: 0.0491, australia: 0.06 }, + europe: { us: 0.0282, europe: 0.02, japan: 0.06, apac: 0.06, australia: 0.06 }, + "tokyo-osaka": { us: 0.09, europe: 0.06, japan: 0.041, apac: 0.041, australia: 0.1132 }, + "apac-other": { us: 0.09, europe: 0.09, japan: 0.042, apac: 0.041, australia: 0.1107 }, + india: { us: 0.085, europe: 0.085, japan: 0.1132, apac: 0.1, australia: 0.11 }, + australia: { us: 0.13, europe: 0.13, japan: 0.1132, apac: 0.1107, australia: 0.042 }, + "south-america": { us: 0.15, europe: 0.1107, japan: 0.17, apac: 0.17, australia: 0.18 }, +}; + +/** + * Flat-rate (2026-09-15), dedicated 10G and 100G only, USD per hour for a + * single port or a whole port-pair (a pair costs the same as one port). + * Tiers 1-3 as listed for the Japan locations; AWS's own Ashburn example + * (10G Tier 1 port-pair at Equinix DC2) is the same $10.96/hour. + */ +export const FLAT_RATE_HOURLY: Record<10000 | 100000, [number, number, number]> = { + 10000: [10.96, 17.12, 23.29], + 100000: [102.74, 160.96, 219.18], +}; + +/** + * AWS's published flat-rate example (10G Tier 1 port-pair at Equinix DC2, + * $10.96/hour), compared with two pay-as-you-go 10G ports at the US → US + * data-transfer rate. + */ +export const FLAT_RATE_EXAMPLE = { + hourly: FLAT_RATE_HOURLY[10000][0], + paygPortHourly: PORT_HOURLY.dedicated[10000][0], + paygPorts: 2, + dtoPerGb: DTO_PER_GB.us.us, +} as const; + +export interface Estimate { + type: ConnType; + mbps: number; + count: number; + dxGeo: DxGeo; + source: SourceRegion; + gbOut: number; +} + +export interface Breakdown { + portHourly: number; + port: number; + dto: number; + total: number; +} + +const round2 = (n: number) => Math.round(n * 100) / 100; + +export function portHourly(type: ConnType, mbps: number, dxGeo: DxGeo): number { + const row = PORT_HOURLY[type][mbps]; + if (!row) throw new Error(`no ${type} port at ${mbps} Mbps`); + return dxGeo === "japan" ? row[1] : row[0]; +} + +export function estimate(e: Estimate): Breakdown { + const hourly = portHourly(e.type, e.mbps, e.dxGeo); + const port = round2(hourly * HOURS_PER_MONTH * e.count); + const dto = round2(e.gbOut * DTO_PER_GB[e.source][e.dxGeo]); + return { portHourly: hourly, port, dto, total: round2(port + dto) }; +} + +/** + * Monthly egress (GB) above which a flat-rate price beats pay-as-you-go ports + * plus DTO. Returns 0 if flat-rate is already cheaper with no traffic. + */ +export function breakEvenGb( + flatHourly: number, + paygPortHourly: number, + paygPorts: number, + dtoPerGb: number, +): number { + const gap = (flatHourly - paygPortHourly * paygPorts) * HOURS_PER_MONTH; + return gap <= 0 ? 0 : gap / dtoPerGb; +} diff --git a/src/features/cost/cost.test.ts b/src/features/cost/cost.test.ts index 91263bb..e4d70a7 100644 --- a/src/features/cost/cost.test.ts +++ b/src/features/cost/cost.test.ts @@ -9,6 +9,19 @@ import { gbAt, SLIDER, } from "./cost"; +import { DTO_PER_GB, FLAT_RATE_HOURLY, PORT_HOURLY } from "@/data/dxPricing"; + +describe("DX prices come from the shared price list", () => { + it("uses the Japan columns of @/data/dxPricing", () => { + expect(P.dxDedicated1g).toBe(PORT_HOURLY.dedicated[1000][1]); + expect(P.dxDedicated10g).toBe(PORT_HOURLY.dedicated[10000][1]); + expect(P.dxHosted50m).toBe(PORT_HOURLY.hosted[50][1]); + expect(P.dxHosted500m).toBe(PORT_HOURLY.hosted[500][1]); + expect(P.dxHosted1g).toBe(PORT_HOURLY.hosted[1000][1]); + expect(P.dxDtoJapan).toBe(DTO_PER_GB["tokyo-osaka"].japan); + expect(P.dxFlat10gTier1).toBe(FLAT_RATE_HOURLY[10000][0]); + }); +}); const TEN_TB = 10_240; const noTgw = { gb: TEN_TB, viaTgw: false, freeTier: false }; diff --git a/src/features/cost/cost.ts b/src/features/cost/cost.ts index 2b4b22d..8b2524b 100644 --- a/src/features/cost/cost.ts +++ b/src/features/cost/cost.ts @@ -1,11 +1,14 @@ import type { L } from "@/i18n/lang"; import { AS_OF } from "@/data/asOf"; +import { DTO_PER_GB, FLAT_RATE_HOURLY, portHourly } from "@/data/dxPricing"; /** * Monthly AWS charges for sending data from ap-northeast-1 (Tokyo) to your * data center, per path. List on-demand USD from the AWS Price List API as * recorded in docs/12-security-and-operations.md ("Unit prices for a - * calculator"). Excludes tax, carrier circuits, colocation and partner fees. + * calculator"); every Direct Connect price comes from the shared DX price + * list in @/data/dxPricing (Japan locations). Excludes tax, carrier + * circuits, colocation and partner fees. */ /** Prices were read on the site-wide verification date. */ @@ -20,13 +23,13 @@ export const P = { { upTo: Infinity, perGb: 0.084 }, ], freeTierGb: 100, - dxDtoJapan: 0.041, - dxDedicated1g: 0.285, - dxDedicated10g: 2.142, - dxHosted50m: 0.029, - dxHosted500m: 0.19, - dxHosted1g: 0.314, - dxFlat10gTier1: 10.96, + dxDtoJapan: DTO_PER_GB["tokyo-osaka"].japan, + dxDedicated1g: portHourly("dedicated", 1000, "japan"), + dxDedicated10g: portHourly("dedicated", 10000, "japan"), + dxHosted50m: portHourly("hosted", 50, "japan"), + dxHosted500m: portHourly("hosted", 500, "japan"), + dxHosted1g: portHourly("hosted", 1000, "japan"), + dxFlat10gTier1: FLAT_RATE_HOURLY[10000][0], vpnConnection: 0.048, tgwAttachment: 0.07, tgwPerGb: 0.02, @@ -241,7 +244,7 @@ export function dxBreakEvenGb(hourly: number): number { /** * Monthly GB at which one 10G flat-rate port (Tier 1) beats one 10G * pay-as-you-go port plus $0.041/GB. A redundant port-pair compares - * differently; Cross Connect's pricing section covers pairs. + * differently; the Direct Connect deep dive's pricing section covers pairs. */ export function flatBreakEvenGb(): number { return ((P.dxFlat10gTier1 - P.dxDedicated10g) * HOURS) / P.dxDtoJapan; From 7f94b695f022712eb596cde61d0ba9c74623b5dc Mon Sep 17 00:00:00 2001 From: kanywst <45947799+kanywst@users.noreply.github.com> Date: Sun, 8 Nov 2026 11:27:31 +0900 Subject: [PATCH 2/7] docs: import the Direct Connect research notes and keep one DX price table --- docs/04-direct-connect.md | 65 +---- docs/06-routing-and-path-selection.md | 4 +- docs/12-security-and-operations.md | 16 +- docs/README.md | 4 + docs/direct-connect/01-overview.md | 145 ++++++++++ docs/direct-connect/02-connections.md | 249 ++++++++++++++++++ docs/direct-connect/03-lag-and-macsec.md | 169 ++++++++++++ docs/direct-connect/04-virtual-interfaces.md | 222 ++++++++++++++++ .../05-direct-connect-gateway.md | 231 ++++++++++++++++ docs/direct-connect/06-bgp-and-routing.md | 238 +++++++++++++++++ docs/direct-connect/07-resiliency.md | 213 +++++++++++++++ docs/direct-connect/08-security.md | 145 ++++++++++ .../09-monitoring-and-troubleshooting.md | 236 +++++++++++++++++ docs/direct-connect/10-pricing.md | 187 +++++++++++++ docs/direct-connect/11-design-patterns.md | 181 +++++++++++++ docs/direct-connect/12-timeline.md | 123 +++++++++ docs/direct-connect/13-why-dx-is-hard.md | 119 +++++++++ docs/direct-connect/README.md | 19 ++ 18 files changed, 2497 insertions(+), 69 deletions(-) create mode 100644 docs/direct-connect/01-overview.md create mode 100644 docs/direct-connect/02-connections.md create mode 100644 docs/direct-connect/03-lag-and-macsec.md create mode 100644 docs/direct-connect/04-virtual-interfaces.md create mode 100644 docs/direct-connect/05-direct-connect-gateway.md create mode 100644 docs/direct-connect/06-bgp-and-routing.md create mode 100644 docs/direct-connect/07-resiliency.md create mode 100644 docs/direct-connect/08-security.md create mode 100644 docs/direct-connect/09-monitoring-and-troubleshooting.md create mode 100644 docs/direct-connect/10-pricing.md create mode 100644 docs/direct-connect/11-design-patterns.md create mode 100644 docs/direct-connect/12-timeline.md create mode 100644 docs/direct-connect/13-why-dx-is-hard.md create mode 100644 docs/direct-connect/README.md diff --git a/docs/04-direct-connect.md b/docs/04-direct-connect.md index 77fa743..e881f6a 100644 --- a/docs/04-direct-connect.md +++ b/docs/04-direct-connect.md @@ -1,6 +1,6 @@ # AWS Direct Connect as a path -This page summarizes AWS Direct Connect (DX) as one of the paths between a corporate network and AWS: connection types and speeds, the three virtual interface (VIF) types and what each reaches, the Direct Connect gateway (DXGW), SiteLink, MACsec, resiliency models and the SLA, MTU, prefix limits, pricing (with Tokyo and Osaka figures), Japanese carrier closed-network services that embed DX, and lead times. It is a summary. The sibling repository [0-draft/cross-connect](https://github.com/0-draft/cross-connect/tree/main/docs) covers DX in much more depth, and this page links to it where it helps. Facts were re-verified against AWS documentation, What's New posts, the SLA page and the AWS Price List API as of 2026-10-10. +This page summarizes AWS Direct Connect (DX) as one of the paths between a corporate network and AWS: connection types and speeds, the three virtual interface (VIF) types and what each reaches, the Direct Connect gateway (DXGW), SiteLink, MACsec, resiliency models and the SLA, MTU, prefix limits, pricing (with Tokyo and Osaka figures), Japanese carrier closed-network services that embed DX, and lead times. It is a summary. The Direct Connect deep dive in [direct-connect/](direct-connect/README.md) covers DX in much more depth (it was the separate 0-draft/cross-connect repository until 2026-11-08), and this page links to it where it helps. Facts were re-verified against AWS documentation, What's New posts, the SLA page and the AWS Price List API as of 2026-10-10. ## Where DX sits among the paths @@ -30,11 +30,11 @@ flowchart LR | Hosted connection | 50, 100, 200, 300, 400, 500 Mbps; 1, 2, 5, 10, 25 Gbps | A Direct Connect Delivery Partner carves it from its interconnect; you accept it | Exactly 1 (private, public or transit) | No | | Hosted VIF | No AWS-assigned capacity; shares the owner's link | The owner of a connection creates a VIF in your account | It is one VIF | No | -- 400 Gbps dedicated ports launched in July 2024 at select locations. The DX locations page lists them only at US sites as of the cross-connect snapshot (2026-09-30); no 400 Gbps port appears in the Japan price list, so treat 400G as not available in Japan. +- 400 Gbps dedicated ports launched in July 2024 at select locations. The DX locations page lists them only at US sites as of the deep dive's snapshot (2026-09-30); no 400 Gbps port appears in the Japan price list, so treat 400G as not available in Japan. - 25 Gbps hosted connections were added on 2024-04-24. Only select partners may sell 1 Gbps and above. - Transit VIFs work on dedicated and hosted connections of any speed. Before 2022-08 they required 1 Gbps or more, and older Japanese blog posts still say that. - AWS no longer accepts new partner integrations based on hosted VIFs. Partners are steered to hosted connections, which AWS polices per connection. -- Depth: [cross-connect 02-connections](https://github.com/0-draft/cross-connect/blob/main/docs/02-connections.md). +- Depth: [direct-connect/02-connections.md](direct-connect/02-connections.md). ## Virtual interfaces and what they reach @@ -51,7 +51,7 @@ flowchart LR - Customer ASNs can be 2-byte private (64512 to 65534) or 4-byte; 4-byte ASNs on all VIF types were announced on 2025-09-12. - On a public VIF, a private customer ASN is replaced by 7224, so AS_PATH prepending is stripped. AWS treats routes learned on a public VIF as `NO_EXPORT`. - Gateway VPC endpoints (S3, DynamoDB) do not carry traffic that enters a VPC from DX. Use interface endpoints or a public VIF. -- Depth: [cross-connect 04-virtual-interfaces](https://github.com/0-draft/cross-connect/blob/main/docs/04-virtual-interfaces.md). +- Depth: [direct-connect/04-virtual-interfaces.md](direct-connect/04-virtual-interfaces.md). ## Direct Connect gateway @@ -74,7 +74,7 @@ A DXGW is a global, free, control-plane object (AWS describes it as a distribute - Allowed prefixes are a filter for VGW associations but the literal advertisement for TGW associations. With a TGW, on-prem receives exactly the listed prefixes, even if no VPC owns them. - A DXGW does not transit VPC to VPC or VIF to VIF, except through SiteLink. - Cloud WAN gained a native DXGW attachment on 2024-11-25. It does not support allowed prefixes or the DX BGP communities; Cloud WAN Routing Policy (2025-11) is the replacement control. -- Depth: [cross-connect 05-direct-connect-gateway](https://github.com/0-draft/cross-connect/blob/main/docs/05-direct-connect-gateway.md) and [05-hubs.md](05-hubs.md) in this repo. +- Depth: [direct-connect/05-direct-connect-gateway.md](direct-connect/05-direct-connect-gateway.md) and [05-hubs.md](05-hubs.md) in this repo. ## SiteLink @@ -88,7 +88,7 @@ SiteLink lets on-prem sites talk to each other across the AWS backbone between D | Private IP Site-to-Site VPN | L3 IPsec | Over a transit VIF to a Transit Gateway only (Cloud WAN cannot use its DXGW attachment as VPN transport; front it with a TGW), outer IPs private | | Public IP VPN over a public VIF | L3 IPsec | To the public VPN endpoints, not accelerated | -MACsec is hop by hop: it encrypts the link between your MACsec device and the AWS device, which need a direct Layer 2 adjacency. If your MACsec device sits in the colocation cage, that is just the cross connect; the carrier circuit to your building is covered only if your device is at your end and the carrier passes Layer 2 through transparently (ask the carrier). 100 and 400 Gbps require GCM-AES-XPN-256; 10 Gbps allows GCM-AES-256 or the XPN variant. Only static CAK mode is supported. Depth: [cross-connect 03-lag-and-macsec](https://github.com/0-draft/cross-connect/blob/main/docs/03-lag-and-macsec.md). +MACsec is hop by hop: it encrypts the link between your MACsec device and the AWS device, which need a direct Layer 2 adjacency. If your MACsec device sits in the colocation cage, that is just the cross connect; the carrier circuit to your building is covered only if your device is at your end and the carrier passes Layer 2 through transparently (ask the carrier). 100 and 400 Gbps require GCM-AES-XPN-256; 10 Gbps allows GCM-AES-256 or the XPN variant. Only static CAK mode is supported. Depth: [direct-connect/03-lag-and-macsec.md](direct-connect/03-lag-and-macsec.md). ## LAGs @@ -108,7 +108,7 @@ A link aggregation group bundles dedicated connections of the same speed on the - Hosted connections and hosted VIFs from partners are not covered by the SLA. Dedicated connections ordered through a partner are covered only if your AWS account owns them. - Planned maintenance is announced 14 days ahead and can last up to 4 hours. AWS says it will not take down redundant connections at the same time. - Flat-rate billing (2026-09-15) includes a free second port in a "port-pair" on a different device or location, but usable bandwidth stays at one port. -- Depth: [cross-connect 07-resiliency](https://github.com/0-draft/cross-connect/blob/main/docs/07-resiliency.md). +- Depth: [direct-connect/07-resiliency.md](direct-connect/07-resiliency.md). ## Failure detection @@ -145,51 +145,12 @@ Exceeding an inbound allocation drops the BGP session to Idle (reported DOWN). W ## Pricing summary -All prices are USD list, pay-as-you-go, from the AWS Price List API (Direct Connect offer for ap-northeast-1 and ap-northeast-3, published 2026-10-05). Japanese consumption tax is extra. Monthly figures use 730 hours. +The Direct Connect price tables (port-hours for dedicated and hosted connections, the full DTO matrix, SiteLink, flat-rate tiers and AWS's worked examples) live in one place: [direct-connect/10-pricing.md](direct-connect/10-pricing.md). The site reads the same numbers from one file, `src/data/dxPricing.ts`. What matters for a Tokyo or Osaka design: -### Dedicated port-hours - -| Speed | Japan locations ($/h) | Japan ≈ $/month | Most other locations ($/h) | -| --- | --- | --- | --- | -| 1 Gbps | 0.285 | 208.05 | 0.30 | -| 10 Gbps | 2.142 | 1,563.66 | 2.25 | -| 100 Gbps | 22.50 | 16,425.00 | 22.50 | -| 400 Gbps | Not offered in Japan | – | 85.00 | - -Japan locations in the price list: Equinix TY2 (Tokyo), AT Tokyo Chuo, NEC Inzai, Equinix OS1 (Osaka), all billed under Asia Pacific (Tokyo), and KDDI Telehouse Osaka 2, billed under Asia Pacific (Osaka). Pay-as-you-go 100 Gbps SKUs appear at AT Tokyo, NEC Inzai and Telehouse Osaka 2 in the price list; check the locations page for the speeds a specific site offers today. - -### Hosted connection port-hours (Japan) - -| Capacity | $/h | ≈ $/month | -| --- | --- | --- | -| 50 Mbps | 0.029 | 21.17 | -| 100 Mbps | 0.057 | 41.61 | -| 200 Mbps | 0.076 | 55.48 | -| 300 Mbps | 0.114 | 83.22 | -| 400 Mbps | 0.152 | 110.96 | -| 500 Mbps | 0.190 | 138.70 | -| 1 Gbps | 0.314 | 229.22 | -| 2 Gbps | 0.627 | 457.71 | -| 5 Gbps | 1.568 | 1,144.64 | -| 10 Gbps | 2.361 | 1,723.53 | -| 25 Gbps | 6.20 | 4,526.00 | - -The partner's own fees come on top. A hosted 10 Gbps costs more per hour than a dedicated 10 Gbps port. - -### Data transfer out (DTO) - -Data transfer in over DX is free. DTO depends on the source Region and the geography of the DX location where traffic exits. - -| From | To a Japan DX location | To Singapore / Hong Kong / KL | To a US location | To a Europe location | -| --- | --- | --- | --- | --- | -| Tokyo (ap-northeast-1) | $0.041/GB | $0.041/GB | $0.09/GB | $0.06/GB | -| Osaka (ap-northeast-3) | $0.041/GB | $0.041/GB | $0.09/GB | $0.06/GB | - -For comparison, US Regions to a US location cost $0.02/GB. If a Transit Gateway is in the path, add the TGW attachment-hour and $0.02/GB data processing (see [05-hubs.md](05-hubs.md)). - -### Flat-rate (2026-09-15) - -Dedicated 10G and 100G connections can instead use a flat hourly rate that includes DTO from Regions in a chosen tier (Tier 1 same metro up to Tier 5 global). At Japan locations the price list shows, for a single 10G port, $10.96/h (Tier 1), $17.12/h (Tier 2) and $23.29/h (Tier 3), and for 100G $102.74, $160.96 and $219.18. Port-pair SKUs are listed at half those rates per port (for example 10G Tier 1 pair $5.48/h per port), which matches AWS's statement that a pair costs the same as a single flat-rate port. Depth: [cross-connect 10-pricing](https://github.com/0-draft/cross-connect/blob/main/docs/10-pricing.md). +- Pay-as-you-go is port-hours plus data transfer out. A dedicated 1 Gbps port at a Japan location is $0.285/h and 10 Gbps is $2.142/h, slightly below most other locations. 400 Gbps is not offered in Japan. +- Data in over DX is free. Out of Tokyo or Osaka to a Japan DX location is $0.041/GB, against $0.114/GB for the first internet tier. +- A hosted 10 Gbps costs more per hour than a dedicated 10 Gbps port, and the partner's own fees come on top. +- Flat-rate (2026-09-15) covers dedicated 10G and 100G only. A port-pair costs the same as a single flat-rate port. If a Transit Gateway is in the path, its attachment-hours and $0.02/GB processing are extra either way (see [05-hubs.md](05-hubs.md)). ## Japanese carrier closed-network services that embed DX @@ -231,7 +192,7 @@ AWS does not publish an end-to-end lead time for a dedicated connection. The car ## Sources -- +- [direct-connect/](direct-connect/README.md) (the deep dive's research notes) - - - diff --git a/docs/06-routing-and-path-selection.md b/docs/06-routing-and-path-selection.md index 7f8ece9..46edf2d 100644 --- a/docs/06-routing-and-path-selection.md +++ b/docs/06-routing-and-path-selection.md @@ -314,5 +314,5 @@ DX_EDGE(dst) for private/transit VIFs: - - - -- -- +- [direct-connect/06-bgp-and-routing.md](direct-connect/06-bgp-and-routing.md) +- [direct-connect/07-resiliency.md](direct-connect/07-resiliency.md) diff --git a/docs/12-security-and-operations.md b/docs/12-security-and-operations.md index b60f8d3..1321048 100644 --- a/docs/12-security-and-operations.md +++ b/docs/12-security-and-operations.md @@ -116,20 +116,6 @@ flowchart LR | Internet DTO over 150 TB | per GB | 0.084 | | Data transfer in (internet, VPN, DX) | per GB | 0.00 | | Inter-Region out (Tokyo → any listed Region, e.g. Osaka, us-east-1) | per GB | 0.09 | -| DX DTO Tokyo → Japan DX locations (Equinix TY2, AT Tokyo Chuo, NEC Inzai, Equinix OS1) | per GB | 0.041 | -| DX DTO Tokyo → Equinix SG2, Taipei locations | per GB | 0.041 | -| DX DTO Tokyo → Equinix LD4–LD6 (London) | per GB | 0.06 | -| DX DTO Tokyo → Equinix SV1/SV5 (Silicon Valley) | per GB | 0.09 | -| DX dedicated port 1 Gbps (Japan locations) | per hour | 0.285 | -| DX dedicated port 10 Gbps | per hour | 2.142 | -| DX dedicated port 100 Gbps (AT Tokyo Chuo, NEC Inzai) | per hour | 22.50 | -| DX hosted 50 / 100 / 200 / 300 / 400 / 500 Mbps | per hour | 0.029 / 0.057 / 0.076 / 0.114 / 0.152 / 0.190 | -| DX hosted 1 / 2 / 5 / 10 Gbps | per hour | 0.314 / 0.627 / 1.568 / 2.361 | -| DX flat-rate 10G, Tier 1 / 2 / 3 (single port) | per hour | 10.96 / 17.12 / 23.29 | -| DX flat-rate 10G port-pair, per port, Tier 1 / 2 / 3 | per hour | 5.48 / 8.56 / 11.64 | -| DX flat-rate 100G, Tier 1 / 2 / 3 (single port) | per hour | 102.74 / 160.96 / 219.18 | -| DX flat-rate 100G port-pair, per port, Tier 1 / 2 / 3 | per hour | 51.37 / 80.48 / 109.59 | -| DX SiteLink | per VIF-hour | 0.50 | | Site-to-Site VPN connection (1.25 Gbps tunnels) | per hour | 0.048 | | Site-to-Site VPN connection, 5 Gbps tunnels | per hour | 0.60 | | Site-to-Site VPN Concentrator / site on concentrator | per hour | 1.95 / 0.01 | @@ -146,7 +132,7 @@ flowchart LR | DataSync Basic / Enhanced | per GB (+0.55 per Enhanced execution) | 0.0125 / 0.015 | | Transfer Family protocol / data | per hour, per GB | 0.30, 0.04 | -Flat-rate Direct Connect (2026-09) applies to 10G and 100G **dedicated** connections only. It zeroes DTO between the DX location and the Regions in the chosen tier (Tier 1 local metro … Tier 5 global); traffic from Regions outside the tier pays standard DX DTO. The second port of a port-pair is included at no extra charge (the pair rate is exactly half the single-port rate per port). For ap-northeast-1, the Price List API marks all four Japan locations (including Equinix OS1, Osaka) as Tier 1, Equinix SG2 and Silicon Valley as Tier 3, London as Tier 4, Taipei as Tier 5. All connections at one DX location in an account must use the same billing mode. TGW/Cloud WAN processing, SiteLink transfer and partner fees are not covered. +Direct Connect unit prices (port-hours, DTO from Tokyo, SiteLink, flat-rate tiers) are not repeated here. They live in one table, [direct-connect/10-pricing.md](direct-connect/10-pricing.md#japan-locations-from-the-aws-price-list-api), which the worked example below uses. ### Worked example: 10 TB/month from ap-northeast-1 to on-prem diff --git a/docs/README.md b/docs/README.md index 627669d..0354aae 100644 --- a/docs/README.md +++ b/docs/README.md @@ -20,3 +20,7 @@ Everything the site says is backed by these notes. Each page ends with the AWS d | 14 | [Why hybrid is hard](14-why-hybrid-is-hard.md) | Ranked confusion points with evidence and the site's fix for each | | 15 | [Timeline](15-timeline.md) | Launches from 2009 to 2026 | | 16 | [Glossary](16-glossary.md) | Terms with official Japanese names and what each is confused with | + +## Direct Connect deep dive + +[direct-connect/](direct-connect/README.md) holds the research notes behind the site's second page, the Direct Connect deep dive (`direct-connect/` on the site). They were the separate 0-draft/cross-connect repository until 2026-11-08. [direct-connect/10-pricing.md](direct-connect/10-pricing.md) is the only Direct Connect price list in this repository; the other pages link to it. diff --git a/docs/direct-connect/01-overview.md b/docs/direct-connect/01-overview.md new file mode 100644 index 0000000..e383acf --- /dev/null +++ b/docs/direct-connect/01-overview.md @@ -0,0 +1,145 @@ +# AWS Direct Connect Overview + +AWS Direct Connect (DX) links your internal network to a Direct Connect location over a standard Ethernet fiber-optic cable, so you can reach AWS public services and your VPCs without going through internet service providers. This page explains what DX is, its building blocks, when to pick it over Site-to-Site VPN or the internet, and what changed between 2023 and 2026. Facts were verified against AWS documentation and What's New posts as of 2026-10-12. + +## What Direct Connect is + +One end of the cable plugs into your router (or your partner's router) and the other into an AWS Direct Connect router in a colocation facility called a *Direct Connect location*. Over that physical link you create *virtual interfaces* (VIFs), which are 802.1Q VLANs carrying BGP sessions to AWS. + +- A Direct Connect location gives you access to AWS in the Region it is associated with. +- A single connection in a public Region or AWS GovCloud (US) can reach public AWS services in all other public Regions (China excluded). +- With a Direct Connect gateway, one connection can reach VPCs in any public Region (China excluded). Traffic stays on the AWS global backbone. + +```mermaid +flowchart LR + subgraph OnPrem["Customer premises"] + R1["Customer router"] + end + subgraph DXL["Direct Connect location (colocation facility)"] + CR["Customer / partner cage"] + AWSR["AWS Direct Connect router"] + CR -- "Cross connect (single-mode fiber)" --- AWSR + end + subgraph AWS["AWS Region"] + VGW["Virtual private gateway / DX gateway / Transit gateway"] + PUB["Public AWS services (S3, etc.)"] + end + R1 -- "Carrier circuit (Metro Ethernet, dark fiber, wavelength, MPLS)" --- CR + AWSR -- "Private / transit VIF" --> VGW + AWSR -- "Public VIF" --> PUB +``` + +## Components + +| Component | What it is | Details | +| --- | --- | --- | +| Direct Connect location | A colocation facility where AWS has DX routers | Over 150 locations worldwide (per 2026 What's New posts). See [02-connections.md](02-connections.md). | +| Connection | A physical Ethernet port on an AWS DX router | Dedicated (1/10/100/400 Gbps) or hosted (50 Mbps to 25 Gbps) | +| Cross connect | The fiber patch between your (or your provider's) equipment and the AWS port | Ordered from the colocation provider using the LOA-CFA | +| LOA-CFA | Letter of Authorization and Connecting Facility Assignment | AWS issues it; it authorizes the cross connect to a specific patch panel port | +| Link aggregation group (LAG) | Several dedicated connections bundled with LACP | See [03-lag-and-macsec.md](03-lag-and-macsec.md) | +| Virtual interface (VIF) | A VLAN plus BGP session on a connection | Private (to a VPC or DX gateway), public (to AWS public IPs), transit (to Transit Gateway or Cloud WAN through a DX gateway) | +| Direct Connect gateway | A global object that lets private/transit VIFs reach VPCs or transit gateways in many Regions and accounts | Not available for China Regions | +| MACsec | IEEE 802.1AE Layer 2 encryption on the cross connect | 10/100/400 Gbps dedicated connections at select locations | + +## Direct Connect vs Site-to-Site VPN vs internet + +AWS positions Direct Connect for dedicated, private network connections, and Site-to-Site VPN for an "immediate need, low to modest bandwidth requirements", where you "can tolerate the inherent variability of internet-based connectivity" (DX FAQ). Many designs use both: VPN as a backup path, or IPsec VPN on top of DX (Private IP VPN on a transit VIF) when you need encryption above Layer 2. + +| Aspect | Direct Connect | Site-to-Site VPN | Plain internet | +| --- | --- | --- | --- | +| Transport | Private fiber to a DX location, then the AWS backbone | IPsec tunnels over the internet (or over DX) | Public internet | +| Bandwidth | Dedicated 1, 10, 100, 400 Gbps; hosted 50 Mbps to 25 Gbps; LAG up to 4 x 10G or 2 x 400G | Up to 1.25 Gbps per standard tunnel, up to 5 Gbps per Large Bandwidth Tunnel (Transit Gateway or Cloud WAN only, launched Nov 2025) | Best effort | +| Latency / jitter | Consistent, provisioned path | Varies with internet conditions | Varies | +| Time to deploy | Days to weeks: port provisioning (up to 72 business hours), then cross connect and carrier circuit | Minutes | Immediate | +| Encryption | Not encrypted by default; add MACsec (L2) or IPsec VPN over DX | IPsec built in | TLS at application layer | +| Cost model | Port hours plus data transfer out at DX rates (flat-rate option since Sep 2026) | Per connection hour plus internet DTO | Internet DTO | +| SLA | Up to 99.99% with the Maximum Resiliency model | Separate VPN SLA | None | + +```mermaid +flowchart TD + A["Need private hybrid connectivity to AWS"] --> B{"Need it today, low to modest bandwidth, can tolerate internet variability?"} + B -- Yes --> VPN["Site-to-Site VPN (optionally as DX backup)"] + B -- No --> C{"Have equipment in a DX location, or need 1 Gbps+ dedicated port?"} + C -- Yes --> DED["Dedicated connection (1/10/100/400 Gbps)"] + C -- No --> HOST["Hosted connection via a Direct Connect Delivery Partner (50 Mbps to 25 Gbps)"] + DED --> ENC{"Need encryption?"} + HOST --> ENC + ENC -- "L2 on the cross connect (dedicated 10/100/400G)" --> MAC["MACsec"] + ENC -- "End to end / hosted" --> IPSEC["IPsec VPN over DX (Private IP VPN on transit VIF)"] +``` + +## Resiliency models and SLA + +The Direct Connect Resiliency Toolkit (the "Connection wizard" in the console) orders the right number of dedicated connections for a target SLA. + +| Model | Topology | SLA | +| --- | --- | --- | +| Maximum Resiliency | Separate connections terminating on separate devices in more than one location | 99.99% | +| High Resiliency | Connections in multiple locations | 99.9% | +| Development and Test | Separate connections on separate devices in one location | Not specified (for non-critical workloads) | +| Classic | One-at-a-time ordering without the toolkit | 95%, no resiliency or redundancy | + +Buildings that together form one Direct Connect location (for example Equinix DC2/DC11, or the Equinix SE2 and Digital Realty SEA10 sub-locations in one Seattle building) do not provide location-level diversity, so for high availability use different locations. Source: the footnotes on . + +## Pricing basics + +- Two billing elements: port hours and data transfer out (DTO). Data transfer into AWS is free. +- Port-hour price depends on capacity and connection type (dedicated or hosted). +- Dedicated connection billing starts when the port becomes active or 90 days after the LOA-CFA is issued, whichever comes first. +- Hosted connection port hours are billed once you accept the hosted connection. +- Flat-rate pricing (announced September 2026): for 10G and 100G dedicated connections, a fixed hourly rate by bandwidth and geographic tier (five tiers from same-metro to global) with no DTO within the tier. A "port-pair" includes a redundant second dedicated connection at no additional charge. You can switch billing modes at any time. Not available in China Regions. + +## Recent changes (2023 to 2026) + +| Date | Change | Layer | +| --- | --- | --- | +| 2024-04-24 | Hosted connections up to 25 Gbps (select partners, only where 100G ports exist) | Connection | +| 2024-07-01 | Native 400 Gbps dedicated connections at select locations (400GBASE-LR4) | Connection | +| Undated (current docs) | MACsec documented for 400 Gbps dedicated connections (GCM-AES-XPN-256); the 400G launch post of 2024-07-01 did not mention MACsec, and the locations page now marks all 400G sites with (M) | Connection | +| 2025-07 | MACsec extended to partner-owned interconnects at 100+ PoPs | Connection | +| 2025 to 2026 | Steady location growth: e.g. Barcelona (2025-08), Auckland, Nairobi, Madrid MAD3 (2025-09), Hanoi (2025-12, first in Vietnam), Sydney SY5 (2026-03); 100G expansions in Chennai, Kansas City, Makati, Auckland, Lima | Locations | +| 2025-11 | AWS Interconnect - last mile (Lumen) gated preview; GA 2026-04; AT&T gated preview 2026-06 | Adjacent product | +| 2025-11 | AWS Interconnect - multicloud preview; GA 2026-04-13; free 500 Mbps tier 2026-05 | Adjacent product | +| 2025-12 | Resilience testing of DX BGP failover with AWS Fault Injection Service | Operations | +| 2026-03 | AWS CloudFormation support for DX resources (connections, VIFs, DX gateways, LAGs) | Operations | +| 2026-06 | VIF Rate Limiters on dedicated connections (up to 10 per connection, 50 Mbps to 1.6 Tbps) | Connection / VIF | +| 2026-07 | BGP route visibility on VIFs (ListVirtualInterfaceRoutes) | Routing | +| 2026-08 | Inbound prefix controls; max prefixes per private/transit VIF raised from 100 to 1,000 per address family | Routing | +| 2026-09 | Flat-rate pricing and port-pairs for 10G/100G dedicated connections | Billing | + +Deprecation note: AWS no longer allows new Direct Connect Partner service integrations using hosted VIFs, because a hosted VIF shares an oversubscribable partner link (see [02-connections.md](02-connections.md)). No deprecation of dedicated or hosted connection speeds was found. + +## Sources + +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- diff --git a/docs/direct-connect/02-connections.md b/docs/direct-connect/02-connections.md new file mode 100644 index 0000000..45edc53 --- /dev/null +++ b/docs/direct-connect/02-connections.md @@ -0,0 +1,249 @@ +# Direct Connect Connections, Locations, and Ordering + +This page covers the physical and connection layer of AWS Direct Connect: dedicated vs hosted connections, hosted connections vs hosted VIFs, Direct Connect locations and how they map to Regions, the LOA-CFA and cross connect workflow with its timelines, physical requirements (optics, fiber, auto-negotiation, VLANs, BGP, BFD, MTU), and the quotas that apply to connections. Verified against AWS documentation as of 2026-10-12. + +## Connection types + +| Type | Speeds | Who orders it | Physical port | VIFs per connection | +| --- | --- | --- | --- | --- | +| Dedicated connection | 1, 10, 100, 400 Gbps | You, via console, CLI, API (or a partner on your behalf) | Single customer's physical Ethernet port on an AWS DX router | Up to 50 private/public + up to 4 transit, 51 total | +| Hosted connection | 50, 100, 200, 300, 400, 500 Mbps; 1, 2, 5, 10, 25 Gbps | An AWS Direct Connect Delivery Partner provisions it; you accept it | Capacity carved out of the partner's interconnect | 1 (private, public, or transit) | + +### Dedicated connections + +- Port speed is fixed at order time. To change it, create and configure a new connection. +- Order through the Connection wizard (Resiliency Toolkit, recommended for first-time setups) or Classic (one connection at a time). +- A connection created in a LAG inherits the LAG's port speed and location. +- The network provider that builds the circuit to the location does not have to be an AWS Direct Connect Partner. +- MACsec is available on 10, 100, and 400 Gbps dedicated connections at select locations (see [03-lag-and-macsec.md](03-lag-and-macsec.md)). +- VIF Rate Limiters (June 2026) are supported only on dedicated connections: up to 10 rate limiters per connection (quota adjustable), bandwidth steps from 50 Mbps up to 1.6 Tbps depending on the connection or LAG capacity. + +### Hosted connections + +- You cannot request a hosted connection in the Direct Connect console. A partner creates it, it appears under **Connections**, and you must **Accept** it before creating a VIF. +- Only partners who meet specific requirements can create 1, 2, 5, 10, or 25 Gbps hosted connections. +- 25 Gbps hosted connections were announced 2024-04-24 and exist only at locations where 100 Gbps ports are available. Before that, the hosted maximum was 10 Gbps. +- Only the partner can change the speed. If the partner supports upgrade/downgrade, you do not need to delete and recreate the connection. +- AWS polices traffic on hosted connections: traffic above the configured rate is dropped, so bursty traffic can see lower throughput than smooth traffic. +- Jumbo frames work only if they were enabled on the partner's parent connection. +- MACsec is not supported on hosted connections (the partner's interconnect can use MACsec, see below). +- Billing: port hours start once you accept the hosted connection. + +### Hosted connection vs hosted VIF + +| Aspect | Hosted connection | Hosted VIF | +| --- | --- | --- | +| What you get | A connection with its own AWS-enforced capacity (policed) | A VIF on someone else's connection (another account's dedicated connection or a partner link) | +| Capacity | Fixed purchased bandwidth, 50 Mbps to 25 Gbps | No capacity assigned by AWS; shares all available capacity of the owner's link | +| Oversubscription risk | Low, AWS polices per connection | Possible, AWS does not limit per-VIF traffic | +| Status for partners | Recommended model | AWS no longer allows new partner service integrations using hosted VIFs | +| Typical use | Sub-1G to 25G access via a partner | Sharing your own dedicated connection with another of your accounts | + +A hosted VIF works like a standard VIF: the other account must accept it, and it can be private, public, or transit. Transit VIFs work on dedicated or hosted connections of any speed. + +### Partner interconnects + +Direct Connect Delivery Partners own *interconnects* (physical connections or LAGs) from which they carve hosted connections. Since July 2025, partners can enable MACsec on supported 10 Gbps and 100 Gbps interconnects at over 100 PoPs, encrypting the link between their edge device and the AWS device. + +## Direct Connect locations + +A Direct Connect location is a colocation facility (for example Equinix, CoreSite, Digital Realty, AT Tokyo) where AWS operates DX routers. AWS What's New posts in 2026 cite "over 150" locations worldwide. + +### How locations map to Regions + +- Each location is associated with one "home" AWS Region; the cross connect tables in the User Guide are grouped by that Region (for example Equinix TY2 under Asia Pacific (Tokyo)). +- From any location in a public Region or GovCloud (US) you can reach public services in every other public Region with a public VIF, and VPCs in any public Region with a Direct Connect gateway. China (Beijing, Ningxia) is excluded. +- Data transfer out of a remote Region is billed at that remote Region's DX data transfer rate. +- AWS advises choosing the location and Region closest to your on-premises infrastructure to minimize cost, management overhead, and latency. +- Some locations span several buildings or sub-locations (for example Equinix DC2/DC11, where the LOA names whichever building has capacity). The locations page states that such sub-locations "do not provide location-level diversity for maximum resiliency configurations". +- Some locations have meet-me rooms on multiple floors; the console then offers a **Sub Location** (floor) choice. + +### Speeds per location + +The locations page lists each site's speeds in an "Available as" column and marks MACsec support per speed with "(M)". Examples as of 2026-10-12: + +| Location | Available as | +| --- | --- | +| Equinix DC2/DC11, Ashburn, VA | 1G, 10G (M), 100G (M), 400G (M) | +| Equinix CH2, Chicago, IL | 1G, 10G (M), 100G (M), 400G (M) | +| CoreSite VA1, Reston, VA | 1G, 10G (M), 100G (M), 400G (M) | +| Equinix SV5, San Jose, CA | 1G, 10G (M), 100G (M), 400G (M) | +| Digital Realty SEA10, Seattle, WA | 1G, 10G (M), 100G (M), 400G (M) | +| Equinix TY2, Tokyo | 1G, 10G (M), 100G (M) | +| AT Tokyo CC1 Chuo Data Center, Tokyo | 1G, 10G (M), 100G (M) | +| NEC Inzai, Inzai | 1G, 10G (M), 100G (M) | +| Equinix OS1, Osaka | 1G, 10G (M), 100G (M) | +| Telehouse Osaka 2, Osaka | 1G, 10G (M), 100G (M) | + +The 400G sites listed on the locations page are all in the United States: CoreSite CH1 and Equinix CH2 (Chicago), 165 Halsey Street (Newark), CoreSite VA1 (Reston), Equinix DC2/DC11 (Ashburn), Equinix DA2 (Dallas), CoreSite SV4 (Santa Clara), Equinix SV5 (San Jose), EdgeConneX PHX01 (Phoenix), and Digital Realty SEA10 (Seattle). + +### Recent location launches and expansions + +| Date | Location | Speeds | +| --- | --- | --- | +| 2025-01 | Equinix MX1, Querétaro, Mexico (new) plus MACsec at KIO Networks Querétaro | 10G, 100G with MACsec | +| 2025-06 | Chief Telecom HD, Taipei (third in Taiwan) | 10G, 100G with MACsec | +| 2025-07 | STT Chennai, India (100G expansion) | 100G with MACsec | +| 2025-08 | Equinix BA1, Barcelona (first in Barcelona) | 10G, 100G with MACsec | +| 2025-09 | Spark Digital MDR, Auckland; EADC NBO1, Nairobi (first in Kenya); Digital Realty MAD3, Madrid; Rack Centre LGS1, Lagos (100G expansion) | 10G, 100G with MACsec | +| 2025-10 | Netrality KC1, Kansas City and ePLDT Makati, Philippines (100G expansions) | 10G, 100G with MACsec | +| 2025-12 | Hanoi, Vietnam (first in Vietnam) | 1G, 10G, 100G; MACsec on 10G/100G | +| 2026-03 | Equinix SY5, Sydney (tenth in Australia) | 10G, 100G with MACsec | +| 2026-04 | Datacom Orbit DH6, Auckland (100G expansion) | 100G with MACsec | +| 2026-07 | Cirion, Lima, Peru (100G expansion, first 100G/MACsec in Peru) | 100G with MACsec | + +## Connectivity options to reach a location + +| Option | How it works | Who runs BGP with AWS | +| --- | --- | --- | +| Colocated | Your equipment is already in the DX facility; the facility provides a cross connect using your LOA-CFA | Your router | +| Layer 2 extension | A partner extends the port to your site over Metro Ethernet, dark fiber, or wavelength | Your router at your site | +| Layer 3 extension | A partner router in the DX location peers with AWS, then with you (for example over MPLS) | Partner router (you peer with the partner) | +| Hosted connection | Partner provisions capacity on its interconnect | Your router over the partner's L2 service | + +## Ordering workflow (dedicated connection) + +```mermaid +sequenceDiagram + autonumber + participant C as Customer + participant AWS as AWS Direct Connect + participant P as Colocation / network provider + C->>AWS: Create connection (location, port speed, provider, optional MACsec request) + AWS-->>C: Review and port provisioning (up to 72 business hours) + AWS-->>C: Possible email asking for more info (reply within 7 days or request is deleted) + AWS-->>C: LOA-CFA available for download (signed, watermarked PDF) + C->>P: Send LOA-CFA and order cross connect (and carrier circuit if not colocated) + P-->>C: Cross connect completion notice + Note over C,AWS: Link comes up (L1). Billing starts at port active or 90 days after LOA issue, whichever first + C->>AWS: Create VIF (VLAN, BGP ASN, peer IPs, MTU) + C->>AWS: Download router config and bring up BGP +``` + +### Step details and timelines + +1. Request the connection in the console (Connection wizard or Classic), CLI (`create-connection`), or API. Provide location, optional sub location, port speed, and service provider. +2. AWS reviews the request and provisions a port. This can take up to 72 business hours. If you get an email asking for more information, reply within 7 days or the connection is deleted. +3. Download the LOA-CFA. It is a digitally signed and watermarked PDF naming the patch panel and strands assigned. If the download link is not enabled after 72 business hours and you got no email, contact AWS Support. +4. Give the LOA-CFA to your colocation provider (if you have equipment there, you must be their customer) or to your partner/network provider, who orders the cross connect. You cannot order a cross connect yourself at a location where you have no equipment. +5. The LOA-CFA authority expires if the cross connect is not completed within 90 days; download it again to renew. +6. Billing starts when the port is active or 90 days after the LOA is issued, whichever comes first. Delete the port before activation or within those 90 days to avoid charges. If the connection is still not up after 90 days, AWS emails that the port will be deleted in 10 days. +7. Once the link is up, create VIFs, download the router configuration, and verify BGP. + +For LAGs, you download one LOA-CFA per new physical connection. + +### Hosted connection workflow + +```mermaid +flowchart LR + A["Choose a Direct Connect Delivery Partner"] --> B["Partner provisions hosted connection in your account (speed, VLAN)"] + B --> C["Accept the hosted connection in the console"] + C --> D["Port hours billing starts"] + D --> E["Create one VIF (VLAN given by partner)"] + E --> F["Bring up BGP"] +``` + +## Physical and link requirements + +| Requirement | Value | +| --- | --- | +| Fiber | Single-mode fiber | +| 1 Gbps optic | 1000BASE-LX (1310 nm) | +| 10 Gbps optic | 10GBASE-LR (1310 nm) | +| 100 Gbps optic | 100GBASE-LR4 | +| 400 Gbps optic | 400GBASE-LR4 | +| Auto-negotiation | Must be disabled for ports faster than 1 Gbps; for 1 Gbps it may need to be enabled or disabled depending on the AWS endpoint. If disabled, set speed and full duplex manually | +| VLAN | 802.1Q encapsulation must be supported end to end, including intermediate devices; VLAN IDs 1 to 4094, not modifiable after VIF creation | +| Routing | BGP with MD5 authentication is required | +| BFD | Optional; asynchronous BFD is enabled on the AWS side of every VIF and takes effect once you configure it on your router | +| IP | IPv4 and IPv6 (dual-stack BGP per VIF) | +| Frame size | 1522 or 9023 bytes at the link layer (14 B Ethernet header + 4 B VLAN tag + IP datagram + 4 B FCS) | +| MACsec (optional) | MACsec-capable device on your side, see [03-lag-and-macsec.md](03-lag-and-macsec.md) | + +### MTU + +| VIF type | Standard MTU | Jumbo MTU | +| --- | --- | --- | +| Private VIF | 1500 | 9001 | +| Transit VIF | 1500 | 8500 | +| Public VIF | 1500 | Not offered (the MTU setting is documented only for private and transit VIFs) | + +- Enabling jumbo MTU can trigger an update of the underlying connection, which disrupts all VIFs on it for up to 30 seconds. Check **Jumbo Frame Capable** on the connection or VIF summary. +- A jumbo VIF can only be associated with a jumbo-capable connection or LAG. +- If two private VIFs advertise the same route with different MTUs, or a Site-to-Site VPN advertises the same route, 1500 is used. +- Jumbo frames on Transit Gateway support only 8500 bytes. + +### Optical light levels (CloudWatch) + +`ConnectionLightLevelTx` and `ConnectionLightLevelRx` should be within -14.4 to 2.50 dBm for 1 and 10 Gbps. For 100 Gbps, keep Tx between -4.3 and 4.5 dBm and Rx between -10.6 and 4.5 dBm. 100 and 400 Gbps optics have four lanes, each to be checked. + +### Layer 1 troubleshooting checklist + +```mermaid +flowchart TD + S["Connection down"] --> A["Cross connect complete? Ports match LOA-CFA?"] + A --> B["Router powered on, port enabled?"] + B --> C["Correct optic (LX / LR / LR4) on single-mode fiber?"] + C --> D["Auto-negotiation off above 1G; speed/duplex set manually"] + D --> E["Acceptable optical signal? Try rolling Tx/Rx strands"] + E --> F["Check CloudWatch light levels and error counts"] + F --> G["Ask colo for Tx/Rx report, then open AWS Support case"] +``` + +## Quotas relevant to connections + +| Quota | Value | Adjustable | +| --- | --- | --- | +| Private or public VIFs per dedicated connection | 50 | No | +| Transit VIFs per dedicated connection | 4 | Contact SA/TAM | +| Total VIFs per dedicated connection | 51 | No | +| VIFs per hosted connection | 1 | No | +| Active connections per location per Region per account | 10 | Contact SA/TAM | +| VIFs per LAG | 51 | No | +| Dedicated connections per LAG | 4 below 100G; 2 at 100G or 400G | No | +| LAGs per Region | 10 | Contact SA/TAM | +| Rate limiters per dedicated connection | 10 | Yes | +| Routes per BGP session, private/transit VIF (on-premises to AWS) | 100 per family by default; up to 1,000 per family with prefix controls (Aug 2026) | Via prefix controls | +| Routes per BGP session, public VIF | 1,000 | No | + +## Sources + +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- diff --git a/docs/direct-connect/03-lag-and-macsec.md b/docs/direct-connect/03-lag-and-macsec.md new file mode 100644 index 0000000..581a8da --- /dev/null +++ b/docs/direct-connect/03-lag-and-macsec.md @@ -0,0 +1,169 @@ +# Direct Connect LAG and MACsec + +This page covers link aggregation groups (LAGs) and MAC Security (MACsec) on AWS Direct Connect: LACP behavior, member limits, the minimum-links attribute, MACsec supported speeds and connection types, CKN/CAK keys, cipher suites, encryption modes, key rotation, and how MACsec interacts with LAGs. Verified against AWS documentation as of 2026-10-12. + +## Link aggregation groups (LAGs) + +A LAG is a logical interface that uses the Link Aggregation Control Protocol (LACP) to aggregate multiple dedicated connections at a single Direct Connect endpoint so you can manage them as one connection. The LAG configuration (VIFs, MACsec key) applies to all members. + +### LAG rules + +| Rule | Value | +| --- | --- | +| Member type | Dedicated connections only (1, 10, 100, or 400 Gbps) | +| Member speed | All members must use the same bandwidth | +| Max members, below 100G (1G, 10G) | 4 | +| Max members, 100G or 400G | 2 | +| Termination | All members must terminate on the same Direct Connect endpoint (same AWS device, same location) | +| Multi-chassis LAG (MLAG) | Not supported by AWS | +| Forwarding mode | All members operate Active/Active | +| VIF types | Public, private, and transit | +| VIFs per LAG | 51 (up to 4 transit) | +| LAGs per Region | 10 (contact SA/TAM to raise) | +| Connection quota | Each member counts toward the per-Region connection limit | + +Maximum aggregate bandwidth therefore is 4 x 1 Gbps = 4 Gbps, 4 x 10 Gbps = 40 Gbps, 2 x 100 Gbps = 200 Gbps, or 2 x 400 Gbps = 800 Gbps per LAG. + +### Minimum links attribute + +Every LAG has a minimum number of operational connections required for the LAG itself to be operational. New LAGs default to 0. If you set a higher value, the whole LAG goes down when operational members drop below it, which prevents the remaining links from being overloaded and pushes traffic to a redundant path instead. + +```mermaid +flowchart LR + subgraph LOC1["Direct Connect location A (one AWS endpoint)"] + D1["AWS DX device"] + end + subgraph CUST["Customer router"] + R["Port-channel (LACP)"] + end + R == "10G member 1" ==> D1 + R == "10G member 2" ==> D1 + R == "10G member 3" ==> D1 + R == "10G member 4" ==> D1 + D1 --> V["VIFs defined once on the LAG"] + N["minimumLinks = 3: LAG goes down if fewer than 3 members are up"] -.-> R +``` + +### LAG operations + +- Create a LAG from existing connections or provision new ones. You can later associate standalone connections, or connections from another LAG. +- A connection created for a LAG inherits the LAG's port speed and location. +- You download a separate LOA-CFA for each new physical connection. +- AWS may not be able to guarantee enough free ports on a given endpoint when you create or grow a LAG. +- VIF Rate Limiters are LAG-aware: on a 2 x 1 Gbps LAG you can set limits from 50 Mbps up to 2 Gbps. + +## MACsec + +MACsec (IEEE 802.1AE) provides data confidentiality, data integrity, and data origin authenticity at Layer 2. On Direct Connect it encrypts the point-to-point link between your MACsec-capable edge device and the AWS Direct Connect device. The two must have direct Layer 2 adjacency, so MACsec is hop-by-hop: it is not end-to-end encryption across multiple network segments. If your router sits in the colo, that hop is just the cross connect, and any carrier circuit from the colo to your site is a separate, unencrypted segment. A carrier circuit is inside the MACsec hop only when your MACsec device is at your end and the carrier passes Ethernet frames through transparently at Layer 2. AWS additionally encrypts data at the physical layer as it flows between Direct Connect locations and AWS Regions. + +```mermaid +flowchart LR + A["Option 1: MACsec router in the colo"] -- "Cross connect: MACsec (L2)" --- B["AWS Direct Connect device"] + S["Option 2: MACsec router at your site"] -- "L2-transparent carrier circuit + cross connect: one MACsec hop" --- B + B -- "AWS backbone (physical-layer encryption by AWS)" --- C["AWS Region"] +``` + +### Where MACsec is supported + +| Connection type | MACsec | +| --- | --- | +| Dedicated 1 Gbps | Not supported | +| Dedicated 10 Gbps | Supported at select locations | +| Dedicated 100 Gbps | Supported at select locations | +| Dedicated 400 Gbps | Supported at select locations | +| LAG | Supported if all members are MACsec-capable dedicated connections of the same speed | +| Partner interconnect | Supported on supported 10G/100G interconnects (since July 2025, 100+ PoPs) | +| Hosted connection | Not supported | + +MACsec-capable speeds are marked "(M)" on the Direct Connect locations page. There is no additional charge for MACsec. The connection must be transparent to Layer 2 traffic, and the device terminating the Layer 2 adjacency must support MACsec. If you use a last-mile provider, check with them that the circuit can carry MACsec. + +### Timeline + +| Date | Change | +| --- | --- | +| 2021-03 | MACsec launched for 10 Gbps and 100 Gbps dedicated connections at select locations | +| 2024-07-01 | 400 Gbps dedicated connections launched (launch post did not mention MACsec) | +| Current docs | MACsec supported on 400 Gbps dedicated connections with GCM-AES-XPN-256; all 400G sites on the locations page show (M) | +| 2025-07 | MACsec extended to partner-owned interconnects | +| 2025 to 2026 | New locations and 100G expansions routinely launch with MACsec on 10G/100G | + +### Cipher suites and prerequisites + +| Speed | Cipher suites | XPN | +| --- | --- | --- | +| 10 Gbps | GCM-AES-256 or GCM-AES-XPN-256 | Optional | +| 100 Gbps | GCM-AES-XPN-256 | Required | +| 400 Gbps | GCM-AES-XPN-256 | Required | + +- Only 256-bit keys (AES-256) are supported. +- Extended Packet Numbering (XPN, IEEE 802.1AEbw-2013) extends the packet number from 32 to 64 bits. Without it, 100G and 400G links would exhaust the packet number space and need key rotation every few minutes. +- Secure Channel Identifier (SCI) must be turned on; it cannot be changed. +- 802.1Q tag offset (dot1q-in-clear) is not supported, so the VLAN tag cannot be moved outside the encrypted payload. +- Request MACsec when creating the connection (`aws directconnect create-connection ... --request-mac-sec`). Check `DescribeConnections` or the console to see whether an existing connection is MACsec-capable. + +### Keys: CKN, CAK, and SAK + +| Key | Role | Details | +| --- | --- | --- | +| CKN (Connectivity Association Key Name) | Names the pre-shared key | 64 hexadecimal characters; you generate it | +| CAK (Connectivity Association Key) | Pre-shared long-term key | 64 hexadecimal characters (AES-256); you generate it | +| SAK (Secure Association Key) | Session key used to encrypt traffic | Derived automatically from the CKN/CAK at both ends; never pre-shared or stored persistently | + +- Only static CAK mode is supported; dynamic CAK mode (802.1X/EAP-based) is not. +- Associate the pair with `associate-mac-sec-key`, either by passing `--ckn` and `--cak` or by referencing an existing AWS Secrets Manager secret with `--secret-arn`. The same pair must be configured on your router. +- AWS stores the CKN/CAK as a Secrets Manager secret encrypted with an AWS managed key. The secret is read-only; you cannot modify an associated key, only disassociate it and associate a new one. +- Scheduling deletion of the secret (7 to 30 days) makes the CKN unreadable. For a pending connection AWS disassociates it; for an available connection AWS emails the owner and disassociates after 30 days without action. If the last CKN is removed while the mode is must_encrypt, AWS switches the mode to should_encrypt to prevent sudden packet loss. +- AWS recommends TLS 1.3 with a post-quantum key exchange such as ML-KEM when sending new CKN/CAK pairs through the console, CLI, or SDK. + +### Encryption modes + +| Mode | Behavior | Trade-off | +| --- | --- | --- | +| should_encrypt (default for new MACsec connections) | Tries to establish MACsec; falls back to unencrypted traffic if negotiation fails | Higher availability, possible cleartext during failures | +| must_encrypt | Transmits nothing unless MACsec is established | Strongest guarantee, outage if MACsec breaks | + +The mode can be set at configuration time and changed later. + +### Key rotation + +- CKN/CAK (manual): the keychain holds up to three CKN/CAK pairs. Associate a new pair and configure it on your device; the AWS device tries the most recently added key and falls back to the previous working key if it does not match, so rotation is hitless. +- SAK (automatic): rotated by the protocol based on time intervals, volume of encrypted traffic, and session establishment, without disruption. + +```mermaid +sequenceDiagram + autonumber + participant Op as Operator + participant DX as AWS DX device + participant R as Customer router + Op->>DX: associate-mac-sec-key (new CKN/CAK, keychain up to 3) + Op->>R: Configure same CKN/CAK + DX->>R: MKA with newest key + alt Keys match + R-->>DX: Session up with new key, SAK derived + else Mismatch + DX->>R: Fall back to previous working key + end + Note over DX,R: SAK auto-rotates by time, traffic volume, and session setup +``` + +### MACsec on LAGs + +- All LAG members must be MACsec-capable dedicated connections of the same bandwidth; MACsec configuration applies uniformly to every member. +- You can create the LAG and enable MACsec at the same time. +- Only one MACsec key is in use across all LAG links at any time; multiple keys exist only for rotation. +- Creating a LAG from existing connections, or associating a connection with a LAG, removes the connections' own MACsec keys and applies the LAG's key. + +## Sources + +- +- +- +- +- +- +- +- +- +- +- +- diff --git a/docs/direct-connect/04-virtual-interfaces.md b/docs/direct-connect/04-virtual-interfaces.md new file mode 100644 index 0000000..c62d5f2 --- /dev/null +++ b/docs/direct-connect/04-virtual-interfaces.md @@ -0,0 +1,222 @@ +# Virtual Interfaces (VIFs) + +A Direct Connect connection is only a Layer 1/Layer 2 pipe. Traffic flows only after you create one or more virtual interfaces (VIFs) on it. Each VIF is an 802.1Q VLAN plus an eBGP session between your router and AWS. There are three types: private (to VPCs), public (to AWS public endpoints), and transit (to Transit Gateways or AWS Cloud WAN through a Direct Connect gateway). This page covers what each type reaches, the BGP and addressing parameters, MTU, hosted VIFs, per-connection limits, and the 2025–2026 changes: 4-byte ASNs, CloudWatch BGP metrics, BGP route visibility, and inbound prefix controls. + +_Last verified: 2026-10-12_ + +## The three VIF types at a glance + +| | Private VIF | Public VIF | Transit VIF | +| --- | --- | --- | --- | +| Reaches | VPC private IPs | All AWS public IP prefixes (for example S3, EC2 public IPs, API endpoints), in every public Region | VPCs and VPNs attached to Transit Gateways, or an AWS Cloud WAN core network | +| Attaches to | A virtual private gateway (VGW, same Region only) or a Direct Connect gateway (DXGW) | Nothing (no gateway). A public VIF cannot attach to a DXGW | A DXGW only | +| AWS-side ASN | The VGW ASN (direct attach) or the DXGW ASN | 7224 | The DXGW ASN | +| Peer IPs | Any valid range. AWS can generate private IPv4 | Public IPv4 that you own, or a /31 provided by AWS through a support case | Any valid range | +| Inbound prefix limit (from you) | 100 per address family by default, up to 1,000 with prefix controls (Aug 2026) | 1,000 (cannot be increased) | 100 per address family by default, up to 1,000 with prefix controls | +| Max MTU | 9001 | 1500 | 8500 | +| SiteLink | Yes, only when attached to a DXGW | No | Yes | +| Per dedicated connection | 50 private + public combined | Counted in the 50 | 4 (counted within the total of 51) | + +```mermaid +flowchart LR + CGW[Customer router] ---|"802.1Q VLAN + eBGP"| DX[(DX connection)] + DX --> PVIF[Private VIF] + DX --> PUB[Public VIF] + DX --> TVIF[Transit VIF] + PVIF --> VGW[Virtual private gateway
same Region VPC] + PVIF --> DXGW1[Direct Connect gateway] + DXGW1 --> VGW2[VGWs in any Region/account] + PUB --> AWSPUB[AWS public prefixes
all public Regions] + TVIF --> DXGW2[Direct Connect gateway] + DXGW2 --> TGW[Transit Gateways] + DXGW2 --> CWAN[Cloud WAN core network] +``` + +### Private virtual interface + +- Used to reach an Amazon VPC with private IP addresses. +- Attached directly to a VGW, a private VIF reaches one VPC in the Region associated with the Direct Connect location. +- Attached to a DXGW, it reaches VGWs in any account and any Region, except the AWS China Regions. +- Jumbo frames (MTU 9001) are supported whether the VIF attaches to a VGW or to a DXGW. + +### Public virtual interface + +- Reaches all AWS public services on public IP addresses, globally. AWS advertises local and remote Region prefixes plus on-net prefixes from non-Region PoPs such as CloudFront and Route 53. +- You do not reach non-Amazon prefixes. It is not an internet transit service. +- Prefixes announced over BGP can be aggregated or de-aggregated relative to `ip-ranges.json`. BYOIP ranges that you bring to AWS are advertised even though they are not in the JSON file. +- AWS does not re-advertise customer prefixes received on a public VIF outside the AWS network. Those prefixes are visible to all AWS customers, so AWS recommends a firewall filter. +- Accelerated Site-to-Site VPN cannot run over a public VIF. + +### Transit virtual interface + +- Must attach to a DXGW. That DXGW is then associated with up to 6 Transit Gateways, or with a single AWS Cloud WAN core network segment (native attachment since 2024-11-25). +- Supported on dedicated and hosted connections of any speed. +- MTU 1500 or 8500. +- Transit VIF is the transport for Private IP Site-to-Site VPN over DX (see [06-bgp-and-routing.md](06-bgp-and-routing.md)). + +## Parameters required to create a VIF + +| Parameter | Detail | +| --- | --- | +| Connection | A dedicated connection, a hosted connection, or a LAG | +| Owner | Your account, or another account ID. That makes it a hosted VIF | +| VLAN | 1–4094, 802.1Q, unique on the connection. It cannot be changed after creation. On hosted connections the Partner provides it | +| Address family | IPv4, IPv6, or both. One BGP session per address family per VIF, so dual-stack means two sessions | +| IPv4 peer IPs | Your IP and the AWS router IP, with the same subnet mask on both. /31 (RFC 3021) is supported on all VIF types | +| IPv6 peer IPs | Amazon always allocates a /125. You cannot choose them | +| Customer ASN | Public (you must own it) or private. 2-byte private range 64512–65534. Long ASNs up to 4,294,967,294 have been supported since 2025 | +| BGP auth | MD5 is always on and cannot be disabled. You supply the key or AWS generates one | +| Prefixes to advertise (public VIF only) | At least 1, at most 1,000. IPv4 /1–/32, IPv6 /1–/64 | +| Jumbo frames (private and transit only) | MTU 1500 by default. 9001 on private VIFs, 8500 on transit VIFs | +| Inbound prefix allocation (private and transit, 2026) | IPv4 and IPv6 allocations, 100 by default, up to 1,000 each | + +### ASN rules + +- You cannot use the same ASN on the customer side as on the VGW or DXGW side of the same VIF. +- The same customer ASN can be reused across many VIFs. +- Two VIFs can share the same AWS ASN and customer ASN pair if they are on different connections. +- Public VIF AWS-side ASN is 7224. With a private customer ASN, AWS replaces it with 7224 when it propagates your prefixes, so AS_PATH prepending is ineffective. With a public ASN, prepending works as expected. +- AWS verifies ownership of public ASNs. + +### Bidirectional Forwarding Detection (BFD) + +Asynchronous BFD is automatically enabled on every VIF on the AWS side, but it takes effect only after you configure it on your router. + +## MTU and jumbo frames + +| VIF type | Allowed MTU | Notes | +| --- | --- | --- | +| Private | 1500 or 9001 | Works when attached to a VGW or a DXGW | +| Transit | 1500 or 8500 | Transit Gateway supports jumbo frames only up to 8500 | +| Public | 1500 | Jumbo frames not supported | + +- Enabling jumbo frames can update the underlying connection, which disrupts **all** VIFs on that connection for up to 30 seconds. +- If the same route is learned over VIFs with different MTUs, or also over a Site-to-Site VPN, 1500 is used. +- On hosted connections, jumbo frames are available only if the Partner's parent connection is jumbo-capable. +- Jumbo frames apply only to routes propagated through Direct Connect and to static routes through Transit Gateways. + +## Hosted VIFs vs hosted connections + +These are different products and are easy to confuse. + +| | Hosted VIF | Hosted connection | +| --- | --- | --- | +| What you get | A VIF created by the connection owner, in their dedicated connection, for your account | A sub-rate connection provisioned by a Partner on the Partner's interconnect | +| Acceptance | You accept it (`ConfirmPrivateVirtualInterface`, `ConfirmPublicVirtualInterface`, `ConfirmTransitVirtualInterface`) and pick a VGW or DXGW | You accept the connection | +| VIFs allowed | Not applicable (it is one VIF) | Exactly 1 VIF (private, public, or transit). This cannot be increased | +| Prefix allocation (2026) | Created with the default of 100/100. Only the parent connection owner can change it after acceptance | The customer can set the per-VIF allocation up to 1,000. There is no connection pool | + +- A hosted VIF otherwise works the same as a standard VIF. +- Only the connection owner can download the router configuration for a hosted VIF. +- For a hosted public VIF, the owner account is the one billed for data transfer out. + +## VIF lifecycle states + +`confirming` (waiting for the owner to accept a hosted VIF), `verifying` (public VIFs only), `pending`, `available`, `down` (BGP down), `testing` (during a failover test), `deleting`, `deleted`, `rejected`, and `unknown`. + +### Public VIF verification + +- Every public VIF is validated before it is provisioned. If a VIF stays in `verifying` for more than 1 hour, AWS automatically opens a support case. +- AWS checks that the ASN is yours (or that you have an LOA), that the peer IPs are valid, that you own the prefixes (or have an LOA on company letterhead), and that the RIR records match the organization on the AWS account. +- LOA review can take up to 3 business days. +- If you advertise prefixes before approval, you must clear the BGP session and re-advertise afterward. +- To add prefixes to an existing public VIF, open an AWS Support case. + +## Per-connection and per-VIF quotas + +| Quota | Value | Adjustable | +| --- | --- | --- | +| Private + public VIFs per dedicated connection | 50 | No | +| Transit VIFs per dedicated connection | 4 | Contact SA/TAM | +| Total VIFs per dedicated connection or LAG | 51 | No | +| VIFs per hosted connection | 1 | No | +| Inbound routes per BGP session, private or transit VIF | 100 per address family by default, up to 1,000 with prefix controls | Beyond 1,000: SA/TAM, reviewed case by case | +| Inbound routes per BGP session, public VIF | 1,000 | No | +| VIFs per VGW | No limit | – | +| Private or transit VIFs per DXGW | 30 | No | + +If you exceed the inbound prefix limit or allocation, the BGP session goes to Idle and reports DOWN. You must withdraw routes and then reset the session. + +## Inbound prefix controls (launched 2026-08-20) + +Before this launch, a private or transit VIF accepted at most 100 prefixes per address family from on premises. Now each VIF gets an allocation drawn from two pools. + +| Limit | Value | +| --- | --- | +| Default allocation per VIF | 100 per address family | +| Max allocation per VIF | 1,000 per address family | +| Pool per dedicated 1G or 10G connection | 5,000 IPv4 + 5,000 IPv6 | +| Pool per dedicated 100G connection | 30,000 + 30,000 | +| Pool per dedicated 400G connection | 50,000 + 50,000 | +| LAG pool | Per-member pool × billable members (up to 4 members for 1G/10G, 2 for 100G/400G) | +| Total allocations per DXGW | 10,000 (IPv4 + IPv6 combined) | +| VIF attachments per DXGW | 30 | + +```mermaid +flowchart TB + subgraph CONN["Dedicated 10G connection pool: 5,000 v4 / 5,000 v6"] + V1["Transit VIF A
alloc 1,000 v4"] + V2["Private VIF B
alloc 50 v4"] + FREE["Unallocated 3,950 v4"] + end + V1 --> G["DXGW pool: 10,000 combined"] + V2 --> G +``` + +- Pool states are Pool size (fixed by port speed), Allocated, Available (unallocated), and In use (prefixes actually advertised). +- You cannot reduce an allocation below the in-use count. You cannot remove a LAG member if that would shrink the pool below the total allocations. +- Public VIFs are not managed by prefix controls and stay at 1,000. +- A larger allocation does not raise the VPC route table quota for propagated routes (100 per route table, not adjustable). A private VIF on a VGW can still be capped by the VPC. +- AWS Interconnect (multicloud) connections consume 2,000 of a DXGW's 10,000 allocation. +- APIs and fields: `prefixPoolAllocatedCountIpv4` and `prefixPoolAllocatedCountIpv6` on `CreatePrivateVirtualInterface`, `CreateTransitVirtualInterface`, and `UpdateVirtualInterfaceAttributes`. `prefixPoolSizeIpv4` and `prefixPoolUnallocatedCountIpv4` (and the IPv6 equivalents) on `DescribeConnections`. `totalPrefixPoolAllocations` on `DescribeDirectConnectGateways`. +- Available at no extra cost in all commercial Regions, GovCloud (US), and China (Beijing, Ningxia). + +## Observability for VIFs (2026) + +| Feature | Date | What it gives you | +| --- | --- | --- | +| CloudWatch BGP metrics | 2026-03-30 | `VirtualInterfaceBgpStatus` (1 = UP), `VirtualInterfaceBgpPrefixesAccepted`, and `VirtualInterfaceBgpPrefixesAdvertised` for private, public, and transit VIFs. You can alarm before hitting the prefix limit | +| BGP route visibility | 2026-07-30 | Console tabs for Accepted and Advertised routes, plus the `ListVirtualInterfaceRoutes` API. Shows prefix, address family, AS path, communities (only supported 7224:* values), and route age. Filter by prefix, AS path, community, or address family | +| FIS BGP disruption | 2025-12-18 | AWS Fault Injection Service can disrupt BGP sessions on VIFs to test failover | + +## Timeline of VIF-related changes + +| Date | Change | +| --- | --- | +| 2016-12-01 | IPv6 BGP peering on VIFs | +| 2018-10-11 | Jumbo frames (9001) on private VIFs | +| 2019-03-27 | Transit VIF with Transit Gateway support | +| 2021-12-01 | SiteLink on private and transit VIFs | +| 2024-07-18 | 400G dedicated connections | +| 2024-11-25 | Transit VIF and DXGW native attachment to AWS Cloud WAN | +| 2025-07-24 / 2025-09-12 | Long (4-byte) ASNs for VIFs (docs update date / What's New date) | +| 2025-12-18 | Resilience testing with AWS FIS (BGP disruption) | +| 2026-03-30 | CloudWatch BGP status and prefix metrics | +| 2026-03 | CloudFormation support for DX resources, including VIFs and BGP peers | +| 2026-07-30 | BGP route visibility (`ListVirtualInterfaceRoutes`) | +| 2026-08-20 | Inbound prefix controls, up to 1,000 prefixes per address family per VIF | + +## Sources + +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- diff --git a/docs/direct-connect/05-direct-connect-gateway.md b/docs/direct-connect/05-direct-connect-gateway.md new file mode 100644 index 0000000..c0676ea --- /dev/null +++ b/docs/direct-connect/05-direct-connect-gateway.md @@ -0,0 +1,231 @@ +# Direct Connect Gateway, Associations, Cloud WAN, and SiteLink + +A Direct Connect gateway (DXGW) is a global, account-level resource that decouples your VIFs from Regions. You attach private or transit VIFs to it, then associate it with virtual private gateways (VGWs), Transit Gateways (TGWs), or one AWS Cloud WAN core network in any Region and in any account, except the China Regions. It acts as a distributed set of BGP route reflectors outside the data path, so a single DXGW has no single point of failure. This page covers association types and their mutual exclusivity, how "allowed prefixes" behave differently for VGW and TGW, cross-account proposals, the non-transitive rules, the Cloud WAN native attachment (2024-11-25), SiteLink, and all DXGW-related quotas, including the 2026 prefix-allocation pool. + +_Last verified: 2026-10-12_ + +## What a DXGW is (and is not) + +- It is global. It connects to any public Region and to AWS GovCloud (US), but not to the AWS China Regions. +- It is a control-plane construct, described by AWS as a "distributed set of BGP route reflectors" that "operates outside the data traffic path". High availability is built in, so you do not need multiple DXGWs for redundancy. +- The AWS-side ASN (`amazonSideAsn`) must be private: 64,512–65,534 or 4,200,000,000–4,294,967,294. The default is 64512. In CloudFormation, changing it requires replacement. +- A public VIF cannot attach to a DXGW. +- There is no charge for the DXGW itself. You pay data transfer out based on the source Region and the DX location. + +## Association types + +| Association target | VIF type used | How many per DXGW | Notes | +| --- | --- | --- | --- | +| Virtual private gateway (VGW) | Private VIF | 20 VGWs (hard limit) | VGW must be attached to a VPC. VPC CIDRs must not overlap | +| Transit Gateway | Transit VIF | 6 TGWs (hard limit) | Use unique ASNs for TGWs in different Regions. A TGW can have up to 20 DXGWs | +| Cloud WAN core network | Transit VIF | 1 core network, 1 segment | Managed only from Network Manager (Cloud WAN) | + +The three types are mutually exclusive on a given DXGW: + +- You cannot associate a VGW with a DXGW that already has a TGW association. +- You cannot associate a TGW with a DXGW that has a VGW association or an attached private VIF. +- A DXGW attached to a Cloud WAN core network cannot be used for any other association type (VGW, TGW, or private VIF) until it is detached. + +```mermaid +flowchart TB + subgraph A["DXGW type A: VGW mode"] + P1[Private VIFs] --> D1((DXGW)) + D1 --> VGW1[VGW / VPC us-east-1] + D1 --> VGW2[VGW / VPC eu-west-1
other account] + end + subgraph B["DXGW type B: TGW mode"] + T1[Transit VIFs] --> D2((DXGW)) + D2 --> TGW1[TGW us-east-1] + D2 --> TGW2[TGW ap-northeast-1] + end + subgraph C["DXGW type C: Cloud WAN mode"] + T2[Transit VIFs] --> D3((DXGW)) + D3 --> CNE[Core network segment
selected edge locations] + end +``` + +A single VGW can also be associated with a DXGW and be attached directly to a private VIF at the same time. + +## Allowed prefixes: VGW vs TGW behave differently + +This is the most commonly misunderstood DXGW setting. + +| | VGW association | TGW association | Cloud WAN attachment | +| --- | --- | --- | --- | +| Role of the list | A filter | The literal advertisement | Not supported | +| What on-prem receives | The VPC CIDR itself, only if an allowed prefix is the same as or wider than the VPC CIDR | Exactly the prefixes in the list, originated from the DXGW ASN, even if no VPC owns them | Every prefix in the segment, with AS_PATH preserved | +| Example: VPC 10.0.0.0/16, list 10.0.0.0/15 | Receives 10.0.0.0/16 | Receives 10.0.0.0/15 | – | +| Example: list 10.0.0.0/24 | Receives nothing (narrower than the VPC) | Receives 10.0.0.0/24 | – | +| Example: list 22.0.0.0/24 | Receives nothing | Receives 22.0.0.0/24 | – | +| Limit | – | 200 prefixes per TGW, IPv4 + IPv6 combined (SA/TAM) | 5,000 prefixes from the core network to on-prem (SA/TAM) | + +Other rules: + +- Allowed prefixes must not overlap across multiple TGWs on the same DXGW. For example, `0.0.0.0/0` is rejected if another TGW is already associated. +- Adding or removing a prefix affects only traffic that uses that prefix. The association goes from `associated` to `updating` and back, and the BGP session does not reset. +- For Private IP VPN, the TGW CIDR block must appear in the allowed prefixes so that on premises can reach the VPN tunnel outside IPs. +- A `/30` point-to-point VIF address range does not propagate to a TGW. +- VIF inside-network prefixes (the BGP peering subnet) are propagated only to TGWs in other Regions, not within the same Region. + +## Cross-account associations (proposals) + +```mermaid +sequenceDiagram + participant A as Account A (owns VGW or TGW) + participant Z as Account Z (owns DXGW) + A->>Z: CreateDirectConnectGatewayAssociationProposal (with requested allowed prefixes) + Z->>Z: Review the proposal (expires after 7 days) + Z->>A: AcceptDirectConnectGatewayAssociationProposal (optional overrideAllowedPrefixesToDirectConnectGateway) + Note over A,Z: Association active. Account Z controls routing to on-premises +``` + +- The gateway owner proposes and the DXGW owner accepts. The DXGW owner can override the requested allowed prefixes. +- A VGW proposal expires 7 days after creation. Accepted or deleted proposals remain visible for 3 days. +- For Cloud WAN, sharing is handled through Network Manager ("shared Direct Connect gateway attachment"). + +## No transitive routing through a DXGW + +A DXGW forwards only between VIFs and gateway associations. The following are **not** supported: + +- VPC to VPC through the same DXGW, including a hairpin through on-premises over a single DXGW. +- VIF to VIF on the same DXGW. The exception is SiteLink, described below. +- VIF to a Site-to-Site VPN that terminates on a VGW associated with the same DXGW. + +There are documented exceptions and caveats: + +- **Supernet exception (since November 2021).** If on premises advertises a supernet (for example `10.0.0.0/8` or `0.0.0.0/0`) that covers several VPCs whose VGWs share the same DXGW, and those VPCs use the same VIF, those VPCs can reach each other through the DX endpoint. To prevent this, use security groups, advertise non-overlapping specific routes, or use one DXGW per VPC. +- **TGW case.** VPCs behind TGWs on the same DXGW can communicate. To block this, use TGW route tables with blackhole routes. + +```mermaid +flowchart LR + VPC1[VPC A] --- VGWa[VGW A] --- DXGW((DXGW)) + VPC2[VPC B] --- VGWb[VGW B] --- DXGW + DXGW --- VIF1[Private VIF 1] --- DC1[DC 1] + DXGW --- VIF2[Private VIF 2] --- DC2[DC 2] + VGWa -. "blocked by default" .- VGWb + VIF1 -. "blocked unless SiteLink" .- VIF2 +``` + +## Migrating a VGW-attached VIF to a DXGW + +- To reach a VPC in the same Region only, you can attach a private VIF directly to the VGW or use a DXGW. The DXGW path adds multi-Region and multi-account reach. +- Enable VPC route propagation only **after** the VGW is associated with the DXGW. Enabling it earlier can propagate routes incorrectly. +- When a VGW sits behind a DXGW, on premises sees only the DXGW ASN in AS_PATH, not the VGW ASN. The VGW ASN appears only when the VIF attaches directly to the VGW. +- Detaching a VGW from its VPC also disassociates it from the DXGW. + +## AWS Cloud WAN native attachment (GA 2024-11-25) + +Before November 2024, Cloud WAN reached DX only through an intermediate TGW that was peered with the core network edge (CNE). Now a DXGW attaches directly as a Cloud WAN "Direct Connect gateway attachment". + +```mermaid +flowchart LR + DC[On-prem router] -->|transit VIF + eBGP| DXGW((DXGW
ASN 64600)) + DXGW -->|DX gateway attachment| CNE1[CNE us-west-2] + DXGW --> CNE2[CNE ap-southeast-2] + CNE1 --- SEG[(Segment: Development)] + CNE2 --- SEG + CNE3[CNE us-east-1
not in attachment] --- SEG +``` + +| Aspect | Behavior | +| --- | --- | +| Management | Created, deleted, and managed only from Network Manager (Cloud WAN). The DX console and API show the association read-only | +| Scope | One core network and one segment per DXGW. Edge locations are "All" (new edges are added automatically) or "Specific" | +| VIF type | Transit VIF | +| Outbound (AWS to on-prem) | Each associated CNE advertises only its local routes to the DXGW. AS_PATH is preserved end to end | +| Inbound (on-prem to AWS) | Learned into the segment route tables of the associated CNEs and routable across all Regions of the segment | +| Allowed prefixes | Not supported. The whole segment is advertised | +| DX BGP communities | Not supported inside Cloud WAN | +| Static routes to the DXGW attachment | Not supported. Routes must be dynamic | +| ASN | The DXGW ASN must be outside the core network ASN range | +| Unsupported with DX as transport | Private IP VPN and Connect attachments | +| Prefix quota | 5,000 prefixes from the core network to on-prem | +| Pricing | Same as other Cloud WAN attachments (per hour plus per GB) | +| Monitoring | CloudWatch Network Monitor latency and loss are supported. Network Health Indicator is not | + +Cloud WAN Routing Policy (GA 2025-11-20) adds route filtering, summarization, and BGP attribute manipulation across Cloud WAN attachments. You map policies to attachments with a "routing policy label", which is also offered when you create a DX gateway attachment. This partly compensates for the lack of allowed-prefix lists and DX communities on the Cloud WAN side. + +## SiteLink (since 2021-12-01) + +SiteLink lets on-premises sites exchange traffic **between Direct Connect locations over the AWS backbone, without going through a Region**. It is the explicit exception to "no VIF-to-VIF transit". + +```mermaid +flowchart LR + DC1[DC Tokyo] -->|SiteLink VIF| L1[DX location Tokyo] + DC2[DC London] -->|SiteLink VIF| L2[DX location London] + DC3[DC Virginia] -->|VIF without SiteLink| L3[DX location Ashburn] + L1 --- DXGW((DXGW)) + L2 --- DXGW + L3 --- DXGW + L1 <-->|"AWS backbone, shortest path"| L2 + DXGW --> R[VGW/TGW in Regions] +``` + +In this example, DC Tokyo and DC London form a full mesh. DC Virginia reaches only the Regions. + +| Aspect | Detail | +| --- | --- | +| Supported | Transit VIFs. Private VIFs attached to a DXGW, with or without VGW associations | +| Not supported | Private VIFs attached directly to a VGW. Public VIFs | +| Partitions | Within the same AWS partition. Not available in GovCloud (US) or China | +| Enabling | A flag on a new or existing private or transit VIF (including hosted VIFs). Toggling it flaps that VIF's BGP session | +| Mesh | Full mesh among all SiteLink-enabled VIFs on the same DXGW. A VIF without SiteLink sends its routes only to the gateway associations | +| AS_PATH | The DXGW prepends its ASN once per AWS logical device (ALD) in the path, so remote sites see the DXGW ASN once or twice | +| Same customer ASN everywhere | Remote routes are dropped by loop prevention. Use unique ASNs or `allowas-in` / `local-as ... replace-as` | +| Communities | Standard communities (except 7224:*) and transitive attributes propagate to other SiteLink VIFs | +| Route preference change | With SiteLink, AWS Regions prefer the path with the shortest AS_PATH regardless of the location's associated Region. Without SiteLink, they prefer locations associated with the Region | +| Prefix limit | Up to 1,000 each for IPv4 and IPv6, configured with prefix controls (a separate SiteLink prefix quota was added 2023-06-15) | +| Constraints | Does not work if the same route is advertised on multiple VIFs. No multicast. DSCP is preserved but no QoS is enforced | +| MTU | Up to 8500 or 9001, depending on VIF type | +| Pricing | $0.50 per hour per SiteLink-enabled VIF (charged even when idle), plus per-GB SiteLink data transfer that varies by source and destination. Not covered by the 2026 flat-rate billing tiers | + +## DXGW and related quotas + +| Quota | Value | Adjustable | +| --- | --- | --- | +| DXGWs per account | 200 | SA/TAM | +| VGWs per DXGW | 20 | No | +| TGWs per DXGW | 6 | No | +| DXGWs per TGW | 20 | No | +| Private or transit VIFs per DXGW | 30 | No | +| Total inbound prefix allocations per DXGW (2026) | 10,000 (IPv4 + IPv6) | – | +| Prefixes from AWS to on-prem per TGW (allowed prefixes) | 200 combined | SA/TAM | +| Prefixes from Cloud WAN core network to on-prem | 5,000 | SA/TAM | +| SiteLink prefixes | Up to 1,000 per address family per VIF | SA/TAM | +| AWS Interconnect (multicloud) cost against the DXGW pool | 2,000 prefixes | – | + +## Related: AWS Interconnect (multicloud) + +AWS Interconnect (multicloud) connections attach through a DXGW. VGWs and TGWs reach only an Interconnect that is local to their Region. Cloud WAN CNEs can reach any Interconnect attached to the same DXGW globally. Each Interconnect consumes 2,000 of the DXGW's 10,000 prefix allocations. A free 500 Mbps tier was announced in May 2026. + +## Sources + +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- diff --git a/docs/direct-connect/06-bgp-and-routing.md b/docs/direct-connect/06-bgp-and-routing.md new file mode 100644 index 0000000..84c1dbf --- /dev/null +++ b/docs/direct-connect/06-bgp-and-routing.md @@ -0,0 +1,238 @@ +# BGP and Routing over Direct Connect + +Every Direct Connect VIF is an eBGP session, and nearly every design decision comes down to how AWS picks a path. That includes active/active or active/passive, DX primary with VPN backup, and Regional scoping of public prefixes. This page covers the public VIF inbound and outbound policies, the full BGP community set (7224:7xxx, 7224:8xxx, 7224:9xxx, NO_EXPORT), AWS path selection on private and transit VIFs, how DX routes compete with VPN routes on a VGW, a Transit Gateway, and in a VPC route table, Private IP VPN over a transit VIF, reaching PrivateLink endpoints over DX, and the route-scale quotas, including the 2026 prefix-control change. + +_Last verified: 2026-10-12_ + +## Route-scale quotas (quick reference) + +| Direction | Where | Limit | +| --- | --- | --- | +| On-prem to AWS | Private or transit VIF, per BGP session | 100 per address family by default. Up to 1,000 with inbound prefix controls (since 2026-08-20). Beyond that, contact SA/TAM | +| On-prem to AWS | Public VIF | 1,000 (hard) | +| On-prem to AWS | Sum of VIF allocations per DXGW | 10,000 (IPv4 + IPv6) | +| AWS to on-prem | Per TGW association (allowed prefixes) | 200 combined IPv4 + IPv6 | +| AWS to on-prem | Cloud WAN core network through a DXGW attachment | 5,000 | +| AWS to on-prem | SiteLink | Up to 1,000 per address family per VIF | +| Into a VPC | Propagated routes per VPC route table (VGW) | 100 (not adjustable. AWS says to advertise a default route instead) | +| Comparison | Private IP VPN on a TGW | 1,000 in, 5,000 out | + +Exceeding the inbound limit or allocation puts the BGP session in **Idle** (BGP DOWN). Reduce the advertised routes, then clear the session. Since 2026-03-30 you can alarm on `VirtualInterfaceBgpPrefixesAccepted` before that happens. + +## Public VIF routing policy + +### Inbound (your prefixes to AWS) + +- You must own the public prefixes (registered with an RIR) or hold an LOA. AWS verifies them before the VIF becomes available. +- Traffic must be destined for Amazon public prefixes. Transitive routing between connections is not supported. +- AWS applies source-address filtering: packets must come from your advertised prefixes. +- AWS treats every route received on a public VIF as if it carried `NO_EXPORT`. Your prefixes stay inside the AWS network and are never re-advertised to other DX customers, to AWS peers, or to transit providers. +- Customer ASN can be public (verified, full 1–4,294,967,295 range, excluding reserved ranges) or private (64512–65534, 4200000000–4294967294). A private ASN is replaced by 7224, so any prepending on it is stripped. + +### Outbound (AWS prefixes to you) + +- AWS advertises all local and remote Region prefixes, plus on-net non-Region PoP prefixes such as CloudFront and Route 53. Commercial and China prefixes are advertised only within their own partition. +- AWS advertises with a minimum AS_PATH length of 3 and tags everything with `NO_EXPORT`. +- AWS uses AS_PATH and longest-prefix match to choose the return path. If you advertise the same prefix to the internet and to DX, advertise more specifics over DX. +- If the same prefix is advertised from two Regions over two public VIFs with identical attributes and prefix length, AWS prefers the home Region. +- AWS-advertised prefixes must not leak beyond your network boundary, for example into the public internet table. +- To load-balance across multiple public VIFs, all the VIFs must be in the same Region. + +## BGP communities + +```mermaid +flowchart LR + subgraph YOU["Communities YOU attach (inbound to AWS)"] + LP["7224:7100 low / 7224:7200 medium / 7224:7300 high
local preference, private and transit VIFs"] + SC["7224:9100 local Region / 7224:9200 continent / 7224:9300 global
scope, public VIF"] + end + subgraph AWS["Communities AWS attaches (outbound to you)"] + RC["7224:8100 same Region / 7224:8200 same continent / no tag = other continents
public VIF"] + NE["NO_EXPORT on all public VIF routes"] + end +``` + +### Public VIF: scope communities (you set, on your prefixes) + +| Community | Propagation of your prefix inside AWS | +| --- | --- | +| `7224:9100` | Local AWS Region only (the Region associated with the DX location) | +| `7224:9200` | All Regions on the same continent (North America, Asia Pacific, or Europe/Middle East/Africa) | +| `7224:9300` | Global, all public Regions | +| No tag | Global (the default) | + +Prefixes with the same community and an identical AS_PATH are candidates for multipath. `7224:1` through `7224:65535` are reserved by Direct Connect. Unsupported communities on a public VIF are stripped. + +### Public VIF: Region communities (AWS sets, on AWS prefixes) + +| Community | Meaning | +| --- | --- | +| `7224:8100` | Prefix originates in the same Region as the DX location | +| `7224:8200` | Prefix originates on the same continent | +| No tag | Other continents | + +Filter on these communities if you want only local or continental AWS prefixes. To receive everything, do not filter. + +The 2026 BGP route visibility page labels 9xxx as "advertised to your router" and 8xxx as "accepted from your router", which is the reverse of the routing-policies page. The routing-policies page, which matches long-standing AWS behavior and the re:Post guidance, is used here. Confirm against live `ListVirtualInterfaceRoutes` output. + +### Private and transit VIF: local preference communities (you set) + +| Community | Local preference AWS applies to the path back to you | +| --- | --- | +| `7224:7100` | Low | +| `7224:7200` | Medium. This is also the value AWS applies implicitly to DX locations associated with the same Region when you set no tag | +| `7224:7300` | High | + +- These communities are mutually exclusive per prefix and are evaluated **before AS_PATH**. +- Active/active: put the same community (for example `7224:7200`) on all paths. If one path fails, ECMP continues over the remaining paths regardless of home Region. +- Active/passive: `7224:7300` on the primary and `7224:7100` on the backup. +- Not supported inside AWS Cloud WAN (DXGW attachment). + +## How AWS chooses a path toward on-prem (private and transit VIFs) + +```mermaid +flowchart TD + S[Multiple VIF paths for a destination] --> A{Longest prefix?} + A -->|unique| W[Use the most specific] + A -->|tie| B{Local preference
7224:7x00 tags} + B -->|no tags| B2[Implicit: prefer DX locations
associated with the sending Region] + B -->|different| W2[Highest local pref wins] + B -->|tie| C{AS_PATH length} + B2 --> C + C -->|shorter| W3[Shortest wins] + C -->|tie| D{MED} + D -->|lower| W4[Lowest MED wins
AWS does not recommend MED] + D -->|tie| E[ECMP across VIFs
ASNs in path need not match] +``` + +- AWS recommends more-specific prefixes as the primary tool, then local preference communities, then AS_PATH prepending. +- AWS Regions prefer DX locations in their own associated Region. ECMP with no community tags works when there are two or more paths from locations in the same associated Region, or two or more from locations outside it. +- With SiteLink enabled, Regions prefer the shortest AS_PATH regardless of the location's Region. +- This logic governs AWS-to-on-prem traffic only. On-prem-to-AWS load sharing is your router's decision. + +### Example: active/passive over two private VIFs + +```text +! Primary VIF (DX location A) +route-map TO-AWS-PRIMARY permit 10 + set community 7224:7300 +! Backup VIF (DX location B) +route-map TO-AWS-BACKUP permit 10 + set community 7224:7100 +! Alternative without communities: prepend on the backup +! route-map TO-AWS-BACKUP permit 10 +! set as-path prepend 65001 65001 65001 +router bgp 65001 + neighbor 169.254.10.1 route-map TO-AWS-PRIMARY out + neighbor 169.254.20.1 route-map TO-AWS-BACKUP out + neighbor 169.254.10.1 send-community + neighbor 169.254.20.1 send-community +``` + +For the inbound direction (AWS to your router), set a higher local preference on routes received over the primary VIF in your own BGP policy. + +## DX vs VPN: who wins? + +### On a virtual private gateway (same prefix length) + +1. BGP routes propagated from Direct Connect +2. Static routes on a Site-to-Site VPN +3. BGP routes propagated from a Site-to-Site VPN +4. Between BGP VPNs: shortest AS_PATH, then lowest MED + +Longest-prefix match applies first. So a VPN that advertises a more specific prefix beats DX. VGWs do not support ECMP across VPN tunnels. + +### On a Transit Gateway (same CIDR, different attachment types) + +1. Static routes +2. Prefix-list-referenced routes +3. VPC-propagated routes +4. **Direct Connect gateway-propagated routes** +5. TGW Connect-propagated routes +6. Site-to-Site VPN over private DX (Private IP VPN) propagated routes +7. Site-to-Site VPN propagated routes +8. VPN Concentrator propagated routes +9. Client VPN propagated routes +10. TGW peering (Cloud WAN) propagated routes + +Within one attachment type, the TGW prefers the shorter AS_PATH, then the lower MED, then eBGP over iBGP. Default MED is 0 for DX and 100 for VPN and Connect when none is sent. The TGW route table shows only the active route, so the VPN backup route appears only after the DX route is withdrawn. + +### In a VPC route table + +- The `local` route always wins, even against a more specific propagated route. +- For an identical destination, static routes (IGW, NAT, ENI, TGW, peering, endpoints, and others) beat routes propagated from the VGW. + +## Encryption over DX: Private IP VPN vs other VPN options + +| Option | Transport | Endpoints | Notes | +| --- | --- | --- | --- | +| Private IP Site-to-Site VPN (introduced June 2022) | Transit VIF, then DXGW, then TGW | Private IPv4 (RFC 1918 or RFC 6598) on the TGW and the customer gateway | Needs a TGW CIDR block, which you must add to the DXGW allowed prefixes. Outer tunnel IPs are IPv4 only (inner BGP can be IPv6). Acceleration does not apply. Not supported when Cloud WAN uses a DXGW attachment as transport | +| Public IP VPN over a public VIF | Public VIF | AWS public VPN endpoints | Uses public IPs. The accelerated option is **not** supported over a public VIF | +| Accelerated Site-to-Site VPN | Internet, through AWS Global Accelerator | TGW only | Not for DX paths. Uses TGW attachments only | +| MACsec | Physical layer, on dedicated connections | – | Layer 2. See the physical-layer docs | + +```mermaid +flowchart LR + CGW[Customer gateway
10.100.0.1] -->|IPsec, private outer IPs| TVIF[Transit VIF] + TVIF --> DXGW((DXGW
allowed prefix = TGW CIDR 10.24.10.0/24)) + DXGW --> TGWDX[TGW DX attachment] + TGWDX --> TGW[Transit Gateway] + TGW --> VPNATT[Private IP VPN attachment
transport = DX attachment] + VPNATT --> VPC[Spoke VPCs] +``` + +Private IP VPN lets you run encrypted and unencrypted traffic side by side by using different TGW route tables for the VPN attachment and the DX attachment. Its route scale (1,000 in and 5,000 out) was historically a workaround for the 100-prefix VIF limit. That motivation is weaker since the prefix controls launch in August 2026. + +Separately, Site-to-Site VPN added 5 Gbps "Large" tunnels on 2025-11-12, which AWS positions as a backup or overlay for high-capacity DX. + +## Reaching PrivateLink and other VPC services over DX + +- Interface VPC endpoints (PrivateLink) are reachable from on premises over a private VIF, a transit VIF, or a Cloud WAN attachment, because they are ENIs with private IPs in the VPC. Endpoint-specific DNS names resolve publicly to the private IPs. +- Gateway endpoints (S3, DynamoDB) do **not** route traffic that enters the VPC from DX, VPN, or TGW. On-premises clients must use interface endpoints, or use a public VIF to reach the public service endpoints. +- A public VIF reaches AWS public service endpoints (S3, DynamoDB, API endpoints, and others) directly, without a VPC. + +## Operational tooling (2025–2026) + +| Date | Feature | Routing relevance | +| --- | --- | --- | +| 2025-09-12 | 4-byte ASN on all VIF types | Use the full RFC 6793 range, up to 4,294,967,294 | +| 2025-11-20 | Cloud WAN Routing Policy | Route filtering, summarization, and BGP attribute control on Cloud WAN, including toward DXGW attachments | +| 2025-12-18 | AWS FIS BGP disruption on VIFs | Test failover to redundant VIFs | +| 2026-03-30 | CloudWatch `VirtualInterfaceBgpStatus`, `...PrefixesAccepted`, `...PrefixesAdvertised` | Alarm before the prefix limit is reached and detect silent route withdrawals | +| 2026-07-30 | BGP route visibility (`ListVirtualInterfaceRoutes`) | See accepted and advertised routes with AS path and communities | +| 2026-08-20 | Inbound prefix controls | Up to 1,000 prefixes per address family per private or transit VIF | + +## Sources + +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- diff --git a/docs/direct-connect/07-resiliency.md b/docs/direct-connect/07-resiliency.md new file mode 100644 index 0000000..cd72a97 --- /dev/null +++ b/docs/direct-connect/07-resiliency.md @@ -0,0 +1,213 @@ +# Resiliency + +Direct Connect (DX) is a physical service: a fiber, an optic, a router port, and a building. Any one of them can fail, and AWS also takes DX devices down for maintenance. This page covers the Resiliency Toolkit models, the SLA tiers and what you must build to qualify for them, failover testing, fast failure detection with BFD, active/active versus active/passive routing, and VPN as a backup path. + +_Last verified: 2026-10-12. SLA text last updated by AWS on 2026-07-24._ + +## Why resiliency matters for DX + +- A single DX connection is a single point of failure: one cross-connect, one AWS device, one location. +- AWS does planned maintenance on DX devices. It is announced 14 days ahead (reminders at 7 days and 1 day) and runs in a window of up to 4 hours. Emergency maintenance can start right away and usually runs in a 2-hour window. If you have a single connection, your connectivity drops during that window. +- AWS says it "will never schedule a planned maintenance event that will simultaneously take down your redundant connections". During planned maintenance it also drains traffic off the device being worked on, but only when you have a redundant path to drain onto. + +## Lesson from the 2021-09-02 Tokyo event + +On 2021-09-02 (JST 07:30–13:42), some AWS network devices in one layer between the Direct Connect locations and the Tokyo Region data centers stopped forwarding traffic correctly, but were not removed automatically. Customers saw intermittent connectivity and packet loss on DX traffic into ap-northeast-1 from every location. Site-to-Site VPN (used by some customers as DX backup), internet access to the Region, and DX traffic to other Regions were not affected. The cause was a latent defect in the device operating system triggered by a rare packet signature. Source: . + +Takeaways: + +- Location diversity protects against a building or device failure, not against a fault inside the AWS network path into one Region. +- Keep a backup of a different kind (Site-to-Site VPN, or DX to another Region) for critical paths. +- Watch for loss and latency (grey failures), not only link and BGP state; Network Synthetic Monitor helps here. + +## Resiliency Toolkit models + +The Resiliency Toolkit is a connection wizard in the DX console. It orders the right number of dedicated connections, spreads them across devices and locations, and checks that they all have the same speed. It also names the connections, builds LAGs for speeds that are not native port speeds, and shows the SLA you can get plus the port-hour cost. + +| Model | Topology | Protects against | SLA target | +| --- | --- | --- | --- | +| Maximum resiliency | 2 or more locations, 2 or more connections per location, each on a separate AWS device (at least 4 connections) | Device failure, fiber cut, complete location failure | 99.99% | +| High resiliency | 1 connection in each of 2 or more locations | Fiber cut, device failure, complete location failure | 99.9% | +| Development and test | 2 connections on separate devices in 1 location | Device failure only (not location failure) | No multi-site SLA | +| Classic (no toolkit) | Whatever you order yourself | Nothing by design | 95% (Single Connection SLA) | + +```mermaid +flowchart LR + subgraph DC1["Customer data center A"] + R1[Router A1] + R2[Router A2] + end + subgraph DC2["Customer data center B"] + R3[Router B1] + R4[Router B2] + end + subgraph L1["DX location 1"] + D1[AWS device 1] + D2[AWS device 2] + end + subgraph L2["DX location 2"] + D3[AWS device 3] + D4[AWS device 4] + end + R1 --- D1 + R2 --- D2 + R3 --- D3 + R4 --- D4 + D1 & D2 & D3 & D4 --> DXGW[Direct Connect gateway] + DXGW --> VPC[VPCs / TGW / Cloud WAN in 2+ AZs] +``` + +The diagram shows the Maximum resiliency model. High resiliency keeps one connection per location. Development and test keeps two connections in one location. + +## SLA tiers and requirements + +The DX SLA has three commitments. Service credits are a percentage of the DX port-hour charges for the affected connections. + +| SLA | Monthly uptime commitment | Credit 10% | Credit 25% | Credit 100% | +| --- | --- | --- | --- | --- | +| Multi-Site Redundant | 99.99% | below 99.99%, at or above 99.0% | below 99.0%, at or above 95.0% | below 95.0% | +| Multi-Site Non-Redundant | 99.9% | below 99.9%, at or above 99.0% | below 99.0%, at or above 95.0% | below 95.0% | +| Single Connection | 95.0% | below 95.0%, at or above 92.5% | below 92.5%, at or above 90.0% | below 90.0% | + +To qualify for the minimum configuration of each deployment type: + +| Deployment type | Requirements | +| --- | --- | +| Multi-Site Non-Redundant (99.9%) | At least 2 connections in at least 2 DX locations, all reaching the same endpoint. Enterprise Support plan. For private endpoints, the endpoint is deployed in 2 or more AZs. | +| Multi-Site Redundant (99.99%) | At least 4 connections in at least 2 DX locations, with at least 2 connections per location. Each connection is on a unique AWS device (check the AWS Device ID in the console). Enterprise Support plan and a completed Well-Architected Review with an AWS Solutions Architect. For private endpoints, the endpoint is deployed in 2 or more AZs. | + +Key definitions and exclusions: + +- "Unavailable" means you completely cannot send or receive data for at least 120 consecutive seconds. +- Ports joined in a LAG count as one "Connection". +- The SLA does **not** cover hosted connections or hosted VIFs provided through a partner. It does cover dedicated connections owned by your account, even when a partner delivers them. +- AWS says it does not recommend any deployment other than Multi-Site Redundant or Multi-Site Non-Redundant for production. +- Credit claims go through the AWS Support Center with the subject "Direct Connect SLA Credit Request". AWS must receive them by the end of the second billing cycle after the incident. + +## Failover testing + +The Resiliency Toolkit failover test (launched June 2020) makes AWS bring down the BGP session on a VIF you choose. You then check that traffic moves to your redundant VIFs. + +| Item | Value | +| --- | --- | +| VIF types | Public, private, transit | +| Who can start it | Only the owner of the account that has the VIF | +| Peering selection | IPv4 or IPv6 BGP peering | +| Duration | Default 180 minutes, maximum 4,320 minutes (72 hours). You can stop it early. | +| After the test | AWS restores BGP with the parameters negotiated before the test | +| CLI | `aws directconnect start-bgp-failover-test` / `stop-bgp-failover-test` / `list-virtual-interface-test-history` | +| Caveat | Do not run it during a DX maintenance window. BGP might come back early. | + +```bash +aws directconnect start-bgp-failover-test \ + --virtual-interface-id dxvif-EXAMPLE \ + --bgp-peers \ + --test-duration-in-minutes 60 +``` + +Make the test part of your regular runbook, for example every quarter and after any routing change. It exercises both directions: on-premises to AWS (your router's policy) and AWS to on-premises (the attributes you advertise). + +## Fast failure detection: BGP timers and BFD + +Without BFD, BGP detects a dead peer only when the hold timer expires. The default is 90 seconds (3 missed keepalives at 30 seconds each). + +| Setting | Value | +| --- | --- | +| Default hold timer | 90 s | +| Minimum hold timer | 3 s (0 is not supported) | +| Default keepalive | 30 s | +| Minimum keepalive | 1 s | +| Graceful restart timer | 120 s. Do not use graceful restart and BFD together. | +| BFD minimum liveness interval | 300 ms | +| BFD minimum multiplier | 3 | +| Resulting BFD detection time | about 300 ms × 3 = 900 ms | +| BGP TTL | 1 (no multihop) | + +- Asynchronous BFD is enabled automatically on the AWS side of every VIF. It only takes effect after you configure BFD on your router. +- BGP timers negotiate down to the lowest value either side offers. BFD uses the slower of the two sides' intervals, and it negotiates each direction separately. +- AWS recommends enabling BFD and turning graceful restart off so failover is fast. + +## Active/active vs active/passive + +Routing on DX follows standard BGP best-path selection, with a few AWS-specific controls. Traffic from AWS to on-premises (the AWS side's choice) is evaluated in this order for private and transit VIFs: + +1. Longest prefix match. A more-specific prefix always wins. +2. Local preference, which you set with BGP communities `7224:7100` (low), `7224:7200` (medium), `7224:7300` (high). With no community, AWS prefers DX locations associated with the same Region, which it treats as medium. +3. AS_PATH length. Prepend to make a path less preferred. +4. MED. AWS does not recommend relying on it. +5. ECMP across VIFs when all of the above are equal. The ASNs in the AS_PATH do not need to match. + +| Pattern | What you advertise from on-premises | Result for AWS to on-premises traffic | +| --- | --- | --- | +| Active/active | Same prefixes, same community (for example `7224:7200`), same AS_PATH length on all VIFs | ECMP per flow across VIFs. If one VIF fails, traffic rebalances across the rest, regardless of home Region. | +| Active/passive (preferred) | Primary VIF tagged `7224:7300`, backup VIF tagged `7224:7100` | All traffic uses the primary. Backup takes over on failure. | +| Active/passive (alternative) | Same prefix with AS_PATH prepends on the backup, or more-specific prefixes on the primary | Works, but local preference communities are evaluated before AS_PATH, so they are the cleaner lever. | + +For traffic from on-premises to AWS, your own routers decide. Set local preference (or weight) on your side to match, or you get asymmetric routing. + +```mermaid +flowchart TB + OnPrem[On-premises routers] -->|"prefix 10.0.0.0/16 + community 7224:7300"| VIF1[VIF on DX location 1: ACTIVE] + OnPrem -->|"prefix 10.0.0.0/16 + community 7224:7100"| VIF2[VIF on DX location 2: PASSIVE] + VIF1 --> GW[DXGW / VGW / TGW] + VIF2 --> GW + GW -->|return traffic prefers high local-pref| VIF1 +``` + +For public VIFs, AWS picks the outbound path using AS_PATH and longest prefix match. The local preference communities above apply only to private and transit VIFs. + +## VPN as a backup + +A Site-to-Site VPN over the internet is the cheapest second path. AWS positions it as a valid option when cost matters most, or as a stopgap until you add a second DX. + +- **Route preference.** For the same prefix, AWS prefers DX over VPN on both a VGW and a TGW. On a TGW, routes learned from DX have a higher preference than routes learned from VPN. Do not use AS_PATH prepending to demote the VPN, because with equal prefixes the DX route wins no matter how long the prepend is. +- **Asymmetric routing trap.** Advertise the same or less-specific prefixes over VPN than over DX. If the VPN carries more-specific routes (it can: VPN on a TGW accepts more routes than DX), return traffic goes over VPN while the forward path uses DX. Filter or summarize the routes on your customer gateway. +- **Throughput.** Historically each tunnel carried up to 1.25 Gbps, and VGW does not support ECMP across VPN tunnels. That is why AWS's resiliency page does not recommend VPN backup for DX links faster than 1 Gbps unless the VPN terminates on a TGW with ECMP (up to 50 Gbps aggregate). +- **2025 change.** Site-to-Site VPN now supports Large Bandwidth Tunnels of up to 5 Gbps per tunnel on Transit Gateway and Cloud WAN VPN attachments (user guide updated 2025-09-25, What's New posted 2025-11-12). AWS explicitly calls out using them "as a backup or overlay for their high capacity AWS Direct Connect connections". +- **No SLA.** An internet VPN has no end-to-end SLA and its performance varies. + +```mermaid +flowchart LR + CGW[Customer router] -->|"DX (preferred)"| DXGW[DX gateway] + CGW -.->|"IPsec VPN over internet (backup)"| TGW + DXGW --> TGW[Transit Gateway] + TGW --> VPCs[VPCs] +``` + +## Multi-Region resiliency + +A DX gateway is a global object. From any DX location you can reach VPCs or TGWs in any commercial Region (not China). For Region-level failure, AWS suggests pairing DX gateways with Transit Gateway inter-Region peering. AWS Cloud WAN also attaches DX gateways directly (since 2024-11-25) and can distribute routes across Regions. + +## Flat-rate port-pairs (2026) + +The flat-rate billing mode launched on 2026-09-15 builds redundancy into the price. A **port-pair** is two dedicated ports on different devices, or in different locations, that share the same speed and pricing tier. The second port is included at no extra charge. Usable capacity equals one port: a 10 Gbps pair gives 10 Gbps, not 20. Pairing across two locations also protects against location failure. See [Pricing](10-pricing.md). + +## Checklist + +- [ ] At least two DX locations for anything in production. +- [ ] Each connection on a separate AWS device (check the AWS Device ID) and a separate customer router. +- [ ] Ideally two carriers or delivery partners, using diverse paths. +- [ ] Capacity sized so that the surviving links can carry the full load (N+1). +- [ ] BFD enabled and graceful restart disabled. +- [ ] Local preference communities or ECMP chosen on purpose, with a matching policy for traffic from on-premises to AWS. +- [ ] Failover test run regularly. +- [ ] CloudWatch alarms on `ConnectionState` and `VirtualInterfaceBgpStatus` (see [Monitoring](09-monitoring-and-troubleshooting.md)). + +## Sources + +- Resiliency Toolkit: +- DX SLA (last updated 2026-07-24): +- Classic connection (95% SLA): +- Failover test: +- Knowledge Center, test resiliency (duration limits): +- Maintenance: +- BGP settings and BFD: +- Knowledge Center, enable BFD: +- Routing policies and BGP communities: +- Active/active and active/passive reference architecture: +- Resiliency recommendations: +- Hybrid Connectivity whitepaper, reliability: +- Knowledge Center, asymmetric routing with VPN backup: +- Site-to-Site VPN 5 Gbps tunnels (2025-11-12): +- Site-to-Site VPN document history: +- Flat-rate billing and port-pairs: diff --git a/docs/direct-connect/08-security.md b/docs/direct-connect/08-security.md new file mode 100644 index 0000000..519f334 --- /dev/null +++ b/docs/direct-connect/08-security.md @@ -0,0 +1,145 @@ +# Security + +Direct Connect is private in the sense that it bypasses the public internet, but it is **not encrypted by default**. This page covers encryption options (MACsec at layer 2, IPsec at layer 3), how a public VIF changes your exposure, and the control-plane side: IAM, tagging, and CloudTrail. + +_Last verified: 2026-10-12._ + +## Encryption posture at a glance + +AWS states that "AWS Direct Connect does not encrypt your traffic that is in transit by default." Private does not mean encrypted: the cross-connect, partner networks, and the DX device all carry your frames in clear text unless you add encryption. + +| Option | Layer | Scope | Connections | Throughput | Notes | +| --- | --- | --- | --- | --- | --- | +| MACsec (IEEE 802.1AE) | L2 | One Layer 2 hop: your MACsec device to the AWS DX device | Dedicated 10/100/400 Gbps at select locations, LAGs, partner interconnects | Near line rate | No extra charge. Not available on 1 Gbps dedicated or hosted connections. | +| IPsec VPN over public VIF | L3 | Your router to VGW, TGW, Cloud WAN, or EC2 VPN endpoints | Any DX connection | Per tunnel limits apply | Needs public IPs and a public VIF | +| Private IP VPN over transit VIF | L3 | Your router to Transit Gateway using private IPs | Any DX connection with a transit VIF | Per tunnel limits apply | GA 2022-06-22. No public IPs needed. | +| Self-managed VPN over private VIF | L3 | Your router to your EC2 VPN appliance | Any | Depends on the appliance | You run both ends | +| Application TLS | L7 | End to end | Any | n/a | Always recommended for sensitive data | + +AWS also notes that it encrypts all data at the physical layer as it moves across the AWS network between DX locations and Regions. MACsec covers the segment from your MACsec device to the AWS DX device, and only that segment. The two ends must be directly adjacent at Layer 2, so what MACsec actually protects depends on where your device sits: + +- **Router in the colo.** MACsec covers the cross connect only. A carrier circuit from the colo back to your site is a separate segment and stays in clear text. +- **Router at your site.** MACsec also covers the carrier circuit, but only if the carrier passes Ethernet frames through transparently at Layer 2 (no device in between that terminates or rewrites the frames). The DX FAQ makes this a prerequisite: the connection "must be transparent to Layer 2 traffic and the device terminating the Layer 2 adjacency must support MACsec." + +The AWS docs put it plainly: MACsec "does not provide end-to-end encryption across multiple sequential Ethernet or other network segments." AWS's MACsec reference architecture says the same for the colo case: if the Layer 2 circuit terminates on a customer or partner device at the DX location, the segment beyond it is the customer's or partner's responsibility. + +```mermaid +flowchart LR + App[On-prem app] --> R[Customer router] + R -- "Carrier circuit (covered by MACsec only if L2-transparent)" --> MMR[Colo meet-me room] + MMR -- "Cross connect (MACsec, L2, one hop)" --> DXD[AWS DX device] + DXD -- "AWS backbone (physical-layer encryption by AWS)" --> Region[AWS Region] + R -. "IPsec (L3, end to end to TGW/VGW)" .-> Region + App -. "TLS (L7)" .-> Region +``` + +## MACsec + +- **What it is.** An IEEE 802.1 layer 2 standard that gives confidentiality, integrity, and origin authenticity. It protects everything on the link, including ARP and BGP. It does **not** give end-to-end encryption across several network segments. +- **Keys.** You supply a CKN/CAK pair: a 64-hex-character, 256-bit key. DX supports only **static CAK** mode, not dynamic CAK. The session key (SAK) is derived automatically and rotated based on time, traffic volume, and session setup. You can store up to 3 CKN/CAK pairs, so you can rotate keys without an outage. +- **Key storage.** Your CKN/CAK is stored in AWS Secrets Manager, encrypted with an AWS managed key. If you schedule the secret for deletion and the connection is `must_encrypt`, AWS switches it to `should_encrypt` to avoid sudden packet loss. +- **Cipher suites.** 10 Gbps supports GCM-AES-256 and GCM-AES-XPN-256. 100 and 400 Gbps support only GCM-AES-XPN-256, because extended packet numbering avoids exhausting the packet number space. +- **Modes.** + - `should_encrypt` is the default. It falls back to clear text if MACsec negotiation fails. + - `must_encrypt` drops traffic if MACsec is down. It is more secure but less available. +- **Other constraints.** The Secure Channel Identifier (SCI) must be on. Dot1q-in-clear (moving the VLAN tag outside the encrypted payload) is not supported. All links in a LAG share one MACsec key. +- **Key distribution guidance.** AWS recommends TLS 1.3 with a post-quantum key exchange such as ML-KEM when you call `associate-mac-sec-key`. +- **Timeline.** MACsec launched on 2021-03-31 for 10 and 100 Gbps. It was extended to 400 Gbps with the 400G launch in 2024, and to partner-owned interconnects on 2025-07-28. Hosted connections still cannot use MACsec. +- **Monitoring.** Use the CloudWatch metric `ConnectionEncryptionState` (1 = up, 0 = down). On a LAG, 1 means every member link is encrypted. + +## IPsec VPN over Direct Connect + +### Over a public VIF + +A public VIF gives your router reachability to AWS public endpoints, including the public endpoints of Site-to-Site VPN. You then build standard IPsec tunnels to a VGW, TGW, or Cloud WAN core network edge. This was the only managed option before 2022. Its drawbacks: you need public IPs, and you now expose a public VIF (see below). + +### Private IP VPN over a transit VIF + +- IPsec tunnels run over a transit VIF, through a DX gateway, to a Transit Gateway, using private (RFC 1918 or RFC 6598) outside IPs on both ends. +- You add a TGW CIDR block to the DX gateway's **allowed prefixes** so that your router learns the tunnel endpoint addresses. +- Encrypted and unencrypted traffic can share one DX. Use separate TGW route tables for the VPN attachment and the DX attachment. +- Private IP VPN supports up to 5,000 outbound and 1,000 inbound routes, versus 200 outbound and 100 inbound for a plain DX transit VIF (AWS docs, pre-2026 figures; see the prefix controls note in [Monitoring and troubleshooting](09-monitoring-and-troubleshooting.md)). +- There is no extra TGW data processing charge for a Private IP VPN attachment beyond what the underlying DX attachment already incurs. Site-to-Site VPN connection-hour charges still apply. +- Private IP VPN does not support IPv6 outer tunnel IPs. The "Enable acceleration" option does not apply. + +```mermaid +flowchart LR + CGW["Customer gateway (private IP 10.x)"] -- "IPsec tunnels over transit VIF" --> DXGW[DX gateway] + DXGW -- "allowed prefix = TGW CIDR" --> TGW["Transit Gateway (private IP from TGW CIDR)"] + TGW --> VPCA[VPC A] + TGW --> VPCB[VPC B] +``` + +### MACsec or IPsec? + +| Requirement | Pick | +| --- | --- | +| 10G+ dedicated, need line-rate encryption, only the hop into the AWS device needs protecting | MACsec | +| 1 Gbps dedicated or any hosted connection | IPsec (MACsec is not available) | +| Compliance requires end-to-end encryption to the VPC edge | IPsec (Private IP VPN), optionally with MACsec | +| No public IPs allowed | Private IP VPN over transit VIF | +| Defense in depth | MACsec plus TLS, or IPsec plus TLS | + +## Public VIF security considerations + +- A public VIF receives **all** AWS public prefixes for all public Regions (except China), plus on-net prefixes such as CloudFront and Route 53, unless you filter them. That includes addresses used by other AWS customers, not just your own resources. +- The prefixes you advertise on a public VIF "will be visible to all customers on AWS". Any AWS public IP, including other tenants' EC2 instances, can route back to you over DX. AWS recommends a firewall filter based on source and destination addresses. +- You must own the public prefixes you advertise (they must be registered with an RIR). AWS filters inbound traffic by source and accepts only traffic from your advertised prefixes. Transitive routing is not supported. +- Use scope communities to limit exposure: + - On your advertisements to AWS: `7224:9100` (local Region), `7224:9200` (continent), `7224:9300` (global, the default). + - On AWS advertisements to you: `7224:8100` (same Region), `7224:8200` (same continent), no tag (other continents). Filter on these. +- AWS tags every route it advertises with `NO_EXPORT`, and it never re-advertises your public VIF prefixes to the internet or to other DX customers. +- With a private ASN on a public VIF, AWS replaces your ASN with 7224, so your AS_PATH prepends have no effect outside AWS. +- Prefer a private or transit VIF plus VPC endpoints (PrivateLink or gateway endpoints) when you only need a handful of AWS services. It is a smaller attack surface than a public VIF. + +## BGP session security + +- BGP MD5 authentication is required on the customer device. +- BGP TTL is fixed at 1 (no multihop), so only a directly connected peer can form a session. +- The AWS troubleshooting guide covers GTSM (BGP TTL security) interactions. +- LOA-CFA documents are digitally signed and watermarked, which prevents forged cross-connect orders at colocation facilities. + +## IAM, tagging, and audit + +| Control | Details | +| --- | --- | +| IAM actions | Service prefix `directconnect:` (for example `CreateConnection`, `CreatePrivateVirtualInterface`, `StartBgpFailoverTest`, `AssociateMacSecKey`). Use least privilege and separate "network admin" and "read-only ops" roles. | +| Tag-based access | Condition keys `aws:RequestTag/${TagKey}`, `aws:ResourceTag/${TagKey}`, `aws:TagKeys`. Tagging has been supported since 2016-11-04. | +| Service-linked role | Used for MACsec, so that DX can read your CKN/CAK secret in Secrets Manager | +| Cross-account | DX gateway association proposals let VPC or TGW owners in other accounts request association. The DXGW owner accepts, and can restrict allowed prefixes. | +| CloudTrail | All DX API actions are logged (supported since 2014-04-04). Watch for `CreateVirtualInterface*`, `AllocateHosted*`, `AcceptDirectConnectGatewayAssociationProposal`, `UpdateDirectConnectGatewayAssociation`, `DeleteConnection`, `StartBgpFailoverTest`. | +| SCPs | Deny `directconnect:Create*`, `directconnect:Allocate*`, and `directconnect:Accept*` outside the network account, so VIFs and DXGWs stay centralized. | + +## Security checklist + +- [ ] Decide on your encryption requirement explicitly. DX alone does not encrypt. +- [ ] Use MACsec on 10/100/400G dedicated ports where possible, and alarm on `ConnectionEncryptionState`. +- [ ] If you need encryption on 1G or hosted connections, use Private IP VPN over a transit VIF. +- [ ] If you have a public VIF: firewall it, filter by scope community, and advertise only the prefixes you must. +- [ ] Restrict DX gateway allowed prefixes to what each VPC or TGW really needs. +- [ ] Centralize DX in a network account. Use SCPs plus tag-based IAM. +- [ ] Send CloudTrail to a central log account and alert on VIF or DXGW association changes. + +## Sources + +- Encryption in transit: +- MACsec: +- MACsec prerequisites (Layer 2 transparency): +- MACsec reference architecture: +- MACsec launch (2021-03-31): +- MACsec on partner interconnects (2025-07-28): +- Well-Architected Hybrid Networking Lens, DX and IPsec: +- Private IP VPN with DX: +- Private IP VPN setup: +- Private IP VPN announcement (2022-06-22): +- Blog, Introducing Private IP VPNs: +- Knowledge Center, encrypted connection over DX: +- Virtual interfaces and public VIF prefix rules: +- Routing policies and BGP communities: +- Knowledge Center, BGP communities on public VIF: +- Dedicated connections and LOA-CFA: +- IAM condition keys: +- Tag-based policy examples: +- CloudTrail logging: +- Transit Gateway pricing (Private IP VPN data processing note): +- DX document history: diff --git a/docs/direct-connect/09-monitoring-and-troubleshooting.md b/docs/direct-connect/09-monitoring-and-troubleshooting.md new file mode 100644 index 0000000..139d107 --- /dev/null +++ b/docs/direct-connect/09-monitoring-and-troubleshooting.md @@ -0,0 +1,236 @@ +# Monitoring and troubleshooting + +This page covers what to watch on a Direct Connect deployment: CloudWatch metrics, the BGP metrics added in 2026, BGP route visibility, VIF rate limiter metrics, Network Synthetic Monitor, AWS Health maintenance notices, and CloudTrail. It then walks through the layer 1, layer 2, layer 3, and routing troubleshooting flow. + +_Last verified: 2026-10-12._ + +## Observability stack + +| Tool | What it tells you | Since | +| --- | --- | --- | +| CloudWatch metrics (namespace `AWS/DX`) | Port state, optics, errors, throughput, encryption, VIF traffic, BGP state and prefix counts | Connection metrics 2017-06-29; VIF metrics 2020-05-11; BGP metrics 2026-03-30 | +| BGP route visibility (`ListVirtualInterfaceRoutes`) | Routes AWS accepted from you and routes AWS advertises to you, with AS_PATH, communities, and install time | 2026-07-30 | +| VIF rate limiter metrics | Per-VIF utilization percentage and policed (dropped) traffic | 2026-06-01 | +| CloudWatch Network Synthetic Monitor | Round-trip time and packet loss from a VPC subnet to on-premises IPs over DX or VPN, plus the AWS Network Health Indicator | GA 2023-12 (as "Network Monitor", renamed 2024) | +| AWS Health and User Notifications | Planned and emergency maintenance events | Ongoing. Email delivery moved to AWS User Notifications on 2025-12-25. | +| CloudTrail | Who changed what (connections, VIFs, DXGW associations, failover tests) | 2014-04-04 | + +## CloudWatch metrics + +By default, data arrives every 5 minutes. Each data point aggregates at least two samples. You can request 1-minute periods, but AWS does not guarantee resolution better than 5 minutes. + +### Connection metrics + +| Metric | Meaning | Alarm idea | +| --- | --- | --- | +| `ConnectionState` | 1 = up, 0 = down. Available for dedicated and hosted connections, and also visible in hosted VIF owner accounts. | Minimum < 1 for 1 datapoint | +| `ConnectionBpsEgress` / `ConnectionBpsIngress` | Bitrate out of AWS / into AWS | Over 70–80% of port speed sustained. Size for N+1. | +| `ConnectionPpsEgress` / `ConnectionPpsIngress` | Packet rate | Baseline anomaly detection | +| `ConnectionErrorCount` | MAC-level errors, including CRC, since the last datapoint (use the Sum statistic). Replaces the retired `ConnectionCRCErrorCount`. | Sum > 0 | +| `ConnectionLightLevelTx` / `ConnectionLightLevelRx` | Optical power in dBm, with the `OpticalLaneNumber` dimension (100G has 4 lanes) | Outside the healthy range (see below) | +| `ConnectionEncryptionState` | MACsec: 1 = up, 0 = down. On a LAG, 1 means all members are encrypted. | < 1 when `must_encrypt` is expected | +| `ConnectionDiscardsPpsEgress` | Packets dropped on egress (buffer overflow, congestion) | > 0 sustained | + +Healthy light levels, according to the AWS Knowledge Center: + +- 1G and 10G: between -14.4 dBm and 2.50 dBm. +- 100G: Tx from -4.3 to 4.5 dBm and Rx from -10.6 to 4.5 dBm, on each of the 4 lanes. + +### Virtual interface metrics + +| Metric | Meaning | +| --- | --- | +| `VirtualInterfaceBpsEgress` / `VirtualInterfaceBpsIngress` | VIF bitrate. On a hosted connection this is your best estimate of total usage. | +| `VirtualInterfacePpsEgress` / `VirtualInterfacePpsIngress` | VIF packet rate | +| `VirtualInterfaceBgpStatus` | BGP session state: 1 = up, 0 = down. Dimension `IpAddressFamily` = `ipv4` or `ipv6`. | +| `VirtualInterfaceBgpPrefixesAccepted` | Number of prefixes AWS accepted from your router | +| `VirtualInterfaceBgpPrefixesAdvertised` | Number of prefixes AWS advertises to your router | + +The three BGP metrics launched on 2026-03-30 for private, public, and transit VIFs in all commercial Regions. Before that, you had to poll the API or build a Lambda function to get BGP state. + +### VIF rate limiter metrics (dedicated connections only) + +| Metric | Meaning | +| --- | --- | +| `VirtualInterfaceUtilizationIngress` / `VirtualInterfaceUtilizationEgress` | Utilization as a percentage of the configured rate limit. It is measured before policing, so it can exceed 100%. | +| `VirtualInterfacePolicedPpsIngress` / `VirtualInterfacePolicedPpsEgress` | Packets per second dropped by the limiter | +| `VirtualInterfacePolicedBpsIngress` / `VirtualInterfacePolicedBpsEgress` | Traffic dropped by the limiter | + +Rate limiters (launched 2026-06-01) cap one VIF so it cannot starve the others ("noisy neighbor"). + +- Up to 10 per dedicated connection by default. +- Limits from 50 Mbps up to 1.6 Tbps (on a large LAG). Supported on private, public, and transit VIFs. +- Egress is always enforced on the device that applies the limit. Ingress may be enforced only after your traffic has already crossed the physical port, so police traffic on your own router as well. + +### Recommended alarm set + +```mermaid +flowchart TD + A[ConnectionState < 1] --> P1[Page on-call: physical link down] + B[VirtualInterfaceBgpStatus < 1] --> P2[Page: BGP down on a VIF] + C[VirtualInterfaceBgpPrefixesAccepted drops or nears quota] --> P3[Ticket: route leak / withdrawal / quota] + D[ConnectionLightLevelRx outside range] --> P4[Ticket: optics or fiber degrading] + E[ConnectionErrorCount Sum > 0] --> P4 + F[ConnectionBpsEgress > 80% of port] --> P5[Capacity planning] + G[ConnectionEncryptionState < 1] --> P6[Security alert: MACsec down] + H[Network Synthetic Monitor loss/RTT or NHI = 100] --> P7[Grey failure: steer traffic] +``` + +## BGP route visibility (2026) + +Since 2026-07-30 you can view, per VIF in the console or through the `ListVirtualInterfaceRoutes` API: + +- **Accepted routes**: what AWS received from your router. +- **Advertised routes**: what AWS sends to your router. + +Each route shows its prefix, address family, AS_PATH, communities, and install timestamp. This answers "did AWS actually accept my prefix?" without opening a support case. It is available in all commercial Regions and the China Regions. + +## Prefix limits and prefix controls (2026) + +| Limit | Value | +| --- | --- | +| Routes from on-premises per BGP session, private or transit VIF | Default 100 each for IPv4 and IPv6. Since 2026-08-20 this can be raised to 1,000 each with inbound prefix controls. | +| Routes per BGP session, public VIF | 1,000 (hard limit) | +| Prefixes per TGW from AWS to on-premises over a transit VIF | 200 combined IPv4 and IPv6 | +| Prefixes a Cloud WAN DXGW attachment advertises to on-premises | 5,000 | +| Propagated routes per VPC route table (from a VGW) | 100 (hard limit) | + +If you exceed your allocation, the BGP session goes **idle** and reports `DOWN`. This is the most common cause of a sudden "BGP down" after someone adds routes on premises. Prefix controls draw each VIF's allocation from pools at the dedicated-connection level and at the DX gateway level. Pool size scales with port speed and with the number of LAG members. + +## Maintenance notifications + +- **Planned maintenance**: announced 14, 7, and 1 calendar days ahead. It runs in a window of up to 4 hours during low-traffic hours at the DX location. +- **Emergency maintenance**: may start immediately and usually runs in a 2-hour window. You get notifications when it starts and when it completes. +- **Hosted connections**: both you and the partner receive the notifications. +- **Third-party (partner or carrier) maintenance**: AWS has no visibility into it. Ask your provider. +- **Where notices arrive**: AWS Health, the Health Dashboard, EventBridge integration, and AWS User Notifications (email delivery moved there on 2025-12-25). Add alternate contacts or distribution lists. +- **No rescheduling**: AWS does not postpone or cancel maintenance for individual customers, because devices are shared. + +Route AWS Health events to EventBridge, then to your ticketing system or chat. Before a known window, you can shift traffic proactively with local preference communities. + +## CloudWatch Network Synthetic Monitor + +This tool catches **grey failures**: BGP stays up but the path loses packets or its latency spikes. + +- You define probes by source subnet, on-premises destination IP, protocol (ICMP or TCP), port, and packet size. AWS runs the probe agents for you. +- It publishes RTT and packet loss, plus a Network Health Indicator (NHI). NHI = 100 means AWS saw degradation on the AWS-controlled part of the path (VPC to DX location). NHI = 0 means it did not. +- NHI is not accurate for DX attachments routed through Cloud WAN. +- AWS Interconnect (multicloud) free-tier interconnects include a Network Synthetic Monitor at no extra cost. + +## CloudTrail + +All DX API actions are logged. High-signal events to alert on: + +- `DeleteConnection`, `DeleteVirtualInterface`, `DeleteDirectConnectGateway` +- `CreatePrivateVirtualInterface`, `CreatePublicVirtualInterface`, `CreateTransitVirtualInterface`, `AllocateHosted*` +- `CreateDirectConnectGatewayAssociation`, `UpdateDirectConnectGatewayAssociation`, `AcceptDirectConnectGatewayAssociationProposal` (these change allowed prefixes) +- `StartBgpFailoverTest`, `AssociateMacSecKey`, `DisassociateMacSecKey` + +## Troubleshooting flow + +```mermaid +flowchart TD + S[Problem reported] --> Q1{ConnectionState = 1?} + Q1 -- No --> L1[Layer 1: cross-connect, optics, light, autoneg] + Q1 -- Yes --> Q2{Can ping Amazon peer IP?} + Q2 -- No --> L2[Layer 2: VLAN, subinterface, ARP, 802.1Q trunking] + Q2 -- Yes --> Q3{BGP Established?} + Q3 -- No --> L3[Layer 3/4: ASN, peer IPs, MD5, prefix limit, TCP 179] + Q3 -- Yes --> Q4{Traffic flows both ways?} + Q4 -- No --> RT[Routing: advertised prefixes, allowed prefixes, VPC/TGW route tables, SG/NACL] + Q4 -- "Yes but slow/lossy" --> PERF[Performance: utilization, errors, MTU, asymmetric paths, grey failure] +``` + +### Layer 1: physical connection down + +1. Confirm the colocation provider has completed the cross-connect, and compare the ports on the completion notice with your LOA-CFA. +2. Check that your router, or your provider's router, is powered on and the port is enabled. +3. Check the optic type: + - 1000BASE-LX for 1G. + - 10GBASE-LR for 10G. + - 100GBASE-LR4 for 100G. + - 400GBASE-LR4 for 400G. + - All run over single-mode fiber. +4. Set auto-negotiation correctly. Disable it for ports faster than 1 Gbps and set speed and duplex manually. For 1 Gbps, whether to enable it depends on the DX endpoint. +5. Check `ConnectionLightLevelTx` and `ConnectionLightLevelRx` in CloudWatch. Try rolling (swapping) the Tx and Rx fiber strands. +6. Ask the colocation provider for a written Tx/Rx light report, then open an AWS Support case with that report and the completion notice. +7. Remember the billing clock: port-hours start when the port becomes active, or 90 days after the LOA is issued, whichever comes first. + +### Layer 2: connection up, VIF down + +1. Configure the peer IP on the VLAN subinterface (for example `Gi0/0.123`), not on the physical interface. +2. Check that the VLAN ID matches the VIF. +3. Check that the ARP table on your router has an entry for the AWS peer. +4. Make sure every intermediate device (partner switches included) trunks your 802.1Q tag. AWS cannot resolve ARP until it receives tagged frames. +5. Clear the ARP cache on your side and ask your provider to clear theirs. + +### Layer 3/4: BGP not establishing + +1. Check your ASN and the Amazon ASN: + - Public VIF: 7224. + - Private VIF: the VGW or DXGW ASN. + - Transit VIF: the DXGW ASN. + - Long (4-byte) ASNs have been supported since 2025. +2. Check the peer IPs and subnet on both sides. +3. Check that the MD5 key matches exactly (watch for trailing spaces). +4. Check that you are within your prefix allocation. The default is 100 on private and transit VIFs, up to 1,000 with prefix controls. Public VIFs allow 1,000. +5. Make sure no ACL or firewall blocks TCP 179 or ephemeral ports. +6. Check that BGP TTL is 1 and that you are not trying multihop. +7. Read your BGP logs, then open a support case. + +### Routing: BGP up, no traffic + +1. Confirm that you actually advertise your on-premises prefix. `VirtualInterfaceBgpPrefixesAccepted` and route visibility show what AWS accepted. +2. **Private VIF on a VGW**: the VPC route table needs a route to the VGW, or enable route propagation (up to 100 propagated routes per table). +3. **DXGW to TGW**: the DXGW association's **allowed prefixes** decide what AWS advertises to on-premises. Missing CIDRs there are a classic cause of "on-premises can't reach the new VPC". +4. **TGW**: the DX attachment must be associated with and propagated to the right TGW route tables. VPC route tables must point to the TGW. +5. Security groups and network ACLs must allow the on-premises CIDRs. +6. For a public VIF, you must advertise public prefixes you own. AWS drops traffic whose source is not in your advertised prefixes. + +### Asymmetric routing + +Symptoms: stateful firewalls drop sessions, or traffic works in one direction only. + +| Cause | Fix | +| --- | --- | +| VPN backup advertises more-specific prefixes than DX | Advertise the same or less-specific prefixes over VPN, or filter on the customer gateway | +| On-premises prefers path A while AWS prefers path B | Align local preference on both sides. Use `7224:7300` and `7224:7100` toward AWS and a matching local-pref inside your network. | +| AWS default Region-affinity preference picks an unexpected location | Tag communities explicitly instead of relying on the default | +| Two private VIFs with different MTUs or a VPN for the same route | The effective MTU drops to 1500. Keep MTUs consistent. | + +### Performance and MTU + +- MTU: 1500 or 9001 on private VIFs, 1500 or 8500 on transit VIFs. Enabling jumbo frames can bounce every VIF on the connection for up to 30 seconds. +- Check `ConnectionBpsEgress` against port speed, `ConnectionErrorCount`, and `ConnectionDiscardsPpsEgress`. +- On hosted connections, compare `VirtualInterfaceBps*` with the purchased capacity. Hosted connections are rate-limited to that capacity. +- Use Network Synthetic Monitor to separate AWS-side from customer-side degradation. + +## Sources + +- CloudWatch metrics and dimensions: +- View DX CloudWatch metrics: +- BGP CloudWatch metrics (2026-03-30): +- Blog, VIF BGP health and prefix count metrics: +- BGP route visibility (2026-07): +- VIF rate limiters: +- VIF rate limiters announcement (2026-06-01): +- Prefix controls (2026-08-20): +- Quotas: +- Maintenance: +- Knowledge Center, maintenance notifications: +- Network Monitor GA (2023-12): +- Blog, Network Synthetic Monitor for hybrid connectivity: +- How Network Synthetic Monitor works (NHI): +- AWS Interconnect free 500 Mbps tier (includes Network Synthetic Monitor): +- CloudTrail: +- Troubleshooting index: +- Layer 1: +- Layer 2: +- Layer 3/4: +- Routing: +- Knowledge Center, light levels: +- Knowledge Center, transit VIF connectivity: +- Knowledge Center, asymmetric routing: +- MTU and jumbo frames: +- Dedicated connections (LOA-CFA and billing start): +- DX document history: diff --git a/docs/direct-connect/10-pricing.md b/docs/direct-connect/10-pricing.md new file mode 100644 index 0000000..ff6bada --- /dev/null +++ b/docs/direct-connect/10-pricing.md @@ -0,0 +1,187 @@ +# Pricing + +This is the one Direct Connect price list in this repository. The road map's DX chapter ([../04-direct-connect.md](../04-direct-connect.md#pricing-summary)) and cost chapter ([../12-security-and-operations.md](../12-security-and-operations.md)) link here instead of repeating the tables, and the site reads the same numbers from `src/data/dxPricing.ts`. Update both together. + +Direct Connect has two billing modes as of September 2026: + +- **Pay-as-you-go**: port-hours plus per-GB data transfer out (DTO). +- **Flat-rate**: launched 2026-09-15 for dedicated 10G and 100G connections. It is a fixed hourly rate that includes DTO for the AWS Regions in a chosen tier. + +Data into AWS over DX is always free. Cross-connect and colocation fees come from the facility operator, not AWS. + +_Prices are USD list prices taken from aws.amazon.com/directconnect/pricing on 2026-10-12, and they exclude tax (Japanese Consumption Tax applies to customers with a Japanese billing address). AWS pricing changes. Always check the live page or the AWS Pricing Calculator. Monthly figures assume 730 hours._ + +## What you pay for + +```mermaid +flowchart LR + subgraph AWS bill + PH[Port-hours: per connection, by speed and type] + DTO[Data transfer out: per GB, by source Region and DX location] + SL[SiteLink: $0.50/VIF-hour + per-GB] + TGW[TGW / Cloud WAN attachment-hours + data processing, if used] + end + subgraph Not AWS + XC[Cross-connect + colocation: colo provider] + LM[Last-mile circuit / hosted service fee: carrier or DX partner] + end + DIN[Data transfer in: $0.00] +``` + +| Component | Billed by | Notes | +| --- | --- | --- | +| Port-hours | AWS | Charged while the port is provisioned, even with zero traffic. Starts when the port goes active or 90 days after the LOA is issued, whichever comes first. | +| DTO | AWS | Per GB. The rate depends on the **source Region** (or Local Zone) and the **DX location's** geography. With a DX gateway, you pay the rate for the source Region to the DX location where the traffic exits. | +| Data transfer in | AWS | $0.00/GB at all locations | +| DX gateway | AWS | No separate DX gateway charge. AWS states there are "no additional charges to use a multi-account AWS Direct Connect gateway". | +| TGW DX attachment | AWS (Transit Gateway) | Hourly attachment charge, billed to the DXGW owner, plus TGW data processing per GB. Example: $0.05/hour and $0.02/GB in US East (Ohio). | +| SiteLink | AWS | $0.50 per SiteLink-enabled VIF-hour plus per-GB SiteLink transfer | +| Cross-connect and colocation | Colo operator or partner | Not on your AWS bill | +| Hosted connection service | DX partner | The partner's own fees apply on top of AWS hosted port-hours | + +## Port-hour prices (pay-as-you-go) + +### Dedicated connections + +Prices are the same at every DX location worldwide except Japan. + +| Speed | $/hour (non-Japan) | ≈ $/month | $/hour (Japan) | ≈ $/month (Japan) | +| --- | --- | --- | --- | --- | +| 1 Gbps | 0.30 | 219.00 | 0.285 | 208.05 | +| 10 Gbps | 2.25 | 1,642.50 | 2.142 | 1,563.66 | +| 100 Gbps | 22.50 | 16,425.00 | 22.50 | 16,425.00 | +| 400 Gbps | 85.00 | 62,050.00 | 85.00 | 62,050.00 | + +### Hosted connections + +| Capacity | $/hour (non-Japan) | ≈ $/month | $/hour (Japan) | +| --- | --- | --- | --- | +| 50 Mbps | 0.03 | 21.90 | 0.029 | +| 100 Mbps | 0.06 | 43.80 | 0.057 | +| 200 Mbps | 0.08 | 58.40 | 0.076 | +| 300 Mbps | 0.12 | 87.60 | 0.114 | +| 400 Mbps | 0.16 | 116.80 | 0.152 | +| 500 Mbps | 0.20 | 146.00 | 0.190 | +| 1 Gbps | 0.33 | 240.90 | 0.314 | +| 2 Gbps | 0.66 | 481.80 | 0.627 | +| 5 Gbps | 1.65 | 1,204.50 | 1.568 | +| 10 Gbps | 2.48 | 1,810.40 | 2.361 | +| 25 Gbps | 6.20 | 4,526.00 | 6.20 | + +The 1 Gbps and higher hosted capacities are available only from select partners. The 25 Gbps hosted capacity was added on 2024-04-24. A hosted 10G costs slightly more per hour than a dedicated 10G ($2.48 versus $2.25), and the partner also charges its own fees. + +## Data transfer out: representative rates (USD/GB) + +Rows are the source AWS Region. Columns are where the DX location is. + +| Source Region to DX location in | Contiguous US | Europe | Japan | Singapore/HK/Korea/Taiwan/Malaysia/Bangkok | Australia/NZ | +| --- | --- | --- | --- | --- | --- | +| Contiguous US (includes GovCloud) | 0.0200 | 0.0200 | 0.0491 | 0.0491 | 0.0600 | +| Europe | 0.0282 | 0.0200 | 0.0600 | 0.0600 | 0.0600 | +| Asia Pacific (Tokyo, Osaka) | 0.0900 | 0.0600 | 0.0410 | 0.0410 | 0.1132 | +| Asia Pacific (Singapore, Seoul, HK, Taiwan, KL, Bangkok) | 0.0900 | 0.0900 | 0.0420 | 0.0410 | 0.1107 | +| Asia Pacific (India) | 0.0850 | 0.0850 | 0.1132 | 0.1000 | 0.1100 | +| Asia Pacific (Australia, Auckland) | 0.1300 | 0.1300 | 0.1132 | 0.1107 | 0.0420 | +| South America (São Paulo, Mexico) | 0.1500 | 0.1107 | 0.1700 | 0.1700 | 0.1800 | + +Takeaways: + +- **US and Europe, same continent: $0.02/GB.** Tokyo Region to a Japan DX location: **$0.041/GB**, about double. US Region to a Japan DX location: $0.0491/GB. Tokyo Region to a US DX location: $0.09/GB. +- Internet DTO from EC2 is much higher at typical volumes. See the EC2 pricing page. Heavy egress is a classic reason to buy DX. +- For public resources (for example S3 or EC2 with public IPs), DTO is metered at the DX rate only if the destination is a public prefix owned by the **same AWS payer account** and advertised over a public VIF. Otherwise internet DTO rates apply. +- On private and transit VIFs, DTO is charged to the AWS account that sent the data, not to the DX owner. + +## Japan locations (from the AWS Price List API) + +The road map's cost lab works from Tokyo, so it uses the Japan columns above and these rows, read from the AWS Price List API (Direct Connect offer for ap-northeast-1 and ap-northeast-3, published 2026-10-05). Japan locations in the price list: Equinix TY2 (Tokyo), AT Tokyo Chuo, NEC Inzai, Equinix OS1 (Osaka), all billed under Asia Pacific (Tokyo), and KDDI Telehouse Osaka 2, billed under Asia Pacific (Osaka). Pay-as-you-go 100 Gbps SKUs appear at AT Tokyo, NEC Inzai and Telehouse Osaka 2; check the locations page for the speeds a specific site offers today. + +| Item | Unit | Price (USD) | +| --- | --- | --- | +| DX DTO Tokyo → Japan DX locations (Equinix TY2, AT Tokyo Chuo, NEC Inzai, Equinix OS1) | per GB | 0.041 | +| DX DTO Tokyo → Equinix SG2, Taipei locations | per GB | 0.041 | +| DX DTO Tokyo → Equinix LD4–LD6 (London) | per GB | 0.06 | +| DX DTO Tokyo → Equinix SV1/SV5 (Silicon Valley) | per GB | 0.09 | +| DX dedicated port 1 Gbps (Japan locations) | per hour | 0.285 | +| DX dedicated port 10 Gbps | per hour | 2.142 | +| DX dedicated port 100 Gbps (AT Tokyo Chuo, NEC Inzai) | per hour | 22.50 | +| DX hosted 50 / 100 / 200 / 300 / 400 / 500 Mbps | per hour | 0.029 / 0.057 / 0.076 / 0.114 / 0.152 / 0.190 | +| DX hosted 1 / 2 / 5 / 10 Gbps | per hour | 0.314 / 0.627 / 1.568 / 2.361 | +| DX flat-rate 10G, Tier 1 / 2 / 3 (single port) | per hour | 10.96 / 17.12 / 23.29 | +| DX flat-rate 10G port-pair, per port, Tier 1 / 2 / 3 | per hour | 5.48 / 8.56 / 11.64 | +| DX flat-rate 100G, Tier 1 / 2 / 3 (single port) | per hour | 102.74 / 160.96 / 219.18 | +| DX flat-rate 100G port-pair, per port, Tier 1 / 2 / 3 | per hour | 51.37 / 80.48 / 109.59 | +| DX SiteLink | per VIF-hour | 0.50 | + +Flat-rate Direct Connect (2026-09) applies to 10G and 100G **dedicated** connections only. It zeroes DTO between the DX location and the Regions in the chosen tier (Tier 1 local metro … Tier 5 global); traffic from Regions outside the tier pays standard DX DTO. The second port of a port-pair is included at no extra charge (the pair rate is exactly half the single-port rate per port). For ap-northeast-1, the Price List API marks all four Japan locations (including Equinix OS1, Osaka) as Tier 1, Equinix SG2 and Silicon Valley as Tier 3, London as Tier 4, Taipei as Tier 5. All connections at one DX location in an account must use the same billing mode. TGW/Cloud WAN processing, SiteLink transfer and partner fees are not covered. + +## SiteLink + +- $0.50 per hour per SiteLink-enabled VIF, charged even when idle. +- Per-GB transfer between DX locations. Examples: US to US $0.02, US to Europe $0.0282, Japan to Japan $0.041, Japan to Singapore group $0.042. +- AWS's example: New York and Amsterdam, 2 VIFs each, 100 TB total. That costs $1,460 in SiteLink hours plus $2,887.68 in transfer, for $4,347.68 per month. +- Flat-rate tiers do **not** cover SiteLink traffic. + +## Flat-rate pricing (2026-09-15) + +| Concept | Detail | +| --- | --- | +| Eligibility | Dedicated connections only (not hosted). Announced for 10 Gbps and 100 Gbps. All commercial Regions except China. | +| What's included | Port plus all DTO from the Regions covered by the chosen tier, for private, public, and transit traffic. DTO from Regions outside the tier is billed at standard DX rates. | +| Tiers | Tier 1 (same metro) to Tier 5 (global). Higher tiers include every path in lower tiers. Tier 1 is cheapest. | +| Port-pair | Two ports on different devices or locations, same speed and tier, grouped in a **resiliency group**. The second port is free. Usable bandwidth = one port (10G pair = 10G). | +| Single flat-rate connection | Allowed, and it costs the **same** as a port-pair. You just don't get the free redundant port. | +| Billing granularity | Hourly, rounded up | +| Switching | You can switch between pay-as-you-go and flat-rate at most 3 times per connection in a rolling 6 months | +| Constraint | All connections in one account at one DX location must use the same billing mode. Use separate accounts to mix modes. LAG members must share a billing mode. | +| Bandwidth change | Not possible. Create a new connection instead. | + +AWS's published examples: + +| Example | Tier | List rate | Monthly (730 h) | +| --- | --- | --- | --- | +| 10G port-pair at Equinix DC2 Ashburn, traffic from us-east-1 | Tier 1 | $10.96/hour | AWS states $8,000.07 (10.96 × 730 = $8,000.80) | +| 100G port-pair at SFO, traffic from us-east-1 (Tier 2 path) and eu-central-1 (Tier 3 path) | Tier 3 | $219.18/hour | "nearly $160,000" | + +### Is flat-rate cheaper? A rough break-even (own calculation) + +Compare a 10G Tier 1 port-pair ($10.96/hour) with two pay-as-you-go 10G dedicated ports ($4.50/hour = $3,285/month) plus DTO at $0.02/GB (US to US): + +- Flat-rate costs $8,000.80 − $3,285 = $4,715.80 per month more in port charges. +- $4,715.80 ÷ $0.02/GB ≈ 235,790 GB ≈ **230 TB of DTO per month** to break even. + +Below about 230 TB/month of same-metro US egress, pay-as-you-go is cheaper. Above it, flat-rate wins and your bill becomes predictable. In higher-priced geographies (for example Tokyo Region to a Japan location at $0.041/GB) the break-even volume is lower, but the tier prices differ too. This is an illustration derived from list prices, not an AWS figure. + +## Worked pay-as-you-go examples (from the AWS pricing page) + +| Scenario | Ports | Port cost | DTO | Total/month | +| --- | --- | --- | --- | --- | +| High resiliency: 2 locations (Chicago and Columbus), 1 × 2G hosted each, 1 TB out from us-east-2 | 2 × $0.66/hour | $963.60 | 1,024 GB × $0.02 = $20.48 | **$984.08** | +| Maximum resiliency: 2 locations (Newark and Columbus), 2 × 10G dedicated each, 400 TB out from us-east-2, 1 PB in | 4 × $2.25/hour | $6,570.00 | 409,600 GB × $0.02 = $8,192.00 | **$14,762.00** | + +The 1 PB of inbound data in the second example costs $0. + +## Cost optimization tips + +- **Right-size the port.** If you don't need the full capacity of a dedicated port, a hosted connection (50 Mbps to 25 Gbps) may be cheaper. You can also consolidate several small links into one larger port. +- **Keep egress local.** DTO depends on the source Region and the DX location. Serve traffic from the Region associated with your DX location's geography, for example Tokyo Region to Tokyo or Osaka locations at $0.041/GB instead of a US Region to Japan at $0.0491/GB. +- **Use DX instead of the internet for bulk egress.** DX DTO rates are far below internet egress. +- **Consider flat-rate** for heavy, predictable 10G or 100G egress. Pick the lowest tier that covers most of your bytes and let outliers pay standard DTO. +- **Delete unused ports and VIFs.** Port-hours accrue with zero traffic. An ordered but unused port starts billing 90 days after the LOA is issued. +- **Avoid needless TGW hops.** A private VIF to a DXGW to a VGW avoids TGW attachment and processing charges if you don't need transitive routing. TGW is worth it when you have many VPCs. +- **Leave SiteLink off when idle.** It costs $0.50/hour per VIF even without traffic. +- **Size the backup to its job.** A VPN backup is cheaper than a second DX, but it has no SLA. Flat-rate port-pairs include the second port for free. +- **Don't forget non-AWS costs.** Cross-connects (monthly fee to the colo), carrier circuits, and partner fees are often larger than the AWS port-hours for small links. + +## Sources + +- DX pay-as-you-go pricing (port-hours, DTO table, SiteLink, examples): +- DX flat-rate pricing (tiers, port-pairs, examples): +- Flat-rate announcement (2026-09-15): +- Flat-rate billing, User Guide: +- DX Pricing Guide, overview (cross-connect fees): +- DX Pricing Guide, flat-rate: +- What is Direct Connect (billing elements, DXGW no extra charge): +- Dedicated connections (billing start / 90 days): +- 25 Gbps hosted connections (2024-04-24): +- Transit Gateway pricing: +- Knowledge Center, reduce DX costs: diff --git a/docs/direct-connect/11-design-patterns.md b/docs/direct-connect/11-design-patterns.md new file mode 100644 index 0000000..9df8e91 --- /dev/null +++ b/docs/direct-connect/11-design-patterns.md @@ -0,0 +1,181 @@ +# Design patterns and anti-patterns + +This page collects reusable Direct Connect topologies, the mistakes that cause real outages, and a decision tree for choosing a topology. It builds on [Resiliency](07-resiliency.md), [Security](08-security.md), and [Pricing](10-pricing.md). + +_Last verified: 2026-10-12._ + +## Building blocks (quick recap) + +| Block | Use it for | Key limits | +| --- | --- | --- | +| Private VIF to VGW | One VPC in the same Region as the DX location | 1 VPC per VIF | +| Private VIF to DX gateway to VGWs | Up to 20 VPCs (VGWs) in any Regions and accounts, no transitive routing | 20 VGWs per DXGW. 30 private or transit VIFs per DXGW. | +| Transit VIF to DX gateway to TGW | Many VPCs through TGW, transitive routing, Private IP VPN | 6 TGWs per DXGW. 4 transit VIFs per dedicated connection. 200 prefixes per TGW advertised to on-premises. | +| Transit VIF to DX gateway to Cloud WAN | Global, policy-driven WAN with segments (since 2024-11-25) | 5,000 prefixes advertised to on-premises. DX communities are not supported inside Cloud WAN. | +| Public VIF | AWS public endpoints (S3, public APIs, VPN endpoints) over DX | 1,000 routes per session | +| SiteLink | Site-to-site traffic between DX locations without going through a Region | $0.50 per VIF-hour plus per-GB | + +## Pattern 1: Single Region, few VPCs (private VIF + DXGW) + +```mermaid +flowchart LR + DC[Data center] -->|2+ DX, 2 locations| DXGW[DX gateway] + DXGW --> VGW1[VGW - VPC prod] + DXGW --> VGW2[VGW - VPC dev] +``` + +- Simple and cheap: no TGW attachment or processing charges. +- Use a DX gateway rather than attaching the VIF directly to a VGW, so you can add Regions later without re-cabling. +- The DXGW carries only north-south traffic (on-premises to VPC). It does not route VPC to VPC. + +## Pattern 2: Hub-and-spoke with Transit Gateway (transit VIF) + +```mermaid +flowchart LR + DC1[DC A] -->|DX loc 1| DXGW[DX gateway] + DC2[DC B] -->|DX loc 2| DXGW + DXGW -->|allowed prefixes: summaries| TGW1[TGW us-east-1] + DXGW --> TGW2[TGW ap-northeast-1] + TGW1 --> V1[VPCs] + TGW2 --> V2[VPCs] + TGW1 <-->|inter-Region peering| TGW2 +``` + +- The standard enterprise pattern for dozens to thousands of VPCs. +- Advertise **summarized** allowed prefixes from each TGW. At most 200 prefixes per TGW go to on-premises, so plan CIDRs so they summarize. +- The TGW ASN must differ from the DXGW ASN. If both use the default 64512, the association fails. +- Private IP VPN runs over the same transit VIF when you need encryption (see [Security](08-security.md)). + +## Pattern 3: Global WAN with Cloud WAN + +- Attach DX gateways directly to a Cloud WAN core network (no TGW required). Routes propagate by BGP, segments give isolation, and attachments are controlled by tag policies. +- Caveats: + - A DXGW associated with a core network can't also serve VGWs or TGWs. + - DX BGP communities are not honored inside Cloud WAN. + - You can't filter the allowed prefixes advertised to on-premises. + - The DXGW ASN must be outside the core network ASN range. + +## Pattern 4: Public services over DX (public VIF) + +- Use it for bulk S3 transfer or IPsec VPN endpoints, or when the organization mandates public-endpoint access without the internet. +- Filter what you accept with the `7224:8100` and `7224:8200` communities. Scope what you advertise with `7224:9100`, `9200`, or `9300`. Put a firewall on the public VIF. +- Alternative: a private VIF plus VPC interface or gateway endpoints keeps everything in private address space. + +## Pattern 5: Encrypted DX + +| Need | Pattern | +| --- | --- | +| 10G+ dedicated, link encryption | MACsec on the ports or LAG, `must_encrypt` after validation | +| Any speed, end-to-end to the VPC edge, no public IPs | Private IP VPN over transit VIF to TGW | +| Both | MACsec on the physical link plus Private IP VPN or TLS | + +## Pattern 6: DX primary, VPN backup + +- DX is preferred automatically on both VGW and TGW for the same prefix. +- Advertise the same or less-specific prefixes over the VPN. +- Use TGW VPN with ECMP, or the 5 Gbps Large Bandwidth Tunnels (2025), when the DX is faster than 1 Gbps. + +## Pattern 7: Branch-to-branch with SiteLink + +- Enable SiteLink on VIFs attached to the same DX gateway. Traffic then takes the shortest path between DX locations without entering a Region. +- It replaces "hairpin through a Region" designs and needs no Region resources. +- Watch the prefix limits (up to 1,000 each for IPv4 and IPv6 with prefix controls). Flat-rate tiers do not cover SiteLink. + +## Pattern 8: Multicloud and last mile (2025–2026) + +- **AWS Interconnect – multicloud**: previewed 2025-11-30, GA 2026-04-13. It gives managed private links from VPC, TGW, or Cloud WAN to Google Cloud (GA), Oracle OCI (GA 2026-07), and Microsoft Azure (preview 2026-08). There is a free 500 Mbps local tier per Region (from May 2026). Consider it before building DX-to-colo-to-other-cloud chains yourself. +- **AWS Interconnect – last mile**: with Lumen in the US, previewed 2025-11 and GA 2026-04. AWS orchestrates the circuit, BGP, and VLAN from the console. Bandwidth scales from 1 to 100 Gbps, and MACsec is on by default. + +## Anti-patterns + +| Anti-pattern | Why it hurts | Instead | +| --- | --- | --- | +| Single DX connection for production | No SLA beyond 95%. Every AWS maintenance window becomes an outage. | 2+ locations (High), or 2 × 2 on separate devices (Maximum) | +| Two connections in the same location "for redundancy" | Doesn't survive a location failure. Development/test grade only. | Spread across 2 DX locations | +| Redundant DX links sharing one carrier conduit or one customer router | Hidden shared fate | Diverse carriers and paths, separate routers | +| Every link at 90% utilization | After a failure the survivors are overloaded | Size N+1. Alarm at 70–80%. | +| Static routing or BGP without BFD | 90-second failover, or no failover at all | BGP + BFD (300 ms × 3), graceful restart off | +| Mismatched active/passive (AWS prefers A, on-premises prefers B) | Asymmetric routing breaks stateful firewalls | Communities toward AWS plus matching local-pref on-premises | +| VPN backup advertising more-specific prefixes than DX | VPN becomes primary for return traffic | Same or less-specific over VPN, and filter | +| AS_PATH prepend to demote a VPN | DX wins anyway for equal prefixes, so it creates confusion | Rely on DX-over-VPN preference or prefix length | +| Advertising hundreds of /24s | Blows past the prefix quota. The BGP session goes idle and DOWN. | Summarize. Use prefix controls (up to 1,000). Alarm on `VirtualInterfaceBgpPrefixesAccepted`. | +| Public VIF with no filtering | Accepts all AWS prefixes, and all AWS tenants can reach your advertised prefixes | Firewall plus community filters, or a private VIF plus endpoints | +| Assuming DX is encrypted | It isn't | MACsec and/or IPsec and/or TLS | +| Never testing failover | You only discover the misconfiguration during maintenance | Regular BGP failover test (up to 72 hours) | +| Same ASN on TGW and DXGW | Association fails | Different private ASNs | +| Mixing MTUs across paths | Falls back to 1500, and PMTUD issues | Consistent MTU (9001 private VIF, 8500 transit VIF) | +| Ignoring non-AWS costs | Cross-connects and circuits can dominate | Include colo and carrier costs in the TCO | + +## Decision tree: choosing a topology + +```mermaid +flowchart TD + A[Start: need private connectivity to AWS] --> B{Production / business critical?} + B -- No --> DT[Dev/Test model: 2 conns, 1 location, or 1 DX + VPN] + B -- Yes --> C{Need 99.99%?} + C -- Yes --> MAX["Maximum resiliency: 2+ locations x 2 devices each, Enterprise Support + WAR"] + C -- No --> HIGH["High resiliency: 1 conn in each of 2+ locations (99.9%)"] + MAX --> D{How many VPCs / Regions?} + HIGH --> D + DT --> D + D -- "1-20 VPCs, no transitive routing" --> P1[Private VIF -> DX gateway -> VGWs] + D -- "Many VPCs / need transit / Private IP VPN" --> P2[Transit VIF -> DX gateway -> TGW] + D -- "Global multi-Region WAN with segments" --> P3[Transit VIF -> DX gateway -> Cloud WAN] + P1 --> E{Need AWS public endpoints over DX?} + P2 --> E + P3 --> E + E -- Yes --> PUB[Add public VIF with filtering, or use VPC endpoints] + E -- No --> F{Encryption required?} + PUB --> F + F -- "10G+ dedicated" --> MS[MACsec] + F -- "1G / hosted / end-to-end" --> IPS[Private IP VPN over transit VIF] + F -- No --> G{Site-to-site between your DCs?} + MS --> G + IPS --> G + G -- Yes --> SL[Enable SiteLink] + G -- No --> H{Speed needed per location?} + SL --> H + H -- "< 1 Gbps or flexible" --> HOSTED[Hosted connection 50M-25G via partner] + H -- "1/10/100/400 Gbps" --> DED[Dedicated connection, LAG if needed] + DED --> I{Heavy predictable egress on 10G/100G?} + I -- Yes --> FR[Evaluate flat-rate port-pair] + I -- No --> PAYG[Pay-as-you-go] +``` + +## Dedicated vs hosted cheat sheet + +| Factor | Dedicated | Hosted | +| --- | --- | --- | +| Speeds | 1, 10, 100, 400 Gbps | 50 Mbps to 25 Gbps | +| VIFs | Up to 51 (50 public/private plus up to 4 transit, 51 total) | 1 | +| LAG | Yes (4 × <100G or 2 × 100/400G) | No | +| MACsec | 10/100/400G at select locations | No | +| SLA | Yes, if you meet the deployment requirements | Not covered by the DX SLA | +| Rate limiters | Yes (up to 10) | Always limited to the purchased capacity | +| Flat-rate | Yes (10G/100G) | No | +| Lead time | Order, LOA-CFA, cross-connect | Partner provisions it, you accept | + +## Sources + +- Quotas: +- Virtual interfaces and MTU: +- Create VIF (TGW/DXGW ASN must differ): +- DX gateways: +- DXGW and Transit Gateway associations: +- DXGW and Cloud WAN: +- Cloud WAN DX attachments (limitations): +- Cloud WAN native DX integration (2024-11): +- Routing policies and BGP communities: +- Resiliency recommendations: +- Hybrid Connectivity whitepaper, reliability and decision tree: +- Well-Architected Hybrid Networking Lens, DX and IPsec: +- SiteLink launch: +- LAG: +- VIF rate limiters: +- AWS Interconnect – multicloud preview (2025-11-30): +- AWS Interconnect – multicloud GA (2026-04-13): +- AWS Interconnect – multicloud with OCI GA (2026-07): +- AWS Interconnect – multicloud with Azure preview (2026-08): +- AWS Interconnect – last mile GA (2026-04): +- Knowledge Center, asymmetric routing: +- DX SLA: diff --git a/docs/direct-connect/12-timeline.md b/docs/direct-connect/12-timeline.md new file mode 100644 index 0000000..07d667a --- /dev/null +++ b/docs/direct-connect/12-timeline.md @@ -0,0 +1,123 @@ +# Timeline + +This is a dated history of notable AWS Direct Connect launches, from the 2011 public release to the 2026 flat-rate pricing. Dates come from the DX User Guide document history and from AWS What's New posts. Where the two differ, both are noted. + +_Last verified: 2026-10-12._ + +> Note: Direct Connect launched on **2011-08-03**, not 2012. The 2012 milestones are the new console, the User Guide, IAM support, and more Regions. + +## At a glance + +```mermaid +timeline + title AWS Direct Connect milestones + 2011 : Public release (Aug 3), 1G and 10G, Equinix Ashburn + 2013 : Hosted connections (sub-1G via partners) + 2016 : IPv6 BGP peering, tagging, self-service LOA-CFA + 2017 : LAG (Feb), CloudWatch metrics (Jun), Direct Connect gateway (Nov) + 2018 : Local preference BGP communities (Feb), jumbo frames (Oct) + 2019 : Transit VIF and Transit Gateway support, Resiliency Toolkit (Oct) + 2020 : VIF CloudWatch metrics (May), failover testing (Jun) + 2021 : Native 100G (Feb), MACsec (Mar), SiteLink (Dec) + 2022 : Private IP VPN over DX (Jun) + 2023 : Network Monitor GA for hybrid paths (Dec) + 2024 : 25G hosted (Apr), native 400G (Jul), Cloud WAN native DX attachment (Nov) + 2025 : MACsec on partner interconnects (Jul), 4-byte ASN (Sep), Interconnect multicloud preview (Nov) + 2026 : BGP metrics (Mar), Interconnect GA (Apr), VIF rate limiters (Jun), route visibility (Jul), prefix controls (Aug), flat-rate pricing (Sep) +``` + +## Detailed timeline + +| Date | Launch | Why it matters | Source | +| --- | --- | --- | --- | +| 2011-08-03 | Public release of AWS Direct Connect. 1G and 10G ports at Equinix Ashburn for US East. | Dedicated private link to AWS, bypassing the internet | [What's New](https://aws.amazon.com/about-aws/whats-new/2011/08/03/Announcing-AWS-Direct-Connect/), [doc history](https://docs.aws.amazon.com/directconnect/latest/UserGuide/AboutThisGuide.html) | +| 2011-09-08 | US West (N. California) | First expansion | doc history | +| 2012-01-10 | Locations for Ireland, Singapore, Tokyo, N. California | Global footprint begins | doc history | +| 2012-08-13 | New DX console. User Guide replaces the Getting Started Guide. São Paulo added. | Self-service management | doc history | +| 2012-12-21 | IAM support | Access control for DX APIs | doc history | +| 2013-10-22 | Hosted connections | Sub-1G capacity through APN partners | doc history | +| 2013-12-19 | Access to remote AWS Regions (public resources) | One location reaches other Regions' public services | doc history | +| 2014-04-04 | CloudTrail support | API audit trail | doc history | +| 2016-06-22 | Self-service LOA-CFA download | Faster cross-connect ordering | doc history | +| 2016-11-04 | Resource tagging | Tag-based IAM and cost allocation | doc history | +| 2016-12-01 | IPv6 BGP peering on VIFs | Dual-stack hybrid | doc history | +| 2017-02-13 | Link aggregation groups (LAG) | Up to 4 ports as one logical link with one BGP session | doc history, [What's New](https://aws.amazon.com/de/about-aws/whats-new/2017/02/aws-direct-connect-announces-support-for-link-aggregation) | +| 2017-06-29 | CloudWatch connection metrics | Native monitoring | doc history | +| 2017-11-01 | Direct Connect gateway. DTO pricing becomes based on source Region and DX location. | One DX reaches VPCs in any Region (except China) | [What's New](https://aws.amazon.com/about-aws/whats-new/2017/11/aws-direct-connect-enables-global-access/), [blog](https://aws.amazon.com/blogs/aws/new-aws-direct-connect-gateway-inter-region-vpc-access/) | +| 2018-02-06 | Local preference BGP communities (`7224:7100/7200/7300`) | Active/active and active/passive control | doc history | +| 2018-10-11 | Jumbo frames (9001 MTU) | Higher throughput for bulk flows | doc history | +| 2019-03-27 (doc) / April 2019 (What's New) | Transit VIF and Transit Gateway support through DXGW | Hub-and-spoke to thousands of VPCs | doc history, [What's New](https://aws.amazon.com/about-aws/whats-new/2019/04/announcing-aws-direct-connect-support-for-aws-transit-gateway/) | +| 2019-10-07 | Resiliency Toolkit (connection wizard with SLA models) | Guided ordering of redundant connections | doc history | +| 2020-05-11 | CloudWatch VIF metrics | Per-VIF traffic visibility | doc history | +| 2020-06-03 | Resiliency Toolkit failover testing | Test BGP failover on demand (up to 72 hours) | doc history | +| 2021-02 | Native 100 Gbps dedicated connections | No need to LAG 10G links | [What's New](https://aws.amazon.com/about-aws/whats-new/2021/02/aws-direct-connect-announces-native-100-gbps-connections-select-locations/), doc history (2021-02-12) | +| 2021-03-31 | MACsec on 10G and 100G dedicated connections | Line-rate L2 encryption | [What's New](https://aws.amazon.com/about-aws/whats-new/2021/03/aws-direct-connect-announces-macsec-encryption-for-dedicated-10gbps-and-100gbps-connections-at-select-locations/) | +| 2021-12-01/02 | SiteLink | Site-to-site over the AWS backbone between DX locations | [What's New](https://aws.amazon.com/about-aws/whats-new/2021/12/aws-direct-connect-sitelink/), doc history | +| 2022-06-22 | Private IP Site-to-Site VPN over DX transit VIF | IPsec over DX without public IPs | [What's New](https://aws.amazon.com/about-aws/whats-new/2022/06/aws-site-vpn-introduces-private-ip-security-privacy) | +| 2022-08-08 | Transit VIFs on hosted connections of any speed (previously 1/2/5/10 Gbps only) | Sub-1G hosted connections can reach Transit Gateway directly | [What's New](https://aws.amazon.com/about-aws/whats-new/2022/08/aws-direct-connect-expands-transit-gateway-support-connection-speeds/) | +| 2023-06-15 | SiteLink prefix limit documented | Scale guardrail | doc history | +| 2023-12 | CloudWatch Network Monitor GA (later renamed Network Synthetic Monitor) | Packet loss and RTT over DX, plus the AWS Network Health Indicator | [What's New](https://aws.amazon.com/about-aws/whats-new/2023/12/amazon-cloudwatch-network-monitor-generally-available/) | +| 2024-04-24 | 25 Gbps hosted connections | Hosted range becomes 50M to 25G | [What's New](https://aws.amazon.com/about-aws/whats-new/2024/04/aws-direct-connect-gbps-hosted-connection-capacities/) | +| 2024-07-01 | Native 400 Gbps dedicated connections (select locations), MACsec capable | AI/ML-scale data movement | [What's New](https://aws.amazon.com/about-aws/whats-new/2024/07/aws-direct-connect-native-400-gbps-dedicated-connections-select-locations/) | +| 2024-11-25 | Cloud WAN native DX gateway attachment (no TGW needed) | Global policy-based hybrid WAN | [What's New](https://aws.amazon.com/about-aws/whats-new/2024/11/aws-cloud-wan-on-premises-connectivity-direct-connect/) | +| 2025-07-28 | MACsec on partner interconnects | Encrypts the partner-to-AWS hop | [What's New](https://aws.amazon.com/about-aws/whats-new/2025/07/aws-direct-connect-extends-macsec-support-partner-interconnects/) | +| 2025-09-12 (What's New) / 2025-07-24 (doc) | 4-byte (long) ASN on all VIF types | ASNs up to 4,294,967,294 | [What's New](https://aws.amazon.com/about-aws/whats-new/2025/09/aws-direct-connect-4-byte-autonomous-system-numbers/) | +| 2025-11-12 | Site-to-Site VPN 5 Gbps tunnels | Viable VPN backup or overlay for faster DX | [What's New](https://aws.amazon.com/about-aws/whats-new/2025/11/aws-site-to-site-vpn-5-gbps-bandwidth-tunnels) | +| 2025-11 | AWS Interconnect – last mile (Lumen) gated preview | Console-ordered last-mile circuits | [What's New](https://aws.amazon.com/about-aws/whats-new/2025/11/gated-preview-interconnect-last-mile/) | +| 2025-11-30 | AWS Interconnect – multicloud preview (Google Cloud first) | Managed private cloud-to-cloud links | [What's New](https://aws.amazon.com/about-aws/whats-new/2025/11/preview-aws-interconnect-multicloud/) | +| 2026-03 | DX resources in CloudFormation (connections, VIFs, DXGW, LAG, BGP peers) | Infrastructure as code | [What's New](https://aws.amazon.com/about-aws/whats-new/2026/03/aws-direct-connect-supports-aws-cloudformation/) | +| 2026-03-30 | CloudWatch BGP metrics (`VirtualInterfaceBgpStatus`, `PrefixesAccepted`, `PrefixesAdvertised`) | Native BGP alarms | [What's New](https://aws.amazon.com/about-aws/whats-new/2026/03/aws-direct-connect-cloudwatch-bgp-monitoring/) | +| 2026-04-13 | AWS Interconnect – multicloud GA (Google Cloud). Last mile GA in April. | Multicloud without self-managed colo | [What's New](https://aws.amazon.com/about-aws/whats-new/2026/04/aws-announces-ga-AWS-interconnect-multicloud/), [last mile GA](https://aws.amazon.com/about-aws/whats-new/2026/04/aws-announces-ga-AWS-interconnect-last-mile/) | +| 2026-05 | Interconnect – multicloud free 500 Mbps tier | Free local interconnect per Region per cloud provider | [What's New](https://aws.amazon.com/about-aws/whats-new/2026/05/aws-interconnect-multicloud-offers-free-500-mbps-tier/) | +| 2026-06-01 | VIF rate limiters (50 Mbps to 1.6 Tbps, up to 10 per connection) | Noisy-neighbor protection | [What's New](https://aws.amazon.com/about-aws/whats-new/2026/06/aws-direct-connect-now-supports-vif-rate-limiters/) | +| 2026-07-24 | DX SLA document updated (99.99 / 99.9 / 95%) | Current SLA terms | [SLA](https://aws.amazon.com/directconnect/sla/) | +| 2026-07 | Interconnect – multicloud with Oracle OCI GA | Second GA cloud partner | [What's New](https://aws.amazon.com/about-aws/whats-new/2026/07/aws-announces-AWS-interconnect-multicloud-OCI-GA/) | +| 2026-07-30 | BGP route visibility (`ListVirtualInterfaceRoutes`) | See accepted and advertised routes per VIF | [What's New](https://aws.amazon.com/about-aws/whats-new/2026/07/aws-direct-connect-bgp-visibility/), doc history | +| 2026-08 | Interconnect – multicloud with Microsoft Azure preview | Third cloud partner | [What's New](https://aws.amazon.com/about-aws/whats-new/2026/08/aws-announces-AWS-interconnect-multicloud-microsoft-azure-preview/) | +| 2026-08-20 | Inbound prefix controls: up to 1,000 IPv4 and 1,000 IPv6 prefixes per private or transit VIF (was 100) | Removes the 100-route constraint | [What's New](https://aws.amazon.com/about-aws/whats-new/2026/08/aws-direct-connect-new-prefix-controls/) | +| 2026-09-15 | Flat-rate pricing for dedicated 10G and 100G with port-pairs and 5 geographic tiers | Predictable bills, with the redundant port included | [What's New](https://aws.amazon.com/about-aws/whats-new/2026/09/aws-direct-connect-announces-flat-rate-pricing/), doc history | + +## Location footprint + +AWS What's New posts give the running count of DX locations: "over 142" (2025-08), "over 146" (2025-09 to 2025-10), "over 149" (2025-12), and "over 150" (2026-03 to 2026-04). Recent additions include Hanoi (the first in Vietnam, 2025-12) and Sydney SY5 (2026-03). 100G expansions include Kansas City (2025-10), Auckland (2026-04), and Lima (2026-07). Two locations are winding down: per the locations page, GDS No. 3 Shenzhen and Equinix MU1 Munich take no new connections after July 1, 2026 and reach end of support in July 2027. The document history gives the same Shenzhen cutoff as "after June 30, 2026". + +## Sources + +- Direct Connect locations: +- DX User Guide document history: +- Announcing AWS Direct Connect (2011-08-03): +- LAG (2017-02): +- LAG blog: +- DX gateway (2017-11-01): +- DX gateway blog: +- TGW support (2019-04): +- Native 100G (2021-02): +- MACsec (2021-03-31): +- SiteLink (2021-12): +- Private IP VPN (2022-06-22): +- Network Monitor GA (2023-12): +- 25G hosted (2024-04-24): +- 400G (2024-07-01): +- Cloud WAN plus DX (2024-11-25): +- MACsec partner interconnects (2025-07-28): +- 4-byte ASN (2025-09-12): +- VPN 5 Gbps tunnels (2025-11-12): +- Interconnect last mile preview (2025-11): +- Interconnect multicloud preview (2025-11-30): +- Kansas City 100G (2025-10): +- Hanoi location (2025-12): +- CloudFormation support (2026-03): +- Sydney SY5 (2026-03): +- BGP CloudWatch metrics (2026-03-30): +- Interconnect multicloud GA (2026-04-13): +- Interconnect last mile GA (2026-04): +- Auckland 100G (2026-04): +- Interconnect free 500 Mbps tier (2026-05): +- VIF rate limiters (2026-06-01): +- Interconnect with OCI GA (2026-07): +- Lima 100G (2026-07): +- BGP route visibility (2026-07): +- Interconnect with Azure preview (2026-08): +- Prefix controls (2026-08-20): +- Flat-rate pricing (2026-09-15): +- DX SLA: diff --git a/docs/direct-connect/13-why-dx-is-hard.md b/docs/direct-connect/13-why-dx-is-hard.md new file mode 100644 index 0000000..648937d --- /dev/null +++ b/docs/direct-connect/13-why-dx-is-hard.md @@ -0,0 +1,119 @@ +# Why Direct Connect is hard to understand + +This page records the concrete confusion points that make AWS Direct Connect (DX) hard to learn, with evidence, and the explainer technique the site uses for each. It drives the design of the web app: every item below maps to a fix in a specific section. Research was done on 2026-09-30 across AWS re:Post and Knowledge Center, AWS docs, practitioner blogs, certification study guides, and Japanese community sources (Qiita, Zenn, DevelopersIO, Serverworks, AWS Japan blog, Black Belt). + +## The short answer + +DX is hard for four structural reasons, and almost every specific confusion is one of them in disguise: + +1. **Four worlds at once.** A single feature spans L1 (fiber, optics, a colocation building), L2 (VLANs, LACP, MACsec), L3 (BGP) and AWS resources (VIF, DXGW, VGW, TGW, Cloud WAN). Most engineers are fluent in one or two of these. +2. **Words that mean two things.** "Hosted" (connection vs VIF), "allowed prefixes" (filter vs advertisement), "location" vs "Region", "DX" itself (Direct Connect vs デジタルトランスフォーメーション in Japanese), and vendor labels (占有型 / 共有型) that do not match the console. +3. **The same knob behaves differently by context.** Allowed prefixes on a VGW vs a TGW, AS_PATH prepend within a Region vs across Regions, prepend on a private vs a public ASN, MTU 9001 vs 8500. +4. **You cannot touch it.** There is no free-tier DX, several companies own different pieces (you, AWS, the colo, the carrier, the partner, often an SIer in Japan), and before 2026 BGP state was not even visible in CloudWatch. + +```mermaid +flowchart TD + H[Why DX is hard] --> A[Four layers at once] + H --> B[Words that mean two things] + H --> C[Same knob, different behavior] + H --> D[Cannot touch it, many owners] + A --> A1[Connection vs VIF vs gateway] + A --> A2[DX = just a leased line?] + B --> B1[Hosted connection vs hosted VIF] + B --> B2[Location vs Region] + C --> C1[Allowed prefixes: filter vs advertisement] + C --> C2[Prepend ignored across Regions] + C --> C3[Two directions, two decision makers] + D --> D1[LOA-CFA, cross connect, who does what] + D --> D2[UP is not healthy; invisible BGP state] +``` + +## Ranked confusion points + +| # | Confusion | What people get wrong | Evidence | Fix on the site | +| --- | --- | --- | --- | --- | +| 1 | Connection vs VIF vs gateway | Cannot tell the physical port from the VLAN + BGP session from the routing hub; a community re:Post answer claimed a private VIF can terminate on a TGW | [re:Post](https://repost.aws/questions/QUDhR9gi2XTwCHj9nDjkUSBg/when-to-use-transit-vif-vs-private-vif-with-aws-transit-gateway-and-direct-connect), [Serverworks](https://blog.serverworks.co.jp/2021/04/05/100639) | Layer stack map, layer chips on every section, VIF switcher | +| 2 | "DX = a leased line from AWS" | AWS only provides location ↔ AWS; you arrange site ↔ location | [Serverworks](https://blog.serverworks.co.jp/2021/04/05/100639), [Zenn](https://zenn.dev/issy/articles/zenn-directconnect-overview) | Airport analogy, ownership-colored path diagram | +| 3 | Allowed prefixes mean opposite things | VGW: filter (same or wider than the VPC CIDR). TGW: the literal advertisement | [AWS doc](https://docs.aws.amazon.com/directconnect/latest/UserGuide/allowed-to-prefixes.html), [DevelopersIO](https://dev.classmethod.jp/articles/aws-direct-connect-gateway-allowed-prefixes-explained-simply/), [Colin Barker](https://colinbarker.me.uk/blog/2024-10-21-aws-direct-connect-allowed-prefix-lists/) | Allowed-prefix lab with "checkpoint vs signboard" analogy | +| 4 | DXGW is not a router | Expect VPC ↔ VPC or VIF ↔ VIF through it; it is a control-plane route reflector | [AWS doc](https://docs.aws.amazon.com/directconnect/latest/UserGuide/direct-connect-gateways-intro.html) | SiteLink toggle with a red ✕, myth card | +| 5 | Why is traffic on the VPN? | Longest prefix beats "DX over VPN" | [Knowledge Center](https://www.repost.aws/knowledge-center/direct-connect-gateway-primary-connection), [VPC route priority](https://docs.aws.amazon.com/vpc/latest/userguide/route-tables-priority.html) | BGP lab preset "VPN wins with a /24", decision ladder | +| 6 | Two directions, two decision makers | Fixing AWS → on-prem with communities but not on-prem → AWS gives asymmetric flows that stateful firewalls drop | [KC asymmetric](https://repost.aws/knowledge-center/direct-connect-asymmetric-routing), [Zenn](https://zenn.dev/yama_1998/articles/02db97e12a61f5) | BGP lab: separate outbound choice and an asymmetry warning | +| 7 | Prepend ignored across Regions | Locations in the sending Region are preferred before AS_PATH is compared | [Routing policies](https://docs.aws.amazon.com/directconnect/latest/UserGuide/routing-and-bgp.html), [KC active/passive](https://repost.aws/knowledge-center/direct-connect-active-passive-connection) | BGP lab preset "Remote-Region location", myth card | +| 8 | "Hosted" means two things | Hosted connection (own policed capacity, 1 VIF) vs hosted VIF (a VIF on someone else's port) | [KC types](https://repost.aws/knowledge-center/direct-connect-types), [NHN Techorus](https://techblog.nhn-techorus.com/archives/23184) | Apartment analogy, glossary "not to be confused with" | +| 9 | Vendor labels vs console terms | 占有型 / 共有型 are marketing labels with loose meaning | [DevelopersIO](https://dev.classmethod.jp/articles/aws-direct-connect-connection-vif-organize-terms/) | Glossary lists official console terms in both languages | +| 10 | Public VIF is not "internet" | It reaches AWS public prefixes only; your prefixes become reachable from all of AWS; needs verified public IPs | [KC verifying](https://repost.aws/knowledge-center/public-vif-stuck-verifying) | VIF switcher note, security callout, myth card | +| 11 | Scope communities are backwards-prone | 9100/9200/9300 tag your prefixes; 8100/8200 tag AWS's; the 2026 route-visibility page labels them in reverse | [Routing policies](https://docs.aws.amazon.com/directconnect/latest/UserGuide/routing-and-bgp.html), [Route visibility](https://docs.aws.amazon.com/directconnect/latest/UserGuide/bgp-route-visibility.html) | Community cheat sheet with explicit direction | +| 12 | Location vs Region | The associated Region is a default preference, not a reach limit; e.g. Equinix OS1 in Osaka is associated with Tokyo | [Remote Regions](https://docs.aws.amazon.com/directconnect/latest/UserGuide/remote_regions.html), [AWS JP blog](https://aws.amazon.com/jp/blogs/news/aws-direct-connect-osaka2-20250414/) | Overview backbone note, myth card | +| 13 | LOA-CFA and who does what | Mistaken for a config value; it is a signed work permit the colo needs to patch a fiber into AWS's port | [AWS doc](https://docs.aws.amazon.com/directconnect/latest/UserGuide/Colocation.html), [Qiita](https://qiita.com/R61/items/feb00b25113c8a068c6a) | Ordering stepper with an owner per step, permit analogy | +| 14 | LAG is not resiliency | The FAQ says a LAG does not make connectivity more resilient: one device, one location | [DX FAQ](https://aws.amazon.com/directconnect/faqs/) | LAG lab callout, myth card | +| 15 | UP is not healthy | In the 2021-09-02 Tokyo DX event, AWS-side devices misforwarded traffic into the Tokyo Region from every location for hours; VPN backup and DX to other Regions were unaffected. Location diversity alone did not help | [AWS event summary](https://aws.amazon.com/message/17908/), [DevelopersIO](https://dev.classmethod.jp/articles/directconnect-redundantize/) | Resiliency callout, grey-failure step in troubleshooting | +| 16 | Invisible state | No BGP status or prefix metrics in CloudWatch until 2026-03-30; prefix overflow silently sends BGP Idle | [What's New](https://aws.amazon.com/about-aws/whats-new/2026/03/aws-direct-connect-cloudwatch-bgp-monitoring), [KC BGP down](https://repost.aws/knowledge-center/direct-connect-down-bgp) | Operations metrics table, troubleshooting tree | +| 17 | MTU differs by VIF type | Private VIF 9001, transit VIF and TGW 8500; oversize packets drop and PMTUD can fail | [VIF doc](https://docs.aws.amazon.com/directconnect/latest/UserGuide/WorkingWithVirtualInterfaces.html) | MTU table and callout | +| 18 | "Closed network = encrypted" (閉域 = 暗号化) | DX is plaintext by default; MACsec is hop-by-hop on dedicated ports only | [Encryption doc](https://docs.aws.amazon.com/directconnect/latest/UserGuide/encryption-in-transit.html) | Encryption-layer diagram, myth card | +| 19 | Who pays what | Port-hours to the connection owner, DTO to the sending account, colo and carrier bill separately | [Multi-account pricing blog](https://aws.amazon.com/blogs/networking-and-content-delivery/understanding-aws-direct-connect-multi-account-pricing/) | Pricing "who gets billed" list | +| 20 | DX hidden inside a carrier service (Japan) | Carrier closed-network services contain DX; unclear which failures are AWS's vs the carrier's | [Zenn NTT Data](https://zenn.dev/nttdata_tech/articles/2562c529df1c12) | "Where DX hides in your carrier's service" note | +| 21 | You cannot try it | No personal-account lab; ANS-C01 still tests VIFs, LAG, DXGW and BGP attributes in depth | [Tutorials Dojo](https://tutorialsdojo.com/aws-certified-advanced-networking-specialty-exam-study-path-guide-ans-c01/) | Every lab on the site is a browser simulator | + +## Analogies that work + +| Concept | Analogy | Where it comes from | +| --- | --- | --- | +| DX location | An airport: your carrier circuit is the airport bus, the AWS router is the boarding gate | Serverworks | +| LOA-CFA | A signed work permit that lets the building's staff plug a cable into AWS's port | Qiita, community | +| VIF | Lanes painted on one road: each lane (VLAN) goes to a different destination | This site | +| Hosted connection vs hosted VIF | Renting a whole flat vs renting a room in someone else's flat | NHN Techorus | +| Allowed prefixes | VGW: a checkpoint that lets matching cars through. TGW: a signboard that announces exactly what is written on it | DevelopersIO | +| DXGW | Directory assistance: it tells each side which numbers exist, but no call flows through it | This site | + +## Official Japanese terms + +The AWS Japanese documentation uses these terms, which the glossary on the site follows. Community writing often differs. + +| English | AWS Japanese docs | Community variants | +| --- | --- | --- | +| Connection | 接続 | 回線 | +| Dedicated connection | 専用接続 | 占有型 (vendor label) | +| Hosted connection | ホスト接続 | ホスト型接続, 共有型 (vendor label) | +| Virtual interface | 仮想インターフェイス | 仮想インターフェース, VIF | +| Hosted VIF | ホスト仮想インターフェイス | ホスト型 VIF | +| Direct Connect gateway | Direct Connect ゲートウェイ | DXGW | +| Virtual private gateway | 仮想プライベートゲートウェイ | VGW | +| Allowed prefixes | 許可されたプレフィックス / 許可されるプレフィックス (both appear) | 許可プレフィックス | +| Link aggregation group | リンク集約グループ (LAG) | LAG | +| LOA-CFA | LOA-CFA (untranslated) | 接続承認書 | + +## Sources + +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- diff --git a/docs/direct-connect/README.md b/docs/direct-connect/README.md new file mode 100644 index 0000000..4c9c190 --- /dev/null +++ b/docs/direct-connect/README.md @@ -0,0 +1,19 @@ +# Research notes: Direct Connect deep dive + +Everything the Direct Connect deep dive page (`direct-connect/` on the site) says is backed by these notes. They came from the former 0-draft/cross-connect repository, merged here on 2026-11-08; the road map's own DX summary is [../04-direct-connect.md](../04-direct-connect.md). Each page ends with the AWS documentation, What's New posts and blogs it was checked against. All pages were verified on 2026-10-12. + +| # | Page | Covers | +| --- | --- | --- | +| 01 | [Overview](01-overview.md) | What DX is, components, DX vs VPN vs internet, 2023–2026 changes | +| 02 | [Connections](02-connections.md) | Dedicated vs hosted, locations, LOA-CFA ordering, optics, MTU, quotas | +| 03 | [LAG and MACsec](03-lag-and-macsec.md) | LACP rules, minimum links, MACsec ciphers, keys and modes | +| 04 | [Virtual interfaces](04-virtual-interfaces.md) | Private, public and transit VIFs, BGP parameters, limits | +| 05 | [Direct Connect gateway](05-direct-connect-gateway.md) | Associations, allowed prefixes, Cloud WAN, SiteLink, quotas | +| 06 | [BGP and routing](06-bgp-and-routing.md) | Communities, path selection, DX vs VPN priority, Private IP VPN | +| 07 | [Resiliency](07-resiliency.md) | Resiliency Toolkit models, SLA, failover testing, BFD | +| 08 | [Security](08-security.md) | MACsec vs IPsec, public VIF exposure, IAM and audit | +| 09 | [Monitoring and troubleshooting](09-monitoring-and-troubleshooting.md) | CloudWatch metrics, route visibility, L1–L3 troubleshooting | +| 10 | [Pricing](10-pricing.md) | Port-hours, data transfer out, SiteLink, flat-rate pricing | +| 11 | [Design patterns](11-design-patterns.md) | Topologies, anti-patterns, decision tree | +| 12 | [Timeline](12-timeline.md) | Launches from 2011 to 2026 | +| 13 | [Why DX is hard](13-why-dx-is-hard.md) | Confusion points with evidence, analogies, official Japanese terms | From 17392bd4224297049fcb229d73bb3c5ec4712cb3 Mon Sep 17 00:00:00 2001 From: kanywst <45947799+kanywst@users.noreply.github.com> Date: Sun, 8 Nov 2026 11:27:31 +0900 Subject: [PATCH 3/7] ci(freshness): cover the Direct Connect deep dive in the monthly check --- .github/workflows/freshness.yml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/freshness.yml b/.github/workflows/freshness.yml index 53cc092..dbb703b 100644 --- a/.github/workflows/freshness.yml +++ b/.github/workflows/freshness.yml @@ -27,12 +27,20 @@ jobs: exit 0 fi gh issue create --repo "$REPO" --title "$title" --body-file - <<'BODY' - Re-verify the facts the site pins to a date, then update `src/data/asOf.ts` and the docs. + Re-verify the facts the site pins to a date, then update `src/data/asOf.ts` (`AS_OF` for the road map, `DX_AS_OF` for the Direct Connect deep dive and the DX price list) and the docs. + Road map - [ ] Site-to-Site VPN quotas and pricing — https://docs.aws.amazon.com/vpn/latest/s2svpn/vpn-limits.html - - [ ] Direct Connect pricing and quotas — https://aws.amazon.com/directconnect/pricing/ - [ ] Transit Gateway and Cloud WAN pricing — https://aws.amazon.com/transit-gateway/pricing/ - [ ] PrivateLink, Route 53 Resolver, Client VPN, Verified Access pricing - [ ] New launches since the last check — https://aws.amazon.com/about-aws/whats-new/networking_and_content_delivery/ - [ ] Timeline (`src/features/timeline/data.ts`, `docs/15-timeline.md`) + + Direct Connect (one price list for both pages: `src/data/dxPricing.ts` and `docs/direct-connect/10-pricing.md`) + - [ ] Pricing: port-hours, DTO matrix, flat-rate tiers, SiteLink — https://aws.amazon.com/directconnect/pricing/ and https://aws.amazon.com/directconnect/pricing/flat-rate/ + - [ ] Quotas — https://docs.aws.amazon.com/directconnect/latest/UserGuide/limits.html + - [ ] New DX launches — the DX User Guide document history + - [ ] Locations and speeds (400G, MACsec) — https://aws.amazon.com/directconnect/locations/ + - [ ] SLA — https://aws.amazon.com/directconnect/sla/ + - [ ] DX timeline (`src/features/direct-connect/content/timeline.ts`, `docs/direct-connect/12-timeline.md`) BODY From f6e8ddfe893131e12c73a428c52a97bf7fe72774 Mon Sep 17 00:00:00 2001 From: kanywst <45947799+kanywst@users.noreply.github.com> Date: Sun, 8 Nov 2026 11:27:31 +0900 Subject: [PATCH 4/7] feat: add the Direct Connect deep dive as a second page --- README.ja.md | 30 +- README.md | 30 +- direct-connect/index.html | 31 + e2e/a11y.spec.ts | 47 +- e2e/direct-connect.spec.ts | 179 ++++ src/app/DirectConnectApp.test.tsx | 193 +++++ src/app/DirectConnectApp.tsx | 67 ++ src/components/layout/Footer.tsx | 31 +- src/components/layout/Header.tsx | 48 +- src/data/site.test.ts | 18 + src/data/site.ts | 15 + src/direct-connect.tsx | 18 + src/features/cost/CostSection.tsx | 10 +- .../direct-connect/components/Beacon.tsx | 94 +++ .../direct-connect/components/HomeLink.tsx | 22 + .../direct-connect/components/Term.tsx | 105 +++ src/features/direct-connect/components/ui.tsx | 249 ++++++ .../direct-connect/content/glossary.ts | 249 ++++++ src/features/direct-connect/content/myths.ts | 121 +++ src/features/direct-connect/content/nav.ts | 19 + .../direct-connect/content/timeline.ts | 252 ++++++ src/features/direct-connect/content/traps.ts | 166 ++++ src/features/direct-connect/content/ui.ts | 13 + .../direct-connect/lib/advisor.test.ts | 82 ++ src/features/direct-connect/lib/advisor.ts | 73 ++ src/features/direct-connect/lib/cidr.test.ts | 51 ++ src/features/direct-connect/lib/cidr.ts | 38 + src/features/direct-connect/lib/dxgw.ts | 17 + src/features/direct-connect/lib/lag.test.ts | 46 + src/features/direct-connect/lib/lag.ts | 43 + .../direct-connect/lib/resiliency.test.ts | 44 + src/features/direct-connect/lib/resiliency.ts | 89 ++ .../direct-connect/lib/routing.test.ts | 124 +++ src/features/direct-connect/lib/routing.ts | 115 +++ .../direct-connect/sections/Connections.tsx | 468 ++++++++++ .../direct-connect/sections/Gateway.tsx | 746 ++++++++++++++++ .../direct-connect/sections/Glossary.tsx | 88 ++ src/features/direct-connect/sections/Hero.tsx | 157 ++++ .../direct-connect/sections/LagMacsec.tsx | 647 ++++++++++++++ .../direct-connect/sections/Myths.tsx | 132 +++ .../direct-connect/sections/Operations.tsx | 382 +++++++++ .../direct-connect/sections/Overview.tsx | 798 ++++++++++++++++++ .../direct-connect/sections/Patterns.tsx | 354 ++++++++ .../direct-connect/sections/Pricing.tsx | 295 +++++++ .../direct-connect/sections/Resiliency.tsx | 430 ++++++++++ .../direct-connect/sections/Routing.tsx | 705 ++++++++++++++++ .../direct-connect/sections/Security.tsx | 536 ++++++++++++ .../direct-connect/sections/Timeline.tsx | 59 ++ src/features/direct-connect/sections/Vifs.tsx | 556 ++++++++++++ .../direct-connect/sections/WhyHard.tsx | 329 ++++++++ src/features/dx/DxSection.tsx | 31 +- src/features/dx/model.ts | 3 +- src/features/glossary/GlossarySection.tsx | 8 +- src/features/hubs/HubsSection.tsx | 10 +- src/features/hubs/ScaleLab.tsx | 10 +- src/features/quiz/QuizSection.tsx | 2 +- src/features/quiz/cards.test.ts | 6 +- src/features/quiz/cards.ts | 3 +- src/features/routing/RoutingSection.tsx | 20 +- src/features/timeline/TimelineSection.tsx | 12 +- src/i18n/LangContext.tsx | 7 +- src/styles/index.css | 22 + vite.config.ts | 7 + 63 files changed, 9433 insertions(+), 119 deletions(-) create mode 100644 direct-connect/index.html create mode 100644 e2e/direct-connect.spec.ts create mode 100644 src/app/DirectConnectApp.test.tsx create mode 100644 src/app/DirectConnectApp.tsx create mode 100644 src/data/site.test.ts create mode 100644 src/data/site.ts create mode 100644 src/direct-connect.tsx create mode 100644 src/features/direct-connect/components/Beacon.tsx create mode 100644 src/features/direct-connect/components/HomeLink.tsx create mode 100644 src/features/direct-connect/components/Term.tsx create mode 100644 src/features/direct-connect/components/ui.tsx create mode 100644 src/features/direct-connect/content/glossary.ts create mode 100644 src/features/direct-connect/content/myths.ts create mode 100644 src/features/direct-connect/content/nav.ts create mode 100644 src/features/direct-connect/content/timeline.ts create mode 100644 src/features/direct-connect/content/traps.ts create mode 100644 src/features/direct-connect/content/ui.ts create mode 100644 src/features/direct-connect/lib/advisor.test.ts create mode 100644 src/features/direct-connect/lib/advisor.ts create mode 100644 src/features/direct-connect/lib/cidr.test.ts create mode 100644 src/features/direct-connect/lib/cidr.ts create mode 100644 src/features/direct-connect/lib/dxgw.ts create mode 100644 src/features/direct-connect/lib/lag.test.ts create mode 100644 src/features/direct-connect/lib/lag.ts create mode 100644 src/features/direct-connect/lib/resiliency.test.ts create mode 100644 src/features/direct-connect/lib/resiliency.ts create mode 100644 src/features/direct-connect/lib/routing.test.ts create mode 100644 src/features/direct-connect/lib/routing.ts create mode 100644 src/features/direct-connect/sections/Connections.tsx create mode 100644 src/features/direct-connect/sections/Gateway.tsx create mode 100644 src/features/direct-connect/sections/Glossary.tsx create mode 100644 src/features/direct-connect/sections/Hero.tsx create mode 100644 src/features/direct-connect/sections/LagMacsec.tsx create mode 100644 src/features/direct-connect/sections/Myths.tsx create mode 100644 src/features/direct-connect/sections/Operations.tsx create mode 100644 src/features/direct-connect/sections/Overview.tsx create mode 100644 src/features/direct-connect/sections/Patterns.tsx create mode 100644 src/features/direct-connect/sections/Pricing.tsx create mode 100644 src/features/direct-connect/sections/Resiliency.tsx create mode 100644 src/features/direct-connect/sections/Routing.tsx create mode 100644 src/features/direct-connect/sections/Security.tsx create mode 100644 src/features/direct-connect/sections/Timeline.tsx create mode 100644 src/features/direct-connect/sections/Vifs.tsx create mode 100644 src/features/direct-connect/sections/WhyHard.tsx diff --git a/README.ja.md b/README.ja.md index 7d3a676..3b605ca 100644 --- a/README.ja.md +++ b/README.ja.md @@ -17,7 +17,7 @@ | 2 | 交通ルール | CIDR スライダー、最長一致の案内標識、BGP、3 つのレイヤー、暗号化がどこに効くか | | 3 | インターネット | パブリックエンドポイントまでの道のり、S3 バケットポリシーのラボ (`aws:SourceIp` と `aws:SourceVpce`) | | 4 | VPN | トンネルのフェイルオーバー、VGW / Transit Gateway / Cloud WAN のスループットラボ (ECMP・大容量トンネル) | -| 5 | Direct Connect | 区間ごとの持ち主、VIF の種類、閉域 ≠ 暗号化。詳細は [Cross Connect](https://0-draft.github.io/cross-connect/?lang=ja) へ | +| 5 | Direct Connect | 区間ごとの持ち主、VIF の種類、閉域 ≠ 暗号化。詳細は [Direct Connect 深掘りページ](https://0-draft.github.io/on-ramp/direct-connect/?lang=ja) へ | | 6 | ハブ | 規模ラボ (VPC × リージョン × 拠点を 4 つの設計で比較、クォータつき)、アプライアンスモード | | 7 | SD-WAN | カプセル化の断面図 (アタッチメントの中の GRE)、Connect の容量ラボ | | 8 | 経路選択 | 同じ経路でもハブが違えば答えが違う: VGW・Transit Gateway・Cloud WAN の判定はしご | @@ -32,7 +32,29 @@ すべての数字の根拠は [`docs/`](docs/README.md) (出典つき、英語) にあります。2026-10-10 時点の AWS 公式ドキュメント・What's New・Price List API で確認済み。 -On-ramp は「全部の道の地図」、[Cross Connect](https://github.com/0-draft/cross-connect) はそのうち 1 本 (Direct Connect) を掘り下げたものです。ここの Direct Connect の出口は要約して Cross Connect にリンクしています。 +## Direct Connect 深掘り + +地図は「全部の道」、2 ページ目の **[Direct Connect を深掘り](https://0-draft.github.io/on-ramp/direct-connect/?lang=ja)** はそのうち 1 本を部品ごとにたどります。地図の Direct Connect の出口は要約して、そちらにリンクしています。2026-11-08 までは別サイト [0-draft/cross-connect](https://github.com/0-draft/cross-connect) でした。調査ノートは [`docs/direct-connect/`](docs/direct-connect/README.md) にあり、Direct Connect の料金表はサイト全体でここ 1 つだけです (`src/data/dxPricing.ts`、説明は [`docs/direct-connect/10-pricing.md`](docs/direct-connect/10-pricing.md))。 + +| セクション | インタラクティブ要素 | +| --- | --- | +| なぜ難しい? | 4 つの根本原因、用語をタップで解説できるレイヤー図、だれが何を持っているか、つまずきポイントと解説先へのリンク | +| 概要 | ルーター、キャリア回線、ケージ、クロスコネクト、DX ルーター、VIF、ゲートウェイをクリックで解説 | +| 接続 | 帯域ラダー、専用 vs ホスト型、LOA-CFA 発注フローのステップ表示 | +| LAG・MACsec | LAG メンバーを切断して最小リンク数の挙動を確認、`should_encrypt` と `must_encrypt` の違い | +| VIF | プライベート / パブリック / トランジットを切り替えて到達先を表示 | +| DX ゲートウェイ | VGW / TGW / Cloud WAN モード、許可プレフィックスラボ、SiteLink の切り替え | +| BGP | 経路選択ラボ: プレフィックス長、`7224:7x00` コミュニティ、AS_PATH プリペンド、ホームリージョン、VPN バックアップ、行きと帰りが食い違うときの非対称ルーティング警告 | +| 冗長性 | Maximum / High / Dev-Test / Classic モデルの障害シミュレーター | +| セキュリティ | MACsec・IPsec・TLS がそれぞれ守る区間 | +| 運用 | はい / いいえで進むトラブルシューティング、アラームを設定すべきメトリクス | +| 料金 | 定価ベースの月額シミュレーター、定額料金の損益分岐 | +| 設計 | 7 つの質問でトポロジーを提案、アンチパターン | +| クイズ | よくある思い込み 10 問の「ほんと? うそ?」 | +| 年表 | 2011〜2026 年のリリース | +| 用語集 | 各用語の英語・日本語の正式名と、混同しやすい用語 | + +深掘りページの内容は 2026-10-12 時点の AWS 公式ドキュメントで確認済み。 ## 開発 @@ -40,12 +62,12 @@ Node.js 24 が必要です。 ```bash npm ci -npm run dev # http://localhost:5173/on-ramp/ +npm run dev # http://localhost:5173/on-ramp/ (深掘り: /on-ramp/direct-connect/) npm run check # 型チェック・lint・整形・markdownlint・テスト・ビルド npm run test:e2e # 実ブラウザでの確認 (要: npx playwright install chromium) ``` -ソースは機能単位です。`src/features/<セクション>/` にセクション本体・ラボ・その裏の純粋関数 (隣に Vitest のテスト) があり、共通 UI は `src/components/`、経路データとナビは `src/data/`、言語切り替えは `src/i18n/` にあります。 +ソースは機能単位です。`src/features/<セクション>/` にセクション本体・ラボ・その裏の純粋関数 (隣に Vitest のテスト) があり、共通 UI は `src/components/`、経路データとナビは `src/data/`、言語切り替えは `src/i18n/` にあります。深掘りページは 2 つ目の Vite エントリ (`direct-connect/index.html` → `src/direct-connect.tsx` → `src/app/DirectConnectApp.tsx`) で、セクションは `src/features/direct-connect/` にあります。 ## CI diff --git a/README.md b/README.md index 66b52b8..958a971 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Every way from a corporate network into AWS, drawn as a road map. A bilingual (E | 2 | Rules of the road | CIDR slider, longest-prefix gantry signs, BGP, the three layers, where each kind of encryption applies | | 3 | Internet | Hop-by-hop walk to a public endpoint; S3 bucket-policy lab (`aws:SourceIp` vs `aws:SourceVpce`) | | 4 | VPN | Tunnel failover stepper; throughput lab for VGW, Transit Gateway and Cloud WAN (ECMP, large tunnels) | -| 5 | Direct Connect | Who owns which stretch, VIF types, 閉域 ≠ 暗号化 — then deep links into [Cross Connect](https://0-draft.github.io/cross-connect/) | +| 5 | Direct Connect | Who owns which stretch, VIF types, 閉域 ≠ 暗号化 — then deep links into the [Direct Connect deep dive](https://0-draft.github.io/on-ramp/direct-connect/) | | 6 | Hubs | Scale lab (VPCs × Regions × sites across four designs, with quotas); appliance-mode stepper | | 7 | SD-WAN | Encapsulation cutaway (GRE inside an attachment); Connect capacity lab | | 8 | Path selection | Same routes, three hubs, three answers: VGW vs Transit Gateway vs Cloud WAN decision ladder | @@ -32,7 +32,29 @@ Every way from a corporate network into AWS, drawn as a road map. A bilingual (E The research behind every number lives in [`docs/`](docs/README.md), with sources. Facts were verified against AWS documentation, What's New posts and the AWS Price List API on 2026-10-10. -On-ramp is the map of every road; [Cross Connect](https://github.com/0-draft/cross-connect) is the deep dive into one of them (Direct Connect: VIFs, BGP communities, resiliency, MACsec, pricing). The Direct Connect exit here summarizes and links there instead of repeating it. +## Direct Connect deep dive + +The map is every road; the second page, **[Direct Connect, up close](https://0-draft.github.io/on-ramp/direct-connect/)** ([日本語](https://0-draft.github.io/on-ramp/direct-connect/?lang=ja)), drives one of them part by part. The Direct Connect exit on the map summarizes and links there instead of repeating it. It was the separate [0-draft/cross-connect](https://github.com/0-draft/cross-connect) site until 2026-11-08; its research notes are in [`docs/direct-connect/`](docs/direct-connect/README.md), and its Direct Connect price list is now the only one on the site (`src/data/dxPricing.ts`, documented in [`docs/direct-connect/10-pricing.md`](docs/direct-connect/10-pricing.md)). + +| Section | Interactive part | +| --- | --- | +| Why is it hard? | The four root causes, a layer map with tap-to-define terms, who owns what, and the common traps linked to where each is untangled | +| Overview | Clickable end-to-end path: router, carrier, cage, cross connect, DX router, VIFs, gateways | +| Connections | Speed ladder, dedicated vs hosted, step-by-step LOA-CFA ordering | +| LAG and MACsec | Cut LAG members and watch minimum links; `should_encrypt` vs `must_encrypt` | +| Virtual interfaces | Switch private / public / transit and see what each reaches | +| Direct Connect gateway | VGW / TGW / Cloud WAN modes, allowed-prefix lab, SiteLink toggle | +| BGP | Path selection lab: prefix length, `7224:7x00` communities, AS_PATH prepend, home Region, VPN backup, and an asymmetric-routing warning when your outbound choice disagrees with AWS | +| Resiliency | Failure lab for the Maximum / High / Dev-Test / Classic models | +| Security | Which segment MACsec, IPsec and TLS protect | +| Operations | Yes/no troubleshooting tree, metrics worth an alarm | +| Pricing | Monthly estimate from list prices, flat-rate break-even | +| Patterns | Seven questions to a topology, anti-patterns | +| Quiz | Ten myth-or-fact cards on the most common misconceptions | +| Timeline | 2011–2026 launches | +| Glossary | Every term with its official English and Japanese console name and what it is often confused with | + +Facts on the deep dive were verified against AWS documentation on 2026-10-12. ## Development @@ -40,12 +62,12 @@ Requires Node.js 24. ```bash npm ci -npm run dev # http://localhost:5173/on-ramp/ +npm run dev # http://localhost:5173/on-ramp/ (deep dive: /on-ramp/direct-connect/) npm run check # typecheck, lint, format, markdownlint, tests, build npm run test:e2e # real-browser checks (needs: npx playwright install chromium) ``` -The source is organized by feature: `src/features/
/` holds a section, its labs and the pure logic behind them (with Vitest tests next to it). Shared UI lives in `src/components/`, route data and navigation in `src/data/`, and the language switch in `src/i18n/`. +The source is organized by feature: `src/features/
/` holds a section, its labs and the pure logic behind them (with Vitest tests next to it). The deep dive is a second Vite entry (`direct-connect/index.html` → `src/direct-connect.tsx` → `src/app/DirectConnectApp.tsx`) whose sections live in `src/features/direct-connect/`. Shared UI lives in `src/components/`, route data and navigation in `src/data/`, and the language switch in `src/i18n/`. ## CI diff --git a/direct-connect/index.html b/direct-connect/index.html new file mode 100644 index 0000000..4cc47c6 --- /dev/null +++ b/direct-connect/index.html @@ -0,0 +1,31 @@ + + + + + + Direct Connect, up close — On-ramp + + + + + + + + + +
+ + + diff --git a/e2e/a11y.spec.ts b/e2e/a11y.spec.ts index d616506..c87f65b 100644 --- a/e2e/a11y.spec.ts +++ b/e2e/a11y.spec.ts @@ -3,24 +3,31 @@ import { expect, test } from "@playwright/test"; // Automated WCAG 2.2 AA checks in both languages and both themes. Dark mode // matters on its own: the route colours are pale there, so text on them flips. -for (const lang of ["en", "ja"] as const) { - for (const scheme of ["light", "dark"] as const) { - test(`no WCAG A/AA violations (${lang}, ${scheme})`, async ({ page }) => { - await page.emulateMedia({ colorScheme: scheme }); - await page.goto(`./?lang=${lang}`); - await expect(page.locator("h1")).toBeVisible(); - await page.evaluate(() => document.fonts.ready); - const { violations } = await new AxeBuilder({ page }) - .withTags(["wcag2a", "wcag2aa", "wcag21a", "wcag21aa", "wcag22aa"]) - .analyze(); - const summary = violations.map( - (v) => - `${v.id} (${v.impact}): ${v.nodes.length}× — ${v.nodes - .slice(0, 3) - .map((n) => n.target.join(" ")) - .join(" | ")}`, - ); - expect(summary).toEqual([]); - }); +// Both pages: the road map and the Direct Connect deep dive. +const PAGES = [ + ["map", "./"], + ["direct-connect", "./direct-connect/"], +] as const; + +for (const [name, path] of PAGES) + for (const lang of ["en", "ja"] as const) { + for (const scheme of ["light", "dark"] as const) { + test(`no WCAG A/AA violations (${name}, ${lang}, ${scheme})`, async ({ page }) => { + await page.emulateMedia({ colorScheme: scheme }); + await page.goto(`${path}?lang=${lang}`); + await expect(page.locator("h1")).toBeVisible(); + await page.evaluate(() => document.fonts.ready); + const { violations } = await new AxeBuilder({ page }) + .withTags(["wcag2a", "wcag2aa", "wcag21a", "wcag21aa", "wcag22aa"]) + .analyze(); + const summary = violations.map( + (v) => + `${v.id} (${v.impact}): ${v.nodes.length}× — ${v.nodes + .slice(0, 3) + .map((n) => n.target.join(" ")) + .join(" | ")}`, + ); + expect(summary).toEqual([]); + }); + } } -} diff --git a/e2e/direct-connect.spec.ts b/e2e/direct-connect.spec.ts new file mode 100644 index 0000000..167ddd8 --- /dev/null +++ b/e2e/direct-connect.spec.ts @@ -0,0 +1,179 @@ +import { expect, test, type Page } from "@playwright/test"; + +// The Direct Connect deep dive, the site's second page. + +const LANGS = ["en", "ja"] as const; + +async function open(page: Page, lang: (typeof LANGS)[number]) { + const errors: string[] = []; + page.on("pageerror", (e) => errors.push(e.message)); + page.on("console", (m) => { + // Google Fonts can be unreachable in CI; that is not a page bug. + if (m.type() === "error" && !m.location().url.includes("fonts.g")) + errors.push(m.text()); + }); + await page.goto(`./direct-connect/?lang=${lang}`); + await expect(page.locator("h1")).toBeVisible(); + // Settle fonts so text measurements are final. + await page.evaluate(() => document.fonts.ready); + return errors; +} + +for (const lang of LANGS) { + test.describe(`layout (${lang})`, () => { + test("renders without errors and never scrolls sideways", async ({ page }) => { + const errors = await open(page, lang); + const { scrollWidth, clientWidth } = await page.evaluate(() => ({ + scrollWidth: document.documentElement.scrollWidth, + clientWidth: document.documentElement.clientWidth, + })); + expect(scrollWidth).toBeLessThanOrEqual(clientWidth); + expect(errors).toEqual([]); + }); + + test("no diagram text is clipped or spills out of its box", async ({ page }) => { + await open(page, lang); + // Scan once as loaded, then again with the labs in their other states, + // where the longest labels appear. + const scan = () => + page.evaluate(() => { + const out: string[] = []; + for (const svg of document.querySelectorAll("main svg")) { + const vb = svg.viewBox.baseVal; + if (!vb || !vb.width) continue; + const boxes = [...svg.querySelectorAll("rect")] + .filter((r) => r.getAttribute("fill") !== "transparent") + .map((r) => r.getBBox()) + .filter((b) => b.width >= 30 && b.height >= 20 && b.width <= 400); + for (const text of svg.querySelectorAll("text")) { + if (text.getAttribute("transform")) continue; + const b = text.getBBox(); + if (!b.width) continue; + const where = `${svg.closest("section")?.id ?? "hero"}: ${text.textContent?.trim()}`; + if (b.x < vb.x - 1 || b.x + b.width > vb.x + vb.width + 1) + out.push(`viewBox ${where}`); + const cx = b.x + b.width / 2; + const cy = b.y + b.height / 2; + for (const r of boxes) { + const inside = + cx > r.x && cx < r.x + r.width && cy > r.y && cy < r.y + r.height; + if (inside && (b.x < r.x - 1 || b.x + b.width > r.x + r.width + 1)) + out.push(`box ${where}`); + } + } + } + // Boxes in the same row must not overlap each other. + for (const svg of document.querySelectorAll("main svg")) { + const row = [...svg.querySelectorAll("rect")] + .filter((r) => r.getAttribute("fill") !== "transparent") + .map((r) => r.getBBox()) + .filter((b) => b.width <= 120 && b.height >= 20); + for (let i = 0; i < row.length; i++) + for (let j = i + 1; j < row.length; j++) { + const a = row[i]; + const c = row[j]; + if (a.y !== c.y || a.height !== c.height) continue; + if (a.x < c.x + c.width - 1 && c.x < a.x + a.width - 1) + out.push(`overlap ${svg.closest("section")?.id ?? "hero"} at y=${a.y}`); + } + } + return [...new Set(out)]; + }); + expect(await scan()).toEqual([]); + + const radio = (section: string, i: number) => + page + .locator(`section#${section} [role=radiogroup]`) + .nth(i) + .locator("[role=radio]"); + await radio("lag-macsec", 1).nth(1).click(); // must_encrypt + await radio("lag-macsec", 2).nth(1).click(); // MKA failed + await radio("vifs", 0).nth(2).click(); // transit VIF + await radio("gateway", 0).nth(1).click(); // Transit Gateway mode + await radio("gateway", 1).nth(1).click(); // SiteLink on + // The phone layout has its own encryption-layer picker. + const layers = page.locator("section#security [role=radiogroup]"); + if (await layers.count()) + await layers.first().locator("[role=radio]").nth(1).click(); + // Cut one connection in the resiliency lab. + await page.locator("section#resiliency svg [aria-pressed]").nth(2).click(); + expect(await scan()).toEqual([]); + }); + + test("glossary tips stay on screen", async ({ page }) => { + await open(page, lang); + const vw = await page.evaluate(() => document.documentElement.clientWidth); + + const terms = page.locator("section#why button[aria-expanded]"); + const n = await terms.count(); + expect(n).toBeGreaterThan(10); + for (let i = 0; i < n; i++) { + const term = terms.nth(i); + await term.scrollIntoViewIfNeeded(); + await term.click(); + const tip = await page.getByRole("note").boundingBox(); + expect(tip!.x, `term ${i}`).toBeGreaterThanOrEqual(0); + expect(tip!.x + tip!.width, `term ${i}`).toBeLessThanOrEqual(vw + 1); + await page.keyboard.press("Escape"); + } + }); + }); +} + +test("every in-page link in the header and the page lands on a section", async ({ + page, +}) => { + await open(page, "en"); + const hrefs = await page + .locator("header nav a[href^='#'], main a[href^='#']") + .evaluateAll((as) => as.map((a) => a.getAttribute("href"))); + expect(hrefs.length).toBeGreaterThan(15); + for (const h of new Set(hrefs)) { + if (!h || h === "#") continue; + await expect(page.locator(h), h).toHaveCount(1); + } +}); + +test("the BGP lab flags asymmetric routing", async ({ page }) => { + await open(page, "en"); + const lab = page.locator("section#routing"); + await lab.getByRole("button", { name: "Active / passive (communities)" }).click(); + await expect(lab.getByText("Asymmetric!")).toHaveCount(0); + await lab.getByLabel(/Your router sends/).selectOption("DX-B"); + await expect(lab.getByText("Asymmetric!")).toBeVisible(); +}); + +test("diagram text stays legible on phones", async ({ page }, info) => { + test.skip(info.project.name !== "phone", "phone-only check"); + for (const lang of LANGS) { + await open(page, lang); + const tiny = await page.evaluate(() => { + const out: string[] = []; + for (const svg of document.querySelectorAll("main svg")) { + const vb = svg.viewBox.baseVal; + const w = svg.getBoundingClientRect().width; + if (!vb || !vb.width || !w) continue; + const scale = w / vb.width; + for (const text of svg.querySelectorAll("text")) { + const size = parseFloat(getComputedStyle(text).fontSize) * scale; + if (size < 10) + out.push( + `${svg.closest("section")?.id}: ${text.textContent?.trim()} ${size.toFixed(1)}px`, + ); + } + } + return out; + }); + expect(tiny, lang).toEqual([]); + } +}); + +test("the road map and the deep dive link to each other", async ({ page }) => { + await page.goto("./?lang=ja"); + const deep = page.locator("section#dx a[href*='direct-connect/']").first(); + await deep.click(); + await expect(page).toHaveURL(/\/direct-connect\/\?lang=ja#/); + await expect(page.locator("h1")).toHaveText(/Direct Connect を深掘り/); + await page.getByRole("link", { name: "道路地図の DX の出口" }).click(); + await expect(page.locator("section#dx")).toBeVisible(); +}); diff --git a/src/app/DirectConnectApp.test.tsx b/src/app/DirectConnectApp.test.tsx new file mode 100644 index 0000000..662c20a --- /dev/null +++ b/src/app/DirectConnectApp.test.tsx @@ -0,0 +1,193 @@ +import { describe, expect, it } from "vitest"; +import { render, screen, within } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import App from "./DirectConnectApp"; +import { DX_DEEP, HOME } from "@/data/site"; +import { LangProvider } from "@/i18n/LangContext"; +import { NAV } from "@/features/direct-connect/content/nav"; +import { EVENTS } from "@/features/direct-connect/content/timeline"; +import { GLOSSARY, GLOSSARY_BY_ID } from "@/features/direct-connect/content/glossary"; +import { MYTHS } from "@/features/direct-connect/content/myths"; +import { TRAPS } from "@/features/direct-connect/content/traps"; + +const renderApp = (initial?: "en" | "ja") => + render( + + + , + ); + +describe("Direct Connect deep dive", () => { + it("renders every section the nav links to", () => { + const { container } = renderApp(); + for (const n of NAV) + expect(container.querySelector(`section#${n.id}`)).not.toBeNull(); + }); + + it("defaults to English and switches to Japanese", async () => { + renderApp(); + expect(document.documentElement.lang).toBe("en"); + expect(screen.getByRole("heading", { level: 1 })).toHaveTextContent( + "Direct Connect, up close", + ); + await userEvent.click(screen.getByRole("button", { name: "日本語" })); + expect(document.documentElement.lang).toBe("ja"); + expect(screen.getByRole("heading", { level: 1 })).toHaveTextContent( + "Direct Connect を深掘り", + ); + expect(localStorage.getItem("on-ramp:lang")).toBe("ja"); + }); + + it("the BGP lab reacts to a failed path", async () => { + renderApp(); + const lab = screen.getByRole("heading", { + name: /Path selection lab/, + }).parentElement!; + // Active/active by default: both DX paths win. + const winner = () => within(lab).getByText(/^Traffic goes via/).textContent; + expect(winner()).toBe("Traffic goes via: DX-A + DX-B"); + const [dxA, dxB] = within(lab).getAllByRole("checkbox", { name: "up" }); + await userEvent.click(dxA); + expect(winner()).toBe("Traffic goes via: DX-B"); + // Both DX paths gone: the VPN takes over. + await userEvent.click(dxB); + expect(winner()).toBe("Traffic goes via: VPN"); + }); + + it("warns when the two directions disagree", async () => { + renderApp(); + const lab = screen.getByRole("heading", { + name: /Path selection lab/, + }).parentElement!; + await userEvent.click( + within(lab).getByRole("button", { name: "Active / passive (communities)" }), + ); + expect(within(lab).queryByText("Asymmetric!")).toBeNull(); + await userEvent.selectOptions( + within(lab).getByLabelText(/Your router sends/), + "DX-B", + ); + expect(within(lab).getByText("Asymmetric!")).toBeInTheDocument(); + }); + + it("radio groups follow the arrow-key pattern", async () => { + renderApp(); + const group = screen.getByRole("radiogroup", { name: "VIF type" }); + const [priv, pub] = within(group).getAllByRole("radio"); + expect(priv).toHaveAttribute("tabindex", "0"); + expect(pub).toHaveAttribute("tabindex", "-1"); + priv.focus(); + await userEvent.keyboard("{ArrowRight}"); + expect(pub).toHaveAttribute("aria-checked", "true"); + expect(pub).toHaveFocus(); + }); + + it("switches wide diagrams to phone layouts on narrow screens", async () => { + const original = Object.getOwnPropertyDescriptor(window, "matchMedia"); + window.matchMedia = ((q: string) => ({ + matches: q.includes("max-width"), + media: q, + addEventListener: () => {}, + removeEventListener: () => {}, + })) as unknown as typeof window.matchMedia; + try { + renderApp(); + const overview = document.querySelector("section#overview") as HTMLElement; + const xc = within(overview).getByRole("button", { + name: "Cross connect", + expanded: true, + }); + expect(within(overview).getByText(/single-mode fiber patch/)).toBeInTheDocument(); + await userEvent.click(within(overview).getByRole("button", { name: "VPCs" })); + expect(xc).toHaveAttribute("aria-expanded", "false"); + expect( + within(overview).getByText(/Your private address space/), + ).toBeInTheDocument(); + } finally { + if (original) Object.defineProperty(window, "matchMedia", original); + else delete (window as { matchMedia?: unknown }).matchMedia; + } + }); + + it("each section lists the traps it untangles", () => { + renderApp(); + const routing = document.querySelector("section#routing") as HTMLElement; + expect(within(routing).getByText("Untangles these traps")).toBeInTheDocument(); + expect( + within(routing).getByRole("link", { name: /Why is my traffic on the VPN/ }), + ).toHaveAttribute("href", "#traps"); + }); + + it("links back to the road map for the other roads, keeping the language", async () => { + renderApp(); + const section = (id: string) => + document.querySelector(`section#${id}`) as HTMLElement; + expect( + within(section("why")).getByRole("link", { name: "the road map" }), + ).toHaveAttribute("href", HOME); + expect( + within(section("routing")).getByRole("link", { name: "path selection" }), + ).toHaveAttribute("href", `${HOME}#routing`); + expect( + within(section("gateway")).getByRole("link", { name: "hubs" }), + ).toHaveAttribute("href", `${HOME}#hubs`); + await userEvent.click(screen.getByRole("button", { name: "日本語" })); + expect( + within(section("gateway")).getByRole("link", { name: "ハブ" }), + ).toHaveAttribute("href", `${HOME}?lang=ja#hubs`); + expect(screen.getByRole("link", { name: "道路地図の DX の出口" })).toHaveAttribute( + "href", + `${HOME}?lang=ja#dx`, + ); + // The footer's own entry for this page stays on this page. + expect( + screen.getByRole("link", { name: "Direct Connect を深掘り (このサイト内)" }), + ).toHaveAttribute("href", DX_DEEP); + }); + + it("does not claim MACsec covers a carrier circuit unconditionally", () => { + renderApp(); + const security = document.querySelector("section#security") as HTMLElement; + // The default focus is MACsec; its note must state the carrier condition. + expect(security).toHaveTextContent(/carrier circuit is covered only when/); + expect(security).toHaveTextContent(/if L2-transparent/); + }); + + it("has both languages for every timeline entry", () => { + for (const e of EVENTS) { + expect(e.text.en.length).toBeGreaterThan(0); + expect(e.text.ja.length).toBeGreaterThan(0); + } + }); + + it("glossary entries are complete and cross-links resolve", () => { + const ids = new Set(NAV.map((n) => n.id)); + for (const e of GLOSSARY) { + expect(e.def.en && e.def.ja && e.en && e.ja).toBeTruthy(); + expect(ids.has(e.see)).toBe(true); + if (e.notTo) expect(GLOSSARY_BY_ID[e.notTo.id]).toBeDefined(); + } + for (const x of TRAPS) expect(ids.has(x.stop)).toBe(true); + }); + + it("a glossary term opens and closes with Escape", async () => { + renderApp(); + const why = document.querySelector("section#why") as HTMLElement; + const btn = within(why).getByRole("button", { name: "LOA-CFA" }); + await userEvent.click(btn); + expect(btn).toHaveAttribute("aria-expanded", "true"); + expect(within(why).getByRole("note")).toHaveTextContent(/work permit/); + await userEvent.keyboard("{Escape}"); + expect(btn).toHaveAttribute("aria-expanded", "false"); + }); + + it("the myth quiz scores answers", async () => { + renderApp(); + const quiz = document.querySelector("section#myths") as HTMLElement; + // Q1 (encrypted by default) is a myth. + expect(MYTHS[0].truth).toBe(false); + await userEvent.click(within(quiz).getAllByRole("button", { name: "Myth" })[0]); + expect(within(quiz).getByText(/^Right!/)).toBeInTheDocument(); + expect(within(quiz).getByText(/1 of 1 correct/)).toBeInTheDocument(); + }); +}); diff --git a/src/app/DirectConnectApp.tsx b/src/app/DirectConnectApp.tsx new file mode 100644 index 0000000..4b69492 --- /dev/null +++ b/src/app/DirectConnectApp.tsx @@ -0,0 +1,67 @@ +import { Header } from "@/components/layout/Header"; +import { Footer } from "@/components/layout/Footer"; +import { HOME } from "@/data/site"; +import { DX_AS_OF } from "@/data/asOf"; +import { useLang } from "@/i18n/useLang"; +import { NAV } from "@/features/direct-connect/content/nav"; +import { Hero } from "@/features/direct-connect/sections/Hero"; +import { Overview } from "@/features/direct-connect/sections/Overview"; +import { Connections } from "@/features/direct-connect/sections/Connections"; +import { LagMacsec } from "@/features/direct-connect/sections/LagMacsec"; +import { Vifs } from "@/features/direct-connect/sections/Vifs"; +import { Gateway } from "@/features/direct-connect/sections/Gateway"; +import { Routing } from "@/features/direct-connect/sections/Routing"; +import { Resiliency } from "@/features/direct-connect/sections/Resiliency"; +import { Security } from "@/features/direct-connect/sections/Security"; +import { Operations } from "@/features/direct-connect/sections/Operations"; +import { Pricing } from "@/features/direct-connect/sections/Pricing"; +import { Patterns } from "@/features/direct-connect/sections/Patterns"; +import { Timeline } from "@/features/direct-connect/sections/Timeline"; +import { WhyHard } from "@/features/direct-connect/sections/WhyHard"; +import { Myths } from "@/features/direct-connect/sections/Myths"; +import { Glossary } from "@/features/direct-connect/sections/Glossary"; + +/** + * The Direct Connect deep dive: every part of the DX road, with its own labs. + * The road map's DX exit is the summary; this page is the long version. + */ +export default function DirectConnectApp() { + const { t } = useLang(); + return ( + <> + + {t({ en: "Skip to content", ja: "本文へスキップ" })} + +
(i === 0 ? "?" : String(i))} + back={{ href: HOME, label: { en: "back to the road map", ja: "道路地図に戻る" } }} + /> +
+ + + + + + + + + + + + + + + + + +
+