March 29, 2026

DNS Africa Resource Center

..sharing knowledge.

Building a serverless dynamic DNS system with AWS | Amazon Web Services – AWS Blog

This blog post was originally published in December 2015. It was updated July 2023 to make the solution more cost-effective and efficient. This post has been updated to replace Amazon API Gateway with AWS Lambda function URLs and Amazon Simple Storage Service (Amazon S3) with Amazon DynamoDB. Using Lambda function URLs reduces the overall cost of the solution. This feature comes at no extra cost when using the Lambda service, and it provides a RESTful HTTPs endpoint that our client interacts with. Replacing Amazon S3 with DynamoDB increases the efficiency of the solution and reduces the overall latency when querying data.
Early-stage startups, small businesses, and home networks often have dynamic public IP addresses that can change without notice. Because of this changing address, you can’t reliably access systems on these networks from the outside. For startups in the early stages of their life cycle, it’s important to provide a reliable and highly available service in order to gain trust with your first set of customers.
Dynamic DNS systems solve this problem by running a software agent inside your network to keep a DNS record updated with the latest public IP address. As long as the DNS record is up to date, you can find your network and customers can reliably access your service.
In this post, we describe how to build your own dynamic DNS system by using serverless AWS services. Building a serverless system using nothing but Amazon Web Services (AWS) services and a few lines of code is simple, cost-effective, and scalable, and allows you to focus on the core business logic of your startup, rather than worrying about scaling and maintaining the underlying infrastructure.
In the next sections, we show you how to use the following AWS services to build a dynamic DNS solution:
Figure 1 shows how a client finds its own IP address by making an API request to a service built using a Lambda function and its attached function URL.
Figure 1. Request flow for client to retrieve IP address of its running service
As shown in Figure 2, now that the client knows its public IP, it makes another request to our service to set a DNS record. The Lambda function first consults the record stored in our DynamoDB table to validate the request. If the check passes, the Lambda function then sets the DNS entry in Route 53 via an API call. Now the network’s current IP is in public DNS and can be found by a standard DNS query.
Figure 2. Request flow to set update DNS record with new IP
Here’s some advantages you will gain by running a serverless dynamic DNS system:
You’ll need two things to build this solution:
At this point, you have enough information to start building your own copy of the system. If you want to learn more about how it works, read on.
If you want to start building, Route 53 dynamic DNS with Lambda is available on GitHub. It provides illustrated instructions and all the necessary code and configuration.
First, the client needs to find the public IP assigned to its network. If you make a request from your network to a service on the internet, that service sees the request coming from your external IP address.
Then, the client makes an HTTP POST request to the Lambda function URL with a request body of {"execution_mode":"get"}, and gets a response containing the current public IP address:
HTTP POST
> https://.....lambda-url.eu-west-1.on.aws
{“return_message”:
“176.32.100.36”, “return_status”: “success”}
During this process, the Lambda function URL converts the HTTP request to JSON, including all request parameters, and passes the requestor’s source IP address to a Python Lambda function. The Lambda function then sends a JSON response with the IP back to the client.
Figure 3 shows a request to get a public IP.
Figure 3. Retrieving public IP address
The client now builds a request token by linking the public IP address returned from the HTTP POST request, the DNS hostname, and a shared secret. For example, if your IP address is 176.32.100.36, your hostname is host1.dyn.example.com, and your shared secret is shared_secret_1, the linked string will be the following:
176.32.100.36host1.dyn.example.comshared_secret_1
Next, the client generates a SHA-256 hash function from the string:
echo -n 176.32.100.36host1.dyn.example.comshared_secret_1 | shasum -a 256
Hash: 96772404892f24ada64bbc4b92a0949b25ccc703270b1f6a51602a1059815535
The client then requests the DNS update by making a second HTTP POST request. It passes the plain text hostname as a key and the hash function as the authentication token within the request body:
HTTP POST > https://....lambda-url.eu-west-1.on.aws
{“execution_mode”:”set”, “ddns_hostname”:”host1.dyn.example.com”, “validation_hash”:”96772404892f24ada64bbc4b92a0949b25ccc703270b1f6a51602a1059815535”}
The Lambda function URL then passes the request parameters back to the Lambda function.
After that, the Lambda function queries its JSON configuration record from DynamoDB using the AWS SDK for Python (Boto3). In this system, interactions between the Lambda service, DynamoDB, and Route 53 use Boto3, which is pre-built into the Lambda service runtime environment.
Once our Lambda function queries the configuration record from DynamoDB, it uses the hostname as a key to find the shared secret, and other configuration associated with that record, similar to the following example record:
{
"host1.dyn.example.com.": {
"aws_region": "us-west-2",
"route_53_zone_id": "MY_ZONE_ID",
"route_53_record_ttl": 60,
"route_53_record_type": "A",
"shared_secret": "SHARED_SECRET_1"
},
"host2.dyn.example.com.": {.....
The client passed host1.dyn.example.com as the key, so the Lambda function reads SHARED_SECRET_1 from the configuration, and rebuilds the hash function token using the hostname, the requestor’s IP address, and the shared secret. If the hash function calculated by the Lambda function and the hash function received from the client match, then the request is considered valid.
Once the request is validated, the Lambda function uses the information from the configuration to make an API call to Route 53 to see if the DNS hostname is already set with the client IP. If no change is necessary, the Lambda function responds to the client and exits:
{“return_message”: “Your IP address matches the current Route53 DNS record.”, “return_status”: “success”}
If there is no record, or if the current record and the client IP do not match, the Lambda function makes an API call to Route 53 to set the record, responds to the client, and exits:
{“return_message”: “Your hostname record host1.dyn.example.com. has been set to 176.32.100.36”, “return_status”: “success”}
Figure 4 shows the request to set the hostname.
Figure 4. Request flow to set hostname
How is this system secured?
The dynamic DNS system we describe in this post shows how to create your own serverless solution on AWS to solve a real-world problem—DNS is susceptible to change and you might not be aware!
Use this solution to run your own dynamic DNS on AWS. Or, use it as an example to learn how you can use AWS services to create your own serverless solutions at any scale.
Visit the Route 53 dynamic DNS with Lambda repository on GitHub for a complete set of code, configuration, and instructions on how to deploy.
Zac Burns is a Startup Solutions Architect with AWS. He helps startup customers in Ireland and Northern Ireland build secure, scalable, and resilient architectures. Zac is also a serverless enthusiast with a deep expertise in building serverless solutions on AWS.
Max Berta is a Startup Solution Architect with AWS. His background includes software development, graphic design, and technical training. Max has a passion for helping customers find the simplest solution to their technical challenges and help them acquire knowledge on the cloud to help them design simple, secure, scalable, flexible, and resilient architectures.

source

About The Author