I tried building a complete AWS Cloud WAN environment with AWS CDK and implemented Network Firewall inspection via Service Insertion and consolidation of outbound Internet traffic

I tried building a complete AWS Cloud WAN environment with AWS CDK and implemented Network Firewall inspection via Service Insertion and consolidation of outbound Internet traffic

When you want to quickly set up a Cloud WAN environment
2026.04.26

This page has been translated by machine translation. View original

Multiple regions with VPCs and adjusting VPC route tables is challenging

Hello, I'm nonPi (@non____97).

Have you ever felt that setting up multiple regions with VPCs and adjusting VPC route tables is challenging when testing AWS Cloud WAN? I certainly have.

I believe one scenario for adopting Cloud WAN is when you want to manage VPCs distributed across multiple regions in an integrated manner.

Actually testing this is quite challenging as you need to set up VPCs in multiple regions each time. Especially since it can take about 20 minutes for a Core Network to be created in Cloud WAN, you'll have to wait before connecting VPCs. It's hard to maintain focus. Particularly when using Service Insertion to inspect East-West traffic with Network Firewall or route traffic to VPCs with NAT Gateways, there are many components to manage.

For more about Service Insertion, please refer to the following AWS Blog posts:

https://aws.amazon.com/jp/blogs/news/simplify-global-security-inspection-with-aws-cloud-wan-service-insertion/

https://aws.amazon.com/jp/blogs/news/migration-to-aws-cloud-wan-multi-region-inspection-using-service-insertion/

https://aws.amazon.com/jp/blogs/networking-and-content-delivery/centralized-ingress-inspection-architecture-in-aws-cloud-wan/

So, I've created an AWS CDK solution to quickly set up a Cloud WAN environment.

Test Environment

Here's the test environment:

Test Environment Architecture Diagram.png

I'm using two regions, ap-northeast-1 and us-east-1, with three segments: dev, prod, and share.

Inter-segment traffic is routed through Network Firewall. Additionally, prod segment traffic going to the internet is routed through an Egress VPC.

I've set up a VPN VPC as an on-premises equivalent, connected via Site-to-Site VPN with BGP route exchange. The VPN server uses Libreswan and FRR.

The hourly cost of this configuration is as follows:

Resource Unit Price (USD/hour) Quantity Subtotal (USD/hour)
Cloud WAN Core Network Edge $0.500 2 $1.000
Cloud WAN VPC Attachment (ap-northeast-1) $0.090 4 $0.360
Cloud WAN VPC Attachment (us-east-1) $0.065 2 $0.130
Cloud WAN Site-to-Site VPN Attachment $0.065 1 $0.065
Network Firewall Endpoint $0.395 1 $0.395
NAT Gateway (ap-northeast-1) $0.062 2 $0.124
NAT Gateway (us-east-1) $0.045 1 $0.045
EC2 t3.micro (ap-northeast-1) $0.0136 2 $0.027
EC2 t3.micro (us-east-1) $0.0104 2 $0.021
EC2 t3.small VPN Router (us-east-1) $0.0208 1 $0.021
VPN Connection $0.048 1 $0.048
EIC Endpoint Free 3 $0.000
Total $2.236

Additional charges for EBS volumes and data transfer will also apply. The cost is reasonable, but avoid leaving it running for extended periods.

AWS CDK Code

The AWS CDK code structure is as follows:

.
├── bin
   └── aws-cdk-cloud-wan.ts          # CDK application entry point. Defines 2 Stacks (Region1/Region2)
├── lib
   ├── constructs
   ├── core-network.ts           # Construct defining Cloud WAN Global Network / Core Network / policies
   ├── egress-vpc.ts             # Construct for internet egress VPC (NAT Gateway / IGW). Belongs to share segment
   ├── index.ts                  # Barrel file for Constructs
   ├── inspection-vpc.ts         # Construct for Network Firewall inspection VPC. Used for send-to and send-via routing
   ├── private-vpc.ts            # Construct for workload VPCs. Used in prod / dev segments
   └── vpn-vpc.ts                # Construct for on-premises connection VPC. Includes VPN Router / Site-to-Site VPN / BGP
   ├── network-config.ts             # Centralized config for CIDR / ASN / segment names / tag keys to inject into Stacks
   ├── region1-stack.ts              # ap-northeast-1 Stack. Deploys Core Network / Egress / Prod / Dev / Inspection VPCs
   └── region2-stack.ts              # us-east-1 Stack. Deploys Egress / Prod / VPN VPCs
├── src
   └── ec2
       └── vpn-router-userdata.sh    # UserData script for VPN Router EC2. Auto-setup for Libreswan (IPsec) / FRR (BGP)
├── test
   └── aws-cdk-cloud-wan.test.ts     # Stack snapshot tests. Validates VPC Attachment tags and resource counts
├── cdk.context.json
├── cdk.json
├── package.json
└── tsconfig.json

To attach us-east-1 VPCs to the Core Network, I pass Core Network information using crossRegionReferences which makes cross-region value references easy:

./bin/aws-cdk-cloud-wan.ts
#!/usr/bin/env node
import * as cdk from 'aws-cdk-lib/core';
import { Region1Stack } from '../lib/region1-stack';
import { Region2Stack } from '../lib/region2-stack';

const app = new cdk.App();

const region1 = 'ap-northeast-1';
const region2 = 'us-east-1';

const region1Stack = new Region1Stack(app, 'CloudWanRegion1Stack', {
  env: { account: process.env.CDK_DEFAULT_ACCOUNT, region: region1 },
  region2,
  crossRegionReferences: true,
});

const region2Stack = new Region2Stack(app, 'CloudWanRegion2Stack', {
  env: { account: process.env.CDK_DEFAULT_ACCOUNT, region: region2 },
  coreNetworkId: region1Stack.coreNetworkId,
  coreNetworkArn: region1Stack.coreNetworkArn,
  crossRegionReferences: true,
});

region2Stack.addDependency(region1Stack);

For more details, see the following article:

https://dev.classmethod.jp/articles/cdk-cross-region-references-for-acm-and-cloudfront/

Note that crossRegionReferences creates strong references, but this isn't a problem as recreating a Core Network would impact the entire network topology anyway.

Deployment takes about 40 minutes total - 25 minutes for the Core Network Stack and 15 minutes for the other Stack.

The code is available in the following GitHub repository:

https://github.com/non-97/aws-cdk-cloud-wan

Checking the Cloud WAN Environment

Global Network

Since there aren't many articles about Cloud WAN on DevelopersIO, I'll share what information you can see in the AWS Management Console.

First, let's look at the Global Network.

The topology graph shows regions, segments, and resources attached to segments. This is useful for understanding the overall network configuration.

1.Topology Graph.png

Clicking on ap-northeast-1 shows the ASN and internal CIDR blocks used by the Core Network Edge.

2.Clicking on Region.png

The internal CIDR blocks are used for Transit Gateway Connect, which isn't used in this environment.

Selecting Metrics shows information about data volume and packet count in this region, which helps understand the overall traffic.

3.Metrics.png

Clicking on a segment shows the Core Network Edge regions it's connected to and the segments it shares with.

4.Clicking on Segment.png

Note: My screenshot shows sharing with the share segment, but I'm not actually doing that in the current environment.

Selecting Routes shows routing information for this segment. A STATIC default route is registered because I'm using Service Insertion with the send-to action. Also, the destination for PROPAGATED routes is the Inspection VPC because I've configured the send-via action for accessing other networks within the Prod segment through the Security NFG.

5.prod routes.png

For reference, here are the routes for the dev and share segments. Since dev and share segments share routes, they have the same routes configured.

10.dev segment routes.png

8.share segment routes.png

Clicking on a VPC shows information such as edge location, attachment type, segment membership, and attachment policy rule numbers.

6.Clicking on VPC.png

Similar information is available when clicking on a Site-to-Site VPN.

7.Clicking on VPN.png

For Site-to-Site VPNs, you can check the current connection status. If a tunnel is down, the normally green line turns red, and hovering over it displays "Core network VPN attachment, at least one connection is down".

9.Core network VPN attachment, at least one connection is down.png

Being able to see the entire connection status of a global network on a single screen is very convenient.

Clicking the Topology Tree tab displays the network topology in a tree format, which some people might find easier to understand.

11.Topology Tree.png

Core Network

Next, let's look at the Core Network.

Here's the current Core Network policy:

{
  "core-network-configuration": {
    "vpn-ecmp-support": true,
    "asn-ranges": [
      "65000-65099"
    ],
    "edge-locations": [
      {
        "location": "ap-northeast-1",
        "asn": 65001
      },
      {
        "location": "us-east-1",
        "asn": 65002,
        "inside-cidr-blocks": [
          "192.168.100.0/24"
        ]
      }
    ],
    "inside-cidr-blocks": [
      "192.168.0.0/16"
    ]
  },
  "version": "2021.12",
  "attachment-policies": [
    {
      "rule-number": 100,
      "condition-logic": "or",
      "description": "attachment segment share",
      "action": {
        "association-method": "constant",
        "segment": "share"
      },
      "conditions": [
        {
          "type": "tag-value",
          "value": "share",
          "operator": "equals",
          "key": "cloudwan-seg"
        }
      ]
    },
    {
      "rule-number": 200,
      "condition-logic": "or",
      "description": "attachment segment prod",
      "action": {
        "association-method": "constant",
        "segment": "prod"
      },
      "conditions": [
        {
          "type": "tag-value",
          "value": "prod",
          "operator": "equals",
          "key": "cloudwan-seg"
        }
      ]
    },
    {
      "rule-number": 300,
      "condition-logic": "or",
      "description": "attachment segment dev",
      "action": {
        "association-method": "constant",
        "segment": "dev"
      },
      "conditions": [
        {
          "type": "tag-value",
          "value": "dev",
          "operator": "equals",
          "key": "cloudwan-seg"
        }
      ]
    },
    {
      "rule-number": 400,
      "condition-logic": "or",
      "description": "attachment nfg security",
      "action": {
        "add-to-network-function-group": "security"
      },
      "conditions": [
        {
          "type": "tag-value",
          "value": "security",
          "operator": "equals",
          "key": "cloudwan-nfg"
        }
      ]
    }
  ],
  "network-function-groups": [
    {
      "name": "security",
      "require-attachment-acceptance": false
    }
  ],
  "segments": [
    {
      "name": "share",
      "require-attachment-acceptance": false,
      "edge-locations": [
        "ap-northeast-1",
        "us-east-1"
      ]
    },
    {
      "isolate-attachments": true,
      "name": "prod",
      "require-attachment-acceptance": false,
      "edge-locations": [
        "ap-northeast-1",
        "us-east-1"
      ]
    },
    {
      "name": "dev",
      "require-attachment-acceptance": false,
      "edge-locations": [
        "ap-northeast-1",
        "us-east-1"
      ]
    }
  ],
  "segment-actions": [
    {
      "mode": "attachment-route",
      "segment": "share",
      "action": "share",
      "share-with": [
        "dev"
      ]
    },
    {
      "segment": "prod",
      "action": "send-to",
      "via": {
        "network-function-groups": [
          "security"
        ]
      },
      "when-sent-to": {
        "segments": "prod"
      }
    },
    {
      "mode": "single-hop",
      "when-sent-to": {
        "segments": [
          "prod"
        ]
      },
      "segment": "prod",
      "action": "send-via",
      "via": {
        "network-function-groups": [
          "security"
        ]
      }
    }
  ]
}

Sample Core Network policies are available in the following AWS official documentation:

https://docs.aws.amazon.com/ja_jp/network-manager/latest/cloudwan/cloudwan-policy-examples.html

For policy parameters, see the following AWS official documentation:

https://docs.aws.amazon.com/network-manager/latest/cloudwan/cloudwan-policies-json.html

In the management console, selecting Core Network shows information about the regions used, network throughput, and attachment information.

12.Core Network.png

Clicking the Logical tab shows the relationships between networks.

13.Logical.png

Note: My screenshot shows routes between Prod and Share segments, but they don't actually exist in the current environment.

By adjusting the Filter by parameters, you can check connectivity between networks.

14.Filter by.png

If there's no connectivity, orange lines won't connect as shown below.

15.No path between Prod and Dev.png

Clicking the Routing Information Base tab lets you check route information flowing to specified segments and edge locations.

16.Routing Information Base.png

You can also check Local Preference, AS Path, MED, and BGP community tags, which helps organize route information when exchanging routes via BGP with Site-to-Site VPN or Direct Connect.

Clicking the Routes tab shows the actual routes as seen in the topology tree.

17.Routes.png

NFG routes can also be checked here.

18.Routes_NFG.png

Clicking the Events tab shows event logs that occurred in the Core Network.

19.Events.png

To use this feature, you need to configure event logging. For details, see the following AWS official documentation:

https://docs.aws.amazon.com/network-manager/latest/cloudwan/cloudwan-onboard-events.html

Logs are output to /aws/events/networkmanagerloggrou in the Oregon region.

20.networkmanagerloggroup.png

Here are some of the actual logs recorded:

Routes in one or more Segments have been installed
{
    "version": "0",
    "id": "911ea313-9caf-9588-4a11-a31b23625678",
    "detail-type": "Network Manager Routing Update",
    "source": "aws.networkmanager",
    "account": "<AWSアカウントID>",
    "time": "2026-04-25T06:37:11Z",
    "region": "us-west-2",
    "resources": [
        "arn:aws:networkmanager::<AWSアカウントID>:global-network/global-network-0530c4e133edd415a",
        "arn:aws:networkmanager::<AWSアカウントID>:core-network/core-network-01a763d8efb75dd43"
    ],
    "detail": {
        "changeType": "SEGMENT_ROUTE_INSTALLED",
        "changeDescription": "Routes in one or more Segments have been installed.",
        "edgeLocation": "us-east-1",
        "segments": [
            "share"
        ],
        "routes": [
            {
                "destinationCidrBlock": "10.102.0.0/16",
                "attachments": [
                    {
                        "attachmentId": "attachment-0cc4803245fdaeb7f",
                        "resourceId": "vpn-0687904978f1a78df",
                        "attachmentType": "vpn",
                        "vpnOutsideIpAddress": "32.195.78.94"
                    },
                    {
                        "attachmentId": "attachment-0cc4803245fdaeb7f",
                        "resourceId": "vpn-0687904978f1a78df",
                        "attachmentType": "vpn",
                        "vpnOutsideIpAddress": "32.195.78.94"
                    }
                ],
                "routeType": "route_propagated",
                "routeState": "active",
                "bgpAttributes": {
                    "med": "0",
                    "asPath": [
                        "AS_SEQ: [64901]"
                    ]
                }
            }
        ],
        "coreNetworkArn": "arn:aws:networkmanager::<AWSアカウントID>:core-network/core-network-01a763d8efb75dd43"
    }
}
BGP for a VPN connection has been established
{
    "version": "0",
    "id": "87e21c34-fb54-ec8d-038c-3486184ad41a",
    "detail-type": "Network Manager Status Update",
    "source": "aws.networkmanager",
    "account": "<AWSアカウントID>",
    "time": "2026-04-25T06:36:39Z",
    "region": "us-west-2",
    "resources": [
        "arn:aws:networkmanager::<AWSアカウントID>:global-network/global-network-0530c4e133edd415a",
        "arn:aws:networkmanager::<AWSアカウントID>:core-network/core-network-01a763d8efb75dd43",
        "arn:aws:ec2:us-east-1:712953625629:vpn-connection/vpn-0687904978f1a78df"
    ],
    "detail": {
        "changeType": "VPN_CONNECTION_BGP_UP",
        "changeDescription": "BGP for a VPN connection has been established.",
        "edgeLocation": "us-east-1",
        "attachmentArn": "arn:aws:networkmanager::<AWSアカウントID>:attachment/attachment-0cc4803245fdaeb7f",
        "vpnConnectionArn": "arn:aws:ec2:us-east-1:712953625629:vpn-connection/vpn-0687904978f1a78df",
        "outsideIpAddress": "32.195.78.94",
        "coreNetworkArn": "arn:aws:networkmanager::<AWSアカウントID>:core-network/core-network-01a763d8efb75dd43"
    }
}
IPsec for a VPN connection has come up
{
    "version": "0",
    "id": "ab55c864-d2d2-9089-6d04-0f17b5c84bf1",
    "detail-type": "Network Manager Status Update",
    "source": "aws.networkmanager",
    "account": "<AWSアカウントID>",
    "time": "2026-04-25T06:36:12Z",
    "region": "us-west-2",
    "resources": [
        "arn:aws:networkmanager::<AWSアカウントID>:global-network/global-network-0530c4e133edd415a",
        "arn:aws:networkmanager::<AWSアカウントID>:core-network/core-network-01a763d8efb75dd43",
        "arn:aws:ec2:us-east-1:712953625629:vpn-connection/vpn-0687904978f1a78df"
    ],
    "detail": {
        "changeType": "VPN_CONNECTION_IPSEC_UP",
        "changeDescription": "IPsec for a VPN connection has come up.",
        "edgeLocation": "us-east-1",
        "attachmentArn": "arn:aws:networkmanager::<AWSアカウントID>:attachment/attachment-0cc4803245fdaeb7f",
        "vpnConnectionArn": "arn:aws:ec2:us-east-1:712953625629:vpn-connection/vpn-0687904978f1a78df",
        "outsideIpAddress": "32.195.78.94",
        "coreNetworkArn": "arn:aws:networkmanager::<AWSアカウントID>:core-network/core-network-01a763d8efb75dd43"
    }
}
IPsec for a VPN connection has gone down
{
    "version": "0",
    "id": "a5cf3fe0-0e14-1ed1-e8f2-5f8d301ae277",
    "detail-type": "Network Manager Status Update",
    "source": "aws.networkmanager",
    "account": "<AWSアカウントID>",
    "time": "2026-04-25T06:30:43Z",
    "region": "us-west-2",
    "resources": [
        "arn:aws:networkmanager::<AWSアカウントID>:global-network/global-network-0530c4e133edd415a",
        "arn:aws:networkmanager::<AWSアカウントID>:core-network/core-network-01a763d8efb75dd43",
        "arn:aws:ec2:us-east-1:712953625629:vpn-connection/vpn-0687904978f1a78df"
    ],
    "detail": {
        "changeType": "VPN_CONNECTION_IPSEC_DOWN",
        "changeDescription": "IPsec for a VPN connection has gone down.",
        "edgeLocation": "us-east-1",
        "attachmentArn": "arn:aws:networkmanager::<AWSアカウントID>:attachment/attachment-0cc4803245fdaeb7f",
        "vpnConnectionArn": "arn:aws:ec2:us-east-1:712953625629:vpn-connection/vpn-0687904978f1a78df",
        "outsideIpAddress": "18.205.62.158",
        "coreNetworkArn": "arn:aws:networkmanager::<AWSアカウントID>:core-network/core-network-01a763d8efb75dd43"
    }
}

Clicking the Monitoring tab shows the overall data transfer volume and packet count for the entire Core Network.

21.Monitoring.png

You can also view a list of Core Network attachments.

28.Attachments.png

Connectivity Testing

ap-northeast-1 Prod Private VPC EC2 instances and us-east-1 Prod Private VPC EC2 instances

Next, I will perform actual connectivity tests.

First, let's check communication between ap-northeast-1 Prod Private VPC EC2 instances and us-east-1 Prod Private VPC EC2 instances.

I'll run ping:

$ hostname -f
ip-10-1-0-180.ap-northeast-1.compute.internal

$ ping -c 4 10.101.0.38
PING 10.101.0.38 (10.101.0.38) 56(84) bytes of data.
64 bytes from 10.101.0.38: icmp_seq=1 ttl=122 time=152 ms
64 bytes from 10.101.0.38: icmp_seq=2 ttl=122 time=150 ms
64 bytes from 10.101.0.38: icmp_seq=3 ttl=122 time=150 ms
64 bytes from 10.101.0.38: icmp_seq=4 ttl=122 time=150 ms

--- 10.101.0.38 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3005ms
rtt min/avg/max/mdev = 149.811/150.464/152.267/1.041 ms

Communication works!

In this case, we've set isolate-attachments : true to prevent direct communication between networks within the same segment, and configured a send-via action to route traffic through the Security NFG.

When checking the Network Firewall alert logs, the following was recorded:

{
    "firewall_name": "ClounVpc825C25AF-Nfw",
    "availability_zone": "ap-northeast-1a",
    "event_timestamp": "1777122477",
    "event": {
        "icmp_type": 8,
        "aws_category": "",
        "src_ip": "10.1.0.180",
        "src_port": 0,
        "event_type": "alert",
        "alert": {
            "severity": 3,
            "signature_id": 2000002,
            "rev": 1,
            "signature": "ICMP ping detected",
            "action": "allowed",
            "category": ""
        },
        "flow_id": 1543805544049109,
        "dest_ip": "10.101.0.38",
        "proto": "ICMP",
        "verdict": {
            "action": "pass"
        },
        "icmp_code": 0,
        "dest_port": 0,
        "pkt_src": "geneve encapsulation",
        "timestamp": "2026-04-25T13:07:57.490517+0000",
        "direction": "to_server"
    }
}

Here's a diagram of the communication path:

ap-northeast-1 Prod Private VPC EC2 instances and us-east-1 Prod Private VPC EC2 instances.png

ap-northeast-1 Prod Private VPC EC2 instances and ap-northeast-1 Dev Private VPC EC2 instances

Next, let's check communication between ap-northeast-1 Prod Private VPC EC2 instances and ap-northeast-1 Dev Private VPC EC2 instances.

This is communication between different segments.

$ hostname -f
ip-10-1-0-180.ap-northeast-1.compute.internal

$ ping -c 4 10.2.0.21
PING 10.2.0.21 (10.2.0.21) 56(84) bytes of data.

--- 10.2.0.21 ping statistics ---
4 packets transmitted, 0 received, 100% packet loss, time 3152ms

This failed, as expected.

This is because there's no route sharing between the Prod segment and Dev segment.

ap-northeast-1 Dev Private VPC EC2 instances and us-east-1 VPN VPC EC2 instances

Now let's check communication between ap-northeast-1 Dev Private VPC EC2 instances and us-east-1 VPN VPC EC2 instances.

This is communication within the same segment.

$ hostname -f
ip-10-2-0-21.ap-northeast-1.compute.internal

$ ping -c 4 10.102.1.18
PING 10.102.1.18 (10.102.1.18) 56(84) bytes of data.
64 bytes from 10.102.1.18: icmp_seq=1 ttl=124 time=151 ms
64 bytes from 10.102.1.18: icmp_seq=2 ttl=124 time=148 ms
64 bytes from 10.102.1.18: icmp_seq=3 ttl=124 time=148 ms
64 bytes from 10.102.1.18: icmp_seq=4 ttl=124 time=149 ms

--- 10.102.1.18 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 148.291/149.107/151.029/1.115 ms

Communication works perfectly.

In this case, since isolate-attachments : false and no segment-action like send-via is configured, traffic doesn't go through the Network Firewall.

Here's a diagram of the communication path:

ap-northeast-1 Dev Private VPC EC2 instances and us-east-1 VPN VPC EC2 instances.png

ap-northeast-1 Prod Private VPC EC2 instances and Internet

Next, let's check communication between ap-northeast-1 Prod Private VPC EC2 instances and the internet.

We'll access https://checkip.amazonaws.com to see which exit point is being used.

$ hostname -f
ip-10-1-0-180.ap-northeast-1.compute.internal

$ curl -m 5 -v https://checkip.amazonaws.com
* Host checkip.amazonaws.com:443 was resolved.
* IPv6: (none)
* IPv4: 3.0.185.196, 18.138.142.246, 52.74.183.204, 18.139.26.116, 52.74.9.231, 13.228.196.61, 52.76.181.204, 54.255.102.50
*   Trying 3.0.185.196:443...
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* SSL Trust Anchors:
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256 / x25519 / RSASSA-PSS
* ALPN: server accepted h2
* Server certificate:
*   subject: CN=checkip.amazonaws.com
*   start date: Nov  3 00:00:00 2025 GMT
*   expire date: Dec  2 23:59:59 2026 GMT
*   issuer: C=US; O=Amazon; CN=Amazon RSA 2048 M04
*   Certificate level 0: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
*   Certificate level 1: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
*   Certificate level 2: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
*   subjectAltName: "checkip.amazonaws.com" matches cert's "checkip.amazonaws.com"
* SSL certificate verified via OpenSSL.
* Established connection to checkip.amazonaws.com (3.0.185.196 port 443) from 10.1.0.180 port 40244 
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://checkip.amazonaws.com/
* [HTTP/2] [1] [:method: GET]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: checkip.amazonaws.com]
* [HTTP/2] [1] [:path: /]
* [HTTP/2] [1] [user-agent: curl/8.17.0]
* [HTTP/2] [1] [accept: */*]
> GET / HTTP/2
> Host: checkip.amazonaws.com
> User-Agent: curl/8.17.0
> Accept: */*
> 
* Request completely sent off
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
< HTTP/2 200 
< date: Sat, 25 Apr 2026 13:32:14 GMT
< content-type: text/plain;charset=UTF-8
< content-length: 13
< server: nginx
< vary: Origin
< vary: Access-Control-Request-Method
< vary: Access-Control-Request-Headers
< 
57.181.60.10
* Connection #0 to host checkip.amazonaws.com:443 left intact

Communication works successfully.

The IP 57.181.60.10 is the NAT Gateway in the ap-northeast-1 Inspection VPC.

38.57.181.60.10.png

This happens because in the Prod segment, we've configured a send-to action to route traffic to the Security NFG.

This path also goes through the Network Firewall. Checking the Network Firewall logs confirms that this communication was recorded:

{
    "firewall_name": "ClounVpc825C25AF-Nfw",
    "availability_zone": "ap-northeast-1a",
    "event_timestamp": "1777123934",
    "event": {
        "aws_category": "",
        "tx_id": 0,
        "app_proto": "tls",
        "src_ip": "10.1.0.180",
        "src_port": 40244,
        "event_type": "alert",
        "alert": {
            "severity": 3,
            "signature_id": 2000001,
            "rev": 1,
            "signature": "Access to checkip.amazonaws.com detected",
            "action": "allowed",
            "category": ""
        },
        "flow_id": 1802298880418392,
        "dest_ip": "3.0.185.196",
        "proto": "TCP",
        "verdict": {
            "action": "pass"
        },
        "tls": {
            "sni": "checkip.amazonaws.com",
            "version": "UNDETERMINED"
        },
        "dest_port": 443,
        "pkt_src": "geneve encapsulation",
        "timestamp": "2026-04-25T13:32:14.425631+0000",
        "direction": "to_server"
    }
}

Here's a diagram of the communication path:

ap-northeast-1 Prod Private VPC EC2 instances and Internet.png

us-east-1 Prod Private VPC EC2 instances and Internet

Next, let's check communication between us-east-1 Prod Private VPC EC2 instances and the internet.

Unlike the previous pattern, the source VPC region and the Inspection VPC region are different.

Here's the communication result:

$ hostname -f
ip-10-101-0-38.ec2.internal

$ curl -m 5 -v https://checkip.amazonaws.com
* Host checkip.amazonaws.com:443 was resolved.
* IPv6: (none)
* IPv4: 44.194.153.254, 107.23.164.39, 98.95.253.57, 100.49.40.12, 44.214.94.248, 52.0.234.61, 54.211.239.28, 34.232.152.199
*   Trying 44.194.153.254:443...
*   Trying 107.23.164.39:443...
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* SSL Trust Anchors:
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256 / x25519 / RSASSA-PSS
* ALPN: server accepted h2
* Server certificate:
*   subject: CN=checkip.amazonaws.com
*   start date: Nov  3 00:00:00 2025 GMT
*   expire date: Dec  2 23:59:59 2026 GMT
*   issuer: C=US; O=Amazon; CN=Amazon RSA 2048 M04
*   Certificate level 0: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
*   Certificate level 1: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
*   Certificate level 2: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
*   subjectAltName: "checkip.amazonaws.com" matches cert's "checkip.amazonaws.com"
* SSL certificate verified via OpenSSL.
* Established connection to checkip.amazonaws.com (44.194.153.254 port 443) from 10.101.0.38 port 43182
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://checkip.amazonaws.com/
* [HTTP/2] [1] [:method: GET]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: checkip.amazonaws.com]
* [HTTP/2] [1] [:path: /]
* [HTTP/2] [1] [user-agent: curl/8.17.0]
* [HTTP/2] [1] [accept: */*]
> GET / HTTP/2
> Host: checkip.amazonaws.com
> User-Agent: curl/8.17.0
> Accept: */*
>
* Request completely sent off
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
< HTTP/2 200
< date: Sat, 25 Apr 2026 13:35:54 GMT
< content-type: text/plain;charset=UTF-8
< content-length: 13
< server: nginx
< vary: Origin
< vary: Access-Control-Request-Method
< vary: Access-Control-Request-Headers
<
57.181.60.10
* Connection #0 to host checkip.amazonaws.com:443 left intact

The same IP 57.181.60.10 was returned.

This confirms that traffic is being routed to the Inspection VPC even across different regions.

The Network Firewall logs also recorded this:

{
    "firewall_name": "ClounVpc825C25AF-Nfw",
    "availability_zone": "ap-northeast-1a",
    "event_timestamp": "1777124154",
    "event": {
        "aws_category": "",
        "tx_id": 0,
        "app_proto": "tls",
        "src_ip": "10.101.0.38",
        "src_port": 43182,
        "event_type": "alert",
        "alert": {
            "severity": 3,
            "signature_id": 2000001,
            "rev": 1,
            "signature": "Access to checkip.amazonaws.com detected",
            "action": "allowed",
            "category": ""
        },
        "flow_id": 622001668079509,
        "dest_ip": "44.194.153.254",
        "proto": "TCP",
        "verdict": {
            "action": "pass"
        },
        "tls": {
            "sni": "checkip.amazonaws.com",
            "version": "UNDETERMINED"
        },
        "dest_port": 443,
        "pkt_src": "geneve encapsulation",
        "timestamp": "2026-04-25T13:35:54.573607+0000",
        "direction": "to_server"
    }
}

Here's a diagram of the communication path:

us-east-1 Prod Private VPC EC2 instances and Internet.png

ap-northeast-1 Dev Private VPC EC2 instances and Internet

Next, let's check communication between ap-northeast-1 Dev Private VPC EC2 instances and the internet.

$ hostname -f
ip-10-2-0-21.ap-northeast-1.compute.internal

$ curl -m 5 -v https://checkip.amazonaws.com
* Host checkip.amazonaws.com:443 was resolved.
* IPv6: (none)
* IPv4: 52.74.9.231, 18.138.142.246, 52.74.183.204, 54.255.102.50, 47.131.141.155, 52.76.181.204, 3.0.185.196, 18.139.26.116
*   Trying 52.74.9.231:443...
*   Trying 18.138.142.246:443...
*   Trying 52.74.183.204:443...
*   Trying 54.255.102.50:443...
*   Trying 47.131.141.155:443...
*   Trying 52.76.181.204:443...
*   Trying 3.0.185.196:443...
*   Trying 18.139.26.116:443...
* Connection timed out after 5001 milliseconds
* closing connection #0
curl: (28) Connection timed out after 5001 milliseconds

Communication failed.

This is because there's no route from the Dev segment that sets the Egress VPC as the default gateway.

While there's route sharing with the Share segment that the Egress VPC belongs to, this only shares routes that propagate from network resources.

As a solution, we need to set up a static default route.

All routing in Cloud WAN is controlled by a single Core Network Policy. Let's update the Core Network Policy.

Click on the policy that's currently "LIVE".

22.Policy version.png

You can check various information in the GUI:

  • "Network settings" tab
    23.Policy_Network settings.png
  • "Segments" tab
    22.Policy_Segments.png
  • "Network function groups" tab
    24.Network function groups.png
  • "Routing policies" tab
    25.Routing policies.png
  • "Segment actions" tab
    26.Segment actions.png
  • "Attachment policies" tab
    27.Attachment policies.png

Let's edit the policy.

Since we want to add a static route, click on the "Segment actions" tab.

29.Create policy.png

Click "Create" under "Routes".

We want to set the default route for the dev segment to go through the Egress VPCs in ap-northeast-1 and us-east-1.

30.Create segment route.png

Note that destinations are limited to one per region, so you can't set up multiple Egress VPCs in the same region.

destinations — Defines the list of attachments to send the traffic to, with up to one attachment-id per Region. Because a segment is a global object, you should design your routing so that every AWS Region has an attachment in the destinations list. Regions that do not have attachments in this list will receive a propagated version of this route through cross-Region peering connections, and will use the static route of another Region. This is the same case for multiple attachments that are defined across multiple remote Regions.

Core network policy version parameters in AWS Cloud WAN - AWS Network Manager

After adding, the routes look like this:

31.Routes after addition.png

In the Core Network Policy JSON, this is added as:

{
.
.
(omitted)
.
.
  "segment-actions": [
    {
      "action": "create-route",
      "segment": "dev",
      "destination-cidr-blocks": [
        "0.0.0.0/0"
      ],
      "destinations": [
        "attachment-01f13397c9dc20640",
        "attachment-03a397f1fcd710d8d"
      ]
    },
.
.
(omitted)
.
.
  ],
.
.
(omitted)
.
.
}

For return traffic from the Egress VPC, no additional routes are needed since we're sharing route information through the Share action.

Clicking "Create policy" creates a new policy version with the alias "LATEST" and status "Ready to execute".

33.Ready to execute.png

Select the new policy version and click "View or apply change set".

This shows what updates will be made, similar to CloudFormation's Change Set:

34.Policy version - 2 change set (5).png

Clicking "Details" shows exactly what changes will be made:

35.Details.png

Click "Apply change set" to apply the new version:

36.Policy change set execution successfully started.png

After about two minutes, all events are completed:

37.5:5 Completed events.png

Now let's try accessing https://checkip.amazonaws.com again:

$ hostname -f
ip-10-2-0-21.ap-northeast-1.compute.internal
$ 
$ curl -m 5 -v https://checkip.amazonaws.com
* Host checkip.amazonaws.com:443 was resolved.
* IPv6: (none)
* IPv4: 18.139.26.116, 52.74.9.231, 3.0.185.196, 52.74.183.204, 54.255.102.50, 47.131.141.155, 13.228.196.61, 18.138.142.246
*   Trying 18.139.26.116:443...
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* SSL Trust Anchors:
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256 / x25519 / RSASSA-PSS
* ALPN: server accepted h2
* Server certificate:
*   subject: CN=checkip.amazonaws.com
*   start date: Nov  3 00:00:00 2025 GMT
*   expire date: Dec  2 23:59:59 2026 GMT
*   issuer: C=US; O=Amazon; CN=Amazon RSA 2048 M04
*   Certificate level 0: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
*   Certificate level 1: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
*   Certificate level 2: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
*   subjectAltName: "checkip.amazonaws.com" matches cert's "checkip.amazonaws.com"
* SSL certificate verified via OpenSSL.
* Established connection to checkip.amazonaws.com (18.139.26.116 port 443) from 10.2.0.21 port 38934 
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://checkip.amazonaws.com/
* [HTTP/2] [1] [:method: GET]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: checkip.amazonaws.com]
* [HTTP/2] [1] [:path: /]
* [HTTP/2] [1] [user-agent: curl/8.17.0]
* [HTTP/2] [1] [accept: */*]
> GET / HTTP/2
> Host: checkip.amazonaws.com
> User-Agent: curl/8.17.0
> Accept: */*
> 
* Request completely sent off
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
< HTTP/2 200 
< date: Sat, 25 Apr 2026 13:56:15 GMT
< content-type: text/plain;charset=UTF-8
< content-length: 13
< server: nginx
< vary: Origin
< vary: Access-Control-Request-Method
< vary: Access-Control-Request-Headers
< 
13.113.18.78
* Connection #0 to host checkip.amazonaws.com:443 left intact

Now the access is successful!

This IP address is the NAT Gateway IP address in ap-northeast-1.

Here's a diagram of the communication path:

ap-northeast-1 Dev Private VPC EC2 instances and Internet.png

us-east-1 VPC EC2 Instance and Internet Communication

Finally, here's the communication between us-east-1 VPC EC2 instance and the Internet.

$ hostname -f
ip-10-102-1-18.ec2.internal

$ curl -m 5 -v https://checkip.amazonaws.com
* Host checkip.amazonaws.com:443 was resolved.
* IPv6: (none)
* IPv4: 18.208.47.218, 98.95.253.57, 54.211.239.28, 32.193.53.71, 107.23.164.39, 44.214.94.248, 52.5.178.197, 3.226.147.200
*   Trying 18.208.47.218:443...
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* SSL Trust Anchors:
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256 / x25519 / RSASSA-PSS
* ALPN: server accepted h2
* Server certificate:
*   subject: CN=checkip.amazonaws.com
*   start date: Nov  3 00:00:00 2025 GMT
*   expire date: Dec  2 23:59:59 2026 GMT
*   issuer: C=US; O=Amazon; CN=Amazon RSA 2048 M04
*   Certificate level 0: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
*   Certificate level 1: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
*   Certificate level 2: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
*   subjectAltName: "checkip.amazonaws.com" matches cert's "checkip.amazonaws.com"
* SSL certificate verified via OpenSSL.
* Established connection to checkip.amazonaws.com (18.208.47.218 port 443) from 10.102.1.18 port 59376 
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://checkip.amazonaws.com/
* [HTTP/2] [1] [:method: GET]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: checkip.amazonaws.com]
* [HTTP/2] [1] [:path: /]
* [HTTP/2] [1] [user-agent: curl/8.17.0]
* [HTTP/2] [1] [accept: */*]
> GET / HTTP/2
> Host: checkip.amazonaws.com
> User-Agent: curl/8.17.0
> Accept: */*
> 
* Request completely sent off
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
< HTTP/2 200 
< date: Sat, 25 Apr 2026 13:59:03 GMT
< content-type: text/plain;charset=UTF-8
< content-length: 14
< server: nginx
< vary: Origin
< vary: Access-Control-Request-Method
< vary: Access-Control-Request-Headers
< 
54.80.107.232
* Connection #0 to host checkip.amazonaws.com:443 left intact

Access was successful. This IP address belongs to the NAT Gateway of the us-east-1 Egress VPC.

39.54.80.107.232.png

I believe this is because of Cloud WAN's evaluation order - when there are different forwarding destinations for the same destination IP address, routes in the same region are prioritized. While the official AWS documentation doesn't specifically mention priorities between Static Routes, it does explain that VPC-propagated routes from the same region are prioritized.

Route evaluation

Cloud WAN evaluates routes at each core network edge in the following order:

  1. The most specific route for the destination
  2. For routes with the same destination IP address, but different targets, the following route priority is used:
    1. Static routes
    2. VPC-propagated routes in the same Region.
    3. For dynamic routes received at the core network with an unequal AS path length and/or MED BGP attributes, Cloud WAN evaluates them in the following order:
      1. AS path length
      2. MED
    4. For dynamic routes received at the core network with equal AS path length and MED BGP attributes, Cloud WAN evaluates them in the following order:
      1. Direct Connect gateway-propagated routes.
      2. Cloud WAN Connect-propagates routes in the same Region.
      3. Site-to-Site VPN-propagated routes in the same Region.
      4. Routes propagated from other sources, such as transit gateway peering and core network edges in other remote Regions over the AWS global infrastructure. If identical routes are received from two or more sources, a single attachment will be chosen in a deterministically random manner.

Attachments in AWS Cloud WAN - AWS Network Manager

The communication path is illustrated below:

us-east-1 VPC EC2 Instance and Internet Communication.png

When you want to quickly set up a Cloud WAN environment

I built a complete AWS Cloud WAN environment using AWS CDK, implementing Network Firewall inspection through Service Insertion and consolidating outbound internet traffic.

Feel free to use this when you want to quickly set up a Cloud WAN environment.

When using patterns with three or more regions, interconnecting with Transit Gateway becomes challenging. In such cases, adopting or migrating to Cloud WAN is a viable option. Let's consider this with reference to the following AWS blog:

https://aws.amazon.com/jp/blogs/networking-and-content-delivery/aws-cloud-wan-and-aws-transit-gateway-migration-and-interoperability-patterns/

Additionally, there's an official workshop for Cloud WAN that can deepen your understanding:

https://catalog.us-east-1.prod.workshops.aws/workshops/3547afcd-0829-4d44-85e8-17b68d4b52bc/ja-JP

I hope this article is helpful to someone.

That's all from nonPi (@non____97) of the Cloud Business Headquarters Consulting Department!

Share this article