This guide is designed to walk through the basic steps and configurations needed to:
Connect Multiple LANs together via a centralized Wireguard server.
Expose services running on the LANs to the internet via the centralized server.
Why use a centralized server for connecting LANs rather than a site to site VPN?
Why use a centralized VPS to expose LAN services to the internet?
VPS1 - Wireguard Server and the server we will be using to expose services on LAN1 to the internet.
VPS2 - Another VPS - added to allow easy access and remove some public ports.
VPS3 - Another VPs - added to allow easy access and remove some public ports.
LAN1 - Home LAN
LAN2 - Work LAN
VPS1 runs Wireguard Server and uses Nginx Proxy Manager for forwarding services across Wireguard network to servers on LAN1.
LAN1 and LAN2 each have a server acting as the Wireguard gateway.
Wireguard Network:
VPS1: 10.0.0.1
LAN1: 10.0.0.2
LAN2: 10.0.0.3
VPS2: 10.0.0.10
VPS3: 10.0.0.11
LAN1:
Subnet: 192.168.100.0\24
Router: 192.168.100.1
WG PC: 192.168.100.4
Static Routes:
10.0.0.0\24 GW 192.168.100.4
192.168.150.0\24 GW 192.168.100.4
LAN2:
Subnet: 192.168.150.0\24
Router: 192.168.150.1
WG PC: 192.168.150.4
Static Routes:
10.0.0.0\24 GW 192.168.150.4
192.168.100.0\24 GW 192.168.150.4
Install Wireguard on the server and all clients.
On Linux distributions this is generally a package named wireguard, wireguard-tools, or both.
(I'm using Debian on my servers and clients, so you may need to adjust accordingly)
Generate the public and private key for the machine:
wg genkey | tee privatekey | wg pubkey > publickey
For gateways PCs and likely server if you don't already have it setup for serving services:
Edit /etc/sysctl.conf
Uncomment or add:
net.ipv4.ip_forward=1
Reload the config:
sysctl --system
Create /etc/wireguard/wg0.conf on each machine:
[Interface] Address = 10.0.0.1/32 ListenPort = 51820 PrivateKey = <server private key> # LAN1 WG PC (home) [Peer] PublicKey = <LAN1 WG PC Public Key> AllowedIPs = 10.0.0.2/32, 192.168.100.0/24 # LAN2 WG PC (work) [Peer] PublicKey = <LAN2 WG PC Public Key> AllowedIPs = 10.0.0.3/32, 192.168.150.0/24 # VPS2 [Peer] PublicKey = <VPS2 Public Key> AllowedIPs = 10.0.0.10/32 # VPS3 [Peer] PublicKey = <VPS3 Public Key> AllowedIPs = 10.0.0.11/32
[Interface] Address = 10.0.0.2/32 PrivateKey = <LAN1 WG PC Private Key> PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o <LAN interface, i.e. eth0> -j MASQUERADE PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o <LAN interface, i.e. eth0> -j MASQUERADE # Server [Peer] PublicKey = <VPS1 Public Key> Endpoint = <VPS1 Public IP>:51820 AllowedIPs = 10.0.0.0/24, 192.168.150.0/24 PersistentKeepalive = 25
[Interface] Address = 10.0.0.3/32 PrivateKey = <LAN2 WG PC Private Key> PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o <LAN interface, i.e. eth0> -j MASQUERADE PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o <LAN interface, i.e. eth0> -j MASQUERADE # Server [Peer] PublicKey = <VPS1 Public Key> Endpoint = <VPS1 Public IP>:51820 AllowedIPs = 10.0.0.0/24, 192.168.100.0/24 PersistentKeepalive = 25
[Interface] Address = 10.0.0.10/32 PrivateKey = <VPS2 Private Key> # Server [Peer] PublicKey = <VPS1 Public Key> Endpoint = <VPS1 Public IP>:51820 AllowedIPs = 10.0.0.0/24, 192.168.100.0/24, 192.168.150.0/24 PersistentKeepalive = 25
[Interface] Address = 10.0.0.11/32 PrivateKey = <VPS3 Private Key> # Server [Peer] PublicKey = <VPS1 Public Key> Endpoint = <VPS1 Public IP>:51820 AllowedIPs = 10.0.0.0/24, 192.168.100.0/24, 192.168.150.0/24 PersistentKeepalive = 25
The AllowedIPs directive specifies what networks the machine will allow to enter the Wireguard interface.
For CLIENTS you want with this to be the Wireguard network (10.0.0/24), and any REMOTE networks they will interact with (So in the case of LAN1 WG PC, you add 192.168.150.0/24 to allow routing to/from LAN2).
For SERVERS you want the Wireguard IP of the client (So 10.0.0.2/32 for LAN1 WG PC) and any networks that will route THROUGH that client (So 192.168.100.0/24 for LAN1 WG PC).
The basic principle here is to allow the Wireguard network and local server to communicate with each other so traffic will actually flow and so you can forward services to the Wireguard network.
I use the Shorewall firewall on my VPS, so that's the examples I'll have here. You should be able to accomplish the same thing with the appropriate UFW or IPTABLES commands.
You should only need to do this on the VPSs, unless you run local firewalls on the LAN WG PCs as well.
net eth0 dhcp,tcpflags,logmartians,nosmurfs,sourceroute=0 vpn wg0 routeback
fw firewall net ipv4 vpn ipv4
$FW net ACCEPT $FW vpn ACCEPT vpn all ACCEPT net all DROP info all all REJECT info
?SECTION NEW # Wireguard ACCEPT net fw udp 51820
Make sure you've restarted the firewall services if necessary, then start Wireguard:
wg-quick up wg0
You should see it bring up the interface and add routes and whatnot.
To view the status run:
wg show
On clients this should show the connection information and stats.
On the server it should have a section for each client. It will show configured clients that aren't connected as well, but with minimal information.
Make sure you can ping the Wireguard IPs back and forth from clients to server and clients to other clients.
Once you have verified, you can configure the system to automatically start the connection on boot“
systemctl enable wg-quick@wg0
To enable proper cross LAN routing, and access to the Wireguard network from machines other than the gateway PCs, you need to add the appropriate static routes.
I'm using UniFi USG Pro's on my home and work LANs, so I just added the routes there.
You need a route for each remote network (including the Wireguard network) that the machines on your LAN will be accessing.
In our case, LAN1 needs access to Wireguard Network and LAN2, and LAN2 needs access to Wireguard network and LAN1.
10.0.0.0/24 GW 192.168.100.4 192.168.150.0/24 GW 192.168.100.4
10.0.0.0/24 GW 192.168.150.4 192.168.100.0/24 GW 192.168.150.4
If everything is correct, machines on each LAN should be able to access all machines on the Wireguard network as well as all machines on the other LAN.
Now that we have a nice hub and spoke Wireguard network, we want to expose some services on LAN1 to the outside world.
We will do this using Nginx Proxy Manager (NPM).
This is a relatively easy to setup and use reverse proxy program.
Side Note: If all you want to expose are http/https services, you may want to explore Cloudflare Tunnels. They are fairly simple to setup and in my small amount of testing seem to work well. However, they do not support non-http/https services - to do that you apparently need their WARP client on every machine exposing a non-http/https service, so I didn't explore that option much due to the number of servers I needed to expose, some of which I can't install anything on anyway.
Pull up the Official Guide to follow, but with a couple key changes to the docker-compoose.yml file:
This will cause the docker container to use the host network instead of the docker bridge network.
If you use the docker bridge network, you'll have to:
NPM is fairly straightforward to use, but there's a few things to be aware of in this use case.
1. Each port you want NPM to handle needs to be open on the firewall, so you need to add the appropriate rules.
Web hosting is the obvious example (and primary focus of NPM)
Another would be opening an OpenVPN server on your LAN for remote connections by your phone/laptop/etc.
Shorewall example rules:
ACCEPT net fw tcp 80 ACCEPT net fw tcp 443 ACCEPT net fw udp 1194
2. Web services (Proxy Hosts) need a hostname and ideally an SSL Certificate.
In my case I have a specific domain that I use for external access services, but you could just use subdomains of any domain you control.
The general process is to point a subdomain to the IP of the VPS, create the forwarding host in NPM, and have NPM use LetsEncrypt to generate an SSL certificate for it.
The LetsEncrypt client supports a number of verification methods, including DNS based verification. If you are using a supported DNS manager this makes things fairly easy.
Since I use a dedicated domain for my public access hosts, I moved the DNS management of that domain to Cloudflare and had NPM use DNS verification with LetsEncrypt via the Cloudflare API plugin to generate a wildcard cert for my domain so I don't have to generate a new cert for each subdomain - I just add the DNS entry for the new subdomain then configure the host in NPM using the existing certificate.
3. For non-http/https services, you configure Streams - these are tied only to the port, not to a specific hostname, so any hostname pointing at the VPS will work (or just use the public IP).
So for our example lets create a Proxy host using the domain home.mydomain.com, that points to our home web on LAN1 at IP 192.168.100.10.
You can also manage and request certs from the SSL Certificates section.
If everything worked correctly and is configured correctly, you should be able to browse to home.mydomain.com from outside your LAN.
Now for the OpenVPN connection:
Let's say our OpenVPN server is on Lan1 at 192.168.100.15.
If everything is configured correctly, your OpenVPN client should now be able to connect from outside your network by pointing it to the VPS IP address (or an associated hostname).
So that's a general guide to how I set this up for myself. Most of it is fairly straightforward once you figure it out.
It took me a few days and lots of searching and testing and pestering friends to get it all working how I wanted, so I thought a write up would be helpful.