Written 17 Sept 2023

Wireguard

virtual private network protocol. Way back when this was hosted out of a dormitory, it was a simpler time where simpler measures were...simple. Now, I find myself behind the bane of every homelabber: Carrier Grade NAT (CGNAT).
Of course not, I expect you to die! ~Sauron
The easiest way around this would be to have a VPN back to my network, but that is impossible with CGNAT between and a reachable IP. However, an externally available VPN server can be used to get around this. In a hub and spoke model, my home network and phone/laptop/tablet become spokes that can talk to each other. The connection between my home network and the central server is what's known as a Site-to-Site connection. But, how do I accomplish this server when I don't have a publicly reachable IP?
The difference between rich people and stupid people
Our last and only option is to, sadly, spend money on goods ands services like members of a modern society that has enabled man to surpass the wildest dreams of a mere 100 years ago. What a drag. If you're a pinko commie, but I like where this is going. Step one was to hit the LowEndBox $1/mth VPS section. Then, I picked up a Black Friday deal from RackNerd. Finally I performed a few steps:
  1. Setup SSH keys
  2. for secure, key only access.
  3. Installed Wireguard
                    
                        sudo apt-get install -y wireguard
                    
                
  4. Setup DNS forwarding on my domain. You can use a dynamic dns, like DuckDNS, but I own a domain and google does that for free.

The biggest piece here is the inital configuration file for the VPN server. Wireguard is dead simple though, and this made the processes easy to figure out. Behold! The config file located at /etc/wireguard/wg0.conf:
        
            [Interface]
            Address = 10.0.0.1/24
            ListenPort = 51820
            MTU = 1380
            PrivateKey = [redacted]

            # packet forwarding
            PreUp = sysctl -w net.ipv4.ip_forward=1
            PreDown = sysctl -w net.ipv4.ip_forward=0

            # wireguard ingress
            PreUp = iptables -I INPUT 1 -p udp --dport 51820 -j ACCEPT
            PreUp = iptables -I INPUT 1 -i wg0 -j ACCEPT
            PostDown = iptables -D INPUT -i wg0 -j ACCEPT
            PostDown = iptables -D INPUT -p udp --dport 51820 -j ACCEPT

            # Masquerading traffic
            PreUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
            PreDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

            [Peer]
            # Router
            PublicKey = [Peer pub key]
            AllowedIPs = 10.0.0.2/32, 192.168.0.0/24
            PresharedKey = [shared key made with wg genkey]

            [Peer]
            # Phone
            PublicKey = [Peer pub key, generated with wg tools]
            AllowedIPs = 10.0.0.3/32
            PresharedKey = [Different shared key made with wg genkey]
        
        
The easiest way to mak the key pairs is using the tools wireguard includes: wg genkey | tee /etc/wireguard/privatekey | wg pubkey | tee /etc/wireguard/publickey
Taking a closer look at the peers, you see the AllowedIPs line. For the home router, this line is AllowedIPs = 10.0.0.2/32, 192.168.0.0/24. The important thing here is that we allow both the address of the peer AND the home network. This informs wireguard it can route, and so long as the other side accepts conections, it will route like any other network. By placing the config file in /etc/wireguard, you can then use the included wireguard command wg-quick up wg0 to bring up the interface, run our PreUp instructions, and add routes to our machine. For the home router, I use OpenWRT, so I can just load a config from file with the wireguard add-on. On Android, I can do the same or it's possible to generate a qrcode if you make a config file that includes the private key of the server. The peer configuration file looks something like this:
        
            [Interface]
            Address = 10.0.0.2/32
            PrivateKey = [private key we generate with wg genkey as before]

            [Peer]
            PublicKey = [public key of our server]
            AllowedIPs = 0.0.0.0/0 # to allow untunneled traffic, use `0.0.0.0/1, 128.0.0.0/1` instead
            PresharedKey = [same key we set in our server config]
            Endpoint = [domain]:[port] # default port is 51820
            PersistentKeepalive = 25 # Keepalive is recommended when behind a NAT
        
    

And that's it. It should just work. Typically, when it doesn't, I have fat fingered part of the config. After that, I have typically fat fingered the firewall. I like to run wg show wg0 to see how much bandwidth has been used by my peers, then run some quick pings into and out of the wireguard network; it gives me the warm fuzzies that something is happening.