Knowledge baseDomains & DNS

Dynamic DNS

Keep a name pointed at a changing IP: from a mesh node with no software, or from a router or ddclient over dyndns2.

On this page

How dynamic DNS works

A home internet connection usually gets a new public IP from time to time. Dynamic DNS (DDNS) keeps an A or AAAA record pointed at the current address, so myhome.mesh-net.space always leads home. mesh-net offers two sources of the address:

  • A mesh network node — no software at all: a device of your private network already tells the network its public IP, and mesh-net updates the record itself.
  • A token — your router, NAS or server reports its IP over the standard dyndns2 protocol (the one routers and ddclient speak).

DDNS works for names in our zones and for A/AAAA records of your own domain.

Before you start

DDNS fills in A and AAAA records only, so the name needs one first. For a name in our zones, add it on the name's page — an empty value is fine there, the source fills it in (see Names and DNS records). Then open the name (click it in the list on Domains) and scroll to Dynamic DNS (DDNS): every A and AAAA record gets its own card. A record of your own domain needs an address from the start — any will do, DDNS replaces it.

Choose a source

A card without a source shows disabled and offers two ways:

Mesh network nodeToken
What runs on your sideNothing extra: the node is already in your networkA router, ddclient or a cron line
NeedsA private network (Paid plan) with that deviceAny plan
Card statussource: mesh nodesource: token

A record has one source at a time. To switch, first remove the current one — Unbind node for a node, Turn off for a token; then the card offers both ways again.

DDNS from a mesh network node

  1. In the record's card, under Mesh network node — no software, pick the device in the list. Each entry shows the device's current public IP of the right family (IPv4 for A, IPv6 for AAAA).
  2. Press Bind. If the device is online, the record gets its address right away; if not, the address appears once the device connects.

From then on mesh-net checks the device about once a minute. A new address must hold for 2 minutes before the record moves, so a short flap doesn't throw the name around; the record follows a change within about 3 minutes. While the device is offline, the record keeps its last address. Unbind node stops the updates.

Keep in mind

The record is public DNS: anyone who looks up the name sees the device's public IP.

The list only has devices of your own private networks that are running. With no such device the card says so — use a token instead.

DDNS with a token

Press Use a token. The card shows everything a client needs:

FieldValue
Server / URLhttps://mesh-net.space/nic/update (server mesh-net.space)
Hostnamethe full name, e.g. myhome.mesh-net.space
Usernameanything — it is ignored
Password (token)the token, shk_…

The token belongs to this one record; treat it like a password. Below the fields the card has ready-made setups for Linux and a cron line with your token already filled in — the same commands as below.

An AAAA record's card is set up for IPv6

On an AAAA record's card, the ddclient config and the cron line work with IPv6 only: the address is found on the machine itself, because our server can't see it. See IPv6.

Linux and Proxmox: ddclient

On Debian, Ubuntu and a Proxmox host (it is Debian too):

  1. Install ddclient. If the installer asks for a protocol or a server, press Enter to skip: the next step writes the config.
    sudo DEBIAN_FRONTEND=noninteractive apt-get update && sudo DEBIAN_FRONTEND=noninteractive apt-get install -y ddclient
  2. Write /etc/ddclient.conf with one command. Put your token and your name in place of TOKEN and myhome.mesh-net.space (the card on the name's page has them filled in):
    sudo tee /etc/ddclient.conf >/dev/null <<'EOF'
    daemon=300
    ssl=yes
    usev4=webv4
    webv4=https://mesh-net.space/nic/ip
    protocol=dyndns2
    server=mesh-net.space
    login=token
    password='TOKEN'
    myhome.mesh-net.space
    EOF
    sudo chmod 600 /etc/ddclient.conf
    The public IP is detected by our own service https://mesh-net.space/nic/ip, so no third-party checkip is needed.
  3. Run a one-off check — it should answer good or nochg with your IP:
    sudo ddclient -daemon=0 -debug -verbose -force
  4. Enable autostart; with daemon=300 it checks every 5 minutes:
    sudo systemctl enable --now ddclient && systemctl status ddclient --no-pager

Without ddclient: one cron line

The server takes the address from the request itself, so nothing has to detect it. On any always-on Linux machine in the same network, open crontab -e and add:

*/5 * * * * curl -fsS "https://mesh-net.space/nic/update?hostname=myhome.mesh-net.space" -u token:TOKEN

Every 5 minutes the line reports the network's current public IP. The answer goes to cron's mail; add >/dev/null if you don't need it.

Routers

A router is the best place for DDNS: it is always on and knows its public address. The parameters are the ones from the card: server mesh-net.space, the full name, any username, the token as the password, protocol dyndns2.

OpenWrt

  1. Install luci-app-ddns in System → Software; for HTTPS also curl and ca-bundle.
  2. Services → Dynamic DNS → add a service with the provider -- custom --.
  3. Custom update URL — the token goes in the URL itself, so it works whichever download program the router uses:
    https://mesh-net.space/nic/update?hostname=[DOMAIN]&myip=[IP]&token=[PASSWORD]
  4. Lookup hostname and Domain — the full name; Username — token; Password — the token; turn on HTTPS.

MikroTik

RouterOS has no custom dyndns2 client, but a two-line script does the job. In the terminal (put your token in place of TOKEN):

/system script add name=mesh-ddns source="/tool fetch url=\"https://mesh-net.space/nic/update\?token=TOKEN\" keep-result=no"
/system scheduler add name=mesh-ddns interval=5m on-event=mesh-ddns

The token goes in the URL (\? is how the RouterOS terminal takes a question mark). The token alone tells which record to update, so the request needs no hostname. It leaves through the router's WAN, and the server records that public address.

Keenetic

Use a dyndns2-compatible (custom) provider in the router's dynamic DNS settings, if your KeeneticOS version offers one, with the parameters above. If it doesn't, put the cron line on any always-on device in the LAN.

ASUS

Stock ASUS firmware can't use a custom dyndns2 server. Either run ddclient or the cron line on another machine in the LAN, or install Asuswrt-Merlin: choose the custom DDNS server and save this as /jffs/scripts/ddns-start (executable):

#!/bin/sh
curl -fsS "https://mesh-net.space/nic/update?hostname=myhome.mesh-net.space&myip=$1" -u token:TOKEN >/dev/null \
  && /sbin/ddns_custom_updated 1 || /sbin/ddns_custom_updated 0

IPv6 (AAAA records)

The card of an AAAA record gives its own setup. Two things differ from an A record:

  • The address is found on the machine itself. Our server has no IPv6, so it can't see yours: /nic/ip and an update without myip get an IPv4 address.
  • Only IPv6 lines. The record follows the family of the address it receives: an IPv4 address turns an AAAA record into an A record, and back. With IPv4 lines next to the IPv6 ones, ddclient sends the IPv4 address first.

ddclient 3.10 or newer takes the address from the network interface that the machine's IPv6 internet route goes through. The shell fills in the interface name when it writes the file — that's why this EOF has no quotes:

sudo tee /etc/ddclient.conf >/dev/null <<EOF
daemon=300
ssl=yes
usev6=ifv6
ifv6=$(ip -6 route show default | grep -o 'dev [^ ]*' | head -n1 | cut -d' ' -f2)
protocol=dyndns2
server=mesh-net.space
login=token
password='TOKEN'
myhome.mesh-net.space
EOF
sudo chmod 600 /etc/ddclient.conf

An empty ifv6= in the file means the machine has no IPv6 route to the internet — there is no IPv6 address to publish. Without ddclient, the cron line passes the machine's global IPv6 address explicitly and sends nothing while there is none:

*/5 * * * * ip6=$(ip -6 -o addr show scope global -temporary -deprecated | grep -o 'inet6 [23][0-9a-f:]*' | head -n1 | cut -d' ' -f2) && [ -n "$ip6" ] && curl -fsS "https://mesh-net.space/nic/update?hostname=myhome.mesh-net.space&myip=$ip6" -u token:TOKEN

Routers usually report only their IPv4 address — for an AAAA record, run ddclient or the cron line on the machine itself.

Which address does mesh-net see?

https://mesh-net.space/nic/ip answers with the public IP your request comes from, as plain text — the same address the update takes when myip isn't given:

curl https://mesh-net.space/nic/ip

The update request and its answers

GET https://mesh-net.space/nic/update with these parameters in the query string. POST is accepted too, but the parameters still go in the URL: a form body is ignored.

ParameterMeaning
Basic auth password, or token=The record's token (the username is ignored)
hostname=The full name; optional, but if given it must match the token's record
myip= (or ip=)The address to publish; the first one if there is a list. Without it — the address of the request
AnswerMeaning
good 203.0.113.7The record now has this address
nochg 203.0.113.7The address hasn't changed; nothing to do
badauthNo token, or it is wrong — the token was changed or DDNS is off. HTTP 401 with WWW-Authenticate: Basic realm="mesh-net DDNS", so clients that wait to be asked send the token
nohosthostname isn't the name of this token's record
dnserrmyip isn't an IP address
911Our DNS server didn't accept the change; the client will retry

If it doesn't work

  • Old ddclient (before 3.10) doesn't know usev4/webv4: use the single line use=web, web=https://mesh-net.space/nic/ip instead. It can't take an IPv6 address from an interface: for an AAAA record, use the cron line.
  • The public IP is right on the interface (the machine isn't behind NAT): use usev4=ifv4, ifv4=eth0; look up the interface name with ip -br a.
  • Behind CGNAT — the address mesh-net sees is in the 100.64–100.127 range: your connection has no public address of its own, and DDNS won't help. Ask your ISP for a public IP, or reach the machine through a mesh network instead.
  • badauth after it used to work — someone pressed Change token: put the new token into the client.
  • badauth although the token is right — the token didn't reach mesh-net. Clients that send the username and password only when the server asks for them get that request with the badauth answer (HTTP 401 with WWW-Authenticate: Basic) and repeat the update with them; a client that still sends nothing can carry the token in the URL instead: https://mesh-net.space/nic/update?token=TOKEN.
  • An AAAA record became an A record — the client sent an IPv4 address (or none, and mesh-net took the address of the request). Set it up as in IPv6.
  • Logs of ddclient: journalctl -u ddclient -n 50 --no-pager.
  • The record changed but the name still resolves to the old address — that's caching; see How fast changes appear.

DDNS for your own domain

Once your own domain has its zone at mesh-net, its page has a Dynamic DNS (DDNS) section with a card for every A and AAAA record of the zone. Press Turn on DDNS: the record gets a token, and everything else is the same — the same https://mesh-net.space/nic/update, ddclient, cron and router setups, with the record's full name as the hostname. Binding to a mesh node is available for names in our zones only.

Change the token or turn DDNS off

  • Change token issues a new token at once; the old one stops working (badauth), so update the client right after.
  • Turn off removes the token. The record keeps its last address and no longer changes.