The tunnel will come up. It usually does, because IKE only needs matching proposals and a reachable peer address. What fails afterwards is the return path: the AWS workload sends packets into a tunnel but nothing on the Azure side knows how to answer 10.10.0.0/16, or the Azure route exists in a table that the workload subnet does not use. Write the route plan before you touch either console, and the tunnel becomes the least interesting part of the job.

Step 1: freeze the address plan

Work with concrete values. An AWS workload sits at 10.10.1.20 inside 10.10.0.0/16 and needs TCP 443 to an Azure service at 10.20.1.30 inside 10.20.0.0/16. The two ranges must not overlap, and the service pair, not the tunnel, is the acceptance test.

Write those four facts down before anything else, because every later step is checked against them.

Step 2: name the gateway that owns each end

AWS Site-to-Site VPN can terminate on a virtual private gateway or a transit gateway, and those are different routing owners. Azure offers its managed VPN Gateway and, separately, VM-based appliances that customers run themselves. Record which pair you have, because the next hop differs in each combination.

For a managed gateway, do not copy a route that points at a guessed private appliance address. For an appliance, do not assume that cloud route propagation configures the guest operating system, because it does not.

Getting this wrong produces a plan that looks complete and routes packets into an address that never answers.

Step 3: write the route each workload really uses

Every boundary below is a separate lookup, and a route in one of them is not a route for the packet. Fill the table in with your own values before the tunnel goes live.

BoundaryMust reachOwner to inspect
AWS workload subnet10.20.0.0/16the subnet's VPC route table
AWS transit gateway, if used10.20.0.0/16 via the VPN attachmentthe table associated with that attachment
Azure workload subnet10.10.0.0/16effective routes on the NIC, whatever their source
VPN scopeboth prefixes, agreedstatic connection ranges or BGP advertisements

On AWS, the workload subnet route table is yours to update even after BGP or a tunnel is healthy; the routing overview treats that as part of the connection. On Azure, a user-defined route table is associated with a subnet rather than linked to the virtual network, so check the effective route at the workload NIC instead of at the VNet blade.

A managed Azure gateway can learn the remote prefix through gateway propagation, and a UDR can override that decision. Add the UDR when you have a reason, not by reflex. If you do add one, point it at the next hop the gateway publishes for the VPN path rather than inventing an appliance address. Then re-read the effective routes on the NIC, because the NIC is where the decision is actually made.

Step 4: reconcile the scope

For BGP, compare what each side advertises with what the other side actually learned, specific prefix by specific prefix. For static routing, compare the configured remote ranges with the workload routes you wrote in step 3.

An IKE relationship that agrees on cryptography is not evidence that either side learned 10.10.0.0/16 or 10.20.0.0/16. Two tunnels can be up while one side advertises a single /24 instead of the /16 you planned. Check the prefix in the routing table, not in the tunnel status. The mismatch shows up later as one working subnet and one that never answers.

Step 5: test the service, from the real source

Permit the intended flow in AWS security groups and network ACLs, in Azure NSGs, and in any appliance filter in the path. Then open one connection from 10.10.1.20 to the approved service address and port and confirm that the reply comes back to that same source.

Both cloud security groups and NSGs are stateful, so a denied return packet is a routing symptom rather than a rule you forgot to write in reverse.

A ping from either gateway settles nothing. ICMP to a gateway address exercises the control plane path, not the forwarded TCP service the workload needs.

Rollback and records

Record the route owners next to the tunnel identifiers, and keep the pre-change route tables. If the change has to come out, remove the workload routes before tearing down the tunnel, so no subnet is left pointing at a next hop that no longer exists.

A later subnet move or spoke attachment then has one defined place to update, instead of a working tunnel carrying the blame for a route it never owned.

ບົດຄວາມທີ່ກ່ຽວຂ້ອງ