I use a Docker instance for my Wireguard server now.
I use 2 forms of vpn (virtual private network) on my home server.
WireGuard is an extremely simple yet fast and modern VPN that utilizes state-of-the-art cryptography. It aims to be faster, simpler, leaner, and more useful than IPsec, while avoiding the massive headache. It intends to be considerably more performant than OpenVPN. WireGuard is designed as a general purpose VPN for running on embedded interfaces and super computers alike, fit for many different circumstances. Initially released for the Linux kernel, it is now cross-platform (Windows, macOS, BSD, iOS, Android) and widely deployable. It is currently under heavy development, but already it might be regarded as the most secure, easiest to use, and simplest VPN solution in the industry.
I want to setup an access within my Linux router to allow external authorise only VPN access into the system. I proposed to use an entirely separate IP address range for this:
There seem to be a lot of methods to use the Wireguard interface, most of them do not align well with my requirements, specifically for firewall they reference iptables, or UFW, instead of nftables and do not in general seem well setup for router access, also some belabour use of variable IP address on domain names, whereas I have organised a static IP address for my domain, or are not setup to utilise a full manual setup Linux router, using OPNsense, pfsense, OpenWRT or consumer modem/router boxes, etc.
Wireguard is not chatty, this actually is a security feature. It is important that the setup information is done correctly, in particular the private and public keys. Also the allowed ips is important. On the server side it is set to the main VPN ip address. On the client side it needs to be set to include ip addresses that are allowed to be access on the client side. Some tools that help fault find:
sudo tcpdump -i wan_device -c 5 port vpn_port, where wan_device is the wan device, in my case ppp1 and vpn_port is the port number wireguard is set to, in my case 51914, the default is 51820. This lets you see if the packets are coming in to the wan.sudo nft list table inet firewall -a will list my firewall settings.ip daddr 192.168.6.1 udp dport 51914 counter packets 1 bytes 176 accept # handle 29 of the router input indicates that the first packet was allowed to the wireguard vpn, 192.168.6.1:51914. After this the packets are captured stateful statementct state established,related counter packets 31276 bytes 9246975 accept # handle 24.sudo nft list table ip nat -a will list my nat settings.ip daddr 112.213.222.38 udp dport 51914 counter packets 287 bytes 50512 dnat to 192.168.6.1 prerouting shows the incoming wan packet on the vpn port are directed to the vpn server ip address.oifname “ppp1” counter packets 129181 bytes 22662174 masquerade # handle 13 postrouting, the vpn packets from 192.168.6.1 are masqueraded onto the wan.
Installation of Wireguard on Ubuntu 20.04 straight forwards: sudo apt install wireguard
The ability to forward packets must be set / allowed, edit or add the following parameters in sudo vim /etc/sysctl.conf:
After applying these changes reboot or apply setting using sudo sysctl -p /etc/sysctl.conf
Create some security keys:
sudo su cd /etc/wireguard umask 077 wg genkey | tee name_1_privatekey | wg pubkey > name_1_publickey wg genkey | tee name_2_privatekey | wg pubkey > name_2_publickey
Use exit to get out of root access. (I prefer to use sudo instead of going full root.) (In Australia English root has another less savoury meaning….)
Clearly the private key needs to be kept private for security reasons. Also no need to unnecessarily flash around the pubic key in general public.
The above keys are simple files that can be viewed as text using standard utilities, e.g. cat name_1_private_key, etc. Example below (real, but not used):
4G8wilxppYxxMibntzBL6lejypNOxU0NAAMi4/azAlY=n3xKCvYWyosT9yBPLTeCy5M8nWHp2mBJuAz79a4KPAo=
While still in /etc/wireguard in root create a wireguard server configuration file: vim wg0.conf or sudo vim /etc/wireguard/wg0.conf.
[Interface] Address = 192.168.6.1/24 SaveConfig = true PrivateKey = <insert server_private_key> ListenPort = 51914 [Peer] PublicKey = <insert client_public_key> AllowedIPs = 192.168.6.2/32 [Peer] PublicKey = <insert client_public_key> AllowedIPs = 192.168.6.3/32
Obviously the correct private and public key values need to be inserted.
sudo systemctl start wg-quick@wg0sudo systemctl enable wg-quick@wg0sudo systemctl status wg-quick@wg0The Router (server) firewall configuration needs to be adjusted to allow Wireguard to function.
sudo vim /etc/nftables.conf
I have had a lot of difficulties getting Wireguard Running. These are some notes on troubleshooting this issue.
sudo nft list tables → to list active nftablessudo nft list table inet firewall -a → to list contents of tablesudo nft list table ip nat -asudo tcpdump -D to see a list the list interfacesany would look at all the interfacessudo tcpdump -i ppp1 -c 5 port 51914-i ppp1 specifies specific use of interface ppp1-c 5 limits the scan to 5 packets captured, ^C can also exit the scan at any timeport 51914 requires to listen only to port 51914sudo tcpdump -c 5 -i eno1 host 112.213.222.38 and port 51914 to see on specific hostI used my iPhone Wireguard app as the other end. It is important that the app is correctly configured. Also the Persistent keepalive is set a 1 second. As the Wireguard is not very chatty this can make it difficult to error check. The iOS app seems to send 20 keep alive packets waiting 5 seconds for a response after which it stops the keep alive attempts. The iOS VPN for Wireguard seems to immediately fall back from the VPN if a connection is not made.
sudo ip a show wg0 :
14: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
link/none
inet 192.168.6.1/24 scope global wg0
valid_lft forever preferred_lft forever
For some reason my system would not link the IP address even though the wg script was clearly running the commands, sudo systemctl status wg-quick@wg0:
Jul 03 21:25:44 Router systemd[1]: Starting WireGuard via wg-quick(8) for wg0... Jul 03 21:25:44 Router wg-quick[3483]: [#] ip link add wg0 type wireguard Jul 03 21:25:44 Router wg-quick[3483]: [#] wg setconf wg0 /dev/fd/63 Jul 03 21:25:44 Router wg-quick[3483]: [#] ip -4 address add 192.168.6.1/24 dev wg0 Jul 03 21:25:44 Router wg-quick[3483]: [#] ip link set mtu 1420 up dev wg0 Jul 03 21:25:44 Router wg-quick[3483]: [#] ip -4 route add 192.168.6.3/32 dev wg0 Jul 03 21:25:44 Router wg-quick[3483]: [#] ip -4 route add 192.168.6.2/32 dev wg0 Jul 03 21:25:44 Router systemd[1]: Started WireGuard via wg-quick(8) for wg0.
then
sudo ip a show wg0
7: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
link/none
After updating to Debian 11 the following quick fix caused an error so I simply removed and rebooted. PostUp = ip -4 address add 192.168.6.1/24 dev wg0 before PrivateKey to in /etc/wireguard/wg0.conf:
[Interface] Address = 192.168.6.1/24 SaveConfig = true ListenPort = 51914 PrivateKey = censored= [Peer] PublicKey = censored= AllowedIPs = 192.168.6.2/32 Endpoint = 1.127.16.49:8898 [Peer] PublicKey = censored= AllowedIPs = 192.168.6.3/32 Endpoint = 192.168.1.34:63009
My first setup was on my iPhone. There is a specific Wireguard application for the iPhone, which can be downloaded for free from the app store. This application can be manually setup. A private and public key can be made in the app and then the public keys manually transferred between the app to the server. This is where it can get clumsy. Phone interfaces are just not as nice to use as a proper full system with full size screen, keyboard and mouse. In fact, as noted above, this is where I got unstuck early in my tinkering with Wireguard.
Interface_name
[Interface] PrivateKey = <insert server_private_key> [required] Address = 192.168.6.2/32 ListenPort = [optional, if not specified chosen randomly] MTU = [optional] DNS = 192.168.1.1 [Peer] PublicKey = <insert client_public_key> Presharedkey = [optional] AllowedIPs = 0.0.0.0/0 Endpoint = kptree.net:51914 PersistentKeepalive = 25
sudo chown root:baumkp -R /etc/wireguardsudo chmod 770 -R /etc/wireguardWith this I should be able to do all configurations without sudo. All setting the execution bit allows the operation of the qrencode utility.
sudo chown root:root -R /etc/wireguardsudo chmod 600 -R /etc/wireguard
The wireguard configuration file can be made into a QR code:

QR code for wiki.kptree.net can be created with qrencode -s 6 -l H -o “kptree_wiki.png” “https://wiki.kptree.net”
A Wireguard configuration file can be printed to terminal screen with: sudo qrencode -t ansiutf8 </etc/wireguard/clients/kptree_router.mobile1, where:
/etc/wireguard/clients/kptree_router.mobile1 is a valid Wireguard configuration file
Similarly the output can be used to create a picture file: sudo qrencode -t ansiutf8 -o /etc/wireguard/clients/kptree_router.mobile1.png </etc/wireguard/clients/kptree_router.mobile1
An online resource is Cloud Savey How To Create QR Codes From The Linux Command Line
Wikipedia QR code
sudo nft list table inet firewall -asudo nft list table ip nat -asudo nft add set inet firewall tcp_open_ports{type inet_service \; flags interval \;}sudo nft add element inet firewall tcp_open_ports{ssh, http, 60000-61000 }sudo nft delete rule ip nat postrouting handle 24sudo nft add rule inet firewall input handle 25 ip saddr udp dport 51914 counter acceptsudo nft add rule inet firewall input ip saddr udp dport 51914 counter acceptsudo systemctl restart wg-quick@wg0sudo wgwg0: sudo wg show wg0