Living Without Hairpin Routing
This page provides a solution to the problem of having a server on your local network which is also accessible over the public internet at a hostname.
Without hairpin routing, you cannot access the server by its public address while on your local network. For a desktop, this is fine as you can simply include a local override in /etc/hosts
, but for a laptop which could be on or off your local network at any given time, this doesn't work. Assuming you use NetworkManager, the following solution will automatically swap out two versions of your /etc/hosts
configuration depending on whether or not the server is reachable by its public address.
- First, create two files in
/etc/
,/etc/normal_hosts
and/etc/lan_hosts
. - In
/etc/normal_hosts
, place your hosts configuration for when you are off your local network. - In
/etc/lan_hosts
, place your hosts configuration for when you are on your local network.
Then, create the file, /etc/NetworkManager/dispatcher.d/99-set_hosts.sh
, with the following contents:
#!/bin/bash [ "$2" = "connectivity-change" ] \ && [ "$CONNECTIVITY_STATE" = "FULL" ] \ || exit 0 WIFI_DEVICE=YOUR WIFI DEVICE HOME_NETWORK_UUID=YOUR HOME NETWORK UUID uuid=` \ nmcli -c no -f device,active,uuid -t connection \ | grep ^$WIFI_DEVICE:yes: | cut -d: -f 3` case $uuid in $HOME_NETWORK_UUID) cp /etc/{lan_,}hosts ;; *) cp /etc/{normal_,}hosts ;; esac
Make sure the file is executable! (chmod 744)
Make sure the file is owned by root! (chown root:root)
You can find your home network's UUID with nmcli -f name,uuid connection
You can find your WiFi device ID with ip link show