Dynamic DNS (DDNS) in VyOS

Dynamic DNS (DDNS) is a service that automatically updates DNS records when an IP address changes. VyOS includes a built-in DDNS client that can update records at various dynamic DNS providers, which is critical for remote access to devices with dynamic IP addresses.

Overview

Dynamic DNS solves the problem of accessing devices with changing IP addresses:

  • Home/small offices: Access to the network through a dynamic IP from the ISP
  • Branch offices: Remote access without static IP addresses
  • VPN connections: Stable endpoints for VPN tunnels
  • Remote management: A persistent DNS name for SSH/HTTPS access
  • Self-hosted services: Access to web servers, cameras, and NAS on a home IP

How DDNS works

  1. VyOS monitors the IP address on the specified interface
  2. When the IP changes, the change is detected
  3. VyOS sends an update to the DDNS provider via an API/protocol
  4. The provider updates the DNS record
  5. The DNS name now points to the new IP address

Supported protocols

VyOS supports a wide range of DDNS providers and protocols:

  • Standard protocols: DynDNS2, Cloudflare, Namecheap, No-IP, Google Domains
  • Custom protocols: RFC2136 (DNS UPDATE), custom HTTP/HTTPS APIs
  • Multiple providers: Several providers and records at the same time

Basic configuration

DynDNS2 protocol (No-IP, DynDNS)

# DDNS configuration for No-IP
set service dns dynamic name noip service noip
set service dns dynamic name noip host-name myrouter.ddns.net
set service dns dynamic name noip username myusername
set service dns dynamic name noip password mypassword
set service dns dynamic name noip interface eth0

commit
save

Cloudflare DDNS

# Cloudflare uses email + API key
set service dns dynamic name cloudflare service cloudflare
set service dns dynamic name cloudflare host-name myrouter.example.com
set service dns dynamic name cloudflare username email@example.com
set service dns dynamic name cloudflare password cloudflare-api-key
set service dns dynamic name cloudflare zone example.com
set service dns dynamic name cloudflare interface eth0

commit
save

Google Domains DDNS

# Google Domains DDNS
set service dns dynamic name google service googledomains
set service dns dynamic name google host-name myrouter.example.com
set service dns dynamic name google username generated-username
set service dns dynamic name google password generated-password
set service dns dynamic name google interface eth0

commit
save

Namecheap DDNS

# Namecheap DDNS
set service dns dynamic name namecheap service namecheap
set service dns dynamic name namecheap host-name myrouter
set service dns dynamic name namecheap username example.com
set service dns dynamic name namecheap password ddns-password
set service dns dynamic name namecheap interface eth0

commit
save

Advanced configuration

RFC2136 (DNS UPDATE)

RFC2136 lets you update DNS records directly on a server that supports dynamic updates (for example, BIND).

# RFC2136 setup
set service dns dynamic name rfc2136 service rfc2136
set service dns dynamic name rfc2136 server ns1.example.com
set service dns dynamic name rfc2136 zone example.com
set service dns dynamic name rfc2136 host-name router.example.com
set service dns dynamic name rfc2136 key /config/auth/ddns-key.txt
set service dns dynamic name rfc2136 ttl 60
set service dns dynamic name rfc2136 interface eth0

commit
save

The key file /config/auth/ddns-key.txt (TSIG key):

key "ddns-key" {
    algorithm hmac-sha256;
    secret "base64-encoded-secret-here==";
};

Multiple DDNS records

# First provider (No-IP for primary access)
set service dns dynamic name primary service noip
set service dns dynamic name primary host-name myrouter.ddns.net
set service dns dynamic name primary username user1
set service dns dynamic name primary password pass1
set service dns dynamic name primary interface eth0

# Second provider (DuckDNS as a backup)
set service dns dynamic name backup service duckdns
set service dns dynamic name backup host-name myrouter.duckdns.org
set service dns dynamic name backup password duckdns-token
set service dns dynamic name backup interface eth0

# Third provider (Cloudflare for the corporate domain)
set service dns dynamic name corporate service cloudflare
set service dns dynamic name corporate host-name vpn.company.com
set service dns dynamic name corporate username admin@company.com
set service dns dynamic name corporate password cloudflare-api-key
set service dns dynamic name corporate zone company.com
set service dns dynamic name corporate interface eth0

commit
save

Monitoring through the provider web interface

# Configuration with an IP-check URL (to determine the external IP)
set service dns dynamic name myservice service custom
set service dns dynamic name myservice host-name myhost.example.com
set service dns dynamic name myservice username myuser
set service dns dynamic name myservice password mypass
set service dns dynamic name myservice interface eth0
set service dns dynamic name myservice protocol dyndns2
set service dns dynamic name myservice server updates.example.com

commit
save

Using a web request to obtain the IP

If the router is behind NAT and you need to determine the external IP:

# DDNS setup with a web-based IP detection method
set service dns dynamic name myservice service noip
set service dns dynamic name myservice host-name myrouter.ddns.net
set service dns dynamic name myservice username myuser
set service dns dynamic name myservice password mypass
set service dns dynamic name myservice interface eth0
set service dns dynamic name myservice ip-check web
set service dns dynamic name myservice web-url https://api.ipify.org

commit
save

Update interval

# Set the check interval (in seconds, default 300)
set service dns dynamic name myservice service noip
set service dns dynamic name myservice host-name myrouter.ddns.net
set service dns dynamic name myservice username myuser
set service dns dynamic name myservice password mypass
set service dns dynamic name myservice interface eth0
set service dns dynamic name myservice timeout 600  # Check every 10 minutes

commit
save

IPv6 DDNS

# DDNS for an IPv6 address
set service dns dynamic name ipv6ddns service cloudflare
set service dns dynamic name ipv6ddns host-name myrouter-v6.example.com
set service dns dynamic name ipv6ddns username email@example.com
set service dns dynamic name ipv6ddns password cloudflare-api-key
set service dns dynamic name ipv6ddns zone example.com
set service dns dynamic name ipv6ddns interface eth0
set service dns dynamic name ipv6ddns ip-version ipv6

commit
save

Configuration examples

Example 1: Home router with No-IP

# Simple configuration for home access
set service dns dynamic name home service noip
set service dns dynamic name home host-name myhome.ddns.net
set service dns dynamic name home username homeuser
set service dns dynamic name home password HomePass123!
set service dns dynamic name home interface eth0

commit
save

Verification:

show dns dynamic status

Example 2: VPN endpoint with Cloudflare

# DDNS for a VPN endpoint on a corporate domain
set service dns dynamic name vpn-endpoint service cloudflare
set service dns dynamic name vpn-endpoint host-name vpn.company.com
set service dns dynamic name vpn-endpoint username admin@company.com
set service dns dynamic name vpn-endpoint password cf_api_key_here
set service dns dynamic name vpn-endpoint zone company.com
set service dns dynamic name vpn-endpoint interface eth0

# The WireGuard VPN endpoint uses this DNS name
set interfaces wireguard wg0 address 10.10.0.1/24
set interfaces wireguard wg0 listen-port 51820
set interfaces wireguard wg0 peer client1 allowed-ips 10.10.0.2/32
set interfaces wireguard wg0 peer client1 public-key 'peer-public-key-here'

commit
save

WireGuard client configuration:

[Interface]
PrivateKey = client-private-key
Address = 10.10.0.2/24

[Peer]
PublicKey = server-public-key
Endpoint = vpn.company.com:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25

Example 3: Multiple branch offices

# Head office
set service dns dynamic name hq service cloudflare
set service dns dynamic name hq host-name hq-router.company.com
set service dns dynamic name hq username admin@company.com
set service dns dynamic name hq password cloudflare-key
set service dns dynamic name hq zone company.com
set service dns dynamic name hq interface eth0

# Backup record on a free service
set service dns dynamic name hq-backup service duckdns
set service dns dynamic name hq-backup host-name company-hq.duckdns.org
set service dns dynamic name hq-backup password duckdns-token
set service dns dynamic name hq-backup interface eth0

commit
save

Example 4: Self-hosted services (web, mail)

# DDNS for a web server
set service dns dynamic name webserver service cloudflare
set service dns dynamic name webserver host-name www.example.com
set service dns dynamic name webserver username admin@example.com
set service dns dynamic name webserver password cloudflare-api-key
set service dns dynamic name webserver zone example.com
set service dns dynamic name webserver interface eth0

# Port forwarding for the web server
set nat destination rule 100 description 'Port forward HTTP'
set nat destination rule 100 inbound-interface name eth0
set nat destination rule 100 destination port 80
set nat destination rule 100 protocol tcp
set nat destination rule 100 translation address 192.168.1.10

set nat destination rule 110 description 'Port forward HTTPS'
set nat destination rule 110 inbound-interface name eth0
set nat destination rule 110 destination port 443
set nat destination rule 110 protocol tcp
set nat destination rule 110 translation address 192.168.1.10

commit
save

Example 5: RFC2136 with your own DNS server

# BIND DNS server with dynamic update support
set service dns dynamic name internal service rfc2136
set service dns dynamic name internal server 192.168.1.53
set service dns dynamic name internal zone internal.company.com
set service dns dynamic name internal host-name router.internal.company.com
set service dns dynamic name internal key /config/auth/ddns-update-key.txt
set service dns dynamic name internal ttl 300
set service dns dynamic name internal interface eth1

commit
save

On the BIND server (/etc/bind/named.conf.local):

key "ddns-key" {
    algorithm hmac-sha256;
    secret "your-base64-secret==";
};

zone "internal.company.com" {
    type master;
    file "/var/lib/bind/db.internal.company.com";
    allow-update { key ddns-key; };
};

Example 6: Dual-stack (IPv4 + IPv6)

# IPv4 DDNS
set service dns dynamic name dual-v4 service cloudflare
set service dns dynamic name dual-v4 host-name router.example.com
set service dns dynamic name dual-v4 username admin@example.com
set service dns dynamic name dual-v4 password cloudflare-key
set service dns dynamic name dual-v4 zone example.com
set service dns dynamic name dual-v4 interface eth0
set service dns dynamic name dual-v4 ip-version ipv4

# IPv6 DDNS (AAAA record)
set service dns dynamic name dual-v6 service cloudflare
set service dns dynamic name dual-v6 host-name router.example.com
set service dns dynamic name dual-v6 username admin@example.com
set service dns dynamic name dual-v6 password cloudflare-key
set service dns dynamic name dual-v6 zone example.com
set service dns dynamic name dual-v6 interface eth0
set service dns dynamic name dual-v6 ip-version ipv6

commit
save

Monitoring and diagnostics

Viewing DDNS status

# Show the status of all DDNS services
show dns dynamic status

# The output includes:
# - Service name
# - Hostname
# - Current IP
# - Last update
# - Status (good, nochange, error)

Example output:

service: cloudflare
hostname: myrouter.example.com
address: 203.0.113.45
status: good
last update: Mon Jan 15 10:30:45 2024

Forcing an update

# Force an update for a specific service
update dns dynamic interface eth0

# This makes VyOS immediately send an update to all configured providers

Viewing DDNS logs

# DDNS logs in syslog
show log | match ddclient

# The last 50 entries
show log tail 50 | match ddclient

# Real-time monitoring
monitor log | match ddclient

Checking the current IP

# Current IP on the interface
show interfaces ethernet eth0 | grep "inet "

# External IP (if behind NAT)
curl ifconfig.me
curl api.ipify.org

Checking DNS resolution

# Verify that the DNS record has been updated
nslookup myrouter.ddns.net

# Or using dig
dig myrouter.ddns.net +short

# Check through a specific DNS server
dig @8.8.8.8 myrouter.ddns.net

Debugging issues

# Check the configuration
show configuration service dns dynamic

# Detailed logs (enable debug)
set system syslog file ddns.log facility daemon level debug
commit

# View the logs
tail -f /var/log/ddns.log

# Disable debug after troubleshooting
delete system syslog file ddns.log facility daemon level debug
commit

Monitoring with a script

#!/bin/bash
# /config/scripts/monitor-ddns.sh

HOSTNAME="myrouter.ddns.net"
EXPECTED_IP=$(curl -s ifconfig.me)
RESOLVED_IP=$(dig +short $HOSTNAME | head -n1)

if [ "$EXPECTED_IP" != "$RESOLVED_IP" ]; then
    echo "DDNS mismatch: Expected $EXPECTED_IP, Got $RESOLVED_IP"
    logger -t ddns-monitor "DDNS mismatch detected"
    # Send an alert
    echo "DDNS issue on $(hostname)" | mail -s "DDNS Alert" admin@example.com
else
    logger -t ddns-monitor "DDNS check OK: $RESOLVED_IP"
fi

Add it to the Task Scheduler:

set system task-scheduler task ddns-monitor interval '*/15 * * * *'
set system task-scheduler task ddns-monitor executable path '/config/scripts/monitor-ddns.sh'
commit
save

Troubleshooting

Problem: DDNS is not updating

Diagnostics:

# 1. Check the configuration
show configuration service dns dynamic

# 2. Check the status
show dns dynamic status

# 3. Check the logs
show log | match ddclient

# 4. Check the interface
show interfaces ethernet eth0

# 5. Check connectivity to the provider
ping updates.no-ip.com

Solution:

# Verify credentials
set service dns dynamic name myservice username correct-username
set service dns dynamic name myservice password correct-password

# Force an update
update dns dynamic interface eth0

# Restart the service (if necessary)
sudo systemctl restart ddclient

commit
save

Problem: The IP is detected incorrectly (behind NAT)

Cause: VyOS uses the interface IP instead of the external IP.

Solution:

# Use the web method to determine the IP
set service dns dynamic name myservice ip-check web
set service dns dynamic name myservice web-url https://api.ipify.org

commit
save

Alternative URLs for IP detection:

  • https://api.ipify.org
  • https://ifconfig.me/ip
  • https://icanhazip.com
  • https://checkip.amazonaws.com

Problem: Updates are too frequent

Cause: The provider may block you for abuse (too many requests).

Solution:

# Increase the check interval
set service dns dynamic name myservice timeout 3600  # 1 hour

commit
save

Problem: Authentication fails

Diagnostics:

# Check the logs
show log | match "authentication failed"
show log | match ddclient

Solution:

# Verify the credentials in the provider's web interface

# Recreate the configuration with the correct credentials
delete service dns dynamic name myservice
set service dns dynamic name myservice service noip
set service dns dynamic name myservice host-name myrouter.ddns.net
set service dns dynamic name myservice username correct-username
set service dns dynamic name myservice password correct-password
set service dns dynamic name myservice interface eth0

commit
save

# Force an update
update dns dynamic interface eth0

Problem: Hostname is not updating on Cloudflare

Cause: Cloudflare requires the zone to be specified.

Solution:

# Make sure the zone is specified
set service dns dynamic name cloudflare zone example.com

# Make sure you use the correct API key (not an API token)
# Cloudflare requires the Global API Key, not a Scoped API Token

commit
save

Problem: RFC2136 updates do not work

Diagnostics:

# Check DNS server availability
ping 192.168.1.53

# Check UDP port 53
nc -vu 192.168.1.53 53

# Check the key
cat /config/auth/ddns-key.txt

Solution:

# Make sure the key is configured correctly on both sides

# On VyOS, the key file must contain:
# key "ddns-key" {
#     algorithm hmac-sha256;
#     secret "base64-secret==";
# };

# On BIND, the zone must allow updates:
# allow-update { key ddns-key; };

# Test the update manually from the client
nsupdate -k /config/auth/ddns-key.txt
> server 192.168.1.53
> zone example.com
> update add test.example.com 300 A 192.168.1.100
> send
> quit

Popular DDNS providers

Free services

ProviderProtocolNotes
No-IPnoip3 hostnames free, requires confirmation every 30 days
DuckDNSduckdnsFree, no limits, simple
FreeDNSfreednsMany domains, free
Dynudynu4 hostnames free

Paid/Freemium services

ProviderProtocolNotes
CloudflarecloudflareFree plan + DNS management
Google DomainsgoogledomainsRequires a domain in Google Domains
NamecheapnamecheapDDNS for Namecheap domains
DynDNSdyndns2Paid service, reliable

Configuration for popular providers

DuckDNS:

set service dns dynamic name duckdns service duckdns
set service dns dynamic name duckdns host-name mysubdomain.duckdns.org
set service dns dynamic name duckdns password token-from-duckdns
set service dns dynamic name duckdns interface eth0

FreeDNS:

set service dns dynamic name freedns service freedns
set service dns dynamic name freedns host-name myhost.freeddns.org
set service dns dynamic name freedns password update-token
set service dns dynamic name freedns interface eth0

Dynu:

set service dns dynamic name dynu service dynu
set service dns dynamic name dynu host-name myhost.dynu.net
set service dns dynamic name dynu username dynu-username
set service dns dynamic name dynu password dynu-password
set service dns dynamic name dynu interface eth0

Best practices

1. Use reliable providers

Choose proven providers with a good SLA:

# For production - Cloudflare or Google Domains
set service dns dynamic name primary service cloudflare

# For home/lab - DuckDNS or No-IP
set service dns dynamic name home service duckdns

2. DDNS redundancy

Configure multiple providers for redundancy:

# Primary
set service dns dynamic name primary service cloudflare
set service dns dynamic name primary host-name router.example.com

# Backup
set service dns dynamic name backup service duckdns
set service dns dynamic name backup host-name router-backup.duckdns.org

3. Secure password storage

Do not use simple passwords:

# Bad
set service dns dynamic name myservice password 123456

# Good - use complex tokens/keys
set service dns dynamic name myservice password 'aB3$kL9@mN5&pQ2#'

4. DDNS monitoring

Set up monitoring for critical hostnames:

# Task Scheduler for checks
set system task-scheduler task ddns-check interval '*/15 * * * *'
set system task-scheduler task ddns-check executable path '/config/scripts/check-ddns.sh'

5. Logging

Enable DDNS logging for auditing:

set system syslog file ddns.log facility daemon level info

6. A proper update interval

Do not set updates too frequently:

# 5-15 minutes is recommended for dynamic IPs
set service dns dynamic name myservice timeout 600  # 10 minutes

7. TTL for DNS records

Use a low TTL for DDNS records:

# For RFC2136
set service dns dynamic name internal ttl 60  # 1 minute

8. Documentation

Document the DDNS hostnames you use:

# Use descriptive names in the configuration
set service dns dynamic name vpn-endpoint ...
set service dns dynamic name web-server ...
set service dns dynamic name remote-access ...

9. Test after setup

Always test DDNS after configuring it:

# Force an update
update dns dynamic interface eth0

# Check the status
show dns dynamic status

# Check DNS
dig myrouter.ddns.net +short

10. Automation for multiple devices

Use Ansible to manage DDNS across many routers:

- name: Configure DDNS
  vyos.vyos.vyos_config:
    lines:
      - set service dns dynamic name {{ ddns_name }} service {{ ddns_provider }}
      - set service dns dynamic name {{ ddns_name }} host-name {{ ddns_hostname }}
      - set service dns dynamic name {{ ddns_name }} username {{ ddns_username }}
      - set service dns dynamic name {{ ddns_name }} password {{ ddns_password }}
      - set service dns dynamic name {{ ddns_name }} interface {{ ddns_interface }}

Useful commands

# Show DDNS status
show dns dynamic status

# Force an update
update dns dynamic interface eth0

# DDNS configuration
show configuration service dns dynamic

# DDNS logs
show log | match ddclient
show log tail 50 | match ddclient

# Real-time log monitoring
monitor log | match ddclient

# Check DNS resolution
nslookup myrouter.ddns.net
dig myrouter.ddns.net +short

# Check the external IP
curl ifconfig.me
curl api.ipify.org

# Restart the DDNS client (if needed)
sudo systemctl restart ddclient

# Service status
sudo systemctl status ddclient

# View the ddclient configuration
sudo cat /etc/ddclient/ddclient.conf

Integration with other features

DDNS + VPN

# DDNS for a WireGuard endpoint
set service dns dynamic name wg-endpoint service cloudflare
set service dns dynamic name wg-endpoint host-name wg.example.com
set service dns dynamic name wg-endpoint username admin@example.com
set service dns dynamic name wg-endpoint password cloudflare-key
set service dns dynamic name wg-endpoint zone example.com
set service dns dynamic name wg-endpoint interface eth0

# WireGuard configuration
set interfaces wireguard wg0 address 10.10.0.1/24
set interfaces wireguard wg0 listen-port 51820

Clients use wg.example.com:51820 as the endpoint.

DDNS + Port Forwarding

# DDNS for self-hosted services
set service dns dynamic name web service cloudflare
set service dns dynamic name web host-name web.example.com

# NAT for HTTP/HTTPS
set nat destination rule 100 inbound-interface name eth0
set nat destination rule 100 destination port 80
set nat destination rule 100 protocol tcp
set nat destination rule 100 translation address 192.168.1.10

set nat destination rule 110 inbound-interface name eth0
set nat destination rule 110 destination port 443
set nat destination rule 110 protocol tcp
set nat destination rule 110 translation address 192.168.1.10

DDNS + Let’s Encrypt

# DDNS updates the DNS record for the Let's Encrypt DNS-01 challenge
set service dns dynamic name acme service cloudflare
set service dns dynamic name acme host-name router.example.com

# Let's Encrypt can verify domain ownership through DNS

Conclusion

Dynamic DNS in VyOS is a reliable solution for keeping devices with dynamic IP addresses reachable. The built-in DDNS client supports all the major providers and protocols, providing both flexibility and reliability.

Key benefits of DDNS in VyOS:

  • Support for multiple providers at the same time
  • Automatic updates when the IP changes
  • Integration with VPN, web services, and remote access
  • RFC2136 for integration with your own DNS servers
  • Dual-stack support (IPv4 + IPv6)

Recommendations for production:

  • Use reliable providers (Cloudflare, Google Domains)
  • Configure backup DDNS records
  • Monitor the status of DDNS updates
  • Use a proper update interval (5-15 minutes)
  • Document all DDNS hostnames
  • Test after every configuration change

Dynamic DNS in VyOS provides stable remote access to your network infrastructure without the need for static IP addresses, which is critical for small offices, branch offices, and home networks.

Reviewed by OpenNix LLC · Last updated on