Home server on a dynamic address
Keeping a hostname pointed at a changing home address — router, Linux and Windows setup, proxying, and what to do about SSH.
Home connections hand out an address for a while. Reboot the router, let the ISP re-establish the session, and the address is different — everything that pointed at it stops answering. The cure: the device reports its current address and we keep the DNS record up to date.
You need: a domain delegated to our nameservers, and a device that can run curl
every ten minutes.
1. Create the hostname
Section titled “1. Create the hostname”- Control panel → DNS for the domain.
- Dynamic IP card → Add hostname. A short name such as
homegives youhome.example.com. - Copy the token. It is shown once: a lost token cannot be recovered, only replaced.
The name appears in the records list right away, marked Dynamic. Until the first update it says “no address reported yet” — that is expected, there is no record in the zone yet.
2. Teach the device to report its address
Section titled “2. Teach the device to report its address”Router
Section titled “Router”Almost every router speaks dyndns2. Find the “DynDNS”, “Dynamic DNS” or “DDNS”
section, pick a custom service — Custom, Other, dyndns2 — and fill in:
| Field | Value |
|---|---|
| Server / Service | dyn.webshield.pro |
| Username | home.example.com |
| Password | the token you copied |
| Hostname | home.example.com |
If the firmware wants a full update URL:
https://dyn.webshield.pro/nic/update?hostname=home.example.com&myip=<IP>It has to be https — we do not accept updates over plain HTTP, the token would travel
in the clear. Very old firmware that does not follow the redirect from port 80 will not
work; use the curl method below instead.
MikroTik
Section titled “MikroTik”The built-in RouterOS client is tied to its own service, so schedule the request:
/system scheduleradd name=webshield-dyndns interval=10m on-event={ /tool fetch url="https://dyn.webshield.pro/update?token=TOKEN" keep-result=no}OpenWrt
Section titled “OpenWrt”The ddns-scripts package, a custom service in /etc/config/ddns:
config service 'webshield' option enabled '1' option lookup_host 'home.example.com' option domain 'home.example.com' option username 'home.example.com' option password 'TOKEN' option update_url 'https://[USERNAME]:[PASSWORD]@dyn.webshield.pro/nic/update?hostname=[DOMAIN]&myip=[IP]' option use_https '1' option ip_source 'web' option ip_url 'https://dyn.webshield.pro/ip'ddclient
Section titled “ddclient”protocol=dyndns2server=dyn.webshield.prossl=yesuse=web, web=https://dyn.webshield.pro/iplogin=home.example.compassword='TOKEN'home.example.comLinux without a router
Section titled “Linux without a router”A machine behind NAT does not know its own public address — and does not need to. Send no address at all and we will use the one the request came from:
curl -fsS "https://dyn.webshield.pro/update?token=TOKEN"In crontab -e:
*/10 * * * * curl -fsS "https://dyn.webshield.pro/update?token=TOKEN" >/dev/nullOr a systemd timer, if you want logs and a run after resume:
[Service]Type=oneshotExecStart=/usr/bin/curl -fsS "https://dyn.webshield.pro/update?token=TOKEN"
# /etc/systemd/system/webshield-dyndns.timer[Timer]OnBootSec=1minOnUnitActiveSec=10minPersistent=true
[Install]WantedBy=timers.targetsystemctl enable --now webshield-dyndns.timerWindows
Section titled “Windows”Task Scheduler, action — PowerShell:
Invoke-RestMethod "https://dyn.webshield.pro/update?token=TOKEN"Or from an elevated console in one line:
schtasks /create /tn "WebShield DynDNS" /sc minute /mo 10 /tr ^ "powershell -NoProfile -WindowStyle Hidden -Command \"Invoke-RestMethod 'https://dyn.webshield.pro/update?token=TOKEN'\""3. IPv4 and IPv6: one request or two
Section titled “3. IPv4 and IPv6: one request or two”It depends on whether you know the addresses.
You know them — one request is enough. Both can travel together:
curl -fsS -u "home.example.com:TOKEN" \ "https://dyn.webshield.pro/nic/update?myip=203.0.113.7,2001:db8::5"Or as separate parameters — myip for IPv4, myipv6 for IPv6. Same result.
You rely on detection — you need two. We see exactly one address: the one the request arrived from. Arrive over IPv4 and IPv4 is all we learn. So:
*/10 * * * * curl -fsS -4 "https://dyn.webshield.pro/update?token=TOKEN" >/dev/null*/10 * * * * curl -fsS -6 "https://dyn.webshield.pro/update?token=TOKEN" >/dev/nullThe two do not fight: an update of one family never touches the other. An IPv4-only
request will not drop the AAAA record, and the other way round. So even if IPv6 at
home comes and goes, the last known address stays put.
Dual-stack routers usually send both families themselves, in one request — nothing extra to configure. To see what we get:
curl https://dyn.webshield.pro/ip # answers with however you arrivedcurl -4 https://dyn.webshield.pro/ipcurl -6 https://dyn.webshield.pro/ip4. Proxying to the home server
Section titled “4. Proxying to the home server”A home address in public DNS is an invitation — it gets scanned within hours. The cure is proxying: visitors reach our edge, and we connect to your server at its current address.
What you get:
- your home address stays out of DNS;
- we issue the certificate, so no need to expose port 80 for validation;
- WAF, bot filtering, caching and DDoS protection apply;
- visitors never notice the address moving.
How to turn it on:
- Wait for the first update — an
Arecord with your address appears in the DNS list. - Flip its Proxy switch.
- Hosts section → protection settings for that name (see CDN and protection).
Everything else keeps working: the client reports its address, and we update not the public record but the address we use to reach you. After a change the switch takes up to a minute.
On the server itself you can then close 80 and 443 to everyone except our addresses.
Mind that the list of our nodes changes, so either keep that rule current or leave the
ports open and check the Host header on your side — simply refuse requests that arrive
with a hostname you do not serve.
5. What goes through the proxy, and what does not
Section titled “5. What goes through the proxy, and what does not”A proxied hostname carries web traffic only: HTTP and HTTPS on ports 80 and 443, WebSocket included. Everything else — SSH, RDP, VPN, game servers, torrents, arbitrary TCP ports — does not pass through us. We are a reverse proxy for the web, not a tunnel.
Which means: once proxying is on, you can no longer SSH to that name. It resolves to our addresses, and there is nothing on port 22 there.
Two ways around it.
A separate hostname without proxying. Create a second dynamic name, say
ssh.example.com, and leave its proxy off. The web lives on the proxied home, while
ssh points straight home. The trade is honest: that name exposes your address, so
- move SSH off the default port and disable password logins — keys only;
- run
fail2banor similar; - if your ISP gives you a static IPv6, allow that address only.
Web access instead of SSH. Anything that speaks HTTPS lives happily behind the proxy: a web terminal, a server control panel, Git over HTTPS, an API. If the goal is “occasionally get into the home machine”, a web console behind our protection beats an SSH port open to the world.
6. When something is off
Section titled “6. When something is off”Look at what the update endpoint answers — the reply is short and to the point:
| Response | Meaning |
|---|---|
good <address> |
accepted and written |
nochg <address> |
same address, nothing to change |
badauth |
the token is wrong or missing |
nohost |
wrong hostname for this token, or updates are switched off |
dnserr |
the address does not look public |
911 |
too often, try again later |
The limit is 10 address changes per 10 minutes per hostname. Repeats with the same address — which is what a router reboot looks like — do not count, so reboot as much as you like.
dnserr almost always means the device sent its private LAN address: 192.168.*,
10.* or a carrier-grade NAT range. Such an address is useless in public DNS, so we
reject it. Remove the address from the client settings and let us detect it.
Protocol details live on the Dynamic IP page.