Build an AWS site-to-site VPN with BGP to an IOS-XE router
AWSWorking
Tasks
- Create the customer gateway, the virtual private gateway, and attach the VGW to the VPC.
- Create a BGP-based VPN connection with IKEv2 only and fixed inside CIDRs per tunnel.
- Enable VGW route propagation on the app route table.
- Configure IKEv2, the IPsec profile and two tunnel interfaces on R1.
- Run eBGP to both AWS inside addresses and advertise the on-prem summary.
Solution
1Customer gateway, VGW and VPN connection
AWS CGW=$(aws ec2 create-customer-gateway --type ipsec.1 \ --public-ip 198.51.100.10 --bgp-asn 65010 \ --query CustomerGateway.CustomerGatewayId --output text) VGW=$(aws ec2 create-vpn-gateway --type ipsec.1 --amazon-side-asn 64512 \ --query VpnGateway.VpnGatewayId --output text) aws ec2 attach-vpn-gateway --vpn-gateway-id $VGW --vpc-id vpc-0c5d6e7f8091a2b34 VPN=$(aws ec2 create-vpn-connection --type ipsec.1 \ --customer-gateway-id $CGW --vpn-gateway-id $VGW \ --options '{"StaticRoutesOnly":false,"TunnelOptions":[ {"TunnelInsideCidr":"169.254.10.0/30","PreSharedKey":"<psk-tunnel-1>","IKEVersions":[{"Value":"ikev2"}]}, {"TunnelInsideCidr":"169.254.20.0/30","PreSharedKey":"<psk-tunnel-2>","IKEVersions":[{"Value":"ikev2"}]}]}' \ --query VpnConnection.VpnConnectionId --output text) aws ec2 enable-vgw-route-propagation --route-table-id rtb-0d6e7f8091a2b3c45 --gateway-id $VGWStaticRoutesOnly: falsemeans BGP. Read the AWS outside addresses withaws ec2 describe-vpn-connections --vpn-connection-ids $VPN --query "VpnConnections[0].Options.TunnelOptions[].[OutsideIpAddress,TunnelInsideCidr]" --output text. AWS can also generate a device config withget-vpn-connection-device-sample-configuration.2IKEv2 and IPsec on R1R1
R1 on Cisco IOS crypto ikev2 proposal AWS-PROP encryption aes-cbc-256 integrity sha256 group 14 ! crypto ikev2 policy AWS-POL proposal AWS-PROP ! crypto ikev2 keyring AWS-KEYS peer AWS-TUN1 address 203.0.113.11 pre-shared-key <psk-tunnel-1> peer AWS-TUN2 address 203.0.113.12 pre-shared-key <psk-tunnel-2> ! crypto ikev2 profile AWS-IKEV2 match identity remote address 203.0.113.11 255.255.255.255 match identity remote address 203.0.113.12 255.255.255.255 identity local address 198.51.100.10 authentication remote pre-share authentication local pre-share keyring local AWS-KEYS lifetime 28800 dpd 10 3 on-demand ! crypto ipsec transform-set AWS-TS esp-aes 256 esp-sha256-hmac mode tunnel ! crypto ipsec profile AWS-IPSEC set transform-set AWS-TS set pfs group14 set ikev2-profile AWS-IKEV2AES-256, SHA-256 and DH group 14 are all in AWS's accepted set. Lifetime 28800 seconds matches the AWS phase 1 default.
3Tunnel interfacesR1
R1 on Cisco IOS interface Tunnel1 description AWS tunnel 1 ip address 169.254.10.2 255.255.255.252 ip tcp adjust-mss 1379 tunnel source GigabitEthernet0/0/0 tunnel mode ipsec ipv4 tunnel destination 203.0.113.11 tunnel protection ipsec profile AWS-IPSEC ! interface Tunnel2 description AWS tunnel 2 ip address 169.254.20.2 255.255.255.252 ip tcp adjust-mss 1379 tunnel source GigabitEthernet0/0/0 tunnel mode ipsec ipv4 tunnel destination 203.0.113.12 tunnel protection ipsec profile AWS-IPSECR1 takes the second address of each /30; AWS has the first. The MSS clamp of 1379 is the value AWS uses in its sample configs.
4eBGP over both tunnelsR1
R1 on Cisco IOS ip route 192.168.0.0 255.255.0.0 Null0 ! router bgp 65010 bgp log-neighbor-changes neighbor 169.254.10.1 remote-as 64512 neighbor 169.254.10.1 timers 10 30 30 neighbor 169.254.20.1 remote-as 64512 neighbor 169.254.20.1 timers 10 30 30 ! address-family ipv4 network 192.168.0.0 mask 255.255.0.0 neighbor 169.254.10.1 activate neighbor 169.254.20.1 activate exit-address-familyThe Null0 route lets the
networkstatement match an exact RIB entry. Keepalive 10 and hold 30 seconds detect a dead tunnel faster than the defaults.
Verify
R1# show crypto ikev2 sa
IPv4 Crypto IKEv2 SA
Tunnel-id Local Remote fvrf/ivrf Status
1 198.51.100.10/500 203.0.113.11/500 none/none READY
Encr: AES-CBC, keysize: 256, PRF: SHA256, Hash: SHA256, DH Grp:14, Auth sign: PSK, Auth verify: PSK
Life/Active Time: 28800/742 sec
Tunnel-id Local Remote fvrf/ivrf Status
2 198.51.100.10/500 203.0.113.12/500 none/none READY
Encr: AES-CBC, keysize: 256, PRF: SHA256, Hash: SHA256, DH Grp:14, Auth sign: PSK, Auth verify: PSK
Life/Active Time: 28800/736 secTwo IKEv2 SAs in READY, one per AWS endpoint, on UDP 500 because there is no NAT in the path.
R1# show ip bgp summary
BGP router identifier 198.51.100.10, local AS number 65010
BGP table version is 3, main routing table version 3
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd
169.254.10.1 4 64512 76 74 3 0 0 00:12:09 1
169.254.20.1 4 64512 75 73 3 0 0 00:12:03 1Both neighbors established with one prefix each, the VPC CIDR 10.30.0.0/16.
aws ec2 describe-vpn-connections --vpn-connection-ids $VPN \
--query "VpnConnections[0].VgwTelemetry[].[OutsideIpAddress,Status,StatusMessage]" --output text
203.0.113.11 UP 1 BGP ROUTES
203.0.113.12 UP 1 BGP ROUTESAWS sees both tunnels UP and accepted the on-prem summary on each.
R1# ping 10.30.10.20 source GigabitEthernet0/0/1
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 10.30.10.20, timeout is 2 seconds:
Packet sent with a source address of 192.168.0.1
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 11/12/14 msEnd to end through the tunnel. Needs the propagated route in the VPC and a security group on APP1 that allows ICMP from 192.168.0.0/16.
Mistakes people make
- Configuring only one tunnel. AWS maintains one endpoint at a time and expects both up.
- Forgetting VGW route propagation, so the VPN is up but replies have no route back.
- Swapping the inside addresses. AWS is always the first host of the /30, the customer the second.
- Advertising a network that is not in the RIB, so BGP never sends it. The Null0 route fixes that.
- Leaving MSS unclamped and seeing large transfers stall through the tunnel.
On other platforms
Azure models the on-prem side as a local network gateway and connects it to a route-based VPN gateway in GatewaySubnet. With BGP, the local network gateway carries R1's ASN and BGP peer address, and R1 peers with the gateway's BGP address inside GatewaySubnet, which is not directly connected, so R1 needs a static route to it over the tunnel and eBGP multihop.
az network local-gateway create -g rg-net -n lng-hq \
--gateway-ip-address 198.51.100.10 \
--local-address-prefixes 192.168.0.1/32 \
--asn 65010 --bgp-peering-address 192.168.0.1
az network vpn-connection create -g rg-net -n cn-hq \
--vnet-gateway1 vgw-hub --local-gateway2 lng-hq \
--shared-key <psk> --enable-bgpSay it in the interview
"AWS gives me two tunnels per VPN connection, to two endpoints in different AZs. I build both as VTIs with IKEv2 and run eBGP to the first address of each /30, advertising the on-prem summary backed by a Null0 route. On the AWS side I enable route propagation on the route tables, otherwise the tunnels come up and nothing flows. I clamp MSS on the tunnels and check both SAs, both BGP sessions and an end-to-end ping."