VPN Wireguard remote access
First I will configure the server machine as a VPN remote access and server server as a VPN client. I will then set up a Windows and Android client.
The first thing we will do is to install both the Wireguard package in both machines:
root@servidor1:~# sudo apt update && sudo apt install wireguard
debian@servidor2:~$ sudo apt update && sudo apt install wireguard
Let’s generate the pairs of keys that will be used to encrypt the connection. We will need a key for the server and a couple of additional keys for each client.
We’ll start with the server key pair 1:
debian@servidor1:~$ wg genkey | sudo tee /etc/wireguard/server_private.key | wg pubkey | sudo tee /etc/wireguard/server_public.key
2/RjGUbiQuaFR7atYaQ8lcczz2wXxO9aIwfzZEMPXCQ=
#Puedes visualizar la clave privada posteriormente :
debian@servidor1:~$ sudo cat /etc/wireguard/server_private.key
2Gg3EnKD+rdyMPEjMikZTwq2w0m78KrEcUsAJ/8icFA=
#Puedes visualizar la clave publica posteriormente :
debian@servidor1:~$ sudo cat /etc/wireguard/server_public.key
2/RjGUbiQuaFR7atYaQ8lcczz2wXxO9aIwfzZEMPXCQ=
We move to the service2 and generate yours:
#Generamos el par de claves para el cliente de acceso remoto servidor2
debian@servidor2:~$ wg genkey | sudo tee /etc/wireguard/client_private.key | wg pubkey | sudo tee /etc/wireguard/client_public.key
gS2ED2zfzMHBttMpFhH3MvRpr8D4ALEDTumNcib8A2g=
#Puedes visualizar la clave privada posteriormente :
debian@servidor2:~$ sudo cat /etc/wireguard/client_private.key
8IdsSwunfU5zJQzS5nZg4D//cFEbRa+27HGOQE1V90k=
#Puedes visualizar la clave publica posteriormente :
debian@servidor2:~$ sudo cat /etc/wireguard/client_public.key
gS2ED2zfzMHBttMpFhH3MvRpr8D4ALEDTumNcib8A2g=
Once the keys are generated, we will proceed to configure the Wireguard remote access server, in my case I will call the wg0.conf configuration file. I’m gonna add you in every parameter of the configuration a comment so you know what you have to put in every field:
debian@servidor1:~$ sudo cat /etc/wireguard/wg0.conf
[Interface]
#IP que tendrá el túnel VPN , en concreto la interfaz wg0 que es como has llamado el fichero de conf
Address = 10.99.99.1
#Clave privada del servidor
PrivateKey = 2Gg3EnKD+rdyMPEjMikZTwq2w0m78KrEcUsAJ/8icFA=
#Puerto de escucha , 51820 es el puerto por defecto de Wireguard
ListenPort = 51820
#Si no tienes activado el bit de forwarding por defecto puedes hacerlo asi :
PreUp = sysctl -w net.ipv4.ip_forward=1
#Este apartado hace referencia a la configuración de los clientes :
[Peer]
#Clave pública del cliente
Publickey = gS2ED2zfzMHBttMpFhH3MvRpr8D4ALEDTumNcib8A2g=
#IP del túnel VPN del cliente
AllowedIPs = 10.99.99.2/32
#Tiempo de espera que tendrá activo el túnel si no hay trafico
PersistentKeepAlive = 25
We will now set up a debian client, I have given the same name to the configuration file so the interface will also be called wg0:
debian@servidor2:~$ sudo cat /etc/wireguard/wg0.conf
[Interface]
Address = 10.99.99.2/24
#Clave privada del cliente
PrivateKey = 8IdsSwunfU5zJQzS5nZg4D//cFEbRa+27HGOQE1V90k=
#Puerto de escucha del servidor
ListenPort = 51820
[Peer]
#Clave pública del servidor
PublicKey = 2/RjGUbiQuaFR7atYaQ8lcczz2wXxO9aIwfzZEMPXCQ=
AllowedIPs = 0.0.0.0/0
#Punto de acceso del servidor
Endpoint = 90.0.0.2:51820
#Tiempo de espera de la conexión
PersistentKeepalive = 25
Once we have configured both files we will lift the tunnel, for this we have several ways to do it, personally the most comfortable I see is using the wg-quick command.
We raise the tunnel on the server:
debian@servidor1:~$ sudo wg-quick up wg0
[#] sysctl -w net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 10.99.99.1 dev wg0
[#] ip link set mtu 1420 up dev wg0
[#] ip -4 route add 10.99.99.2/32 dev wg0
We raise the other end, in this case our client is servant2:
debian@servidor2:~$ sudo wg-quick up wg0
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 10.99.99.2/24 dev wg0
[#] ip link set mtu 1420 up dev wg0
[#] wg set wg0 fwmark 51820
[#] ip -4 route add 0.0.0.0/0 dev wg0 table 51820
[#] ip -4 rule add not fwmark 51820 table 51820
[#] ip -4 rule add table main suppress_prefixlength 0
[#] sysctl -q net.ipv4.conf.all.src_valid_mark=1
[#] iptables-restore -n
Once this is done we will check that at both ends we have created a new interface, which is called the same as our configuration file without the .conf extension.
We check that it was created in servant1:
debian@servidor1:~$ ip -4 a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
altname enp0s3
inet 90.0.0.2/24 brd 90.0.0.255 scope global ens3
valid_lft forever preferred_lft forever
3: ens4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
altname enp0s4
inet 192.168.0.1/24 brd 192.168.0.255 scope global ens4
valid_lft forever preferred_lft forever
6: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
inet 10.99.99.1/32 scope global wg0
valid_lft forever preferred_lft forever
We check that it was created in servers2:
debian@servidor2:~$ ip -4 a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
altname enp0s3
inet 100.0.0.2/24 brd 100.0.0.255 scope global ens3
valid_lft forever preferred_lft forever
3: ens4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
altname enp0s4
inet 192.168.1.1/24 brd 192.168.1.255 scope global ens4
valid_lft forever preferred_lft forever
6: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
inet 10.99.99.2/24 scope global wg0
valid_lft forever preferred_lft forever
We will also check the routes that have been created on the server and on the client:
debian@servidor1:~$ ip r
default via 90.0.0.1 dev ens3 onlink
10.99.99.2 dev wg0 scope link
10.99.99.4 dev wg0 scope link
90.0.0.0/24 dev ens3 proto kernel scope link src 90.0.0.2
192.168.0.0/24 dev ens4 proto kernel scope link src 192.168.0.1
debian@servidor2:~$ ip r
default via 100.0.0.1 dev ens3 onlink
10.99.99.0/24 dev wg0 proto kernel scope link src 10.99.99.2
100.0.0.0/24 dev ens3 proto kernel scope link src 100.0.0.2
192.168.1.0/24 dev ens4 proto kernel scope link src 192.168.1.1
Let’s check that from our client (server 2) we have access to the different machines of our network:
##Ping con el túnel del extremo servidor1
debian@servidor2:~$ ping 10.99.99.1 -c 1
PING 10.99.99.1 (10.99.99.1) 56(84) bytes of data.
64 bytes from 10.99.99.1: icmp_seq=1 ttl=64 time=14.9 ms
--- 10.99.99.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 14.862/14.862/14.862/0.000 ms
##Pings con cliente1 :
debian@servidor2:~$ ping 192.168.0.2 -c 1
PING 192.168.0.2 (192.168.0.2) 56(84) bytes of data.
64 bytes from 192.168.0.2: icmp_seq=1 ttl=63 time=17.5 ms
--- 192.168.0.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 17.503/17.503/17.503/0.000 ms
#Ping con cliente2
debian@servidor2:~$ ping 192.168.0.3 -c 1
PING 192.168.0.3 (192.168.0.3) 56(84) bytes of data.
64 bytes from 192.168.0.3: icmp_seq=1 ttl=63 time=16.5 ms
--- 192.168.0.3 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 16.522/16.522/16.522/0.000 ms
##Ping con la ip privada del servidor1
debian@servidor2:~$ ping 192.168.0.1 -c 1
PING 192.168.0.1 (192.168.0.1) 56(84) bytes of data.
64 bytes from 192.168.0.1: icmp_seq=1 ttl=64 time=20.3 ms
--- 192.168.0.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 20.272/20.272/20.272/0.000 ms
Although my stage is set, the private IP addresses are not erased we will check that the traffic goes through the tunnel, making use of traceroute:
debian@servidor2:~$ traceroute 192.168.0.2
traceroute to 192.168.0.2 (192.168.0.2), 30 hops max, 60 byte packets
1 10.99.99.1 (10.99.99.1) 18.692 ms 28.987 ms 28.951 ms
2 192.168.0.2 (192.168.0.2) 28.912 ms 28.877 ms 28.859 ms
android client configuration
The virtual android machine is quite uncomfortable to control, so I’m going to generate the keys and your configuration file on the server. Then we’ll get him out of this with Apache.
We generate the keys to android:
debian@servidor1:~$ wg genkey | tee androidprivate | wg pubkey > androidpublic
debian@servidor1:~$ cat androidprivate
CBY5o2iko7xXQrNAFcFDIKohOngawB1uvws7aDDgl0g=
debian@servidor1:~$ cat androidpublic
cBGl5QWOsbZyI2GN1MXDxUsfeMmI5sKnp3VkxW9lO3g=
The configuration file would be as follows:
debian@servidor1:~$ sudo cat android.conf
[Interface]
Address = 10.99.99.4
PrivateKey = CBY5o2iko7xXQrNAFcFDIKohOngawB1uvws7aDDgl0g=
ListenPort = 51820
[Peer]
Publickey = 2/RjGUbiQuaFR7atYaQ8lcczz2wXxO9aIwfzZEMPXCQ=
AllowedIPs = 0.0.0.0/0
Endpoint = 90.0.0.2:51820
I have installed apache and will copy this file to the document root to get it to the android machine. I use this medium as it is a fictional scenario.
debian@servidor1:~$ sudo cp android.conf /var/www/html/
From a terminal, as the browser does not work too well we download the file:
Now let’s add this new client to the server configuration file:
debian@servidor1:~$ sudo cat /etc/wireguard/wg0.conf
#Al final del todo :)
[Peer]
Publickey = cBGl5QWOsbZyI2GN1MXDxUsfeMmI5sKnp3VkxW9lO3g=
AllowedIPs = 10.99.99.4/32
PersistentKeepAlive = 25
Don’t forget to restart the tunnel:
debian@servidor1:~$ sudo wg-quick down wg0
debian@servidor1:~$ sudo wg-quick up wg0
Now open the wireguard application and give it import from file and activate the connection. Activate the tunnel and make sure the handshake occurs:
If we open a terminal we can pings the customers:
Windows client configuration
We’re going to repeat the process but now with our Windows client.
In order to copy and paste, I will make the key generation of this client in the service machine.
We’ll start by generating the key pair.
debian@servidor1:~$ wg genkey | tee winprivate | wg pubkey > winpublic
debian@servidor1:~$ cat winprivate
QKGQEdrB9FBYRZsLNgc3qr9m8/lx+uc9n5vvj67I9m8=
debian@servidor1:~$ cat winpublic
E8VdupsWJ7vCTO7SF3oXUciUrsRgJ3p6T+F5UbbLngo=
We create the configuration file for this client:
debian@servidor1:~$ cat win.conf
[Interface]
Address = 10.99.99.5
PrivateKey = QKGQEdrB9FBYRZsLNgc3qr9m8/lx+uc9n5vvj67I9m8=
ListenPort = 51820
[Peer]
Publickey = 2/RjGUbiQuaFR7atYaQ8lcczz2wXxO9aIwfzZEMPXCQ=
AllowedIPs = 0.0.0.0/0
Endpoint = 90.0.0.2:51820
I’ll move it to the document root so I can download it on my Windows, don’t do this in a real environment.
debian@servidor1:~$ sudo cp win.conf /var/www/html/
Remember to set up this new customer in the service machine:
debian@servidor1:~$ sudo nano /etc/wireguard/wg0.conf
[Peer]
Publickey = E8VdupsWJ7vCTO7SF3oXUciUrsRgJ3p6T+F5UbbLngo=
AllowedIPs = 10.99.99.5/32
PersistentKeepAlive = 25
For the changes to be applied, restart the tunnel:
debian@servidor1:~$ sudo wg-quick down wg0
debian@servidor1:~$ sudo wg-quick up wg0
Once we have all set up, access the Windows machine and download the configuration file:
Open the wireguard application and select to import from file:
Once the tunnel is activated and the handshake has been checked:
If we return to our Windows, we will have created a new interface:
And we’ll have connectivity to the network machines 192.168.0.0 / 24:
By way of curiosity we can see on the server that customers are connected:
debian@servidor1:~$ sudo wg show
interface: wg0
public key: 2/RjGUbiQuaFR7atYaQ8lcczz2wXxO9aIwfzZEMPXCQ=
private key: (hidden)
listening port: 51820
peer: cBGl5QWOsbZyI2GN1MXDxUsfeMmI5sKnp3VkxW9lO3g=
endpoint: 100.0.0.2:51820
allowed ips: 10.99.99.4/32
latest handshake: 1 minute, 14 seconds ago
transfer: 6.43 KiB received, 788 B sent
persistent keepalive: every 25 seconds
peer: E8VdupsWJ7vCTO7SF3oXUciUrsRgJ3p6T+F5UbbLngo=
endpoint: 100.0.0.2:49981
allowed ips: 10.99.99.5/32
latest handshake: 1 minute, 32 seconds ago
transfer: 46.23 KiB received, 1.64 KiB sent
persistent keepalive: every 25 seconds
peer: gS2ED2zfzMHBttMpFhH3MvRpr8D4ALEDTumNcib8A2g=
allowed ips: 10.99.99.2/32
persistent keepalive: every 25 seconds