Once an on-premises network reaches a VPC through Cloud VPN, the destination for a Compute Engine service is normally the VM's internal address. The external IPv4 address is not a second address you can substitute into the same private route. Most confusion in this area comes from three addresses with three jobs being treated as interchangeable, so start by naming which one a given packet is using.

Three addresses, three jobs

Name all three before you debug any of them, because the answer changes the object you inspect next.

AddressJob
Cloud VPN endpointwhere the IPsec peers meet
Internal IPthe address your route and firewall must name
External IPv4the platform's inbound mapping, not a guest address

The first one belongs to the tunnel. The second belongs to your route and firewall design. The third belongs to inbound internet access and is mapped, not attached. A design that works for one of them says nothing about the other two.

Why the external address is not a second interface

The addressing guide is the authority for how internal and external reachability differ on Compute Engine. A Compute Engine external IPv4 is a one-to-one mapping onto the instance's single internal NIC, so the guest never sees a second interface or a second address on that NIC. What the VM reports inside is still one primary internal address.

That is why a private client routing toward 10.24.1.7 through the tunnel and a client targeting the VM's external address are on different paths. Opening a firewall rule for the public address changes nothing about the VPC route that has to carry the tunnel traffic, and editing a guest route does not move the platform's mapping. Pick the address your route names, then check only the objects that govern it. That discipline removes most of the guesswork from this troubleshooting path.

Walk the path with gcloud

Start from the instance and read both addresses from the same object, so you know which one your documentation is talking about:

gcloud compute instances describe app-1 --zone=europe-west1-b \
  --format="value(networkInterfaces[0].networkIP,networkInterfaces[0].accessConfigs[0].natIP)"

Then confirm the routing and the permission that the path actually depends on:

gcloud compute routes list --filter="destRange:10.24.1.0/24"
gcloud compute firewall-rules list --filter="sourceRanges:10.99.0.0/24"
gcloud compute vpn-tunnels describe TUNNEL_NAME --region=europe-west1

Read the tunnel's advertised and learned ranges, the VPC route for the workload subnet, and the firewall rule that permits the on-premises source. Those three have to agree before a guest listener is even relevant.

Then check the guest: is the service listening on the internal address, and does its return path point back through the VPC? A listener bound only to a public-facing address will fail this test even when every cloud-side object is correct.

A public prefix is a different question

None of the above means every address carried inside a VPN must be RFC1918. A remote network can legitimately be numbered from public space, provided the platform supports the routing and the operator holds the address authority. That is a normal design choice.

It is not the same as treating an ordinary external-NAT address as though it were another internal subnet address. One is a prefix you route; the other is a mapping the platform applies to inbound access.

External IPv6 and specially designed address arrangements have their own semantics. If your plan depends on one of those, read the platform documentation for that feature rather than generalising from the IPv4 case. The IPv4 mapping is the common case, not the only one, and the exceptions each have their own rules.

Overlapping ranges are a different problem

Overlapping private ranges are a real reason people reach for the public address, and it is the wrong lever. Changing the destination to the VM's NAT address does not resolve the overlap; it changes which address the packet claims to be for, without defining how the return path works.

Solve the overlap deliberately: renumber, use a supported translation design, or route through a network where the prefixes do not collide. Each of those is a design with an owner. The NAT address is not a design.

Document the two fields separately

Record the tunnel peer and the workload destination as two separate runbook fields, each with the route and firewall rule that supports it. An IPsec tunnel that comes up only tells you the peers agree; it says nothing about which address the workload is reachable on, and nothing about whether its private route is complete.

Verify with a real client on the far side: resolve the name, confirm it returns the internal address, connect, and check the return traffic. The Compute Engine IP address documentation is the reference for the internal-versus-external distinction used above.

Ũhoro ũhĩtĩte