When working with customers on consulting engagements, it is often useful to have the capability to setup and provision test systems, to help accelerate your own learning and understanding of a new product, or work through a problem.

I have a small home lab that I use to support home based services (IoT devices, WiFi), personal projects, and the occasional work thing. In addition, I have a number of Cloud accounts (AWS, Azure, GCP, Packet.net), that I use to support more work focused activities. This flexibility works well, but it does mean I sometimes have a complex arrangement of distributed systems. To help bring some degree of order to the chaos, I use DNS zones, and delegate subdomains out to each cloud provider. This provides a standards based, well understood, and easy to manage approach to addressing each system, without the burden of running an end-to-end DNS solution. The following diagram describes this setup.

DNS2

Here's how I do it, using AWS and Azure as an example.


NOTE
As always, this works for me, YMMV. It may not be the best idea, and there may be a much better approach out there, but for my simple brain it makes my life easier. Use or don't at your own risk.


Pre-Reqs

First off, you're going to need a proper, bought and paid for, domain name. eg eti.io, google.com my-awesome-site.com, whatever. Go buy one from any of the usual suspects, GoDaddy, domains.google, Fasthosts, etc.

As I use AWS for a lot of the above hackery, I was super lazy and simply bought one from within the Route53 console. My domain is portalvein.io.

Presuming you have the same use case as me, you'll need your Cloud Provider credentials. Be aware that just like any cloud service, using the DNS services costs cash, but it is pennies per record, so shouldn't be too harmful to your wallet.

Root Domain

In whatever tool manages your root domain (AWS Route53 here), take a look in the Hosted Zone for your chosen domain. In my example, this is portalvein.io and the hosted zone was auto-created by the AWS Registrar. (Hosted Zone is AWS terminology, and hence other providers may use an different term for the same thing. Azure calls these DNS Zones).

aws_hosted_zone_01

Inside the hosted zone, you'll see the usual domain anchors, with a Start of Authority (SOA) and Name Server (NS) record.

aws_hosted_zone_02

Create Delegated SubDomain (AWS)

I'm going to delegate a subdomain ether.portalvein.io to a different AWS account (my work one).

Login and navigate to the AWS Route53 console.

Create a hosted zone that reflects your delegated subdomain. If you've not created a subdomain for your domain before, AWS will need to confirm you own your top level domain.

aws_create_ether_zone

Once created, take a look at the zone. Once again, you should see the standard domain anchors of SOA and NS.

aws_ether_hosted_zone_01

Make a note of the NS record entries, as we'll need these to add a NS record within our Top Level Domain to handle the delegation.

Create NS Record for AWS SubDomain

Once you've created the hosted zone, head back to your top level domain. We need to create a Name Server (NS) record which tells clients which DNS servers are authoritative for the ether.portalvein.io subdomain.

aws_hosted_zone_03

All we are doing here, is creating a record informing any clients, that the Name Servers listed, are managing all records within ether.portalvein.io, and hence the client will need to query these.

Create Delegated SubDomain (Azure)

OK, so we've set things up for AWS, lets now add the same for Azure.

Login to the Azure portal, and create a DNS Zone that represents the subdomain we wish to delegate.

azure_dns_create_01

Azure groups resources into a Resource Group, which in the following example is pre-created. The Name is the delegated zone name, in my example thrush.portalvein.io.

azure_dns_create_02

Once created, take a look at the Zone. Similarly to AWS, you'll see the standard anchor records (SOA & NS).

azure_dns_create_03

Again, take a note of the contents of the NS record, as we'll need these entries to add to our top level domain.

Create NS Record for Azure SubDomain

Rinse and repeat. Go back to your top level domain, and create a Name Server (NS) record which tells clients which DNS servers are authoritative for the thrush.portalvein.io subdomain.

azure_thrush_ns

Test It Out

So we've created all the needed records, lets run some tests. Here I'm using dig to query and retrieve DNS resource records.

Name Server Records for portalvein.io?

Should be AWS...

$ dig NS portalvein.io

; <<>> DiG 9.10.6 <<>> NS portalvein.io
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 3266
;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 2

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;portalvein.io.			IN	NS

;; ANSWER SECTION:
portalvein.io.		86400	IN	NS	ns-1835.awsdns-37.co.uk.
portalvein.io.		86400	IN	NS	ns-1399.awsdns-46.org.
portalvein.io.		86400	IN	NS	ns-85.awsdns-10.com.
portalvein.io.		86400	IN	NS	ns-936.awsdns-53.net.

;; ADDITIONAL SECTION:
ns-936.awsdns-53.net.	17988	IN	A	205.251.195.168

;; Query time: 612 msec
;; SERVER: 10.200.1.13#53(10.200.1.13)
;; WHEN: Tue Apr 28 12:53:09 BST 2020
;; MSG SIZE  rcvd: 197

Name Server Records for ether.portalvein.io?

Should also be AWS...

$ dig NS +noall +answer ether.portalvein.io
ether.portalvein.io.	178	IN	NS	ns-867.awsdns-44.net.
ether.portalvein.io.	178	IN	NS	ns-1533.awsdns-63.org.
ether.portalvein.io.	178	IN	NS	ns-409.awsdns-51.com.
ether.portalvein.io.	178	IN	NS	ns-1746.awsdns-26.co.uk.

Name Server Records for thrush.portalvein.io

Should be Azure...

$ dig NS +noall +answer thrush.portalvein.io
thrush.portalvein.io.	201	IN	NS	ns1-07.azure-dns.com.
thrush.portalvein.io.	201	IN	NS	ns2-07.azure-dns.net.
thrush.portalvein.io.	201	IN	NS	ns4-07.azure-dns.info.
thrush.portalvein.io.	201	IN	NS	ns3-07.azure-dns.org.

OK, so each provider is now managing DNS for each subdomain.

For simplicity to test, I've simply created a fake A record within each subdomain, that I could then attach to a service endpoint or VM within each provider. Lets query these.

ec2.ether.portalvein.io

$ dig ec2.ether.portalvein.io

; <<>> DiG 9.10.6 <<>> ec2.ether.portalvein.io
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 36229
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 4, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;ec2.ether.portalvein.io.	IN	A

;; ANSWER SECTION:
ec2.ether.portalvein.io. 300	IN	A	10.10.20.1

;; AUTHORITY SECTION:
ether.portalvein.io.	300	IN	NS	ns-409.awsdns-51.com.
ether.portalvein.io.	300	IN	NS	ns-867.awsdns-44.net.
ether.portalvein.io.	300	IN	NS	ns-1746.awsdns-26.co.uk.
ether.portalvein.io.	300	IN	NS	ns-1533.awsdns-63.org.

;; Query time: 41 msec
;; SERVER: 10.200.1.13#53(10.200.1.13)
;; WHEN: Tue Apr 28 13:10:11 BST 2020
;; MSG SIZE  rcvd: 208

Note the IP address returned in the ANSWER section is 10.10.20.1 and has been returned by AWS DNS servers.

azure1.thrush.portalvein.io

$ dig azure1.thrush.portalvein.io

; <<>> DiG 9.10.6 <<>> azure1.thrush.portalvein.io
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 31956
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 4, ADDITIONAL: 5

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;azure1.thrush.portalvein.io.	IN	A

;; ANSWER SECTION:
azure1.thrush.portalvein.io. 3600 IN	A	10.10.10.1

;; AUTHORITY SECTION:
thrush.portalvein.io.	300	IN	NS	ns3-07.azure-dns.org.
thrush.portalvein.io.	300	IN	NS	ns4-07.azure-dns.info.
thrush.portalvein.io.	300	IN	NS	ns2-07.azure-dns.net.
thrush.portalvein.io.	300	IN	NS	ns1-07.azure-dns.com.

;; ADDITIONAL SECTION:
ns1-07.azure-dns.com.	165451	IN	A	40.90.4.7
ns3-07.azure-dns.org.	7700	IN	A	13.107.24.7
ns1-07.azure-dns.com.	165451	IN	AAAA	2603:1061::7
ns3-07.azure-dns.org.	7700	IN	AAAA	2a01:111:4000::7

;; Query time: 603 msec
;; SERVER: 10.200.1.13#53(10.200.1.13)
;; WHEN: Tue Apr 28 13:08:47 BST 2020
;; MSG SIZE  rcvd: 297

Note that the IP address returned in the ANSWER section is 10.10.10.1 and has been returned by Azure DNS servers.

Closing Up

So hope that was useful. In this blog we quickly looked at and setup delegated DNS zones with two popular cloud providers.

Using DNS in this way allows you to simply and cleanly separate networks into mangeable zones based upon location, region or business function, that can easily scale, without lots of admin headache.

Extending this to cover other providers, and internal DNS solutions is simple, just follow the steps described, mapping each subdomain into each provider, or another cloud or on-premise solution. I currently delegate subdomains for my internal LAN to a BIND server in exactly the same way.

Further Reading

As we're nearly always standing on the shoulders of those that have done this before, I found the following articles, blogs and documentation useful when setting this up.

Using Amazon Route 53 as the DNS service for subdomains without migrating the parent domain

10 Linux DIG Command Examples for DNS Lookup