Pointing a static route at a gateway name feels like it should survive an address change, and it does not. The name lives in DNS, while the route sits in the client's routing table as a numeric next hop. When the Pi moves to a different address, every consumer that already installed the old hop keeps sending traffic to the same number. No resolver is wired to the forwarding table, so nothing rewrites that entry for you.

The DNS answer and the route are different objects

Say your Pi answers to vpn-gw.lan and forwards 10.44.0.0/16 onto a tunnel. Clients on 192.168.30.0/24 reach it through a static route. When the Pi's address moved from 192.168.30.4 to 192.168.30.11, the record followed within its TTL and the routes did not.

The two views disagree in a way that is easy to miss, because both look plausible when you query them separately:

$ ip route get 10.44.0.1
10.44.0.1 via 192.168.30.4 dev eth0 src 192.168.30.20
$ dig +short vpn-gw.lan
192.168.30.11

Only the first line decides where packets go. The second line answers a question the kernel never asked. A record with several A records does not become a failover policy either, since each address still has to be a workable next hop on that segment.

What survives in the table after the command exits

A Linux route records two things that matter here: the next hop as a protocol address, and the egress interface as an index number. The rtnetlink route attributes name that first field RTA_GATEWAY, and it holds bytes. Once the entry is in place, no TTL is attached to it and no background lookup refreshes it.

This is why ip route add 10.44.0.0/16 via vpn-gw.lan can appear to work. The tool resolves the name while the command runs, writes the resulting address, and forgets the name entirely. Run ip route show 10.44.0.0/16 afterwards and you get a literal address back.

That behavior is worth knowing before you blame the tunnel.

Tools that resolve a name for you, and when

Some routers and firewalls do accept hostnames in a route or gateway field. What matters is when the resolution happens. If the device resolves the name only while you commit the configuration, the stored entry is just as static as a typed address, and a later address change needs another commit. The field accepting a name tells you nothing about refresh.

Managed setups tend to split the job. A DHCP reservation or static lease keeps the Pi on one address, and the DNS record simply follows the lease. Nothing has to track a moving target because the target does not move.

A monitored updater is the other legitimate pattern, and it needs an owner.

Pin the address or run the updater yourself

For a small LAN, a reservation on the DHCP server is the cheapest fix. Pick an address outside the dynamic pool, bind it to the Pi's MAC address, and confirm it with ip -4 addr show dev eth0 after the next lease renewal. Then point the clients' next hop at that address once. You now have a stable gateway and a record that describes it, which is the order the relationship actually works in.

If the Pi genuinely has to move, keep the route repair in one place instead of hand-editing every client. A short script that resolves, compares and replaces is enough to make the step repeatable:

new=$(dig +short vpn-gw.lan | head -n1)
cur=$(ip route get 10.44.0.1 | awk '{print $3}')
if [ "$new" != "$cur" ]; then
  ip route replace 10.44.0.0/16 via "$new"
fi
ip route get 10.44.0.1

The last command is the acceptance test, because it prints the gateway the kernel will actually use. If the printed address is still the old one, the script ran in the wrong network namespace or lacked permission, and the DNS side is irrelevant.

Check the return path as well. The Pi has to know how to reach the client subnet, and its firewall has to allow the tunnel traffic. A default route added to paper over the mismatch usually hides the real gap and breaks something else a week later.

Ũhoro ũhĩtĩte