Resolve Internal GCP Domains over Wireguard
At my current job, we use Wireguard for VPN access to our GCP resources. One cool feature is that you can configure an address from the internal network you’re accessing to act as your DNS resolver while connected to the VPN. This allows you to resolve things like myapp.int.example.com
on an internal domain, without needing to create publicly viewable DNS records. Initially, all of our Wireguard configs were set to point to 169.254.169.254
, the instance metadata service for GCP (and most other cloud providers).
And this setup works - mostly. Virtual machines running inside GCP also point to the instance metadata service for resolving DNS, which is why it works when you’re using it over the VPN. However, it does break from time to time. I don’t know how many times a developer would come to me saying that whenever they were on the Wireguard VPN, they couldn’t reach anything (“my internet isn’t working!”). After getting more info about the actual verbiage of the errors they were seeing, it always came down to DNS. Usually, doing some dance of restarting the VPN, the Wifi on their Mac, or reloading the Wireguard config, would get it working again. But obviously, this is a problem.
I eventually found a Stack Overflow answer regarding details about setting up an inbound DNS server policy. What this does is setup DNS server endpoints for one or more networks that can act as DNS resolvers for any internal DNS zones. You can point your DNS clients to these endpoints, and they’ll resolve any of your internal DNS zone records. GCP will create an endpoint in every single subnet for that network (so if you’re running in the default network, it will create one in every region’s subnet).
Per the SO question, you can create this via the gcloud
CLI. Doing so for the default network looks like below:
gcloud dns policies create vpn-dns \
--description='Internal DNS server for internal name resolution over Wireguard VPN' \
--networks=default \
--enable-inbound-forwarding \
--enable-logging
The key setting is --enable-inbound-forwarding
. This setting is specifically for the use-case of connecting on-prem servers to GCP via their managed VPN offerings. However, we can use it in our case for our own WIreguard VPN.
You can view the resolver endpoints avaialble to you by querying your compute addresses. The resolver endpoints have the “TYPE” of DNS_RESOLVER
, so you can grep for that.
gcloud compute addresses list | grep DNS_RESOLVER
You can further refine it by grep
ing for the region you’d need to connect from (in case there are people working in other parts of the world). Choosing a region closest to you will give you faster DNS resolution. Just make sure your ALlowedIPs
setting in Wireguard includes the CIDR for that subnet.
From there, you just need to add the DNS configuration to your Wireguard config. For example:
DNS = 10.150.2.27
BONUS: Terraform
The glcoud CLI is great, but IaC is better.
data "google_compute_network" "private-network" {
name = "private"
}
resource "google_dns_policy" "vpn-dns" {
name = "vpn-dns"
enable_inbound_forwarding = true
enable_logging = true # Optional, but good to have for auditing purposes
networks {
network_url = data.google_compute_network.private-network.id
}
}