I use a Docker instance for my Wireguard server now.

I use 2 forms of vpn (virtual private network) on my home server.

  1. VPN to gain remote secure private access to my home LAN from the WAN (internet). This is the one I am describing here.
  2. VPN to anonymize my public internet access, making it more difficult for others to track my online behavior. This is where I describe this VPN setup including nftable force to anonymize WAN usage

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.

My Setup

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:

  • Main home LAN is on 192.168.1.0/24
  • Access to my VDSL modem is on 192.168.5.0/24
  • VPN (Wireguard) LAN range is 192.168.6.0/24

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.

Greatest Difficulties in Setting

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:

  • On the server side: 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.
  • The next is checking the firewall to see if the packets are being directed to the wireguard IP address
    • 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.

Basic Wireguard Installation on Router

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:

  • net.ipv4.ip_forward = 1
  • net.ipv4.conf.all.proxy_arp = 1

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):

  • privatekey: 4G8wilxppYxxMibntzBL6lejypNOxU0NAAMi4/azAlY=
  • publickey: 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.

  • To start/stop the Wireguard service: sudo systemctl start wg-quick@wg0
  • To enable/disable the Wireguard service: sudo systemctl enable wg-quick@wg0
  • To check status of the Wireguard service: sudo systemctl status wg-quick@wg0

Router Firewall changes for Wireguard

The Router (server) firewall configuration needs to be adjusted to allow Wireguard to function.

  1. definitions
    1. define wan = ppp1
    2. define lan = br0
    3. define router_ip4 = 192.168.1.1
    4. define wan_ip4 = 112.213.222.38
    5. define vpn = wg0
    6. define vpn_ip4 = 192.168.6.0/24
    7. define vpn_port = 51914
  2. From external (Internet) to router:
    1. Pin hole fire wall and direct to Wireguard server:
    2. sudo nft add rule ip nat prerouting ip daddr $wan_ip4 udp dport $vpn_port counter dnat to $vpn_ip4
    3. sudo nft add rule inet firewall input iifname $wan dport $vpn_port counter accept
  3. Wireguard server to LAN
    1. Forward from wireguard LAN to general LAN:
    2. sudo nft add rule inet firewall forward iifname $vpn counter accept
    3. sudo nft add rule inet firewall forward ip daddr $vpn_ip4 ct status dnat counter accept
    4. sudo nft add rule inet firewall input iifname $vpn counter accept
  4. From LAN to Wireguard
    1. Forward from general LAN to Wireguard LAN:
    2. sudo nft add rule inet firewall forward oifname $vpn counter accept
  5. From router to to external (Internet)
    1. Mangle or SNAT to internet
    2. sudo nft add rule ip nat postrouting ip saddr $vpn_ip4 oifname $wan counter snat $wan_ip4 (not necessary is already have masquerade on oifname $wan

Full NFTables Code

sudo vim /etc/nftables.conf

''nftables router script''

Wireguard Trouble Shooting

I have had a lot of difficulties getting Wireguard Running. These are some notes on troubleshooting this issue.

  1. Make sure the public keys are properly shared and match the private keys. Wireguard will simply not respond to incorrect information!
  2. Ensure the sure of counter in nftables setup to be able to see the actual packets counted by each nftables chain
  3. Use of the nftables list to list the chains and actual counted packets and bytes
    1. sudo nft list tables → to list active nftables
    2. sudo nft list table inet firewall -a → to list contents of table
    3. sudo nft list table ip nat -a
  4. Use the tcpdump command to see the actual activity on each interface
    1. sudo tcpdump -D to see a list the list interfaces
      1. the interface any would look at all the interfaces
    2. sudo tcpdump -i ppp1 -c 5 port 51914
    3. where:
      1. -i ppp1 specifies specific use of interface ppp1
      2. -c 5 limits the scan to 5 packets captured, ^C can also exit the scan at any time
      3. port 51914 requires to listen only to port 51914
    4. sudo tcpdump -c 5 -i eno1 host 112.213.222.38 and port 51914 to see on specific host

I 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

Client Setup

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

Linux security can be a pain in the arse sometime

To work on Wireguard Configuration files

  • sudo chown root:baumkp -R /etc/wireguard
  • sudo chmod 770 -R /etc/wireguard

With this I should be able to do all configurations without sudo. All setting the execution bit allows the operation of the qrencode utility.

To Leave Wireguard Configuration files Secure, if I remember

  • sudo chown root:root -R /etc/wireguard
  • sudo chmod 600 -R /etc/wireguard

QR codes

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
  • The permissions of the directory in which the file is located allow this.

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

Some NFTables and Wireguard Commands

  • to list table inet firewall with handles: sudo nft list table inet firewall -a
  • To list table ip nat with handles: sudo nft list table ip nat -a
  • To add a set tcp_open_ports in inet firewall: sudo nft add set inet firewall tcp_open_ports{type inet_service \; flags interval \;}
  • To add elements to set tcp_open_ports: sudo nft add element inet firewall tcp_open_ports{ssh, http, 60000-61000 }
  • To delete rule in ip nat postrouting: sudo nft delete rule ip nat postrouting handle 24
  • To add rule to inet firewall input, before handle 25: sudo nft add rule inet firewall input handle 25 ip saddr udp dport 51914 counter accept
  • To append new rule to end of inet firewall input: sudo nft add rule inet firewall input ip saddr udp dport 51914 counter accept
  • To restart wg0 interface: sudo systemctl restart wg-quick@wg0
  • To see status of wireguard: sudo wg
  • To see status of wireguard device wg0: sudo wg show wg0

Docker Wireguard Setup

/app/www/public/data/pages/linux_router/wireguard.txt · Last modified: 2025-05-24 Sat wk21 21:09
CC Attribution-Share Alike 4.0 International Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution-Share Alike 4.0 International