Connect a Google Cloud VPC to a VPNGeek gateway over IKEv2 IPsec — HA VPN with Cloud Router and BGP, or Classic VPN with static routes, end to end.
This guide connects a Google Cloud VPC to a VPNGeek gateway over IKEv2 IPsec. Google offers two products: HA VPN, the current recommendation, which gives a 99.99% SLA using two tunnel interfaces and BGP via a Cloud Router; and Classic VPN, a single-tunnel gateway that supports static (policy-based or route-based) routing. This guide covers HA VPN as the primary path and notes the Classic alternative where it differs. When you finish, the VPC and the VPNGeek side reach each other over an encrypted link — with automatic failover on HA VPN.
Before you start
Collect the following before you touch either side. Getting the ASNs and interface addressing straight now avoids the most common BGP problems.
- A VPNGeek plan that includes IPsec Gateways, with a static public IP on the gateway.
- A GCP project with the Compute Engine API enabled and rights to create networking resources, plus the
gcloudCLI or the console. - An existing VPC network and subnet — example VPC range 10.100.0.0/16 in region
europe-west1. - Non-overlapping CIDRs — VPC 10.100.0.0/16 vs the VPNGeek side 10.20.0.0/16.
- For HA VPN/BGP: a Cloud Router ASN (e.g. 65010) and a peer ASN for VPNGeek (e.g. 65020), plus link-local /30 addresses in 169.254.0.0/16 for the BGP session(s).
1. Create the HA VPN gateway and Cloud Router
The HA VPN gateway is a Google-managed resource with two interfaces, each getting its own public IP. The Cloud Router runs BGP and propagates learned routes into the VPC.
gcloud compute vpn-gateways create vpngeek-havpn-gw \
--network=vpngeek-vpc \
--region=europe-west1
# Cloud Router for BGP
gcloud compute routers create vpngeek-router \
--network=vpngeek-vpc \
--region=europe-west1 \
--asn=65010
# Read back the two interface IPs — you peer with BOTH:
gcloud compute vpn-gateways describe vpngeek-havpn-gw \
--region=europe-west1 \
--format='value(vpnInterfaces[].ipAddress)'
2. Register the VPNGeek side as an external VPN gateway
Google needs a peer object describing your VPNGeek gateway. A single-IP VPNGeek gateway is a one-interface external gateway; HA VPN will still stand up two tunnels from its two interfaces to that single peer IP.
gcloud compute external-vpn-gateways create vpngeek-peer \
--interfaces 0=203.0.113.10
3. Create the VPN tunnels
Create one tunnel from each HA VPN interface to the external gateway. IKEv2 is set explicitly, and each tunnel references its Cloud Router for BGP. Note the --interface (0 and 1) selects which HA VPN interface the tunnel uses.
--peer-external-gateway=vpngeek-peer \
--peer-external-gateway-interface=0 \
--region=europe-west1 \
--ike-version=2 \
--shared-secret='<tunnel-0-psk>' \
--router=vpngeek-router \
--vpn-gateway=vpngeek-havpn-gw \
--interface=0
gcloud compute vpn-tunnels create vpngeek-tunnel-1 \
--peer-external-gateway=vpngeek-peer \
--peer-external-gateway-interface=0 \
--region=europe-west1 \
--ike-version=2 \
--shared-secret='<tunnel-1-psk>' \
--router=vpngeek-router \
--vpn-gateway=vpngeek-havpn-gw \
--interface=1
4. Configure BGP on the Cloud Router
Add a router interface with a link-local /30 for each tunnel, then a BGP peer on each. VPNGeek advertises 10.20.0.0/16 and learns the VPC ranges dynamically — no static routes to maintain.
gcloud compute routers add-interface vpngeek-router \
--interface-name=if-tunnel-0 \
--vpn-tunnel=vpngeek-tunnel-0 \
--ip-address=169.254.21.1 --mask-length=30 \
--region=europe-west1
gcloud compute routers add-bgp-peer vpngeek-router \
--peer-name=peer-tunnel-0 \
--interface=if-tunnel-0 \
--peer-ip-address=169.254.21.2 \
--peer-asn=65020 \
--region=europe-west1
# Repeat for tunnel 1 with 169.254.22.1/30 and peer .22.2
5. Configure the VPNGeek side
In the dashboard open Gateways > Tunnels and add a tunnel to each HA VPN interface IP from step 1. Force IKE version 2, use the matching per-tunnel shared secret, and configure the BGP peering to mirror the Cloud Router.
peer_address: 198.51.100.40 # HA VPN interface 0 IP
ike_version: 2
proposal: aes256-sha256 # phase 1 & 2
dh_group: 14
psk: <tunnel-0-psk>
# BGP peering (mirrors the Cloud Router):
inside_local: 169.254.21.2/30
inside_peer: 169.254.21.1
local_asn: 65020
peer_asn: 65010
advertise: 10.20.0.0/16
# Second tunnel → 198.51.100.41, 169.254.22.2/30, tunnel-1 psk
# CLASSIC VPN alternative (single tunnel, static routing) uses
# local_subnet 10.20.0.0/16 and remote_subnet 10.100.0.0/16
# instead of BGP.
6. Verify the connection
Both tunnels should report Established on GCP and ESTABLISHED in the VPNGeek dashboard, and the BGP sessions should come up. Check status, then send real traffic from a Compute Engine VM to a host on the VPNGeek side.
gcloud compute vpn-tunnels describe vpngeek-tunnel-0 \
--region=europe-west1 --format='value(status,detailedStatus)'
# BGP session state and learned routes
gcloud compute routers get-status vpngeek-router \
--region=europe-west1 \
--format='value(result.bgpPeerStatus[].status,result.bgpPeerStatus[].numLearnedRoutes)'
# From a Compute Engine VM in the VPC:
ping 10.20.0.1
# Confirm VPC firewall rules allow ingress from 10.20.0.0/16.
Troubleshooting
Tunnel stuck in First Handshake / negotiating
Usually a per-tunnel shared secret mismatch, or a phase 1/2 proposal mismatch. Confirm IKEv2, aes256-sha256, and DH group 14 on both sides, and that each VPNGeek tunnel uses the secret from its matching gcloud tunnel.
Tunnel established but no traffic
On HA VPN, a BGP session that is not up means no routes exchange. Check get-status shows the peer as established with a non-zero learned-route count, and that VPNGeek is advertising 10.20.0.0/16. Also verify VPC firewall rules permit the traffic.
BGP will not establish
The link-local /30 addresses must line up — Cloud Router uses .1, VPNGeek uses .2 on each /30 — and the ASNs must not be swapped (Cloud Router 65010, VPNGeek 65020). A wrong mask or reused /30 across tunnels is the usual culprit.
Classic VPN no traffic with static routes
Confirm you created a matching route in the VPC pointing 10.20.0.0/16 at the tunnel, and that the remote/local traffic selectors mirror exactly. Policy-based Classic VPN is intolerant of selector mismatches.
