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@wg0
sudo systemctl enable wg-quick@wg0
sudo systemctl status wg-quick@wg0
The 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 -a
sudo 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/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.
sudo chown root:root -R /etc/wireguard
sudo 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 -a
sudo nft list table ip nat -a
sudo 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 24
sudo nft add rule inet firewall input handle 25 ip saddr udp dport 51914 counter accept
sudo nft add rule inet firewall input ip saddr udp dport 51914 counter accept
sudo systemctl restart wg-quick@wg0
sudo wg
wg0
: sudo wg show wg0