Set Up Your Own WireGuard VPN Server on Debian 11 & Debian 10
This tutorial is going to show you how to set up your own WireGuard VPN server on Debian 11 bullseye and Debian 10 Buster. WireGuard is made specifically for the Linux kernel. It runs inside the Linux kernel and allows you to create fast, modern, and secure VPN tunnel.
Features of WireGuard VPN
- Lightweight and super fast speed, blowing OpenVPN out of the water.
- Cross-platform. WireGuard can run on Linux, BSD, macOS, Windows, Android, iOS, and OpenWRT.
- User authentication is done by exchanging public keys, similar to SSH keys.
- It assigns static tunnel IP addresses to VPN clients. Some folks may not like it, but it can be useful in some cases.
- Mobile devices can switch between Wi-Fi and mobile network seamlessly without dropping any connectivity.
- It aims to replace OpenVPN and IPSec in most use cases.
Requirements
To follow this tutorial, you will need a VPS (Virtual Private Server) that can access blocked websites freely (Outside of your country or Internet filtering system). I recommend Kamatera VPS, which features:
- 30 days free trial.
- Starts at $4/month (1GB RAM)
- High-performance KVM-based VPS
- 9 data centers around the world, including United States, Canada, UK, Germany, The Netherlands, Hong Kong, and Isreal.
Follow the tutorial linked below to create your Linux VPS server at Kamatera.
Once you have a VPS running Debian, follow the instructions below.
This tutorial assumes that the VPN server and VPN client are both running Debian operating system.
Step 1: Install WireGuard on Debian Server and Desktop
Log into your Debian server. WireGuard is included in the Debian 11 (Bullseye) repository, so you can run the following commands to install it.
sudo apt update sudo apt install wireguard wireguard-tools linux-headers-$(uname -r)
Debian 10 users need to add the backport repository with the following command.
echo "deb http://deb.debian.org/debian buster-backports main" | sudo tee /etc/apt/sources.list.d/buster-backports.list
Then install WireGuard.
sudo apt update sudo apt -t buster-backports install wireguard wireguard-tools wireguard-dkms linux-headers-$(uname -r)
Use the same commands to install WireGuard on your local Debian computer (the VPN client). Note that you also need to install the openresolv
package on the client to configure DNS server.
sudo apt install openresolv
Step 2: Generate Public/Private Keypair
Server
Run the following command on the Debian server to create a public/private key pair, which will be saved under /etc/wireguard/
directory.
wg genkey | sudo tee /etc/wireguard/server_private.key | wg pubkey | sudo tee /etc/wireguard/server_public.key
Client
Run the following command to create a public/private key pair on the local Debian computer (the VPN client).
wg genkey | sudo tee /etc/wireguard/client_private.key | wg pubkey | sudo tee /etc/wireguard/client_public.key
Step 3: Create WireGuard Configuration File
Server
Use a command-line text editor like Nano to create a WireGuard configuration file on the Debian server. wg0
will be the network interface name.
sudo nano /etc/wireguard/wg0.conf
Copy the following text and paste it to your configuration file. You need to use your own server private key and client public key.
[Interface] Address = 10.10.10.1/24 ListenPort = 51820 PrivateKey = cD+ZjXiVIX+0iSX1PNijl4a+88lCbDgw7kO78oXXLEc= [Peer] PublicKey = AYQJf6HbkQ0X0Xyt+cTMTuJe3RFwbuCMF46LKgTwzz4= AllowedIPs = 10.10.10.2/32
Where:
- Address: Specify the private IP address of the VPN server. Here I’m using the 10.10.10.0/24 network range, so it won’t conflict with your home network range. (Most home routers use 192.168.0.0/24 or 192.168.1.0/24). 10.10.10.1 is the private IP address for the VPN server.
- PrivateKey: The private key of VPN server, which can be found in the
/etc/wireguard/server_private.key
file on the server. - ListenPort: WireGuard VPN server will be listening on UDP port 51820, which is the default.
- PublicKey: The public key of VPN client, which can be found in the
/etc/wireguard/client_public.key
file on the client computer. - AllowedIPs: IP addresses the VPN client is allowed to use. In this example, the client can only use the 10.10.10.2 IP address inside the VPN tunnel.
Save and close the file. (To save a file in Nano text editor, press Ctrl+O
, then press Enter to confirm. Press Ctrl+X
to exit.)
Change the file permission mode so that only root user can read the files.
sudo chmod 600 /etc/wireguard/ -R
Client
Use a command-line text editor like Nano to create a WireGuard configuration file on your local Debian computer. wg-client0
will be the network interface name.
sudo nano /etc/wireguard/wg-client0.conf
Copy the following text and paste it to your configuration file. You need to use your own client private key and server public key.
[Interface] Address = 10.10.10.2/24 DNS = 10.10.10.1 PrivateKey = cOFA+x5UvHF+a3xJ6enLatG+DoE3I5PhMgKrMKkUyXI= [Peer] PublicKey = kQvxOJI5Km4S1c7WXu2UZFpB8mHGuf3Gz8mmgTIF2U0= AllowedIPs = 0.0.0.0/0 Endpoint = 12.34.56.78:51820 PersistentKeepalive = 25
Where:
- Address: Specify the private IP address of the VPN client.
- DNS: specify 10.10.10.1 (the VPN server) as the DNS server. It will be configured via the
resolvconf
command. You can also specify multiple DNS servers for redundancy like this:DNS = 10.10.10.1 8.8.8.8
- PrivateKey: The client’s private key, which can be found in the
/etc/wireguard/client_private.key
file on the client computer. - PublicKey: The server’s public key, which can be found in the
/etc/wireguard/server_public.key
file on the server. - AllowedIPs: 0.0.0.0/0 represents the whole Internet, which means all traffic to the Internet should be routed via the VPN.
- Endpoint: The public IP address and port number of VPN server. Replace 12.34.56.78 with your server’s real public IP address.
- PersistentKeepalive: Send an authenticated empty packet to the peer every 25 seconds to keep the connection alive. If PersistentKeepalive isn’t enabled, the VPN server might not be able to ping the VPN client.
Save and close the file.
Change the file mode so that only root user can read the files.
sudo chmod 600 /etc/wireguard/ -R
Step 4: Enable IP Forwarding on the Server
In order for the VPN server to route packets between VPN clients and the Internet, we need to enable IP forwarding. Edit sysctl.conf
file.
sudo nano /etc/sysctl.conf
Add the following line at the end of this file.
net.ipv4.ip_forward = 1
Save and close the file. Then apply the changes with the below command. The -p option will load sysctl settings from /etc/sysctl.conf file. This command will preserve our changes across system reboots.
sudo sysctl -p
Step 5: Configure IP Masquerading on the Server
We need to set up IP masquerading in the server firewall, so that the server becomes a virtual router for VPN clients. I will use UFW, which is a front end to the iptables firewall. Install UFW on Debian with:
sudo apt install ufw
First, you need to allow SSH traffic.
sudo ufw allow 22/tcp
Next, find the name of your server’s main network interface.
ip addr
As you can see, it’s named ens3
on my Debian server.
To configure IP masquerading, we have to add iptables command in a UFW configuration file.
sudo nano /etc/ufw/before.rules
By default, there are some rules for the filter
table. Add the following lines at the end of this file. Replace ens3
with your own network interface name.
# NAT table rules
*nat
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -o ens3 -j MASQUERADE
# End each table with the 'COMMIT' line or these rules won't be processed
COMMIT
In Nano text editor, you can go to the end of the file by pressing Ctrl+W
, then pressing Ctrl+V
.
The above lines will append (-A) a rule to the end of of POSTROUTING chain of nat table. It will link your virtual private network with the Internet. And also hide your network from the outside world. So the Internet can only see your VPN server’s IP, but can’t see your VPN client’s IP, just like your home router hides your private home network.
By default, UFW forbids packet forwarding. We can allow forwarding for our private network. Find the ufw-before-forward
chain in this file and add the following 3 lines, which will accept packet forwarding if the source IP or destination IP is in the 10.10.10.0/24
range.
# allow forwarding for trusted network -A ufw-before-forward -s 10.10.10.0/24 -j ACCEPT -A ufw-before-forward -d 10.10.10.0/24 -j ACCEPT
Save and close the file. Then enable UFW.
sudo ufw enable
If you have enabled UFW before, then you can use systemctl to restart UFW.
sudo systemctl restart ufw
Now if you list the rules in the POSTROUTING chain of the NAT table by using the following command:
sudo iptables -t nat -L POSTROUTING
You can see the Masquerade rule.
Step 6: Install a DNS Resolver on the Server
Since we specified the VPN server as the DNS server for client, we need to run a DNS resolver on the VPN server. We can install the bind9 DNS server.
sudo apt install bind9
Once it’s installed, BIND will automatically start. You can check its status with:
systemctl status bind9
Sample output:
● named.service - BIND Domain Name Server Loaded: loaded (/lib/systemd/system/named.service; enabled; vendor preset: enabled) Active: active (running) since Sun 2020-05-17 08:11:26 UTC; 37s ago Docs: man:named(8) Main PID: 13820 (named) Tasks: 5 (limit: 1074) Memory: 14.3M CGroup: /system.slice/named.service └─13820 /usr/sbin/named -f -u bind
If it’s not running, start it with:
sudo systemctl start bind9
Edit the BIND DNS server’s configuration file.
sudo nano /etc/bind/named.conf.options
Add the following line to allow VPN clients to send recursive DNS queries.
allow-recursion { 127.0.0.1; 10.10.10.0/24; };
Save and close the file. Then edit the /etc/default/named
files.
sudo nano /etc/default/named
Add -4
to the OPTIONS
to ensure BIND can query root DNS servers.
OPTIONS="-u bind -4"
Save and close the file.
By default, BIND enables DNSSEC, which ensures that DNS responses are correct and not tampered with. However, it might not work out of the box due to trust anchor rollover and other reasons. To make it work properly, we can rebuild the managed key database with the following commands.
sudo rndc managed-keys destroy sudo rdnc reconfig
Restart BIND9 for the changes to take effect.
sudo systemctl restart bind9
Then you need to run the following command to allow VPN clients to connect to port 53.
sudo ufw insert 1 allow in from 10.10.10.0/24
Step 7: Open WireGuard Port in Firewall
Run the following command to open UDP port 51820 on the server.
sudo ufw allow 51820/udp
Step 8: Start WireGuard
server
Run the following command on the server to start WireGuard.
sudo wg-quick up /etc/wireguard/wg0.conf
To stop it, run
sudo wg-quick down /etc/wireguard/wg0.conf
You can also use systemd service to start WireGuard.
sudo systemctl start [email protected]
Enable auto-start at system boot time.
sudo systemctl enable [email protected]
Check its status with the following command. Its status should be active (exited)
.
systemctl status [email protected]
Now WireGuard server is ready to accept client connections.
Client
Start WireGuard.
sudo systemctl start [email protected]
Enable auto-start at system boot time.
sudo systemctl enable [email protected]
Check its status:
systemctl status [email protected]
Now go to this website: http://icanhazip.com/
to check your public IP address. If everything went well, it should display your VPN server’s public IP address instead of your client computer’s public IP address.
You can also run the following command to get the current public IP address.
curl https://icanhazip.com
Troubleshooting Tips
Check if UDP port 51820 is open
Install the tshark
network traffic analyzer on the server. Tshark is the command-line version of Wireshark.
sudo apt install tshark
If you are asked “Should non-superusers be able to capture packets?”, answer Yes. Once it’s installed, run the following command to add your user account to the wireshark
group so that you can capture packets.
sudo adduser your-username wireshark
Then, start tshark to capture packets on UDP port 51820. Replace ens3
with your main network interface.
tshark -i ens3 -f "udp port 51820"
If the WireGuard client is able to connect to UDP port 51820 of the server, then you will see packets being captured by tshark like below. As you can see, the client started the handshake initiation, and the server sent back a handshake response. Once the connection is established, the client sends keepalive packets.
Capturing on 'ens3' ** (tshark:902085) 02:47:41.865227 [Main MESSAGE] -- Capture started. ** (tshark:902085) 02:47:41.866056 [Main MESSAGE] -- File: "/tmp/wireshark_eth0JVEWT1.pcapng" 1 105.092578905 11.22.33.44 → 12.34.56.78 WireGuard 190 Handshake Initiation, sender=0x3F1A04AB 2 110.464628716 12.34.56.78 → 11.22.33.44 WireGuard 134 Handshake Response, sender=0x34ED7471, receiver=0xD4B23800 3 110.509517074 11.22.33.44 → 12.34.56.78 WireGuard 74 Keepalive, receiver=0x34ED7471, counter=0
If the WireGuard client can not conenct to UDP port 51820 of the server, then you will only see handshake initiation packets. There’s no handshake respsone.
Capturing on 'ens3' ** (tshark:902085) 02:47:41.865227 [Main MESSAGE] -- Capture started. ** (tshark:902085) 02:47:41.866056 [Main MESSAGE] -- File: "/tmp/wireshark_eth0JVEWT1.pcapng" 1 105.092578905 11.22.33.44 → 12.34.56.78 WireGuard 190 Handshake Initiation, sender=0x3F1A04AB 2 149.670118573 11.22.33.44 → 12.34.56.78 WireGuard 190 Handshake Initiation, sender=0x7D584974 3 152.575188680 11.22.33.44 → 12.34.56.78 WireGuard 190 Handshake Initiation, sender=0x8D2407B9 4 153.706876729 12.34.56.78 → 11.22.33.44 WireGuard 190 Handshake Initiation, sender=0x47690027 5 154.789959772 11.22.33.44 → 12.34.56.78 WireGuard 190 Handshake Initiation, sender=0x993232FC 6 157.956576772 11.22.33.44 → 12.34.56.78 WireGuard 190 Handshake Initiation, sender=0x06AD433B 7 159.082825929 12.34.56.78 → 11.22.33.44 WireGuard 190 Handshake Initiation, sender=0x8C089E1
Ping test
You can ping from the VPN server to VPN client (ping 10.10.10.2
) to see if the tunnel works. If you see the following error message in the ping,
ping: sendmsg: Required key not available
it might be that the AllowedIPs
parameter is wrong, like a typo.
If the ping error message is
ping: sendmsg: Destination address required
it could be that the private/public key is wrong in your config files.
Not able to browse the Internet
If the VPN tunnel is successfully established, but the client public IP address doesn’t change, that’s because the masquerading or forwarding rule in your UFW config file is not working. I once had a typo in the /etc/ufw/before.rules
file, which caused my computer not to be able to browse the Internet.
Note that I don’t recommend using SaveConfig=true
in the [Interface]
section of the WireGuard configuration file. SaveConfig
tells WireGuard to save the runtime configuration on shutdown. So if you add additional [Peer]
in the configuration file and then restart WireGuard, your newly-added configs will be overwritten.
Enable Debug logging in Linux Kernel
If you use Linux kernel 5.6+, you can enable debug logging for WireGuard with the following command.
sudo su - echo module wireguard +p > /sys/kernel/debug/dynamic_debug/control
Then you can view the debug logs with
sudo dmesg -wH
or
sudo journalctl -kf
Restart
If your VPN still doesn’t work, try restarting the VPN server.
sudo systemctl restart [email protected]
Then stop the VPN client.
sudo systemctl stop [email protected]
And upgrade software packages on the VPN client.
sudo apt update; sudo apt upgrade
Next, reboot the VPN client.
sudo shutdown -r now sudo systemctl start [email protected]
Adding Additional VPN Clients
WireGuard is designed to associate one IP address with one VPN client. To add more VPN clients, you need to create a unique private/public key pair for each client, then add each VPN client’s public key in the server’s config file (/etc/wireguard/wg0.conf
) like this:
[Interface] Address = 10.10.10.1/24 PrivateKey = UIFH+XXjJ0g0uAZJ6vPqsbb/o68SYVQdmYJpy/FlGFA= ListenPort = 51820 [Peer] PublicKey = 75VNV7HqFh+3QIT5OHZkcjWfbjx8tc6Ck62gZJT/KRA= AllowedIPs = 10.10.10.2/32 [Peer] PublicKey = YYh4/1Z/3rtl0i7cJorcinB7T4UOIzScifPNEIESFD8= AllowedIPs = 10.10.10.3/32 [Peer] PublicKey = EVstHZc6QamzPgefDGPLFEjGyedJk6SZbCJttpzcvC8= AllowedIPs = 10.10.10.4/32
Each VPN client will have a static private IP address (10.10.10.2, 10.10.10.3, 10.10.10.4, etc). Restart the WireGuard server for the changes to take effect.
sudo systemctl restart [email protected]
Then add WireGuard configuration on each VPN client as usual.
Configure VPN Client on iOS/Andorid
Since I have an iPhone, I will show you how to configure WireGuard client on iOS. Install the WireGuard app from the App store. Then open this app and click the Add a tunnel button.
You have 3 methods to create a new WireGuard tunnel.
- create from file or archive
- create from QR code
- Create from scratch
Choose the QR code method, since it’s easier. Run the following command on the server to generate a WireGuard public/private key for the iOS client.
wg genkey | sudo tee /etc/wireguard/ios_private.key | wg pubkey | sudo tee /etc/wireguard/ios_public.key
Next, create a WireGuard config file for the iOS client.
sudo nano /etc/wireguard/ios.conf
Add the following lines.
[Interface] Address = 10.10.10.3/24 DNS = 10.10.10.1 PrivateKey = mNiZvB+sASN/+ZiJkMyan1ZZOzCXkrjYPlbg7rZJ7Fc= [Peer] PublicKey = OMaXX7XD+wEYWfYyFcZZBN4vFSC16A1e8t80ONiJKWY= AllowedIPs = 0.0.0.0/0 Endpoint = 12.34.56.78:51820 PersistentKeepalive = 25
Where:
- Address: Specify the private IP address for the iOS client.
- DNS: specify 10.10.10.1 (the VPN server) as the DNS server. You can also specify multiple DNS servers for redundancy like this:
DNS = 10.10.10.1,8.8.8.8
. Note that the iOS app doesn’t support theDNS = 10.10.10.1 8.8.8.8
syntax. - PrivateKey: The iOS client’s private key, which can be found in the
/etc/wireguard/ios_private.key
file. - PublicKey: The server’s public key, which can be found in the
/etc/wireguard/server_public.key
file on the server. - AllowedIPs: 0.0.0.0/0 represents the whole Internet, which means all traffic to the Internet should be routed via the VPN.
- Endpoint: The public IP address and port number of VPN server. Replace 12.34.56.78 with your server’s real public IP address.
- PersistentKeepalive: Send an authenticated empty packet to the peer every 25 seconds to keep the connection alive. If PersistentKeepalive isn’t enabled, the VPN server might not be able to ping the VPN client.
Save and close the file. Then run the following command on the WireGuard VPN server to generate a QR code from the iOS config file.
sudo apt install qrencode sudo cat /etc/wireguard/ios.conf | qrencode -t ansiutf8
Next, scan a QR code from the iOS WireGuard app, so the content in the /etc/wireguard/ios.conf
file will be imported to the WireGuard iOS client.
Once the tunnel is added on the iOS client, we also need to add a [peer]
in the WireGaurd server config file.
sudo nano /etc/wireguard/wg0.conf
Like this:
[Interface] Address = 10.10.10.1/24 PrivateKey = UIFH+XXjJ0g0uAZJ6vPqsbb/o68SYVQdmYJpy/FlGFA= ListenPort = 51820 [Peer] PublicKey = 75VNV7HqFh+3QIT5OHZkcjWfbjx8tc6Ck62gZJT/KRA= AllowedIPs = 10.10.10.2/32 [Peer] # iOS client PublicKey = YYh4/1Z/3rtl0i7cJorcinB7T4UOIzScifPNEIESFD8= AllowedIPs = 10.10.10.3/32
Save and close the file. Then restart the WireGuard VPN server.
sudo systemctl restart [email protected]
Now you can establish WireGuard VPN connection from the iOS app.
Configure Windows Client
Download the WireGuard installer for Windows.
Once it’s installed, start the WireGuard program. You need to right-click on the left sidebar to create a new empty tunnel. It will automatically create a public/private key for the Windows client.
Now you need to add other information.
[Interface] PrivateKey = mNiZvB+sASN/+ZiJkMyan1ZZOzCXkrjYPlbg7rZJ7Fc= Address = 10.10.10.4/24 DNS = 10.10.10.1 [Peer] # VPN server PublicKey = OMaXX7XD+wEYWfYyFcZZBN4vFSC16A1e8t80ONiJKWY= AllowedIPs = 0.0.0.0/0 Endpoint = 12.34.56.78:51820 PersistentKeepalive = 25
Where:
- Address: Specify the private IP address for the Windows client.
- DNS: specify 10.10.10.1 (the VPN server) as the DNS server. You can also specify multiple DNS servers for redundancy like this:
DNS = 10.10.10.1,8.8.8.8
. Note that the Windows app doesn’t support theDNS = 10.10.10.1 8.8.8.8
syntax. - PrivateKey: The Windows client’s private key, which is automatically created.
- PublicKey: The server’s public key, which can be found in the
/etc/wireguard/server_public.key
file on the server. - AllowedIPs: 0.0.0.0/0 represents the whole Internet, which means all traffic to the Internet should be routed via the VPN.
- Endpoint: The public IP address and port number of VPN server. Replace 12.34.56.78 with your server’s real public IP address.
- PersistentKeepalive: Send an authenticated empty packet to the peer every 25 seconds to keep the connection alive. If PersistentKeepalive isn’t enabled, the VPN server might not be able to ping the VPN client.
Hint: On Windows, you can use the PowerShell program to SSH into your Linux server.
Save the configuration.
Once the tunnel is added on the Windows client, we also need to add a [peer]
in the WireGaurd server config file.
sudo nano /etc/wireguard/wg0.conf
Like this:
[Interface] Address = 10.10.10.1/24 PrivateKey = UIFH+XXjJ0g0uAZJ6vPqsbb/o68SYVQdmYJpy/FlGFA= ListenPort = 51820 [Peer] PublicKey = 75VNV7HqFh+3QIT5OHZkcjWfbjx8tc6Ck62gZJT/KRA= AllowedIPs = 10.10.10.2/32 [Peer] # iOS client PublicKey = YYh4/1Z/3rtl0i7cJorcinB7T4UOIzScifPNEIESFD8= AllowedIPs = 10.10.10.3/32 [Peer] # Windows client PublicKey = wJpwC/gCWXZTGa5lQReKowRvymaaEUav0N1qeK74HlQ= AllowedIPs = 10.10.10.4/32
Save and close the file. Then restart the WireGuard VPN server.
sudo systemctl restart [email protected]
Now you can establish WireGuard VPN connection on Windows.
Policy Routing, Split Tunneling & VPN Kill Switch
Now I will show you how to use policy routing, split tunneling, and VPN kill switch with WireGuard VPN. Note that it’s not recommended to use them in conjunction with each other. If you use policy routing, then you should not enable split tunneling or VPN kill switch, and vice versa.
Policy Routing
By default, all traffic on the VPN client will be routed through the VPN server. Sometimes you may want to route only a specific type of traffic, based on the transport layer protocol and the destination port. This is known as policy routing.
Policy routing is configured on the client computer, and we need to stop the WireGuard client process.
sudo systemctl stop [email protected]
Then edit the client configuration file.
sudo nano /etc/wireguard/wg-client0.conf
For example, if you add the following 3 lines in the [interface]
section, then WireGuard will create a routing table named “1234” and add the ip rule into the routing table. In this example, traffic will be routed through VPN server only when TCP is used as the transport layer protocol and the destination port is 25, i.e, when the client computer sends emails.
Table = 1234 PostUp = ip rule add ipproto tcp dport 25 table 1234 PreDown = ip rule delete ipproto tcp dport 25 table 1234
Save and close the file. Then start WireGuard client again.
sudo systemctl start [email protected]
Split Tunneling
By default, all traffic on the VPN client will be routed through the VPN server. Here’s how to enable split tunneling, so only traffic to the 10.10.10.0/24
IP range will be tunneled through WireGuard VPN. This is useful when you want to build a private network for several cloud servers, because VPN clients will run on cloud servers and if you use a full VPN tunnel, then you will probably lose connection to the cloud servers.
Edit the client configuration file.
sudo nano /etc/wireguard/wg-client0.conf
Change
AllowedIPs = 0.0.0.0/0
To
AllowedIPs = 10.10.10.0/24
So traffic will be routed through VPN only when the destination address is in the 10.10.10.0/24 IP range. Save and close the file. Then restart WireGuard client.
sudo systemctl restart [email protected]
VPN Kill Switch
By default, your computer can access the Internet via the normal gateway when the VPN connection is disrupted. You may want to enable the kill switch feature, which prevents the flow of unencrypted packets through non-WireGuard interfaces.
Stop the WireGuard client process.
sudo systemctl stop [email protected]
Edit the client configuration file.
sudo nano /etc/wireguard/wg-client0.conf
Add the following two lines in the [interface]
section.
PostUp = iptables -I OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT PreDown = iptables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT
Like this:
[Interface] Address = 10.10.10.2/24 DNS = 10.10.10.1 PrivateKey = cOFA+x5UvHF+a3xJ6enLatG+DoE3I5PhMgKrMKkUyXI= PostUp = iptables -I OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT PreDown = iptables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT [Peer] PublicKey = kQvxOJI5Km4S1c7WXu2UZFpB8mHGuf3Gz8mmgTIF2U0= AllowedIPs = 0.0.0.0/0 Endpoint = 12.34.56.78:51820 PersistentKeepalive = 25
Save and close the file. Then start the WireGuard client.
sudo systemctl start [email protected]
Installing Linux Kernel 5.x on Debian 10
The current Linux kernel version on Debian 10 is 4.19. In step 1, we added the backport repository on Debian 10. The backport repository includes Linux kernel 5.10, at the time of this writting. You may probably know that the wireguard module is included in the Linux kernel starting from version 5.4. If we install Linux kernel 5.10 on Debian 10, we don’t need to build the wireguard module when the system is upgrading the Linux kernel. As a matter of fact, my Debian 10 server once had a problem in building the wireguard module with wireguard-dkms.
Note that by the time you read this article, the Debian 10 backport repository might have removed kernel 5.10 and included kernel 5.11. Simply repalce 5.8 with 5.9 in the following commands.
To install Linux kernel 5.8 on Debian 10 cloud servers, run the following command.
sudo apt install linux-image-5.10.0-0.bpo.7-cloud-amd64 linux-headers-5.10.0-0.bpo.7-cloud-amd64
To install Linux kernel 5.8 on a Debian 10 PC, run the following command.
sudo apt install linux-image-5.10.0-0.bpo.7-amd64 linux-headers-5.10.0-0.bpo.7-amd64
Then restart your Debian 10 box.
sudo shutdown -r now
Check your Linux kernel version.
uname -r
Sample output
5.10.0-0.bpo.7-cloud-amd64
Although we no longer need the wireguard-dkms
package, it’s a dependency for the wireguard
package, so we can’t remove it from the system. You will probably see the following error when upgrading the wireguard
package.
Error! The dkms.conf for this module includes a BUILD_EXCLUSIVE directive which does not match this kernel/arch. This indicates that it should not be built
This indicates wireguard-dkms
is trying to build the wireguard
module into the Linux kernel, but Linux 5.10 includes a native wireguard
module, so the build operation is prevented and you can ignore this error.
Wrapping Up
That’s it! I hope this tutorial helped you install and configure WireGuard on Debian. As always, if you found this post useful, then subscribe to our free newsletter to get more tips and tricks 🙂
Thanks for the lovely tutorial…
Could you also include how to configure SPLIT TUNNELING so that you can configure certain services through VPN and rest of it through your ISP ?
I think the “policy routing” in this article is what you want with split tunneling by services. You just need to adjust the protocol type and destination port.
If you need split tunneling by IP addresses like in a typical corporate environment, edit the client configuration file.
Change
To
So traffice will be routed through VPN only when the destination address is in the 10.10.10.0/24 network range.
Save and close the file. Then restart WireGuard client.
Note that it’s generally not a good idea to use split tunneling and policy routing at the same time. When using policy routing, the
AllowedIPs
should be set to0.0.0.0/0
.Does WireGuard work in China? What other than OpenConnect work in China?
Did you compare the speed of the two?
Thanks.
Yes, it works in China.
WireGuard is super fast, no doubt about it. OpenConnect VPN is very fast too, when you enable the TCP BBR algorithm. Actually you have to disable UDP in OpenConnect and use TCP only, because the Great Firewall of China (GFW) blocks DTLS connections.
When it comes to speed, it doesn’t make much difference by switching to WireGuard, because of the bad network connection from China to the international Internet. The maximum download speed at my home is capped around 16Mbit/s, when downloading files from a server outside of China, though my ISP provides me with 100Mbit/s bandwidth.
WireGuard can be easily identified by GFW, so it might be blocked at any time. OpenConnect VPN looks like normal HTTPS connection, so I prefer to use OpenConnect VPN to bypass GFW and use WireGuard for other use cases.
Thanks for explaining all that. I think there’s no need for WireGuard in countries where vpn can be blocked like China, Middle East, Iran, etc… OpenConnect is still the way to go. What do you think? Should we have both setup on the server?
I’m going to set up a remote desktop to bypass GFW. I will use the Guacamole software, which allows you to type an URL in the web browser and use the remote desktop. No other software is needed on the client computer, and the traffic is identical to HTTPS.
If you forget to install the kernel headers for your new 4.x kernel before updating to it with apt, the update of wireguard-dkms will fail. To fix this, this is what you do:
1. Reboot to run the new kernel version.
2. sudo apt-get install linux-headers-$(uname -r)
3. sudo dpkg-reconfigure wireguard-dkms
4. Reboot
with this line at the # NAT table rules in /etc/ufw/before.rules
seems to cause this
So I commented that line out and ufw enable works.
should *nat be something else?
The instructions in this article are correct. Maybe you put
*nat
in the wrong place. It should not be placed inside thefilter
table.nat
is a table of its own. Each table should be ended with aCOMMIT
line.Please check the screenshot in the article.
putting the *nat rule after the last COMMIT line fixed my error. thank you for the help.
I configured unbound on top of pihole on my RPI4 running Debian 11.
What do i have to do in Step 6 ?
Thanks for this article! I think there is a small error: In “Step 3: Create WireGuard Configuration File”, “Server”:
AllowedIPs = 10.10.10.2/32
and in the same section, under “Client”:
Address = 10.10.10.2/24
I think these must actually match? I got an error “wireguard: wg0: Invalid handshake initiation from XXX:YY” in dmesg. After changing AllowedIPs to 10.10.10.2/24 in the server’s config file, the tunnel worked for me.
Actually, I think you probably want 10.10.10.2/32 both for AllowedIPs on the server and for Address on the client, right?
Best tutorial I’ve ever read regarding wireguard.
Install on Armbian.
Instructions are clear and .. efficient : worked on first start, just as expected.
Thanks, Linuxbabe!!
It’s not routing IPv6, only IPv4. “curl -L ip4.me” is OK, but not “curl -L ip6.me”.
A reddit example has IPv6 network added to config:
—
[Interface]
Address = 10.7.0.36/24, fddd:2c4:2c4:2c4::36/64
DNS = 45.67.219.208, 5.2.75.75
PrivateKey = Key
PostUp = iptables -I OUTPUT ! -o %i -m mark ! –mark $(wg show %i fwmark) -m addrtype ! –dst-type LOCAL -j REJECT && ip6tables -I OUTPUT ! -o %i -m mark ! –mark $(wg show %i fwmark) -m addrtype ! –dst-type LOCAL -j REJECT
PreDown = iptables -D OUTPUT ! -o %i -m mark ! –mark $(wg show %i fwmark) -m addrtype ! –dst-type LOCAL -j REJECT && ip6tables -D OUTPUT ! -o %i -m mark ! –mark $(wg show %i fwmark) -m addrtype ! –dst-type LOCAL -j REJECT
[Peer]
PublicKey = Key
PresharedKey = Key
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = IP
PersistentKeepalive = 25
—
Please add IPv6 to the tutorial LinuxBabe.
Great tutorial.
Thank you very much
I only could reach internet by a client connection after adding the above rules on server
sudo ufw allow 80
sudo ufw allow 443
Kind regards
Great tutorial. Crystal clear, concise and precise.
-One minuscule and obvious correction :
sudo rndc managed-keys destroy
sudo rdnc reconfig
-should obviously read rndc on the 2nd line
Thank you so much again !
Thanks for the detailed writeup. I’m getting the following error from one of the ufw commands.
The working command is
Does WireGuard work in Iran?