Serverless DynDNS and IP Reflection with AWS CDK

Some time ago, I built a DynDNS solution using AWS CDK. It worked well, but the ecosystem has evolved. Here’s an updated version—fully serverless, more secure, and with extended functionality.

Improvements over the previous version

Enhanced IP Reflection with MaxMind DB

The /get endpoint now provides detailed information about your IP address, including:

  • IP Address
  • Hostname
  • ISP
  • Geographic details (city, region, country, continent, latitude, longitude)
  • Local timezone
  • EU membership status

This makes the service useful for diagnostics, API integrations, or privacy checks.

Consistent TypeScript Usage

The previous Python implementation has been replaced entirely with TypeScript, including Lambda functions. Using a unified tech stack simplifies maintenance, promotes type consistency, and reduces complexity.
AWS is phasing out Python 3.8. The updated version now runs on Node.js 22, ensuring long-term AWS support and security.

Cost Efficiency

This solution runs entirely within the AWS free tier for most personal uses. I’ve tested it myself with frequent API checks (every 15 seconds), and costs remain minimal. The only unavoidable expense is Route53, approximately $0.50 monthly, plus annual domain fees.


Technical Overview

The service exposes two main endpoints:

  • /get: Provides detailed information about your public IP.
  • /update: Securely updates DNS records with your current IP.

Initial Configuration

Upon first deployment, the CDK stack creates a DynamoDB table (ServerlessDynamicDnsStack-ConfigTable{randomId}). This table stores the configuration:

  • domain: e.g., home.yourdomain.com
  • hostedZoneId: Route53 hosted zone ID
  • secret: A secure shared secret (password), ideally randomly generated.

Example Configuration:

domainhostedZoneIdsecret
home.yourdomain.comZ0123456789ABCDEF(random_secret)

Secure DNS Update Mechanism

To automatically update your DNS record, you’ll need a small script that calculates an authentication hash and then calls the /update endpoint.

Here’s a working example script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
const { createHash } = await import("node:crypto");

const HOSTED_ZONE_ID = "ZXXXXXXXXXXXXXX"; // Replace with your actual Hosted Zone ID
const SHARED_SECRET = "your_shared_secret"; // Replace with your actual shared secret
const HOSTNAME = "home.yourdomain.com"; // The domain you want to update

const currentIp = await fetch("https://dyndns.yourdomain.com/get")
.then(response => response.json())
.then(data => data.ip);

const hashCalc = createHash('sha256');
hashCalc.update(SHARED_SECRET + HOSTED_ZONE_ID + currentIp);
const hash = hashCalc.digest('hex');

const url = `https://dyndns.yourdomain.com/update?hostname=${HOSTNAME}&hash=${hash}`;

fetch(url)
.then(response => {
if (response.ok) {
console.log("IP updated successfully");
} else {
console.error("Failed to update IP:", response.statusText);
}
})
.catch(error => {
console.error("Error:", error);
});

Explanation

  • Current IP Retrieval:
    The script queries the /get endpoint to determine your current IP address.

  • Authentication Hash:
    Combines your shared secret, hosted zone ID, and current IP address, hashing them with SHA-256 for secure authentication.

  • DNS Record Update:
    The /update endpoint independently computes the same hash. If the hashes match, the IP is updated securely within Route53.


Deployment Instructions

Prerequisites

  • AWS Account with Route53 domain setup
  • AWS CLI and CDK installed and configured for your account
  • Docker (required by AWS CDK for bundling Lambda functions)

Deploy and Configure

  1. Check out the GitHub repository

  2. update your deployment parameters in ./bin/serverless-dynamic-dns.ts:

1
2
3
4
5
6
7
8
9
import * as cdk from 'aws-cdk-lib';
import { ServerlessDynamicDnsStack } from '../lib/serverless-dynamic-dns-stack';

const app = new cdk.App();
new ServerlessDynamicDnsStack(app, 'ServerlessDynamicDnsStack', {
env: { account: 'xxxx', region: 'eu-central-1' },
hostedZoneName: 'yourdomain.com',
apiGwARecord: 'dyndns'
});
  1. Deploy using:
1
2
3
npm install
npm run build
cdk deploy
  1. Done, try it out under https://dyndns.yourdomain.com/get

This upgraded version gives you a secure, reliable, and cost-effective serverless DynDNS solution suitable for private or small-group usage.

For questions or suggestions, you can reach out via GitHub.