What is Dynamic DNS?

Dynamic DNS is a way of automatically updating DNS records via a program that runs periodically and responds to changing network conditions. Dynamic DNS is particularly useful to expose services running on residential network connections, where subscribers very often get IP addresses that change every few days.

PTRDNS supports dynamic DNS via 2 different methods: the PowerDNS API and the RFC 2136 standard method. The basic principle is the same:

  1. configure the record to be updated with your current IP address
  2. execute a program to update the record in your zone
Dynamic DNS via API

Here’s a sample bash script to retrieve your current IPv4 address and update a record server.example.com with it: just plug in your PTRDNS API key and execute this script periodically to make sure that this record points to your actual IP address.

#!/bin/bash

# Configuration
PDNS_API_URL="https://api.ptrdns.net/api/v1/servers/localhost/zones/example.com."
API_KEY="your_api_key"
RECORD_NAME="server.example.com"

# Get the current public IPv4 address
CURRENT_IP=$(curl -4 -s http://canhazip.com)

if [[ -z "$CURRENT_IP" ]]; then
  echo "Failed to retrieve current IP address."
  exit 1
fi
echo "Current IP: $CURRENT_IP"

# Fetch the current DNS record
DNS_RECORD=$(curl -s -H "X-API-Key: $API_KEY" "$PDNS_API_URL" | jq -r '.rrsets[] | select(.name=="'"$RECORD_NAME"'." and .type=="A")')

if [[ -z "$DNS_RECORD" ]]; then
  echo "Failed to fetch DNS record for $RECORD_NAME."
  exit 1
fi

# Extract the current IP address from the DNS record
CURRENT_DNS_IP=$(echo "$DNS_RECORD" | jq -r '.records[0].content')

if [[ "$CURRENT_IP" == "$CURRENT_DNS_IP" ]]; then
  echo "No update needed. DNS is already up-to-date."
  exit 0
fi

# Prepare the update payload
UPDATE_PAYLOAD=$(cat <<EOF
{
  "rrsets": [
    {
      "name": "$RECORD_NAME.",
      "type": "A",
      "ttl": 300,
      "changetype": "REPLACE",
      "records": [
        {
          "content": "$CURRENT_IP",
          "disabled": false
        }
      ]
    }
  ]
}
EOF
)

# Send the update request
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" -X PATCH "$PDNS_API_URL" \
  -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  --data "$UPDATE_PAYLOAD")

if [[ "$RESPONSE" -eq 204 ]]; then
  echo "DNS record updated successfully."
else
  echo "Failed to update DNS record. HTTP response code: $RESPONSE"
  exit 1
fi

The API-based method can update any record (or combination of records) in any of the zones in your account.

Dynamic DNS via RFC 2136

Let’s begin by creating a TSIG key which will allow us to prevent unauthorized updates:

Then, create a zone, associate this TSIG key and allow updating from any IP address (0.0.0.0/0). You need to allow updates from any IP address, since with a dynamic IP you cannot know in advance the address you will get at any given moment; the TSIG key is the secret value that allows only you to update your zone.

Copy the value of the TSIG key and use a bash script such as the following, again executed periodically to keep the record updated:

#!/bin/bash

# Configuration
ZONE="example.com"
RECORD_NAME="server.example.com."
TTL=300
KEY_FILE="/path/to/tsig.key"  # Path to your TSIG key
DNS_SERVER="tempo.ns.ptrdns.net"

# Get the current public IPv4 address
CURRENT_IP=$(curl -4 -s http://canhazip.com)

if [[ -z "$CURRENT_IP" ]]; then
  echo "Failed to retrieve current IP address."
  exit 1
fi

echo "Current IP: $CURRENT_IP"

# Create the nsupdate command file
NSUPDATE_CMD=$(mktemp)

cat <<EOF >"$NSUPDATE_CMD"
server $DNS_SERVER
zone $ZONE
update delete $RECORD_NAME A
update add $RECORD_NAME $TTL A $CURRENT_IP
send
EOF

# Run nsupdate
echo "Updating DNS record..."
nsupdate -k "$KEY_FILE" "$NSUPDATE_CMD"

if [[ $? -eq 0 ]]; then
  echo "DNS record updated successfully."
else
  echo "Failed to update DNS record."
  exit 1
fi

# Clean up
rm -f "$NSUPDATE_CMD"

The file containing the TSIG key must be formatted as follows:

key "ddns.example.com." {
    algorithm hmac-sha256;
    secret "paste the key hash here";
};

Contrarily to the API method above, the RFC 2136 method can only update the zones associated to the TSIG key referenced in the script.

Routers and firewalls

Some routers have a RFC 2136-compatible Dynamic DNS client out-of-the-box, making this process even easier: here’s how it looks in the popular OPNSense product:


If you need an affordable and robust Dynamic DNS service, sign up for PTRDNS and enjoy all of its features: plans start from 5 EUR per month with 5 zones, unlimited records, TTL as low as 120s (30s on larger plans), PowerDNS API support and of course Dynamic DNS!