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.