abstract: Setting up your own vpn using wireguard and a Debian 11 server in the cloud
This tutorial largely stolen from Linuxbabe It is slightly more up to date than her version at the time of writing.
Openvpn uses ssl, (not to be confused with ssh) Wireguard uses algorithms and code developed by privacy advocates. SSL has numerous well known vulnerabilities, notably that it is subject to active attack by any group that has a CA in its pocket. The NSA has a passive attack, which is not understood, but OpenSSL has an enormous codebase, that is impossible to audit with an architecture that seems designed for hiding obfuscated vulnerabilities, and NSA has contributed much to its codebase through innumerable proxies, who are evasive when I talk to them.
Wireguard uses cryptographic libraries developed by our allies, rather than our enemies.
Wireguard is lightweight and fast, blowing OpenVPN out of the water.
Openvpn is a gigantic pile of code, a maze of strange architectural decisions that slow things down, which vast complicated pile of incomprehensible things seem to be to provide no useful purpose other than places to hide backdoors in.
Wireguard is open source and and 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.
Assigns static tunnel IP addresses to VPN clients.
Mobile devices can switch between Wi-Fi and mobile network seamlessly without dropping any connectivity.
Supercedes OpenVPN and IPSec, which are obsolete and insecure.
I assume you have a host in the cloud, with world accessible network address and ports, that can access blocked websites freely outside of your country or Internet filtering system.
We are going to enable ip4 and ipv6 on our vpn. The tutorial assumes ipv6 is working. Check that it is working by pinging your server ping -6 «server»
, then ssh in to your server and attempt to ping -6 «something»
It may well happen that your server is supposed to have an ipv6 address and /64 ipv6 subnet, but something is broken.
The VPN server is running Debian 11 operating system. This tutorial is not going to work on Debian 10 or lower. Accessing your vpn from a windows client, however, easy since the windows wireguard windows client is very friendly. Setting up wireguard on windows is easy. Setting up a wireguard VPN server on windows is, on the other hand, very difficult. Don’t even try. I am unaware of anyone succeeding.
No end of people are strangely eager to provide free nameservice. If it is a free service, you are the product. And some of them have sneaky ways to get you use their nameservice whether you want it or not.
Nameservice reveals which websites you are visiting. We are going to set up our own nameserver for the vpn clients, but it will have to forward to a bigger nameserver, thus revealing which websites the clients are visiting, though not which client is visiting them. Lots of people are strangely eager to know which websites you are visiting. If you cannot control your nameservice, then when you set up your own nameserver, it is likely to behave strangely.
No end of people’s helpful efforts to help you automatically set up nameservice are likely foul up your nameservice for your vpn clients.
cat /etc/resolv.conf
Probably at least two of them are google, which logs everything and shares the data with the Global American Empire, and the other two are mystery meat. Maybe good guys provided by your good guy ISP, but I would not bet on it. Your ISP probably went along with his ISP, and his ISP may be in the pocket of your enemies.
I use Yandex.com resolvers, since Russia is currently in a state of proxy war with the Global American Empire which is heading into flat out war, and I do not care if the Russian government knows which websites I visit, because it is unlikely to share that data with the five eyes.
So for me
cat /etc/resolv.conf
nameserver 2a02:6b8::feed:0ff
nameserver 2a02:6b8:0:1::feed:0ff
nameserver 77.88.8.8
nameserver 77.88.8.1
Of course your mileage may vary, depending on which enemies you are worried about, and what the political situation is when you read this (it may well change radically in the near future). Read up on the resolver’s privacy policies, but apply appropriate cynicism. Political alignments and vulnerability to power matter more that professed good intentions.
We are going to change this when we set up our own nameserver for the vpn clients, but if you don’t have control, things are likely to get strange.
You cannot necessarily change your nameservers by editing
/etc/resolv.conf
, since no end of processes are apt to rewrite that file
durig boot up. Changing your nameservers depends on how your linux is
set up, but editing /etc/resolv.conf
currently works on the standard
distribution. But may well cease to work when you add more software.
If it does not work, maybe you need to subtract some software, but it is hard to know what software. A clean fresh install may be needed.
It all depends on which module of far too many modules gets the last
whack at /etc/resolv.conf
on bootup. Far too many people display a
curious and excessive interest in controlling what nameserver you are
using, and if they have their claw in your linux distribution, you are going
to have to edit the configuration files of that module.
If something is whacking your /etc/resolv.conf
, install openresolv
,
which will generally make sure it gets the last whack, and edit its
configuration files. Or install a distribution where you can control
nameservice by editing /etc/resolv.conf
apt update -qy
apt full-upgrade -qy
apt install -qy wireguard wireguard-tools linux-headers-$(uname -r)
On the server
sudo mkdir -p /etc/wireguard
wg genkey | sudo tee /etc/wireguard/server_private.key | wg pubkey | sudo tee /etc/wireguard/server_public.key
sudo chmod 600 /etc/wireguard/ -R
sudo chmod 700 /etc/wireguard
On the client
sudo mkdir -p /etc/wireguard
wg genkey | sudo tee /etc/wireguard/private.key | wg pubkey | sudo tee /etc/wireguard/public.key
sudo chmod 600 /etc/wireguard/ -R
sudo chmod 700 /etc/wireguard
This configuration file is for two clients, one of which is a bitcoin peer for which port forwarding is provided, and to provide them a nat translated IPv4 address, and an IPv6 address on a random /112 subnet of the vpn servers /64 subnet. Adjust to taste. IPv6 is tricky.
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.
The curly braces mean that you do not copy the text inside the curly braces, which is only there for example. You have to substitute your own private key (since everyone now knows this private key), and your own client public key., mutas mutandis.
[Interface]
# public key = «CHRh92zutofXTapxNRKxYEpxzwKhp3FfwUfRYzmGHR4=»
Address = 10.10.10.1/24, «AAAA:AAAA:AAAA:AAAA»:«BBBB:BBBB:BBBB»:0001/112
ListenPort = 115
PrivateKey = iOdkQoqm5oyFgnCbP5+6wMw99PxDb7pTs509BD6+AE8=»
[Peer]
PublicKey = «rtPdw1xDwYjJnDNM2eY2waANgBV4ejhHEwjP/BysljA=»
AllowedIPs = 10.10.10.4/32, «AAAA:AAAA:AAAA:AAAA»:«BBBB:BBBB:BBBB»:0009/128
[Peer]
PublicKey = «YvBwFyAeL50uvRq05Lv6MSSEFGlxx+L6VlgZoWA/Ulo=»
AllowedIPs = 10.10.10.8/32, «AAAA:AAAA:AAAA:AAAA»:«BBBB:BBBB:BBBB»:0019/128
[Peer]
PublicKey = «XpT68TnsSMFoZ3vy/fVvayvrQjTRQ3mrM7dmyjoWJgw=»
AllowedIPs = 10.10.10.12/32, «AAAA:AAAA:AAAA:AAAA»:«BBBB:BBBB:BBBB»:0029/128
[Peer]
PublicKey = «f2m6KRH+GWAcCuPk/TChzD01fAr9fHFpOMbAcyo3t2U=» AllowedIPs = 10.10.10.16/32, «AAAA:AAAA:AAAA:AAAA»:«BBBB:BBBB:BBBB»:0039/128
[Interface]
Address = 10.10.10.1/24
ListenPort = «51820»
PrivateKey = «cD+ZjXiVIX+0iSX1PNijl4a+88lCbDgw7kO78oXXLEc=»
[Peer]
PublicKey = «AYQJf6HbkQ0X0Xyt+cTMTuJe3RFwbuCMF46LKgTwzz4=» AllowedIPs = 10.10.10.2/32
As always «…» means that this is an example value, and you need to substitute your own actual value. “Mutas mutandis” means “changing that which ought to be changed”. In other words, watch out for those «…» .
Or, as those that want to baffle you would say, metasyntactic variables are enclosed in «…» .
In the above example «AAAA:AAAA:AAAA:AAAA» is the 64 bits of the IPv6 address range of your host and «BBBB:BBBB:BBBB» is a random 48 bit subnet that you invented for your clients.
This should be a random forty eight bit number to avoid collisions, because who knows what other subnets have been reserved.
This example supports IPv6 as well as IPv4, but getting IPv6 working is likely to be hard so initially forget about IPv6, and just stick to IPv4 addresses.
Where:
/etc/wireguard/server_private.key
file on the server./etc/wireguard/public.key
file on the client computer.Change the file permission mode so that only root user can read the files. Private keys are supposed to be private,
sudo chmod 600 /etc/wireguard/ -R
sudo chmod 700 /etc/wireguard
This just does not work on many hosts, depending on arcane incomprehensible and always different and inaccessible aspects of their networking setup. But when it works, it works.
For IP6 to work, without network address translation, you just give each client a subrange of the host IPv6 address (which you may not know, or could be changed underneath you)
When it works, no network address translation needed. When IPv6 network address translation is needed, you probably will not be able to get it working anyway, because if it is needed, it is needed because the host network is doing something too clever by half with IPv6, and you don’t know what they are doing, and they probably do not know either.
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:
apt -qy install ufw
If ufw is already installed and running
ufw disable
First, you need to allow SSH traffic.
ufw allow 22/tcp
Next, find the name of your server’s main network interface.
ip addr | grep BROADCAST
server_network_interface=$(ip addr | grep BROADCAST |sed -r "s/.*:[[:space:]]*([[:alnum:]]+)[[:space:]]*:.*/\1/")
echo $server_network_interface
As you can see, it’s named eth0
on my Debian server.
:~# ip addr | grep BROADCAST
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq state UP group default qlen 1000
:~# server_network_interface=$(ip addr | grep BROADCAST |sed -r "s/([[:alnum:]]+):[[:space:]]*(.*)[[:space:]]*:(.*)/\2/")
:~# echo $server_network_interface
eth0
To configure IP masquerading, we have to add iptables command in a UFW configuration file.
nano /etc/ufw/before.rules
By default, there are some rules for the filter
table. Add the following
lines at the end of these default rules. Replace eth0
with your own
network interface name.
# NAT table rules
*nat
:POSTROUTING ACCEPT [0:0]
-F
-A POSTROUTING -o «eth0» -j MASQUERADE
# End each table with the 'COMMIT' line or these rules
# won't be processed
COMMIT
“MASQUERADE” is NAT packet translation. This puts your IP4 forwarded network addresses behind a NAT firewall, so that they appear on the internet with network address of the server.
If you want to NAT translate your IPv6 addresses, will have to do
something similar in /etc/ufw/before6.rules
. But you usually have lots
of IPv6 addresses, so you seldom want to nat translate IPv6
In Nano text editor, you can go to the end of the file by pressing Ctrl+W
, then pressing Ctrl+V
.
-A ufw-before-input -p udp -d 239.255.255.250 --dport 1900 -j ACCEPT
# don't delete the 'COMMIT' line or these rules won't be processed
COMMIT
# NAT table rules
*nat
:POSTROUTING ACCEPT [0:0]
-F
-A POSTROUTING -o eth0 -j MASQUERADE
COMMIT
The above lines will append -A
a rule to the end of thePOSTROUTING
chain of the 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.
Like your home router, it means your client system behind the nat has no open ports.
If you want to open some ports, for example the bitcoin port 8333 so that you can run bitcoin core and the Monero ports.
NAT table rules
*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -o eth0 -j MASQUERADE
-A PREROUTING -d «123.45.67.89»/32 -i eth0 -p tcp --dport 8333 -j DNAT --to-destination 10.10.10.«5»:8333
-A PREROUTING -d «123.45.67.89»/32 -i eth0 -p udp --dport 8333 -j DNAT --to-destination 10.10.10.«5»:8333
-A PREROUTING -d «123.45.67.89»/32 -i eth0 -p tcp --dport 18080 -j DNAT --to-destination 10.10.10.«5»:18080
-A PREROUTING -d «123.45.67.89»/32 -i eth0 -p tcp --dport 18089 -j DNAT --to-destination 10.10.10.«5»:18089
COMMIT
Then open the corresponding ports in ufw
ufw allow in 8333
ufw enable
ufw status verbose
If you have made an error in /etc/ufw/before6.rules
enable will fail.
If you have enabled UFW before, then you can use systemctl to restart UFW.
By default, UFW forbids packet forwarding. We can allow forwarding for our private network, mutas mutandis.
ufw route allow in on wg0
ufw route allow out on wg0
ufw allow in on wg0
ufw allow in from 10.10.10.0/24
ufw allow in from «AAAA:AAAA:AAAA:AAAA»:«BBBB:BBBB:BBBB:0001»/112
ufw allow «51820»/udp
ufw allow to 10.10.10.1/24
# Danger Will Robertson
ufw allow to «AAAA:AAAA:AAAA:AAAA»:«BBBB:BBBB:BBBB»:0001/112
# This las last line ileaves your clients naked on the IPv6
# global internet with their own IPv6 addresses
# as if they were in the cloud with no firewall.
As always «…» means that this is an example value, and you need to substitute your actual value. “Mutas mutandis” means “changing that which should be changed”, in other words, watch out for those «…» .
Note that the last line is intended to leave your clients naked on the IPv6 global internet with their own IPv6 addresses, as if they were in the cloud with no firewall.This is often desirable for linux systems, but dangerous for windows, android, and mac systems which always have loads of undocumented closed source mystery meat processes running that do who knows what.
It would be safer to only allow in specific ports.
You could open only part of the IPv6 subnet to incoming, and put windows, mac, and android clients in the part that is not open.
wg0
is the virtual network card that wg0.conf
specifies. If you called it «your name».conf
then mutatis mutandis.
You just told ufw to allow your vpn clients to see each other on the internet, but allowing routing does not in itself result in any routing.
To actually enable routing, edit the system kernel configuration file, and uncomment the following lines. nano /etc/sysctl.conf
# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1
# Uncomment the next line to enable packet forwarding for IPv6
# Enabling this option disables Stateless Address Autoconfiguration
# based on Router Advertisements for this host
net.ipv6.conf.all.forwarding=1
For these changes to take effect:
sysctl -p
Now if you list the rules in the POSTROUTING chain of the NAT table by using the following command:
iptables -t nat -L POSTROUTING
You can see the Masquerade rule.
:~# iptables -t nat -L POSTROUTING
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- anywhere anywhere
Since we will specify 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.
apt install bind9
Once it’s installed, BIND will automatically start. You can check its status with:
systemctl status bind9
Sample output:
:~$ systemctl status bind9
● named.service - BIND Domain Name Server
Loaded: loaded (/lib/systemd/system/named.service; enabled; vendor preset: enabled)
Active: active (running) since Wed 2022-09-21 20:14:33 EDT; 6min ago
Docs: man:named(8)
Main PID: 1079 (named)
Tasks: 5 (limit: 1132)
Memory: 16.7M
CPU: 86ms
CGroup: /system.slice/named.service
└─1079 /usr/sbin/named -f -u bind
Sep 21 20:14:33 rho.la named[1079]: command channel listening on ::1#953
Sep 21 20:14:33 rho.la named[1079]: managed-keys-zone: loaded serial 0
Sep 21 20:14:33 rho.la named[1079]: zone 0.in-addr.arpa/IN: loaded serial 1
Sep 21 20:14:33 rho.la named[1079]: zone 127.in-addr.arpa/IN: loaded serial 1
Sep 21 20:14:33 rho.la named[1079]: zone 255.in-addr.arpa/IN: loaded serial 1
Sep 21 20:14:33 rho.la named[1079]: zone localhost/IN: loaded serial 2
Sep 21 20:14:33 rho.la named[1079]: all zones loaded
Sep 21 20:14:33 rho.la named[1079]: running
Sep 21 20:14:33 rho.la named[1079]: managed-keys-zone: Initializing automatic trust anchor management for zone '.'; >
Sep 21 20:14:33 rho.la named[1079]: resolver priming query complete
If it’s not running, start it with:
systemctl start bind9
Check that lookups still work:
curl -6 icanhazip.com
curl -4 icanhazip.com
See what dns server you are in fact using
dig icanhazip.com
You will notice you are not using your own bind9
Edit the BIND DNS server’s configuration file.
nano /etc/bind/named.conf.options
Add some acls above the options block, one for your networks, and one for potential attackers.
Add some real forwarders
And add allow recursion for your subnets.
After which it should look something like this:
:~# cat /etc/bind/named.conf.options | tail -n 9
acl bogusnets {
0.0.0.0/8; 192.0.2.0/24; 224.0.0.0/3;
10.0.0.0/8; 172.16.0.0/12; 192.168.0.0/16;
};
acl my_net {
127.0.0.1;
::1;
116.251.216.176;
10.10.10.0/24;
«AAAA:AAAA:AAAA:AAAA»::/64;
};
options {
directory "/var/cache/bind";
forwarders {
2a02:6b8::feed:0ff;
2a02:6b8:0:1::feed:0ff;
77.88.8.8;
77.88.8.1;
};
//==========================
// If BIND logs error messages about the
// root key being expired,
// you will need to update your keys.
// See https://www.isc.org/bind-keys
//==========================
dnssec-validation auto;
listen-on-v6 { any; };
allow-recursion { my_net; };
blackhole { bogusnets; };
};
Then edit the /etc/default/named
files.
nano /etc/default/named
If on an IPv4 network, add -4
to the OPTIONS
to ensure BIND can query root DNS servers.
OPTIONS="-u bind -4"
If on the other hand, you are on a network that supports both IPv6 and IPv4, this will cause unending havoc and chaos, as bind9’s behavior comes as a surprise to other components of the network, and bind9 crashes on IPv6 information in its config files.
Save and close the file.
Restart bind9
for the changes to take effect.
systemctl restart bind9
systemctl status bind9
dig -t txt -c chaos VERSION.BIND @127.0.0.1
Your ufw firewall will allow vpn clients to access bind9
because you earlier allowed everything from wg0
in.
Run the following command on the server to start WireGuard.
wg-quick up /etc/wireguard/wg0.conf
To stop it, run
wg-quick down /etc/wireguard/wg0.conf
You can also use systemd service to start WireGuard.
systemctl start wg-quick@wg0.service
Enable auto-start at system boot time.
systemctl enable wg-quick@wg0.service
Check its status with the following command. Its status should be active (exited)
.
systemctl status wg-quick@wg0.service
Now WireGuard server is ready to accept client connections.
apt -qy install openresolv
nano /etc/wireguard/wg-client0.conf
You will edit the wireguard client config file so that the client will use
openresolv
to use your server’s resolver to find the network addresses of
domain names instead of leaking your activities all over the internet.
Copy the following text and paste it to your configuration file. You need to use your own client private key and server public key, and your own endpoint and port. Remember, curly braces mean that the material is only for example, and has to be customized. Mutas mutandis. Metasyntactic variables.
[Interface]
Address =10.10.10.4/32, «AAAA:AAAA:AAAA:AAAA»:«BBBB:BBBB:BBBB»:0009/128
DNS = 10.10.10.1
PrivateKey = «cOFA+x5UvHF+a3xJ6enLatG+DoE3I5PhMgKrMKkUyXI=»
[Peer]
PublicKey = «kQvxOJI5Km4S1c7WXu2UZFpB8mHGuf3Gz8mmgTIF2U0=»
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = «123.45.67.89: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/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 IPv4 Internet, which means all IPv4 traffic to the Internet should be routed via the VPN. ::/0 represents the whole IPv6 Internet. If you specify one but not the other, and your client has both IPv4 and IPv6 capability, only half your traffic will go through the vpn. If your client has both capabilities, but your vpn does not, this is bad, but things still work.Endpoint
: The public IP address and port number of VPN server. Replace 123.45.67.89 with your server’s real public IP address and the port number with your server’s real port number.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.
chmod 600 /etc/wireguard/ -R
chmod 700 /etc/wireguard
Start WireGuard.
wg-quick up /etc/wireguard/wg-client0.conf
To stop it, run
wg-quick down /etc/wireguard/wg-client0.conf
You can also use systemd service to start WireGuard.
systemctl start wg-quick@wg-client0.service
Enable auto-start at system boot time.
systemctl enable wg-quick@wg-client0.service
Check its status:
systemctl status wg-quick@wg-client0.service
The status should look something like this:
# systemctl status wg-quick@wg-client0.service
wg-quick@wg-client0.service - WireGuard via wg-quick(8) for wg/client0
Loaded: loaded (/lib/systemd/system/wg-quick@.service; enabled; preset: enabled)
Active: inactive (dead)
Docs: man:wg-quick(8)
man:wg(8)
https://www.wireguard.com/
https://www.wireguard.com/quickstart/
https://git.zx2c4.com/wireguard-tools/about/src/man/wg-quick.8
https://git.zx2c4.com/wireguard-tools/about/src/man/wg.8
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
To get the geographic location
curl https://www.dnsleaktest.com |grep from
Install the tshark
network traffic analyzer on the server. Tshark is the command-line version of Wireshark.
apt install -qy tshark
adduser «your-username» wireshark
su -l «your-username»
tshark -i «eth0» "udp port «51820»"
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.
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 'eth0'
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 connect to UDP port 51820 of the server, then you will only see handshake initiation packets. There’s no handshake respsonse.
Capturing on 'eth0'
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
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.
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, typically typo in the
/etc/ufw/before.rules
file
If you use Linux kernel 5.6+, you can, as root, enable debug logging for WireGuard with the following command. As a non root wireguard user, cannot log kernel.
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
If your VPN still doesn’t work, try restarting the VPN server and client.
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.
Then add WireGuard configuration on each VPN client as usual.
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 scratch” means that the Wireguard app gives you a private and public key pair, and an empty wg-client.conf file that you populate in the wireguard app ui. This is likely to result in a lot of typing where you are bound to do a typo, even though the correct and working information is already on your debian server and client and you would like to just copy and paste it.
Create from QR code means that you create ios.conf
in your client, as before for debian, add the public key to your server wg0.conf
as before for debian, restart the server as before, and then generate the QR code with
apt install -qy qrencode
cat /etc/wireguard/ios.conf | qrencode -t ansiutf8
This is apt to be easier, because it is likely to be hard to transfer information between android systems.
QRencode is very useful for transferring data to android systems, which tend to be locked down against ordinary users transferring computer data.
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.
And from there on, same as with the android client.
On Windows, you can use the PowerShell program to SSH into your Linux server, so you do not have the problem you had with android.
It’s not recommended to use policy routing, split tunneling, or VPN kill switch in conjunction with each other. If you use policy routing, then you should not enable split tunneling or VPN kill switch, and vice versa.
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 and edit the client configuration file.
systemctl stop wg-quick@wg0.service
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
[Interface]
Address = 10.10.10.2/24
DNS = 10.10.10.1
PrivateKey = «cOFA+x5UvHF+a3xJ6enLatG+DoE3I5PhMgKrMKkUyXI=»
Table = 1234
PostUp = ip rule add ipproto tcp dport 25 table 1234
PreDown = ip rule delete ipproto tcp dport 25 table 1234
[Peer]
PublicKey = «kQvxOJI5Km4S1c7WXu2UZFpB8mHGuf3Gz8mmgTIF2U0=»
AllowedIPs = 0.0.0.0/0
Endpoint = «123.45.67.89:51820»
PersistentKeepalive = 25
Save and close the file. Then start WireGuard client again.
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.
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 wg-quick@wg0.service
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 and the client configuration file.
systemctl stop wg-quick@wg0.service 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.
reaction.la gpg key 154588427F2709CD9D7146B01C99BB982002C39F
This work is licensed under the Creative Commons Attribution 4.0 International License.