AWS

AWS

AWS

Nov 8, 2017

Amazon GovCloud has no Route53! How to solve this?

Amazon GovCloud has no Route53! How to solve this?

Amazon GovCloud has no Route53! How to solve this?

Users of Amazon Web Services are

used to having Route53 available to provide DNS records within

their clouds. However, if you’re a government contractor or an

agency, your deployments likely live on an Amazon GovCloud environment. And on that

environment, Route53 is not yet available. So does that mean you

should forego deploying any services that need custom DNS records

on GovCloud? Of course not!


We will show how to circumvent

this restriction by deploying our own DNS server inside a GovCloud

VPC in a way that makes it easy to update and manage zone

records.


Pre-requisites

  • Terraform

  • AWS command-line tools — i.e. aws-cli

  • Amazon GovCloud credentials configured for aws-cli

  • Git for version control

Terraform is used to ensure

reproducible environments between engineers. You should read more

how it and other technologies help streamline operations

productivity here.


We assume you will be using a terminal emulator

under a UNIX or UNIX-like operating system. Your GovCloud account

must have enough availability in its EC2 quota for at least one

more instance. If you never had to deal with quotas before, you

likely will not exceed your quota with the extra instance and can

ignore this point. Examples preceded by $ means the line is supposed to be typed and run from your terminal emulator:


Initial setup

We will create an empty environment for deployment, and add fpco-terraform-aws,

which includes the module you will need. FP complete created and

open-sourced fpco-terraform-aws as a collection of modules that

ease managing resources in an AWS cloud. As you will see below, a

few of its modules are used, and they considerably shorten the

amount of code you need to build your environment. We will need a

git repository to bring in fpco-terraform-aws, and it’s also good practice to always version

your infrastructure. This way, not only you but your team can

collaborate in developing and operating it:


Add the usual AWS credentials and your cloud environment variables to main.tf.

Now we need to create a VPC and add our DNS to it. Include the

following:


This is our basic VPC, with

still only Amazon DNS available, and no Route53 in sight. It

already allows us access to the internet, but has no private parts.

This should be enough for our scenario, but in a real setting, you

will want to protect your resources with private subnets and

additional machinery. Next, we will add an EC2 instance with BIND

pre-installed, which will receive our configuration

changes.



Creating a BIND config

We will now add BIND. Create a file named dns.tf and add it alongside main.tf in the repo, with the following contents:

You will also need a few other parameters on the dns module, and security groups for

ports used by BIND, as well as internet access. Adding these is

easy, and it’s a good exercise to fill in the gaps before deploying

the examples we’re giving here.


As we can see from the snippet above, the dns module expects to receive at least named.conf.options, named.conf.local and a folder of pre-generated zone

records files. For BIND options, we want to ensure that it forwards

requests for which we are not authoritative servers upstream to

Amazon’s DNS on the VPC. The following is an example of how you

could accomplish that with data/dns/templates/named.conf.options:


You will need to double check allow-query on a real environment. The IP under forwarders is a fixed address always available

inside AWS VPCs. This ensures other names other than those under

our own management can be resolved.


Adding your zones

You will then need to tell BIND which zones we respond to authoritatively. This happens under both named.conf.options and the DNS resource records (RRs) files. Let’s start with named.conf.options first:

Great. Now, whenever a query comes for yourdomain.com,

BIND will look for it locally and return whatever it has under its

RRs. This solves the Route53 part of being able to answer for DNS

records for ourselves. It still does not solve the dynamic updates

part that the Route53 API provides us. For that, we will change the

RRs directly. Whenever that happens and we run Terraform, BIND will

read back those changes, achieving the same functionality. Here is

an example of data/dns/templates/db_records/db.yourdomain.com:


RRs and directives for DNS

follow a straightforward format set by RFC 1035 alongside a few

later amendments. The snippet above is a text representation of

this format used by BIND. Whenever you would have wanted to call

the Route53 API to add a record on your behalf, you will instead

add the resource record directly on those files and get Terraform

to apply the changes.


Testing

Once you have terraform applyed the configuration

above — alongside the security groups and other changes not shown —

you should SSH into the host and test that it’s capable of

resolving queries to your own zone, as well as to other

zones:


Both queries should return an

IP. If the first doesn’t, then you cannot resolve names using the

Amazon-provided DNS. If the second fails, there is an error in your

RRs. Make sure that BIND is running on your instance by

using systemctl status bind9 and checking

your system journal. You can later turn this into a test suite and

add an alarm whenever some names fail resolving, prompting a DevOps

engineer to verify the situation.


Finally, we need to change who provides DNS for the VPC by changing the vpc module parameters:

From that point on, other resources will start

resolving using the BIND instance. Use the templates as your

interface to DNS, and terraform apply to keep in sync.


Where to go next

The previous configuration works

just fine, but has quite a few things missing to make it into a

production-grade environment. For a start, it has only a public

subnet, meaning your DNS server is exposed to the entire internet.

Without further security, it could be used for attacks on this and

other environments. Secondly, if the instance fails, there is some

time until auto-recovery kicks in, time during which the entire VPC

remains unable to resolve names. There are various strategies to

mitigate both issues, but they are beyond the scope for this

article. Lastly, you might have sensitive data that needs to live

in the BIND server. For those cases, you should take a look

at another of our blog posts.


In case you need further support with GovCloud

to ensure important government-sensitive data is kept reliable,

available and manageable, get in touch with us.


Related Articles

  • Intro to DevOps on GovCloud

  • Containerizing a legacy application: an overview

  • Manage Secrets on AWS with Credstash and Terraform