revs412@portfolio:~/notes/ddns-setup-with-duckdns-on-openwrt$cat ddns-setup-with-duckdns-on-openwrt.md

Why This Note Exists

This note documents the practical setup direction for using DuckDNS with OpenWrt.

The goal was to make a home network reachable through a stable domain name even when the public IP changes.

Instead of remembering or manually checking the current public IP, a DDNS hostname can point to the latest address:

revs412.duckdns.org → current public IP

This is useful for:

  • WireGuard remote access
  • home lab access
  • testing self-hosted services
  • temporary remote administration
  • avoiding manual IP updates
  • making connection profiles easier to manage

DDNS is simple, but it is often misunderstood. It solves changing IP addresses. It does not solve every reachability problem.

Project Context

The environment was an OpenWrt router used as the main home network control point.

The setup involved:

  • OpenWrt on a router device
  • dynamic residential internet connection
  • DuckDNS hostname
  • WireGuard remote access direction
  • port forwarding/firewall rules
  • self-hosted services
  • possible CGNAT limitations

A DuckDNS domain was used as the stable endpoint name.

Example:

revs412.duckdns.org

The hostname is easier to use in VPN/client configs than a changing public IP address.

What This Setup Is Meant To Prove

  • dynamic public IPs can be handled cleanly
  • OpenWrt can update DDNS automatically
  • remote access profiles should use hostnames instead of raw IPs
  • DDNS and port forwarding are separate problems
  • DDNS does not bypass CGNAT
  • verification should check both DNS updates and real connectivity
  • a small network feature can improve reliability of self-hosted access

Stack and Tools Used

Network Layer

  • OpenWrt
  • WAN interface
  • dynamic public IP
  • firewall rules
  • port forwarding
  • WireGuard endpoint direction

DDNS Layer

  • DuckDNS
  • DuckDNS token
  • DDNS update URL
  • OpenWrt dynamic DNS client
  • scheduled updates
  • public IP detection

Verification Layer

  • DNS lookup
  • external IP check
  • router logs
  • mobile data testing
  • remote WireGuard test
  • port reachability checks

Intended Build

The intended build is an OpenWrt DDNS setup that automatically updates a DuckDNS hostname whenever the public IP changes.

A finished setup should:

  • update DuckDNS automatically
  • survive router reboot
  • use the correct WAN/public IP
  • show update status in logs
  • work with a WireGuard endpoint
  • avoid exposing the DuckDNS token publicly
  • make remote configs easier to maintain
  • clearly identify when CGNAT prevents inbound access

How DDNS Fits Into Remote Access

Without DDNS, a remote client may need:

Endpoint = current.public.ip.address:51820

If the ISP changes the public IP, the client breaks.

With DDNS:

Endpoint = revs412.duckdns.org:51820

The hostname stays the same while DuckDNS updates the IP behind it.

This is useful for WireGuard because the phone/laptop config does not need to be edited every time the ISP changes the IP.

What DuckDNS Actually Does

DuckDNS maps a hostname to an IP address.

Example:

revs412.duckdns.org

102.x.x.x

When the public IP changes, OpenWrt sends an update request to DuckDNS.

DuckDNS then changes the DNS record.

That is all DDNS does.

It does not:

  • open ports
  • configure firewall rules
  • bypass CGNAT
  • secure the service
  • start WireGuard
  • expose private LAN devices by itself

It only keeps the hostname pointing to the current IP.

Correct Mental Model

A correct model:

DDNS = name points to current public IP
Firewall = decides what traffic is allowed
Port forward = sends traffic to an internal host
WireGuard = secure tunnel endpoint
CGNAT = possible ISP-level blocker

These are separate layers.

If the hostname updates correctly but WireGuard still does not connect, the problem may be firewall, port forwarding, WireGuard config, CGNAT, or server status.

Basic OpenWrt DDNS Direction

On OpenWrt, DDNS can be handled by the dynamic DNS service.

A typical setup needs:

DDNS package
DuckDNS service config
DuckDNS token
domain name
WAN/public IP detection
update interval

The exact package names can vary by OpenWrt build, but the usual direction is:

install ddns client
configure DuckDNS service
enable service
start service
check logs

The setup should be persistent across reboot.

DuckDNS Update URL Direction

DuckDNS updates normally use a token and domain.

The update request conceptually looks like:

https://www.duckdns.org/update?domains=<domain>&token=<token>&ip=

When ip is empty, DuckDNS can detect the source public IP.

For OpenWrt, it is usually better to let the DDNS client handle this instead of manually running the URL forever.

The token must stay private.

Config Values To Track

Important values:

DuckDNS domain
DuckDNS token
WAN interface
update interval
public IP source
enabled/disabled state
last update status

Example documentation without exposing secrets:

Domain: revs412.duckdns.org
Token: stored privately
Interface: wan
Update mode: automatic
Use case: WireGuard endpoint

Do not commit real tokens to GitHub.

Using DDNS With WireGuard

A WireGuard client can use the DuckDNS hostname as its endpoint.

Example direction:

Endpoint = revs412.duckdns.org:51820

or with a custom external UDP port:

Endpoint = revs412.duckdns.org:45777

This depends on the actual public port exposed by the router.

The important point:

WireGuard client uses domain
DuckDNS updates domain
OpenWrt/firewall handles UDP traffic
WireGuard server handles tunnel

All parts must be correct.

Firewall Relationship

DDNS does not open the WireGuard port.

The firewall still needs to allow the inbound UDP port.

For a WireGuard server on OpenWrt, that usually means allowing UDP traffic to the router itself.

For a WireGuard server behind OpenWrt, it may require a port forward to the internal host.

The distinction matters:

WireGuard server on router
  → allow input to router

WireGuard server behind router
  → port forward to internal host

Using DDNS does not change this.

CGNAT Limitation

DDNS does not bypass CGNAT.

If the home router is behind CGNAT, DuckDNS may point to the ISP’s shared public IP, but unsolicited inbound traffic may still never reach the home router.

In that case:

DuckDNS updates correctly
domain resolves correctly
port still appears closed
WireGuard still cannot connect from outside

That does not mean DuckDNS is broken.

It means the public route does not reach the router.

Possible fixes:

  • ask ISP for real public IP
  • use IPv6 if available
  • use a VPS as a WireGuard endpoint
  • use a reverse tunnel
  • use mesh VPN / overlay network
  • keep access local-only

Testing DNS Update

First test whether the hostname resolves.

Example:

nslookup revs412.duckdns.org

or:

dig revs412.duckdns.org

The result should match the current public IP, not necessarily the router WAN IP if CGNAT exists.

Check public IP:

curl -s ifconfig.me

Then compare:

DuckDNS result
external public IP
router WAN IP

This comparison tells you which layer is working.

Testing Real Connectivity

DNS resolution is not enough.

After DDNS resolves correctly, test the actual service.

For WireGuard:

turn off Wi-Fi on phone
use mobile data
connect WireGuard
check handshake
ping VPN router IP
access internal service

For a web service:

open domain from mobile data
check reverse proxy logs
check router logs
check service logs

The best test is from outside the home network.

Testing from inside the same LAN may be affected by NAT reflection/hairpin behavior.

Common Failure Cases

Hostname Does Not Update

Possible causes:

  • DDNS service not enabled
  • wrong DuckDNS token
  • wrong domain
  • no internet from router
  • DNS/package issue on OpenWrt
  • script/service not running
  • update interval not triggered yet

Hostname Updates But Service Is Unreachable

Possible causes:

  • firewall rule missing
  • wrong port
  • wrong protocol TCP vs UDP
  • WireGuard not listening
  • service not running
  • wrong internal IP
  • CGNAT
  • ISP blocks inbound traffic

WireGuard Works Locally But Not Outside

Possible causes:

  • client endpoint uses local IP instead of DDNS
  • UDP port not open
  • upstream router blocks traffic
  • CGNAT
  • wrong external port
  • server listens on different port
  • allowed IPs/routes wrong

DDNS Points To Shared ISP IP

Likely cause:

  • CGNAT or upstream NAT

DDNS may still be doing its job, but inbound hosting may not work.

Logs To Check

On OpenWrt, useful places to check include:

DDNS service status
system log
service logs
firewall logs if enabled
WireGuard status

Useful command direction:

logread | grep -i ddns

or:

logread | grep -i duck

For WireGuard:

wg show

Look for:

latest handshake
transfer rx/tx
peer endpoint

If DNS works but no handshake appears, traffic may not be reaching the WireGuard server.

Update Intervals

DDNS should update often enough to recover from IP changes, but not so often that it spams the provider.

A practical interval is usually:

check periodically
update only when IP changes

The DDNS client should avoid unnecessary updates when the IP is unchanged.

After a router reboot or WAN reconnect, an update should happen automatically.

Token Safety

The DuckDNS token is a secret.

Anyone with the token can update the DuckDNS record.

Do not place it in:

  • public GitHub repos
  • screenshots
  • README files
  • shared config examples
  • chat logs
  • public issue reports

For documentation, show:

DUCKDNS_TOKEN=replace_me

not the real value.

File/Config Hygiene

A clean project or note should separate:

real config
example config
documentation

Example:

ddns.example.conf
README.md
.env.example

Avoid committing real OpenWrt config exports if they include tokens, PPPoE credentials, Wi-Fi passwords, VPN private keys, or internal IP details that should stay private.

Public Services vs Private Access

DDNS can be used for public services, but it does not mean everything should be public.

Better exposure model:

Public:
  - website
  - reverse proxy if needed
  - selected game server ports if intended

Private:
  - router admin
  - Proxmox
  - databases
  - dashboards
  - SSH
  - internal apps

For private access, use DDNS as the WireGuard endpoint, then access internal systems through VPN.

That is cleaner than exposing admin panels directly.

OpenWrt Router Reboot Behavior

A finished setup should survive reboot.

Check:

DDNS service enabled
WAN reconnect triggers update
DuckDNS hostname still correct
WireGuard still uses same endpoint
firewall rule still active

A reboot test is useful because many configs appear to work until the router restarts.

Practical Decision Tree

Need stable name for home IP?
  → Use DDNS.

Need WireGuard access to home?
  → Use DDNS as endpoint + open correct UDP port.

Domain resolves but connection fails?
  → Check firewall, service, protocol, CGNAT.

Behind CGNAT?
  → DDNS is not enough; use public IP, IPv6, VPS tunnel, or mesh VPN.

Need public reliable hosting?
  → Consider VPS or public IP instead of residential DDNS only.

Practical Decisions

Use hostname in clients

Remote clients should use the DuckDNS hostname, not a raw IP.

Verify DNS separately from connectivity

A correct DNS record does not prove the service is reachable.

Keep secrets private

DuckDNS tokens should be treated like credentials.

Check CGNAT early

Do not waste time tuning DDNS if the ISP blocks inbound traffic.

Prefer VPN for admin services

DDNS should point to the VPN endpoint, not directly to admin panels.

Test from outside

Mobile data or a VPS gives a more honest test than LAN access.

Testing Checklist

DDNS Setup

  • DuckDNS domain exists
  • token is correct
  • OpenWrt DDNS service installed/configured
  • service enabled
  • update succeeds
  • logs show successful update

DNS Verification

  • hostname resolves
  • resolved IP matches external public IP
  • update survives WAN reconnect
  • update survives router reboot

WireGuard Verification

  • endpoint uses DuckDNS hostname
  • correct UDP port is used
  • firewall allows inbound UDP
  • handshake appears from outside
  • VPN client can reach router VPN IP
  • internal services route correctly if intended

CGNAT Verification

  • compare router WAN IP with external public IP
  • check if WAN IP is private or 100.64.0.0/10
  • test from outside network
  • check whether service logs show attempts

Security Verification

  • token not committed
  • screenshots hide sensitive values
  • admin panels not public
  • only intended ports exposed
  • firewall rules reviewed

What A Finished Setup Should Show

A strong finished setup should show:

  • DuckDNS hostname configured
  • OpenWrt DDNS service enabled
  • successful update logs
  • hostname resolving to current public IP
  • WireGuard endpoint using hostname
  • outside-network connection test
  • firewall rule documented
  • CGNAT limitation documented if present
  • no exposed secrets
  • reboot test completed

Evidence Worth Capturing

Useful evidence for this note would include:

  • DuckDNS domain page with token hidden
  • OpenWrt DDNS config screenshot with secrets hidden
  • update success log
  • nslookup or dig result
  • external public IP comparison
  • WireGuard client endpoint using hostname
  • wg show handshake after outside connection
  • firewall rule screenshot
  • simple topology diagram
  • CGNAT check if relevant

Technical Assumptions

This note assumes OpenWrt is the router or main network gateway.

It assumes the public IP may change over time.

It assumes DuckDNS is used as the DDNS provider.

It also assumes the user wants remote access or self-hosting convenience, not only a decorative domain name.

Key Risks

  • assuming DDNS opens ports
  • ignoring CGNAT
  • using the wrong protocol for firewall rules
  • pointing WireGuard to the wrong port
  • testing only from inside LAN
  • exposing router/admin panels publicly
  • leaking DuckDNS token
  • router reboot disabling DDNS service
  • hostname updating to shared ISP public IP
  • stale DNS cache during testing
  • confusing DNS success with service reachability

Current State

This note represents the DDNS layer of a home/self-hosting setup.

It connects directly to:

  • OpenWrt routing
  • WireGuard remote access
  • dynamic public IPs
  • CGNAT troubleshooting
  • firewall rules
  • safe admin access

The main value is making the public endpoint stable while keeping the rest of the network design understandable.

What This Note Does Not Claim

This note does not claim DuckDNS bypasses CGNAT.

It does not claim DDNS is a security feature.

It does not claim a hostname makes a service reachable by itself.

It documents how DDNS fits into a larger remote-access setup and where its limits are.

Practical Takeaway

The useful lesson is:

DDNS solves the changing-name problem, not the reachability problem.

A correct setup needs all of these layers to work:

DuckDNS hostname
current public IP
firewall rule
correct protocol/port
running service
no upstream CGNAT block
outside-network test

Once those are checked separately, DDNS becomes a simple and reliable part of the remote-access workflow.