As I run most of this infrastructure on a 5G hotspot I experienced a limitation from my carrier, they use whats called CGNAT. This is common across cellular networks and now even many fixed line broadband providers. It essentially means you don’t have a public facing routable IP that you can forward ports to internal services on and are left with an RFC1918 address. This will work for any type of closed network really as a punch through. Given I want to expose some services to the outside world I wanted a way to circumvent this restriction without sacrificing too much performance. The tool for the job… Wireguard.
As long as you have a VPS or Server somewhere that is Internet reachable and has at least 2 Public IP addresses, its actually quite trivial. Wireguard is a good weapon of choice because its highly performant, easy to configure and is built into the Linux kernel.
Requirements
- A remote host (e.g. VPS) with 2 Public facing routable IP addresses, they do not have to be contiguous or part of the same Subnet. Something geographically local is probably best for performance and usability reasons.
- An internal Wireguard capable host to setup the client facing side of this. (A router is the best pick for simplicity, however you can use any internal host + a Static Route if required).
- We’ll assume
12.13.14.15
and12.13.14.16
are your two Public facing routable IP’s.
Initial setup of Wireguard
Wireguard is a VPN technology that utilises a “peer” model rather than a client/server model. It comes with all the neccesary tooling to generate keys and configs too. Assuming you’re on a debian based system, you’ll first need the tooling to interact with Wireguard:
sudo apt update
sudo apt install wireguard
The next step is to generate keys needed for all peers. In this case its simply two, your VPS/Remote host and your local machine/router.
wg genkey | sudo tee /etc/wireguard/private.key
sudo cat /etc/wireguard/private.key | wg pubkey | sudo tee /etc/wireguard/public.key
you should run these on both your VPS/Remote host and your local machine/router and after should have a key pair for each. Alternatively you can use a simple service such as Wireguard Config but do so at your own risk.
Wireguard configuration
On your VPS/Remote host its time to create the wireguard configuration.
sudo nano /etc/wireguard/wg0.conf
We’ll assume that your VPS/Remote host is reachable via 12.13.14.15
which is likely its main network interface address.
[Interface]
Address = 172.16.10.1 # or any other IP from RFC1918
PrivateKey = WPA9kEYtoJnJFi3dCzofjImSwvzZzJF93hCWdFWOkfC= #Your Private key
DNS = 1.1.1.1
ListenPort = 51820 # or any other port
[Peer]
PublicKey = dSp9iFKFoic9rDEBiIUIgSKckcF9hU6LqJU9K34jAcI=
AllowedIPs = 12.13.14.16/32 # here goes your public IP
Now on your local Router / host you need to create the corresponding config for the peer you just created.
[Interface]
PrivateKey = WIKck93j4nFkcDAlXnrkgjaCHGkoi941491d=
Address = 12.13.14.16/32
[Peer]
PublicKey = /PAsJci3fFCfaXGqvIoqOJnfl13414NPkrTKcne4hO=
AllowedIPs = 1.0.0.0/8, 2.0.0.0/8, 3.0.0.0/8, 4.0.0.0/6, 8.0.0.0/7, 11.0.0.0/8, 12.0.0.0/6, 16.0.0.0/4, 32.0.0.0/3, 64.0.0.0/2, 128.0.0.0/3, 160.0.0.0/5, 168.0.0.0/6, 172.0.0.0/12, 172.32.0.0/11, 172.64.0.0/10, 172.128.0.0/9, 173.0.0.0/8, 174.0.0.0/7, 176.0.0.0/4, 192.0.0.0/9,
192.128.0.0/11, 192.160.0.0/13, 192.169.0.0/16, 192.170.0.0/15, 192.172.0.0/14, 192.176.0.0/12, 192.192.0.0/10, 193.0.0.0/8, 194.0.0.0/7, 196.0.0.0/6, 200.0.0.0/5, 208.0.0.0/4 #Or simply 0.0.0.0/0
Endpoint = 12.13.14.15:51820
None of the keys used here are real and don’t match up if you derive the Public Keys from a given Private key, so don’t be surprised.
Final setup
There are only a few simple steps remaining. Enable your wireguard config on your VPS/Remote host and set it up as a system service so you can sit back and not worry about it.
sudo systemctl enable [email protected]
Bear in mind if you have ufw
or a similar firewall running, you’ll have to create an exception for port 51820
. Do the same on your local router/endpoint that you setup the second config in. You can also find guides to setup this end on pfSense and
OpenWRT pretty
easily on your favourite search engine.
As a last step, make sure you have IPv4 forwarding enabled on your VPS/Remote server and allow a few other tricks for this to work with:
sysctl -w net.ipv4.ip_forward=1
sysctl -w net.ipv4.conf.all.proxy_arp=1
At this point, your tunnel is up and you should be able to reach your Internal network from anywhere in the world using 12.13.14.16
, treating it exactly like you would a routable IP from a normal ISP. This works using a technique called
Proxy ARP which is technically a hack, but it works!.