Two names can describe the same branch and answer completely different questions. vpn.branch.example tells a remote peer where to find the VPN endpoint, and it has to resolve before any tunnel exists. inventory.branch.example tells an authorised user where a private application lives, and it only matters once the tunnel is up. Maintaining one of them does nothing for the other.

Name the two records before you debug either

Write both down with their owners. For the endpoint, record who updates the public address and how the VPN client refreshes its answer. For the service, record who owns the private address, which zone holds the record, and which resolvers are supposed to answer for it.

That short list prevents the most common misdiagnosis in this area: restarting a working site tunnel to repair a record that lives entirely inside it. The tunnel is the transport for the service name; it is not the authority for it.

When a change is proposed, ask which of the two records it touches. If nobody can answer, the change is not ready to schedule.

The endpoint must resolve before any tunnel exists

Suppose the branch internet connection receives a new public address. The endpoint updater publishes the new address, and the remote VPN implementation has to be able to read the changed answer. Whatever resolver provides that answer must be reachable without the tunnel, or the client is chasing a name it can only resolve after connecting to the thing it cannot find.

That bootstrap dependency is worth stating plainly, because it is easy to create by accident when all internal resolvers sit behind the VPN. Keep a pre-tunnel path for the endpoint lookup, and confirm the client's reconnection behaviour rather than assuming a new answer is picked up immediately.

Dynamic DNS also has limits that the record update cannot cross. Updating a record opens no firewall port, creates no NAT mapping and proves no peer identity. A published address with a closed port yields a client that resolves correctly and still cannot connect to anything.

Finally, a running client may keep using a cached endpoint until it reconnects. Separate the publication, the cache and the reconnection policy in your notes, so a stale peer is not mistaken for a broken updater.

The service name describes where the application lives

Now suppose the tunnel stays healthy but the inventory server moves from 172.26.14.20 to 172.26.14.35. The public endpoint record is unaffected, while the private service record has to change. Using an address reserved for that service, or a static assignment, keeps this rarer; an authorised update path handles the times it is intended.

Two update mechanisms get conflated here. RFC 2136 defines a protocol for adding and deleting DNS records in a zone, while a commercial dynamic DNS provider may expose a completely different HTTP API for a different purpose. Using one does not imply the other exists in your environment. Check which mechanism your zone actually accepts before you write an updater against it.

A correct private answer is only the first condition. For a remote caller to use it, the client needs a resolver that carries the private zone, a policy that permits queries to that resolver, and forwarding for the address that comes back. A name that resolves to an address the client cannot reach produces a timeout that looks like a server fault.

Test the two paths separately

Check the endpoint from outside the tunnel and the service from inside it, and keep the results as two independent facts:

$ dig +short vpn.branch.example @1.1.1.1
$ dig +short inventory.branch.example @172.26.0.53
$ ip route get 172.26.14.35

If the first query fails, the problem is public publication or the pre-tunnel resolution path, and no internal change will help. If the second returns an address but the third shows no route through the tunnel, the DNS layer is fine and the forwarding policy is not.

Run the pair after every address change, and note which record moved. A handover that says only "DNS was updated" leaves the next engineer guessing which of the two lifecycles actually ran.

Artaigilean co-cheangailte