Alright, let’s talk about Route 53 Resolver endpoints. You’ve probably got a network that’s part cloud, part on-premises—a hybrid setup. And in this world, DNS is the glue that holds everything together. It’s how your on-prem servers find your EC2 instances and how your Lambda functions talk to your dusty old physical database server. The Route 53 Resolver is the brains of this operation, and its Inbound and Outbound Endpoints are the dedicated phone lines it uses to make those cross-network calls.

The default setup—using the built-in DNS resolver in your VPC—works fine… until it doesn’t. It’s like using a communal office phone: it gets the job done, but everyone can hear your conversations, and you have no control over the line. For a proper hybrid setup, you need a dedicated, reliable, and bi-directional connection. That’s what these endpoints provide.

How the Resolver Endpoints Actually Work

Think of it this way: the Resolver is a smart DNS proxy. It resolves queries. An Outbound Endpoint is for egress—it lets DNS queries from your VPC jump over to your on-prem network. An Inbound Endpoint is for ingress—it lets DNS queries from your on-prem network reach into your VPC to resolve those private hosted zones or instance names.

The magic sauce is the set of IP addresses AWS provisions for you in your subnets when you create an endpoint. For an Inbound Endpoint, you get static IPs. You then point your on-prem DNS forwarders to these IPs. For an Outbound Endpoint, you define rules that say, “Hey, for any query destined for corp.internal, don’t use the default Internet resolver; shunt it through this Outbound Endpoint and send it to my on-prem DNS servers at these IP addresses.”

Here’s the kicker, and a place where the AWS designers were perhaps a bit too clever: the Outbound Endpoint itself doesn’t do the resolving. It’s just a tunnel. You must tell it where to forward the queries. This is done via Resolver Rules.

Creating an Inbound Endpoint

You create an Inbound Endpoint to give your on-prem systems a target. You specify the VPC and at least two subnets (for redundancy, please don’t skip this). AWS hands you two static IPs. You then take these IPs and configure your on-prem DNS servers (like your Windows AD servers or BIND boxes) to conditionally forward all queries for your private AWS domains (e.g., us-west-2.compute.internal, myapp.private) to these two IPs.

Here’s how you’d create one using the AWS CLI. Notice the SecurityGroupIds—this is crucial. Your on-prem systems need to be able to hit these IPs on TCP and UDP port 53.

aws route53resolver create-resolver-endpoint \
    --name "my-inbound-endpoint" \
    --direction INBOUND \
    --creator-request-id "inbound-unique-id-$(date +%s)" \
    --security-group-ids "sg-1234567890abcdef0" \
    --ip-addresses SubnetId=subnet-abc123,Ip=192.168.1.10 SubnetId=subnet-def456,Ip=192.168.2.10

The Ip field here is optional. If you don’t specify it, AWS will just grab any available IP from the subnet, which is usually fine. But if you need to pre-populate firewall rules, specifying it is a lifesaver.

Configuring an Outbound Endpoint and Rules

The Outbound Endpoint is your VPC’s getaway car to on-prem DNS. You create the endpoint, which gives you more dedicated IPs. Then, you create a rule that maps a domain name to the IPs of your on-prem DNS servers.

First, create the endpoint:

aws route53resolver create-resolver-endpoint \
    --name "my-outbound-endpoint" \
    --direction OUTBOUND \
    --creator-request-id "outbound-unique-id-$(date +%s)" \
    --security-group-ids "sg-1234567890abcdef0" \
    --ip-addresses SubnetId=subnet-abc123 SubnetId=subnet-def456

Now, the important part: the rule. This rule says, “For any query ending in corp.internal, forward it to my on-prem DNS servers at 10.0.1.10 and 10.0.1.11.”

aws route53resolver create-resolver-rule \
    --name "ForwardToOnPrem" \
    --rule-type FORWARD \
    --domain-name "corp.internal" \
    --creator-request-id "rule-unique-id-$(date +%s)" \
    --target-ips "Ip=10.0.1.10,Port=53" "Ip=10.0.1.11,Port=53" \
    --resolver-endpoint-id "rslvr-out-abcdef0123456789"

Finally, you must associate this rule with your VPC to make it active.

aws route53resolver associate-resolver-rule \
    --resolver-rule-id "rslvr-rr-abcdef0123456789" \
    --vpc-id "vpc-12345678"

The Pitfalls and “Oh Crap” Moments

  1. Security Groups: This is the number one cause of failure. Your Inbound Endpoint’s security group must allow UDP/TCP 53 from the IP ranges of your on-prem DNS forwarders. Your Outbound Endpoint’s security group must allow UDP/TCP 53 to the IPs of your on-prem DNS servers. It seems obvious, but you’d be surprised.
  2. The Creator Request ID: The --creator-request-id is absurdly required by the API but feels redundant with the --name field. It must be unique per account per region. Using a timestamp is the easiest way to not lose your mind.
  3. Rule Specificity: Rules are evaluated in order of most specific to least specific. A rule for dev.corp.internal will take precedence over a rule for corp.internal. Plan your rule hierarchy carefully.
  4. The Bill: Remember, you’re charged per endpoint per hour and per query. Those endpoints are not free. An idle endpoint still costs money, so don’t just leave test ones running. The query cost is low, but at massive scale, it adds up.
  5. Limits: There are limits on the number of endpoints and rules per region. If you’re a large enterprise, you’ll likely bump into these and need to request an increase. Plan ahead.

The beauty of this system, once you wrestle it into submission, is that it just works. It provides a robust, monitored, and scalable way to unify your DNS across environments, which is honestly one of the most foundational and under-appreciated steps to a successful hybrid cloud.