DNS at home

In a typical home network, the router provided by the ISP serves as the local DNS resolver. It automatically resolves global DNS names and local hostnames, e.g., for bonfert.io it returns, while for printer it might return, the IP address assigned via DHCP to your local printer. While this approach works great for most users, not having global DNS names in a local network poses several limits:

  1. Local names like printer or printer.local do not resolve globally. Therefore, SSL certificates cannot be issued by domain validation, like Let’s Encrypt does.
  2. Applications cannot be easily configured to contact a service via internal networks when at home, and via internet when not at home.
  3. Each host is assigned only one name, making the distinction between multiple services on one host thorugh different DNS names (SNI) impossible.

Split DNS solves these issues by adding a local DNS resolver, that resolves local DNS names to their local address. This approach yields different responses for the same DNS name, depending on your current location. When inside your local network, the local address is returned, while otherwise a different DNS server returns a globally routed IP. To implement such a system, two configuration parts are required: Global DNS and local DNS.

In both parts I will assume the goal is to configure the resolution for `vpn.example.com’ and that one is able to configure the public DNS records for example.com.

Global DNS

This part is rather simple. Figure out the public IP address of your home network (e.g. by looking at the status page of your router or modem) and configure the DNS record for vpn.example.com to point to this IP address. Furthermore, to make the service reachable from the internet, port forwarding for the required ports to the destination host needs to be set up.

Since your public IP address might change at any time depending on your ISP, this DNS record needs to be updated if that happens. This can be either done by a script that checks the address and does the update or with the help on a dynamic DNS service and a CNAME record for vpn.example.com.

To ease the configuration for multiple hostnames, one might want to dedicate home.example.com for internal usage and have a DNS record for *.home.example.com. Then vpn.home.example.com could be used without additional configuration for that specific name.

Local DNS

In my setup I use unbound as my local DNS server with the following configuration file:

  port: 53
  do-ip4: yes
  do-ip6: no
  do-udp: yes
  do-tcp: yes
  do-daemonize: no
  access-control: allow
  use-syslog: no
  root-hints: "/etc/unbound/root.hints"
  auto-trust-anchor-file: "/etc/unbound/root.key"
  prefetch: yes
  hide-identity: yes
  hide-version: yes
  harden-glue: yes
  harden-dnssec-stripped: yes
  use-caps-for-id: yes
  cache-min-ttl: 300
  cache-max-ttl: 86400
  statistics-interval: 600
  statistics-cumulative: yes

  local-zone: "home.example.com." transparent
  local-data: "vpn.home.example.com. 86400 IN A"
  local-data: "mqtt.home.example.com. 86400 IN A"
  local-data: "traefik.home.example.com 86400 IN A"

  name: "home.example.com."

The first block in the configuration defines the basic behavior of unbound, as outlined in the docs. The second block contains all local hostnames that I would like unbound to resolve, along with their corresponding IP address.

The last block instructs unbound to forward all queries for *.home.example.com that are not explicitly covered in the config to the router, in order to cover dynamically assigned names as well. All queries not covered are resolved iteratively using the usual DNS mechanisms.

At this point the resolution should work fine for any computers that use this unbound server as their DNS resolver. This can be either configured manually or via DHCP. Most DHCP servers in home routers have appropriate configuration options.

Limitations of this approach

Since a typical home internet connection only has one public IPv4 address, only one host can be publically exposed for each port. It is possible to forward port 1194 to a host running a VPN server and ports 80 and 443 to a different host with a web server. However, forwarding based on the hostname used is not possible. So when running multiple web servers that should be accessible, a reverse proxy is required, that serves as a single entrypoint for ports 80 and 443.

If your ISP does not assign a public IPv4 address to your connection, this approach does not work and additional measures like a jump host need to be put in place.