DNS split horizon
Split-horizon DNS ensures internal users (LAN & VPN) resolve selected public hostnames to internal IPs, while external users keep resolving them normally. This avoids hairpin NAT and keeps internal access deterministic.
When you need this
Section titled “When you need this”Use split-horizon DNS when:
- A service is hosted inside the LEF network.
- The service has a public hostname.
- LAN/VPN users must access it without routing out and back in.
Architecture (high level)
Section titled “Architecture (high level)”Technitium DNS (https://dns.core.lef) serves different answers depending on where the client is coming from (RFC1918 ranges for LAN/VPN).
Domains covered
Section titled “Domains covered”Split-horizon is applied per root domain (and then per hostname inside the zone).
The canonical list of internal zones vs public domains (and which public domains have split-horizon documented) lives under Domains. The conceptual model is described at DNS behavior.
Source of truth
Section titled “Source of truth”NGINX on np-web is the single source of truth for which hostnames exist and what their internal targets are. The script get_hairpins.sh reads the NGINX configuration and generates the DNS record blocks to apply in Technitium.
Operational workflow
Section titled “Operational workflow”- Update or add an NGINX virtual host on
np-web. - Run
get_hairpins.shonnp-webto generate the Technitium records. - In Technitium (https://dns.core.lef), update the matching conditional forwarder zone for the domain.
- Validate internal vs external resolution.
Validate
Section titled “Validate”Internal (use the internal resolver):
nslookup s3.coragem.app dns.core.lefExternal (use a public resolver):
nslookup s3.coragem.app 1.1.1.1Failure modes
Section titled “Failure modes”- Internal users get public IPs: record missing or not applied to the split-horizon zone.
- External users get internal IPs: zone scoping is wrong (public resolvers should never see internal answers).
- Drift: NGINX changed, DNS block not regenerated/imported.
- Caching: stale answers remain until TTL expires; flush client cache if needed.