On October 23, 2018, Google introduced private DNS zones for Google Cloud DNS. This is an important announcement as this keeps internal DNS names private. Today’s article covers how to implement this new feature in Google Cloud Platform.
Update: May 8, 2019. At Google Next ’19, Google announced new features for Cloud DNS. This article discusses the new features. This article still applies as the features in this article transitioned from beta to production.
What is Google Cloud Private DNS Zones? A DNS server can provide a feature called split-horizon DNS. This means that the information returned to a DNS query can change based upon the location of who is asking. For Google Cloud DNS, you have queries that can arrive from the Public Internet or from Google Cloud VPC.
Google Cloud DNS can now provide:
- Create private DNS zones to provide DNS name resolution to your private network resources (VMs, load balancers, etc.).
- Connect a private zone to a single network or multiple networks, giving you flexibility when designing your internal network architectures.
- Create split-horizon DNS architectures where identical or overlapping zones can coexist between public and private zones in Cloud DNS, or across different GCP networks.
- Utilize IAM-based, DNS-specific roles to delegate administrative or editor access to manage or view managed private zones.
Above four bullets copied from “Introducing Private DNS Zones“.
Private zones for Google Cloud DNS is a beta feature. This requires creating the private zone using the gcloud CLI.
Update: May 8, 2019. Google has released these features and you can now use with the CLI or the GUI to create your zones. I have changed the CLI examples to no longer use the beta features as these are production now.
For this article, we will use the domain name “example.com” for the Cloud DNS name. We will set up both private and public zones. The public and private zones both use the same DNS name.
Step 1 – Create the private zone.
1 |
gcloud dns managed-zones create --dns-name="example.com" --description="Private Zone" --visibility=private --networks=default "private-zone" |
Step 2 – Create the public zone.
Note you can skip this step if you are not using Google Cloud DNS for your domain name.
1 |
gcloud dns managed-zones create --dns-name="example.com" --description="Public Zone" --visibility=public "public-zone" |
Step 3 – Make the private zone visible to the default network. The Cloud DNS Zone name is “private”.
1 |
gcloud dns managed-zones update private --networks default |
Step 4 – Get a VM instance full and short hostname.
This step requires manually figuring out what the internal hostname for an instance is. Connect to the instance. These commands run from the instance console.
1 |
hostname |
This command returns the short hostname.
1 |
web-server-1 |
Now get the long hostname.
1 |
hostname -f |
This command returns the long hostname.
1 |
web-server-1.us-east4-c.c.development-123456.internal |
Note: You can get the private DNS name from the metadata server:
1 |
curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/hostname" |
Step 5 – Add an instance to the private zone using its private DNS name.
This step uses the Google Cloud Console. Console -> Network Services -> Cloud DNS. Notice the two zones we just created “private zone” and “public zone”. Select the private zone.
The console should display two entries for this zone. The NS (name server) record and the SOA (Start of Authority).
Near the top of the Google Console window is the button “ADD RECORD SET”. Click this button.
For the DNS Name enter: web-server-1
For the Resource Record Type change to: CNAME
For the Canonical name enter: web–server–1.us–east4–c.c.development–123456.internal
Step 6 – Add an instance to the public zone using its public IP address.
Go back to the Cloud DNS. Select the public zone. Click “ADD RECORD SET”.
For the DNS Name enter: web-server-1 (or the name you want the public DNS to support).
For the Resource Record Type: A
For the IPv4 Address enter: <the public IP address>
Note: You can get the external (public) IP address from the metadata server:
1 |
curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip" |
Step 7 – Verify the public DNS resolution.
From your desktop or another computer connected to the Internet, open a command shell/prompt and “ping web-server-1.example.com”. This should resolve to the public IP address.
Step 8 – Verify the private DNS resolution.
From another VM instance in the same Google Cloud VPC, open a command shell/prompt and “ping web-server-1.example.com”. This should resolve the private DNS name and IP address.
There you have it. Google Cloud DNS now supports split-horizon DNS (often called split-brain DNS).
I design software for enterprise-class systems and data centers. My background is 30+ years in storage (SCSI, FC, iSCSI, disk arrays, imaging) virtualization. 20+ years in identity, security, and forensics.
For the past 14+ years, I have been working in the cloud (AWS, Azure, Google, Alibaba, IBM, Oracle) designing hybrid and multi-cloud software solutions. I am an MVP/GDE with several.
January 22, 2019 at 12:41 PM
Hey John,
Nice post but wondering about another feature of Cloud DNS which is forwarding.
Your split-DNS works because you have record sets in both zones but what if you want to simply forward traffic to another set of (internal) dns servers (through a VPN tunnel) and that zone is actually a public zone? I have noticed during dig +trace sessions that root hints are queried before anything so if example.com is actually a zone not under my control, root hints will point me first to the public nameserver instead of looking at my forwarding rules for the same private zone.
Lets make it real – If I create a private zone for google.com but forward to my own name server and still rely on the default GCP resolver (metadata.google.internal) I notice during dig +trace that root hints are queried first and found so my forwarder never gets hit. Any ideas around that?
January 22, 2019 at 2:19 PM
Assuming your Google VMs are running Linux.
If you look at the resolv.conf you will see how Google handles name servers:
# Local domain name. Computed from your project name.
domain [ZONE].c.[PROJECT_ID].internal
# Search list for hostname lookup. Starting with entries that represent
# your project and ending with google.internal to facilitate metadata server requests.
search [ZONE].c.[PROJECT_ID].internal. c.[PROJECT_ID].internal. google.internal.
# Address of the DNS server to resolve project specific, and global domain names.
nameserver 169.254.169.254
Do not modify resolv.conf directly as this file is overwritten every hour (when the DHCP leases expire).
If you want to forward your VM’s DNS traffic to another set of internal DNS servers over a VPN, then you will need to modify /etc/dhcp/dhclient.conf and prepend your names servers (probably with their IP addresses). Example line to add:
prepend domain-name-servers 172.16.1.1;
Now your names servers will resolve first. How your name servers handle name resolution (your comment about dig +trace) depends on the name server. I have not actually tried what you are asking (rezone a public domain name), so I don’t know. Most DNS servers allow you to add entries with specific IP addresses, so maybe your could. This would open up all kinds of security problems.
Please fire back. Networking and security is one of my favorite items. You have me thinking on this one.
October 24, 2019 at 5:03 PM
I’m a bit confused about something here. You create the private zone, named “private-zone” as your example zone:
gcloud dns managed-zones create --dns-name="example.com" --description="Private Zone" --visibility=private --networks=default "private-zone"
You’ve already given the “default” network access to it, best I can tell. You mention that you’re then going to update your private zone to allow the default network to access.
gcloud dns managed-zones update private --networks default
is this a mistake? a) seems like you’ve already given access to the default network your private zone named “private-zone”, but b) you you’re of course updating a zone named “private” in this subsequent step, that shouldn’t be there unless I’m missing something. Is there some magic I’m missing here in your example?
November 8, 2019 at 5:57 PM
Thank you Patrick. In the next few days, I will re-verify this article with the current documentation.
April 29, 2021 at 10:23 AM
HI John,
Nice articles.
Are there options to handle weighted dns records and root alias records in google cloud dns like we have in route53 ?
thanks
May 11, 2021 at 7:11 PM
Google Cloud DNS does not support weighted records. Those features in Route53 are AWS specific (value-added).
September 26, 2021 at 7:28 PM
Great post! I know this is an old thread, but it appears it’s still not possible to create a Google managed SSL cert for domains in the private zone. Is this correct?
September 28, 2021 at 4:25 PM
That is correct. Since a private zone is private, Let’s Encrypt cannot automatically verify the requested name.
Google has become its own CA (Google Trust Services), so that might change.
https://pki.goog/
Google Cloud offers a private certificate authority service. I believe that you can create certificates with that service, but I have not started testing that service.
https://cloud.google.com/certificate-authority-service