VPN Chaining with Wireguard
Introduction
VPN Chaining is a method, where a client is connected to internet with 2 VPNs in between. This is usually for 2 purposes, masking the real IP address when web surfing and to improve network speed. The latter will only be good, when there is direct routes between the two VPNs or from the client to the first VPN. For better security with VPN chaining, there should be a good implementation of network security is required, which I am not going to cover in this topic. This doc is for speed improvement.
Requirement
- 2 VPS or Servers. Cloud linux servers will be best as the internal routing will be very fast, and the network to access internet will be optimised because of the cloud.
Server1
will be referred as Middleman andServer2
will be referred as Gate - IP forwarding enabled on the server. If not enabled, add
net.ipv4.ip_forward=1
to/etc/sysctl.conf
file and runsysctl -p
to enable this kernel parameter. - An internal IP range. For convenience, I will choose the range 10.10.10.0/24
Design
Client ==> Middleman(Server1) ==> Gate(Server2) ==> Internet
Procedure
Configure Gate
First we will install wireguard and then configure
sudo apt update
sudo apt install wireguard -y
Next we will need to generate a Key pair for communication with wireguard tool.
wg genkey | sudo tee /etc/wireguard/private.key
sudo chmod go= /etc/wireguard/private.key
The sudo chmod go=
command removes any permissions on the file for users and groups other than the root user to ensure that only it can access the private key.
Now we can create the public key from the created private key
sudo cat /etc/wireguard/private.key | wg pubkey | sudo tee /etc/wireguard/public.key
Now the wireguard configuration /etc/wireguard/gate0.conf
[Interface]
Address = 10.10.10.2/32
PostUp = ufw route allow in on gate0 out on enp1s0
PostUp = iptables -t nat -A POSTROUTING -s 10.200.200.0/24 -o enp1s0 -j MASQUERADE
PreDown = ufw route delete allow in on gate0 out on enp1s0
PreDown = iptables -t nat -D POSTROUTING -s 10.200.200.0/24 -o enp1s0 -j MASQUERADE
ListenPort = 51820
PrivateKey = private-key-of-gate-created[Peer]
PublicKey = public-key-of-server1
AllowedIPs = 10.10.10.0/24
Endpoint = IP-of-server1:51820
Here we add the iptables and firewall rules so that we add the config and forget to remove. Make sure the value enp1s0
should be replaced with proper interface.
The Peer config is for the Middleman, where we are allowing the Middleman to communicate with Gate. The public key is the one to add from the next section. We are allowing the whole network, because we need the client communication to be allowed through this server.
Configure Middleman
sudo apt update
sudo apt install wireguard -y
Generate Keys
wg genkey | sudo tee /etc/wireguard/private.key
sudo chmod go= /etc/wireguard/private.key
sudo cat /etc/wireguard/private.key | wg pubkey | sudo tee /etc/wireguard/public.key
Configure Wireguard in. /etc/wireguard/wg0.conf
[Interface]
Address = 10.10.10.3/32
PostUp = echo 1 > /proc/sys/net/ipv4/ip_forward
PostUp = echo 1 > /proc/sys/net/ipv4/conf/all/proxy_arp
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT && iptables -A FORWARD -o wg0 -j ACCEPT
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT && iptables -D FORWARD -o wg0 -j ACCEPT
PostDown = echo 0 > /proc/sys/net/ipv4/ip_forward
PostDown = echo 0 > /proc/sys/net/ipv4/conf/all/proxy_arp
ListenPort = 51820
PrivateKey = private-key-of-middleman[Peer]
PublicKey = public-key-of-client
AllowedIPs = 10.10.10.4/32[Peer]
PublicKey = public-key-of-gate
AllowedIPs = 0.0.0.0/0
Endpoint = IP-of-Gate:51820
Similar configuration as the Gate, except for the iptables rule, which is basically forwarding the packets and Peer configuration. There is peer configuration for the client and then another config to connect to the Gate server. Here, Middleman is the client to Gate. The public key for client will be created in the next section.
Configure client
sudo apt update
sudo apt install wireguard -y
Generate Keys:
wg genkey | sudo tee /etc/wireguard/private.key
sudo chmod go= /etc/wireguard/private.key
sudo cat /etc/wireguard/private.key | wg pubkey | sudo tee /etc/wireguard/public.key
Configure Wireguard in. /etc/wireguard/vpn0.conf
[Interface]
PrivateKey = private-key-of-client
Address = 10.10.10.4/32PostUp = ip rule add table 200 from 10.0.2.15
PostUp = ip route add table 200 default via 10.0.2.2
PreDown = ip rule delete table 200 from 10.0.2.15
PreDown = ip route delete table 200 default via 10.0.2.2[Peer]
PublicKey = public-key-of-middleman
AllowedIPs = 0.0.0.0/0
Endpoint = IP-address-of-middleman:51820
This configuration is to redirect all requests to the VPN interface. If only certain traffic should go through the VPN interface, then you can remove the PostUp
and PreDown
rules and replace the Allowed IPs with the proper network.
Note that the values for ip rule
can be figured out from the output of the command ip route list table main default
and the value for ip route
can be figured out from the output of the command ip -brief address show eth0
, where eth0
is the default interface.
Once everything is configured, try to connect to each server and start the VPN.
For gate:
wg-quick up gate0
For Middleman:
wg-quick up wg0
For Client:
wg-quick up vpn0
Note that, when running the command on Middleman, the current connection will be cut-off, as the SSH will then be only available through the VPN network. You can create complex iptable rules to allow only SSH to access from Public IP, but its in one way, not worth the trouble and it kindof defeats the purpose of having a VPN.
On the client run a traceroute to see if communication is going as expected:
osboxes@osboxes:~$ traceroute 8.8.8.8
traceroute to 8.8.8.8 (8.8.8.8), 30 hops max, 60 byte packets
1 10.10.10.3 (10.10.10.3) 60.068 ms 60.068 ms 60.068ms
2 10.10.10.2 (10.10.10.2) 74.959 ms 74.959 ms 74.959 ms
3 * * *
4 * * *
5 * * *
6 * * *
7 * * *
8 74.125.242.33 (74.125.242.33) 364.959 ms 364.973 ms 108.170.240.225 (108.170.240.225) 366.528 ms
9 74.125.242.33 (74.125.242.33) 365.752 ms 72.14.232.101 (72.14.232.101) 366.475 ms 108.170.240.225 (108.170.240.225) 366.473 ms
10 dns.google (8.8.8.8) 365.681 ms 142.251.52.49 (142.251.52.49) 365.688 ms dns.google (8.8.8.8) 365.687 ms
osboxes@osboxes:~$
Conclusion
Its interesting to use VPN chaining to have a bit of anonymity and improve performance. As you can see, my DNS query to Google is not so fast, but still it might be better for some sites which are slow in normal network
Have a nice day!