Deploy a Node#
If you want to run on >1 server, for example to allow for more connections, or to have nodes in multiple locations, you can deploy additional nodes.
Running a node requires to run wg-daemon, and optionally proxyguard-server.
You probably want to configure TLS as well, for which we recommend certbot so
the TLS certificate management can be handled automatically.
The software can be installed from the repository using apt
or dnf. We assume below that you installed the software packages and enabled
them.
On Debian / Ubuntu:
$ sudo apt install wg-daemon proxyguard-server certbot
$ sudo systemctl enable --now wg-daemon
$ sudo systemctl enable --now proxyguard-server
On Fedora / Enterprise Linux:
$ sudo dnf install wg-daemon proxyguard-server certbot
$ sudo systemctl enable --now wg-daemon
$ sudo systemctl enable --now proxyguard-server
NOTE: on Enterprise Linux you need to install the epel-release package
first to have access to EPEL packages which includes certbot.
TLS#
It probably makes sense to first get a TLS key and certificate for your node,
the easiest way is certonly using the “standalone” web server embedded in
certbot:
$ sudo certbot certonly --standalone -d node.vpn.example.org
We’ll use the certificate later on to configure wg-daemon and
proxyguard-server.
wg-daemon#
In order to allow connecting to the wg-daemon service from your portal, you
need to change the configuration. This can be done using systemctl.
$ sudo systemctl edit wg-daemon
Add the following top the top of the file as instructed:
[Service]
Environment=LISTEN=:51194
LoadCredential=fullchain.pem:/etc/letsencrypt/live/node.vpn.example.org/fullchain.pem
LoadCredential=privkey.pem:/etc/letsencrypt/live/node.vpn.example.org/privkey.pem
You SHOULD restrict access to tcp/51194 to only allow connections from your
portal. This can be done by modifying the firewall.
When wg-daemon starts it generates an API key and stores it in
/var/lib/wg-daemon/auth.key. It is a 256 bit Base64 encoded random string.
Use the exact value as the --key parameter in the add-node command below.
proxyguard-server#
$ sudo systemctl edit proxyguard-server
Add the following top the top of the file as instructed:
[Service]
Environment=LISTEN=:443
LoadCredential=fullchain.pem:/etc/letsencrypt/live/node.vpn.example.org/fullchain.pem
LoadCredential=privkey.pem:/etc/letsencrypt/live/node.vpn.example.org/privkey.pem
Portal#
NOTE: make sure you get the trailing / correct for the URLs!
$ sudo /usr/libexec/vpn-mini-portal/add-node \
--name "My Node" \
--url https://node.vpn.example.org:51194/ \
--host node.vpn.example.org \
--proxy-url https://node.vpn.example.org/ \
--key 5BnH5QrzRGxpqrva5oILg12k+9pD9IRjhRRK7rvchFQ=
After running this command, the node should be visible on the “Nodes” pages in the portal admin. Viewing the node details should not show any errors.
TLS Renewal Hook#
If you use certbot, you can install the following hook that gets run after
certificate renewal. It will restart the processes so they’ll use the updated
certificates. This way, you SHOULD not need to ever do something regarding TLS.
$ cat << EOF | sudo tee /etc/letsencrypt/renewal-hooks/post/restart_services.sh
#!/bin/sh
systemctl restart wg-daemon
systemctl restart proxyguard-server
EOF
$ sudo chmod +x /etc/letsencrypt/renewal-hooks/post/restart_services.sh
To enable the timer to automatically renew certificates, only needed on Fedora / Enterprise Linux, run this:
$ sudo systemctl enable --now certbot-renew.timer
Firewall#
Below you’ll find a pretty minimal firewall for running on a node using
nftables. On Debian / Ubuntu you put this file in /etc/nftables.conf. On
Fedora and Enterprise Linux in /etc/sysconfig/nftables.conf. Make sure you
first remove firewalld on Fedora and Enterprise Linux before installing
nftables. Replace ens18 with the external “default gateway” interface of
your VPN server.
#!/usr/sbin/nft -f
flush ruleset
define EXTERNAL_IF = ens18
table inet filter {
chain input {
type filter hook input priority filter; policy drop;
ct state vmap { invalid : drop, established : accept, related : accept }
iif "lo" accept
# we do not use tcp/80, except for certbot DV, but it does not really
# hurt to leave it open
tcp dport { 22, 80, 443 } accept
udp dport { 51820 } accept
# IPs of your portal that need access to wg-daemon
ip saddr 192.0.2.10/32 tcp dport 51194 accept
ip6 saddr 2001:db8::10/128 tcp dport 51194 accept
meta l4proto ipv6-icmp accept
meta l4proto icmp accept
}
chain forward {
type filter hook forward priority filter; policy drop;
tcp flags syn tcp option maxseg size set rt mtu
ct state vmap { invalid : drop, established : accept, related : accept }
iifname { "vpn0" } oifname $EXTERNAL_IF accept
}
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
ip saddr { 10.0.0.0/8 } oifname $EXTERNAL_IF masquerade
ip6 saddr fd00::/8 oifname $EXTERNAL_IF masquerade
}
}
To permanently start/enable nftables:
$ sudo systemctl enable nftables
$ sudo systemctl restart nftables
Now enable IP forwarding for both IPv4 and IPv6. For IPv6 we need to keep
allowing receiving router advertisements (RAs) if that’s how we receive the
IPv6 address on the server from the router. Replace ens18 with the external
“default gateway” interface of your VPN server.
$ cat << EOF | sudo tee /etc/sysctl.d/70-vpn.conf
net.ipv6.conf.ens18.accept_ra = 2
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
EOF
$ sudo sysctl --system