A hostname like git.celilo.computer has to resolve to different addresses
depending on who’s asking. A laptop on the home network reaches the service one
way; a server inside the lab reaches it another. Getting that wrong meant devices
couldn’t reach Celilo-hosted sites without a VPN — or worse, an outage. This work
untangled the split-horizon DNS so the resolver answers each client correctly,
and does it at the right layer.
One name, two honest answers
The trouble is that the same hostname points at genuinely different places. A
device on the operator’s home LAN has no direct route into the lab’s internal
network, so it must reach a service through the firewall’s ingress address — its
natIp. A server already inside the lab routes straight to the service’s own
address. The internal resolver used to hand everyone a single answer, so one
audience always lost. The fix teaches it a source-based view: it reads which
network a query came from and returns the right address for that network.
Fixing it where DNS belongs
The earlier workaround had every application pin the address into its own hosts file. That put DNS correctness in the wrong layer — each app became responsible for resolution — and it was fragile: a rebooting VM would regenerate its hosts file and wipe the pin, crash-looping the service. Moving the logic into the resolver deletes all of that. The resolver does its job, and no application has to co-own a hosts file with the operating system.
Placement is the mechanism
For source-based views to work at all, the resolver has to see each client’s
real network. That turned out to hinge entirely on where the resolver lives:
placed among the lab’s protected zones, it sees the true source of every internal
query and can answer each one its correct view, while home-LAN devices reach it
through a dedicated firewall entry and get the natIp they need. The whole
split-horizon collapses to one clean question — did this query cross the
firewall’s translation boundary or not — and the answer follows.