From eca17022b03fd6afe785437d79d4f32a282782fc Mon Sep 17 00:00:00 2001 From: Akemi Izuko Date: Sun, 7 Jul 2024 16:17:37 -0600 Subject: [PATCH] Unix: split-horizon dns --- .../unix/reaching-yourself-from-wan.md | 191 ++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 src/content/unix/reaching-yourself-from-wan.md diff --git a/src/content/unix/reaching-yourself-from-wan.md b/src/content/unix/reaching-yourself-from-wan.md new file mode 100644 index 0000000..724f726 --- /dev/null +++ b/src/content/unix/reaching-yourself-from-wan.md @@ -0,0 +1,191 @@ +--- +title: 'Reaching Yourself Over the Internet' +description: 'SOCKS5 and DNSmasq' +updateDate: 'July 07 2024' +--- + +As I've started hosting more and more services on my home network, I've +increasingly found the need to contact myself over the internet. + +For example, I host Forgejo locally at git.mami2.moe. The problem is that from +*my* computer, I can't type `git.mami2.moe` in the address bar and get on +Forgejo, I need something like `localhost:8080` on my computer or +`10.0.0.2:8080` on my laptop. + +The problems become compounded with some services like Cvat, which only +allowlist a specific set of domains in the header. This means I can't even reach +Cvat on `localhost:8080` from my own computer, as Cvat will deny that request. +Additionally, it's important to make sure your DNS settings are correct, so +people on the internet can reach Cvat, but that's not possible to test on your +home network. + +In this article I'll go over my solutions to this problem. Hopefully you learn +some networking on the way! + +## /etc/hosts + +The easiest way to go about this is the most basic DNS possible: `/etc/hosts`. +Simply add a line to redirect to the loopback, and your reverse proxy should +handle it from there. Systemd-resolved reads `/etc/hosts` without even needing +to reload! + +``` +127.0.0.1 git.mami2.moe +``` + +## SOCKS + +SOCKet Secure is a widely-available TCP/UDP proxy, which is even baked into +OpenSSH! This means any computer you can SSH into can become your SOCKS proxy. +In my case, I found this to be by far the easiest solution. + +Start by adding dynamic forwarding to your `~/.ssh/config`. Below we specify +9042, but this can be any open port: + +```ssh-config +Host orca + IdentitiesOnly=yes + Hostname 123.4.23.84 + User emiliko + DynamicForward 8081 + Compression yes + LogLevel QUIET +``` + +Connect to your proxy `ssh orca`. Now start chromium with this proxy: + +```bash +chromium --proxy-server='socks5://localhost:8081' +``` + +However, I often find I also want to still be able to use a browser without this +proxy. In this case, I start up two distinct chromium sessions. For example: + +```bash +chromium # Leave this one open for yourself +chromium --proxy-server='socks5://localhost:8081' --user-data-dir=/dev/shm/chromium_socks +``` + +From this, my first browser can reach Forgejo only on `localhost:8080`, while the +second one will only reach it on `git.mami2.moe`, allowing me to develop locally +but still test changes from an external user's perspective! + +## Cellular Connection + +This one is a bit silly, but also the least technical option. If you need to +help someone with limited technical expertise, this is the best option to +suggest. + +You can access your website (git.mami2.moe) from your phone when wifi is turned +off! Throw up a hotspot and any computer connected through this hotspot has +access too! + +The major limitations are that you still can't access git.mami2.moe on the +computer actually hosting git.mami2.moe and you're now using more expensive +data. + +## Hairpin NAT + +If you have access to your router/modem and it has Hairpin NAT support, enable +it and everything should just work. Hairpin NAT makes the router analyse where +an outbound request is being sent. If the request is trying to reach that +router's IP address, it'll simply reflect the packet, acting as if it came over +the internet. + +While this seems like the ideal solution, most residential internet service +providers [do not provide Hairpin +NAT](https://forum.telus.com/t5/Internet-Home-Phone/Hairpin-Nat-on-Telus-WIFI-hub-modem/m-p/112975/highlight/true#M27472) +on their modems. I don't know why... Additionally, most commercial networks have +moved away from this solution replacing it instead with Split-horizon DNS. + +# Split-horizon DNS + +Split-horizon DNS allows for multiple layers of DNS resolution to be present on +your network. This is the most complicated setup, but also the most flexible, as +it allows us to become the DNS resolver for the entire network. + +We'll go through a simple setup, which will function similarly to the +`/etc/hosts` solution, then step it up to work on all devices on this network. + +## Local Setup +We'll use `dnsmasq` as it's the easiest to deal with. Place the following in +`/etc/dnsmasq.conf`, modifying as needed + +```ini +# Must match with /etc/resolv.conf +listen-address=127.0.0.1 +# Don't look any further in /etc/resolv.conf +no-resolv + +# DNS Servers +server=9.9.9.9 +server=149.112.112.112 +server=2620:fe::fe +server=2620:fe::9 + +# Local resolution. Relies on a reverse proxy to choose the port (Caddy) +# Both ipv4/6 just in case +address=/git.mami2.moe/127.0.0.1 +address=/git.mami2.moe/::1 +``` + +There's a good chance you have `systemd-resolved` or some other sort of DNS +resolver running (NetworkManager does something along these lines too). Kill all +competing DNS resolvers: + +```bash +systemctl disable --now systemd-resolved.service +systemctl enable --now dnsmasq.service +``` + +Now you should be able to resolve external domains `example.com` as well as +override the resolution for your local domains `git.mami2.moe`. Try both in +chromium, it should just work. + +## Full Network + +Let's first modify our `/etc/dnsmasq.conf` a little bit. We want to replace the +loopback with your LAN interface's IP. Often, `eth0` will hold this address. You +need both the static IPv4 address and the link-local IPv6. In these examples, my +static IPv4 is `10.0.0.2` and my linklocal is `fe80::200:ff:fe00:40`: + +```ini +# For the server itself +listen-address=127.0.0.1 +# For all other devices on the network contacting the server +interface=eth0 + +# Don't look any further in /etc/resolv.conf +no-resolv + +# DNS Servers +server=9.9.9.9 +server=149.112.112.112 +server=2620:fe::fe +server=2620:fe::9 + +# Local resolution. Relies on a reverse proxy to choose the port (Caddy) +# Both ipv4/6 just in case. Notice, you'll need your linklocal +address=/git.mami2.moe/10.0.0.40 +address=/git.mami2.moe/fe80::200:ff:fe00:40 +``` + +You may need to open up your firewall (see `firewall-cmd`), but it's often +already open to the local network. + +Login to your router and set the IPv4/6 DNS servers to point to the IPs of your +server. You could also add a fallback DNS server, but I've found that one might +take precedence, circumventing the whole split-horizon. + +DHCP leases are held for several hours usually, so to test it, "forget" the +network and reconnect. Try accessing git.mami2.moe and something like +example.com, which isn't in your dnsmasq records. + +For devices using `systemd-resolved`, you must accept DNS records from DHCP. You +can do this by explicitly leaving `DNS` and `FallbackDNS` blank: + +```ini +[Resolve] +DNS= +FallbackDNS=9.9.9.9 +```