Google APIs Over VPN: Route the VIP, Not Just the Subnet
A route to a VPC subnet does not select the API VIPs. Resolve the right names, advertise the VIP prefix, keep the VPC return path, then test HTTPS.
SSH into the on-premises server, bring the tunnel up, and the private VM answers; then the first call to a Google API fails with no route. The VM subnet and the API VIPs are different destinations, so a route for one does not select the other. Three conditions have to hold before a private API call can work. The API name must resolve to a VIP, the VIP prefix must be advertised across the tunnel, and the VPC must know how to send the reply back. A ping tells you none of that, and neither does a working SSH session to a machine in the subnet.
The API VIPs are separate destinations
Google publishes dedicated VIPs for on-premises API access, and those are the addresses your DNS has to return for the API names. Both are small prefixes and neither is RFC 1918 space:
| Record | Resolves to | What it does not give you |
|---|---|---|
| private.googleapis.com | 199.36.153.8/30, the general front door for Google APIs | not a bypass around a service perimeter |
| restricted.googleapis.com | 199.36.153.4/30, reachable only for services a perimeter allows | not the whole API surface, so some names stay out of reach |
Public-looking addresses do not mean the route should leave the tunnel for the ordinary internet. The prefixes exist so an on-premises client can reach Google front ends through a supported path instead of an arbitrary egress point. Treat them as destinations that belong to the tunnel, not as hosts to probe. A firewall rule written for internet egress will usually drop them, which is one common reason a call fails before it starts.
DNS decides which endpoint you reach
Point the on-premises resolver at the records Google documents for the chosen endpoint, so the names the application needs answer with that VIP. Mapping googleapis.com alone is not an inventory: package registries, container registries and migration connectors have their own documented names. The restricted VIP does not carry every service either, so a name that resolves can still be unsupported. Write down the domains the application actually contacts before you touch the resolver.
Guessing a VPC VM address as a replacement for a service name is not a fix, and it usually hides the DNS gap until a different client fails.
Advertise the VIP prefix, keep the rest
With a BGP-based connection, the Cloud Router has to advertise the selected VIP prefix so the on-premises router can learn that range across the intended session. Advertising the VPC subnets alone does not add that range, and the on-premises router keeps using its default path for those addresses. The prefix in the routing table is the only proof that the advertisement crossed the session.
Preserve the existing advertisements while you add it, because router-level and peer-level options have different reach, and swapping the set can withdraw networks that already worked. Then check the effective advertisement on each session rather than on the router as a whole. A missing prefix and a withdrawn prefix look identical from the on-premises side, so the session view is what separates an omission from a regression.
The VPC side needs its own route and return path
Inside the VPC, the VIP path has to use the default internet gateway next hop, and despite the name that traffic stays within Google's network. The VPC also needs a route back to the on-premises source through the VPN, which is a separate object from the advertised prefix. Account for the documented regional routing requirements when the tunnel and the client are not in the same region.
Check the return path independently, because a working request direction can hide a broken reply direction. Two directions, two routes, and each one fails with its own symptom.
Test the request, then read the rejection
ICMP echo gets no answer from these VIPs, so a failed ping proves nothing and a successful one proves very little. From the actual client, inspect the name's answer and the selected route, then make an authorised HTTPS request to the service you care about. If the request reaches the service and is rejected, look at credentials, IAM and any service perimeter policy that applies.
Private routing does not grant API authorisation, and it does not change what the identity is allowed to do. Transport success and an authorised response are separate results, and you need both. Keep the IPv6 path explicit too, since configuring the IPv4 prefixes says nothing about a client that prefers IPv6.
Google's on-premises Private Google Access guide covers the DNS records and the routing requirements together, so compare your resolver and advertisement settings against it rather than against a forum post. Then re-run the same request and note the answer and the route in the same ticket.