Ditch the DDNS Providers: How to Build Your Own Dynamic DNS Server

Building your own Dynamic DNS (DDNS) server can be a rewarding project, giving you full control over your domain name and its IP address mapping. It’s a great way to access your home network resources (like a web server, VPN, or media server) from anywhere in the world, even if your Internet Service Provider (ISP) changes your public IP address.

Here’s a step-by-step guide to building your own DDNS server, ranging from a simple setup to a more robust, automated solution.

Prerequisites
Before you start, you’ll need the following:

A Domain Name: You must own a domain name (e.g., yourdomain.com).

A VPS (Virtual Private Server) or Cloud Service: You need a server with a static public IP address that will act as your DDNS server. Services like DigitalOcean, Linode, Vultr, or AWS are good options.

A Computer/Device on Your Home Network: This is the machine that will send your updated IP address to the DDNS server. This could be a Raspberry Pi, a home server, or even your router.

Basic Linux Command-Line Knowledge: You’ll be working with a Linux-based server.

Method 1: The Simple Script Method (Manual/Cron Job)
This is the most straightforward method and is perfect for a basic setup. You’ll create a script on your home network that checks your public IP and updates a DNS record on your VPS.

Step 1: Set up the DDNS Server (VPS)

Install a DNS Server: You’ll need a DNS server to manage your domain records. BIND is the most common, but Unbound or dnsmasq are also great options. Let’s use BIND as an example.

Bash


sudo apt update
sudo apt install bind9

Configure BIND for your Domain:

Edit the named.conf.local file to define your domain’s zone.

Bash

sudo nano /etc/bind/named.conf.local

Add the following block:

Code snippet

zone "yourdomain.com" {
type master;
file "/etc/bind/db.yourdomain.com";
allow-update { any; };
};

Create the zone file (db.yourdomain.com) based on an example.

Bash

sudo cp /etc/bind/db.local /etc/bind/db.yourdomain.com
sudo nano /etc/bind/db.yourdomain.com

Modify the file to look something like this:

Code snippet

;` BIND data file for yourdomain.com
$TTL 60
@ IN SOA ns1.yourdomain.com. admin.yourdomain.com. (
2023010101 ; Serial
60 ; Refresh
120 ; Retry
2419200 ; Expire
60 ) ; Negative Cache TTL
;
IN NS ns1.yourdomain.com.

ns1 IN A
home IN A `
Restart the BIND Service:

Bash

sudo systemctl restart bind9

Make sure to configure your domain registrar to use your VPS as the nameserver.

Step 2: Create a Script on Your Home Network

Create a script to get your public IP and update the DNS record.

Bash

nano update-ddns.sh

Bash

#!/bin/bash
# Get the current public IP address
CURRENT_IP=$(curl -s http://whatismyip.akamai.com/)
# Get the last known IP address from a local file
LAST_IP=$(cat /path/to/last_ip.txt)

if [ "$CURRENT_IP" != "$LAST_IP" ]; then
    # Use nsupdate to update the DNS record
    nsupdate << EOF
    server <Your_VPS_IP_Address>
    update delete home.yourdomain.com A
    update add home.yourdomain.com 60 A $CURRENT_IP
    send
EOF

    echo "$CURRENT_IP" > /path/to/last_ip.txt
fi

Make the script executable:

Bash


chmod +x update-ddns.sh

Run it periodically with Cron:

Bash


crontab -e

Add a line to run the script every 5 minutes:

Bash


*/5 * * * * /path/to/update-ddns.sh

Method 2: The API Method (More Robust)
This method is more robust and secure. Instead of using nsupdate, you’ll create a simple API on your VPS that your home script can call to update the DNS record.

Step 1: Set up the DDNS Server (VPS) with a Web Server

Install a Web Server and a Scripting Language: Let’s use Nginx and Python.

Bash


sudo apt install nginx python3-pip
pip3 install Flask

Create a simple Flask API:

Python

`from flask import Flask, request, jsonify
import subprocess

app = Flask(name)
AUTH_KEY = “your_secret_auth_key”

@app.route(‘/update_ddns’, methods=[‘POST’])
def update_ddns():
data = request.json
if data and data.get(‘auth_key’) == AUTH_KEY:
new_ip = data.get(‘ip’)
if new_ip:
# Use nsupdate to update the DNS record
nsupdate_command = f”””
server 127.0.0.1
update delete home.yourdomain.com A
update add home.yourdomain.com 60 A {new_ip}
send
“””
subprocess.run([‘nsupdate’], input=nsupdate_command.encode(), check=True)
return jsonify({“status”: “success”, “message”: “DNS updated.”}), 200
return jsonify({“status”: “error”, “message”: “Invalid request.”}), 400

if name == ‘main‘:
app.run(host=’0.0.0.0′, port=5000)`
Set up Nginx as a reverse proxy to handle incoming requests and pass them to your Flask app. This also allows you to use HTTPS for a secure connection.

Step 2: Create a Script on Your Home Network

Create a script to call the API:

Bash

nano update-ddns.sh

Bash


#!/bin/bash
# Get the current public IP address
CURRENT_IP=$(curl -s http://whatismyip.akamai.com/)
# Get the last known IP address
LAST_IP=$(cat /path/to/last_ip.txt)

if [ "$CURRENT_IP" != "$LAST_IP" ]; then
    # Call the API with the new IP and auth key
    curl -X POST -H "Content-Type: application/json" 
         -d "{"auth_key": "your_secret_auth_key", "ip": "$CURRENT_IP"}" 
         https://yourdomain.com/update_ddns

    echo "$CURRENT_IP" > /path/to/last_ip.txt
fi

Set up a cron job to run this script periodically, just like in Method 1.

Security Considerations
Firewall: Always configure a firewall (ufw is a great choice) on your VPS to only allow traffic on necessary ports (e.g., 53 for DNS, 80/443 for web traffic).

Authentication: The API method is more secure because it requires a secret key to make an update. The nsupdate method, by default, is less secure with allow-update { any; };. You should restrict this to specific IP addresses if possible.

HTTPS: Always use a secure connection for your API calls. Use Let’s Encrypt to get a free SSL certificate for Nginx.

this blog is presented to you by idream technology, which is authorized solution partner of microsoft. idream provides microsoft products like microsoft 365 apps for business with free migration, installation and admin/user training.

Similar Posts