Table of contents
Multihopping WireGuard
Multihopping is connecting to one VPN, then using that tunnel to connect to another (and if you want, using that tunnel to connect another, and so on). The main reason anyone would want this is because it makes correlation attacks more difficult. If the first server is in a jurisdiction that's not known to work with the jurisdiction the second server is in, it's unlikely they're going to share information to try to figure out your real IP. It also minimizes the data sent to a VPN provider, if you're connecting to two different VPN providers:
Some VPN providers will try to sell this feature as something that's only available with them, but the truth is that you can do this with any VPN provider. It is possible for a VPN provider to do the multihopping for you on the server's side, and that is better for speeds, but the downside is that you can't connect to a server outside of their network (like a competing VPN provider).
This page will focus on multihopping with Linux. It's probably possible in Windows, but my guess is it would be much more arduous. For example, on Linux, creating two WireGuard interfaces from the terminal is straightforward using `wg-quick`, but on Windows there's no wg-quick.exe, only a wg.exe, so you would have to recreate the functionality of wg-quick (handling the routing etc. yourself). The Windows WireGuard client did at one point have a registry hack that allowed multiple tunnels to be activated at the same time, but it seems that code has since been removed. And doing the single multihop config shown in the Triple hop section doesn't have the same effect in Windows (it just connects directly to the final hop). If you're doing something that requires the added protection of multiple tunnels, you probably shouldn't be using Windows anyways: https://www.gnu.org/proprietary/malware-microsoft.html
If you're looking for instructions on multihopping with OpenVPN, that's at https://cryptostorm.is/multihop
Double hop
Follow the instructions on https://cryptostorm.is/wireguard to get your system setup with WireGuard. You should have the `wg` and `wg-quick` commands installed, and your /etc/wireguard/ folder should look something like:
root@x:/etc/wireguard# ls confgen.sh cs-india.conf cs-poland.conf cs-atlanta.conf cs-ireland.conf cs-portugal.conf cs-austria.conf cs-la.conf cs-romania.conf cs-barcelona.conf cs-latvia.conf cs-rome.conf cs-belgium.conf cs-london.conf cs-seattle.conf cs-berlin.conf cs-madrid.conf cs-serbia.conf cs-brazil.conf cs-maine.conf cs-singapore.conf cs-bulgaria.conf cs-manchester.conf cs-sk.conf cs-chicago.conf cs-mexico.conf cs-slovakia.conf cs-czech.conf cs-milan.conf cs-sweden.conf cs-dallas.conf cs-moldova.conf cs-switzerland.conf cs-dc.conf cs-montreal.conf cs-sydney.conf cs-denmark.conf cs-nc.conf cs-tokyo.conf cs-dusseldorf.conf cs-netherlands.conf cs-vancouver.conf cs-finland.conf cs-newyork.conf cs-vegas.conf cs-florida.conf cs-norway.conf privatekey cs-frankfurt.conf cs-oregon.conf publickey cs-hungary.conf cs-paris.conf
To avoid messing up the configs you already have (and to make things easier when you want to do a single-hop VPN), you should first make a copy of the configs for the two nodes you'll be using in this multihop chain. In this example, I'll use the Atlanta node for the first hop and the Dallas node for the second:
root@x:/etc/wireguard# cp cs-atlanta.conf hop1.conf root@x:/etc/wireguard# cp cs-dallas.conf hop2.conf
You will need the IPs of the nodes you're going to connect to, so use `grep` to get the endpoint hostnames from hop1.conf and hop2.conf, then use `host` to lookup the IPs. And if your system doesn't have a `host` command, use `nslookup` or `dig` or whatever command you have to resolve hostnames to IPs.
root@x:/etc/wireguard# grep Endpoint hop1.conf hop2.conf
hop1.conf:Endpoint = atlanta.cstorm.is:443
hop2.conf:Endpoint = dallas.cstorm.is:443
root@x:/etc/wireguard# host atlanta.cstorm.is
atlanta.cstorm.is has address 64.42.181.244
root@x:/etc/wireguard# host dallas.cstorm.is
dallas.cstorm.is has address 108.181.101.28
dallas.cstorm.is has address 209.58.147.38
dallas.cstorm.is has address 108.181.101.29
dallas.cstorm.is has address 209.58.150.203
dallas.cstorm.is has address 209.58.150.202
dallas.cstorm.is has address 108.181.101.70
dallas.cstorm.is has address 108.181.101.30
dallas.cstorm.is has address 108.181.101.69
Open up hop1.conf in your favorite text editor and change the Endpoint line in hop1.conf to use the IP instead of the hostname (In this example, you would change atlanta.cstorm.is to it's IP, which is 64.42.181.244). I'll use sed for my text editor:
root@x:/etc/wireguard# sed -e's/Endpoint = atlanta.cstorm.is/Endpoint = 64.42.181.244/' -i hop1.conf
While you're editing hop1.conf, go ahead and remove the default "DNS = 10.31.33.8" line too since we don't need it for the first hop (and there won't be any routing to 10.31.33.8 yet anyways):
root@x:/etc/wireguard# sed -e'/^DNS = .*/d' -i hop1.conf
Next, you're going to copy the IP of the hostname used for the endpoint in the second hop. If the hostname resolves to multiple IPs like the Dallas node does, just pick a single IP from that list (I'll use 209.58.147.38). Still in hop1.conf, change the line "AllowedIPs = 0.0.0.0/0" to "AllowedIPs = 209.58.147.38/32". I'll use sed again:
root@x:/etc/wireguard# sed -e's_AllowedIPs = 0.0.0.0/0_AllowedIPs = 209.58.147.38/32_' -i hop1.conf
Next, you're going to copy the IP of the hostname used for the endpoint in the first hop. In my example, it's 64.42.181.244, the Atlanta node. We need to exclude it from AllowedIPs in hop2.conf, but WireGuard doesn't have an inverse of AllowedIPs (like a DisallowedIPs), so we need to get a list of every possible subnet on the internet except for 64.42.181.244
Luckily, we have something on our website that makes it easy (use curl if you don't have wget):
root@x:/etc/wireguard# wget -qO- https://cryptostorm.is/wga?ip=64.42.181.244
AllowedIPs = 128.0.0.0/1, 0.0.0.0/2, 96.0.0.0/3, 80.0.0.0/4, 72.0.0.0/5, 68.0.0.0/6, 66.0.0.0/7, 65.0.0.0/8, 64.128.0.0/9, 64.64.0.0/10, 64.0.0.0/11, 64.48.0.0/12, 64.32.0.0/13, 64.44.0.0/14, 64.40.0.0/15, 64.43.0.0/16, 64.42.0.0/17, 64.42.192.0/18, 64.42.128.0/19, 64.42.160.0/20, 64.42.184.0/21, 64.42.176.0/22, 64.42.182.0/23, 64.42.180.0/24, 64.42.181.0/25, 64.42.181.128/26, 64.42.181.192/27, 64.42.181.224/28, 64.42.181.248/29, 64.42.181.240/30, 64.42.181.246/31, 64.42.181.245/32
Open up hop2.conf in a text editor and replace the 0.0.0.0/0 part of the line "AllowedIPs = 0.0.0.0/0" with that long list of subnets. I'll use sed as my text editor again:
root@x:/etc/wireguard# sed -e's_AllowedIPs = 0.0.0.0/0_AllowedIPs = 128.0.0.0/1, 0.0.0.0/2, 96.0.0.0/3, 80.0.0.0/4, 72.0.0.0/5, 68.0.0.0/6, 66.0.0.0/7, 65.0.0.0/8, 64.128.0.0/9, 64.64.0.0/10, 64.0.0.0/11, 64.48.0.0/12, 64.32.0.0/13, 64.44.0.0/14, 64.40.0.0/15, 64.43.0.0/16, 64.42.0.0/17, 64.42.192.0/18, 64.42.128.0/19, 64.42.160.0/20, 64.42.184.0/21, 64.42.176.0/22, 64.42.182.0/23, 64.42.180.0/24, 64.42.181.0/25, 64.42.181.128/26, 64.42.181.192/27, 64.42.181.224/28, 64.42.181.248/29, 64.42.181.240/30, 64.42.181.246/31, 64.42.181.245/32_' -i hop2.conf
Next, while you still have hop2.conf open in your editor, replace the hostname in the "Endpoint = dallas.cstorm.is:443" line with the IP you got from the `host` command earlier. So, again, with sed:
root@x:/etc/wireguard# sed -e's/dallas.cstorm.is/209.58.147.38/' -i hop2.conf
Now your hop2.conf should look something like:
root@x:/etc/wireguard# cat hop2.conf
[Interface]
PrivateKey = 4H5chAJHcdBGXhvizIFrs1VKYA6yvS67D6Uz8F38d0E=
Address = 10.10.200.146
DNS = 10.31.33.8
[Peer]
Presharedkey = 4aRLSgf/1AtPgPTQ+xYEP9eh2BY7hELR+Vk1LMBIT4o=
PublicKey = qrZ3+Jp0y2+eYlOE0heVBfFzcHhuWJ31Y5UF/mHQLRA=
Endpoint = 209.58.147.38:443
AllowedIPs = 128.0.0.0/1, 0.0.0.0/2, 96.0.0.0/3, 80.0.0.0/4, 72.0.0.0/5, 68.0.0.0/6, 66.0.0.0/7, 65.0.0.0/8, 64.128.0.0/9, 64.64.0.0/10, 64.0.0.0/11, 64.48.0.0/12, 64.32.0.0/13, 64.44.0.0/14, 64.40.0.0/15, 64.43.0.0/16, 64.42.0.0/17, 64.42.192.0/18, 64.42.128.0/19, 64.42.160.0/20, 64.42.184.0/21, 64.42.176.0/22, 64.42.182.0/23, 64.42.180.0/24, 64.42.181.0/25, 64.42.181.128/26, 64.42.181.192/27, 64.42.181.224/28, 64.42.181.248/29, 64.42.181.240/30, 64.42.181.246/31, 64.42.181.245/32
PersistentKeepalive = 25
If you don't have word wrapping enabled in your text editor, that AllowedIPs line will probably appear shorter. As long as the subnets after AllowedIPs are all on the same line, it's fine. I'm only word-wrapping it here to show what the line contains.
Your hop1.conf should look something like:
root@x:/etc/wireguard# cat hop1.conf
[Interface]
PrivateKey = 4H5chAJHcdBGXhvizIFrs1VKYA6yvS67D6Uz8F38d0E=
Address = 10.10.200.146
[Peer]
Presharedkey = 4aRLSgf/1AtPgPTQ+xYEP9eh2BY7hELR+Vk1LMBIT4o=
PublicKey = EZZUsR5l+Oe47s5900Q1JamvMYF6HB2Dbs6+ZAhXAzU=
Endpoint = 64.42.181.244:443
AllowedIPs = 209.58.147.38/32
PersistentKeepalive = 25
Now you're ready to bring up the interface for the first hop:
root@x:/etc/wireguard# wg-quick up hop1 [#] ip link add hop1 type wireguard [#] wg setconf hop1 /dev/fd/63 [#] ip -4 address add 10.10.200.146 dev hop1 [#] ip link set mtu 1420 up dev hop1
[#] ip -4 route add 209.58.147.38/32 dev hop1
Then start up the second hop:
root@x:/etc/wireguard# wg-quick up hop2 [#] ip link add hop2 type wireguard [#] wg setconf hop2 /dev/fd/63 [#] ip -4 address add 10.10.200.146 dev hop2 [#] ip link set mtu 1340 up dev hop2 [#] resolvconf -a tun.hop2 -m 0 -x [#] ip -4 route add 64.42.181.245/32 dev hop2 [#] ip -4 route add 64.42.181.246/31 dev hop2 [#] ip -4 route add 64.42.181.240/30 dev hop2 [#] ip -4 route add 64.42.181.248/29 dev hop2 [#] ip -4 route add 64.42.181.224/28 dev hop2 [#] ip -4 route add 64.42.181.192/27 dev hop2 [#] ip -4 route add 64.42.181.128/26 dev hop2 [#] ip -4 route add 64.42.181.0/25 dev hop2 [#] ip -4 route add 64.42.180.0/24 dev hop2 [#] ip -4 route add 64.42.182.0/23 dev hop2 [#] ip -4 route add 64.42.176.0/22 dev hop2 [#] ip -4 route add 64.42.184.0/21 dev hop2 [#] ip -4 route add 64.42.160.0/20 dev hop2 [#] ip -4 route add 64.42.128.0/19 dev hop2 [#] ip -4 route add 64.42.192.0/18 dev hop2 [#] ip -4 route add 64.42.0.0/17 dev hop2 [#] ip -4 route add 64.43.0.0/16 dev hop2 [#] ip -4 route add 64.40.0.0/15 dev hop2 [#] ip -4 route add 64.44.0.0/14 dev hop2 [#] ip -4 route add 64.32.0.0/13 dev hop2 [#] ip -4 route add 64.48.0.0/12 dev hop2 [#] ip -4 route add 64.0.0.0/11 dev hop2 [#] ip -4 route add 64.64.0.0/10 dev hop2 [#] ip -4 route add 64.128.0.0/9 dev hop2 [#] ip -4 route add 65.0.0.0/8 dev hop2 [#] ip -4 route add 66.0.0.0/7 dev hop2 [#] ip -4 route add 68.0.0.0/6 dev hop2 [#] ip -4 route add 72.0.0.0/5 dev hop2 [#] ip -4 route add 80.0.0.0/4 dev hop2 [#] ip -4 route add 96.0.0.0/3 dev hop2 [#] ip -4 route add 0.0.0.0/2 dev hop2 [#] ip -4 route add 128.0.0.0/1 dev hop2
Your multihop tunnel should now be active. You can check your IP with:
root@x:/etc/wireguard# wget -qO- https://cryptostorm.is/test
209.58.147.37 IS cryptostorm
On all of our VPN servers, only one IP is used for WireGuard's exit IP, which is why this test shows the IP as 209.58.147.37 instead of 209.58.147.38 (the hop2 entry IP). Dallas has 3 physical servers behind it, and on one of them 209.58.147.37 is what all WireGuard clients would get as the exit IP, no matter which entry IP they connect to (209.58.147.38, 209.58.150.202, or 209.58.150.203).
Anyways, if you run tcpdump or any other packet sniffer against your main network interface, you can confirm that traffic leaving your system is using the IP of hop1 (64.42.181.244 in this example):
root@x:/etc/wireguard# tcpdump -nni enp0s3 & ping -c 1 yahoo.com
[1] 5397
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on enp0s3, link-type EN10MB (Ethernet), snapshot length 262144 bytes
PING yahoo.com (98.137.11.164) 56(84) bytes of data.
20:34:25.962928 IP 64.42.181.244.443 > 192.168.12.213.53515: UDP, length 272
20:34:25.966461 IP 64.42.181.244.443 > 192.168.12.213.53515: UDP, length 336
20:34:25.966807 IP 192.168.12.213.53515 > 64.42.181.244.443: UDP, length 192
20:34:26.086830 IP 64.42.181.244.443 > 192.168.12.213.53515: UDP, length 192
20:34:26.086964 IP 192.168.12.213.53515 > 64.42.181.244.443: UDP, length 192
64 bytes from media-router-fp73.prod.media.vip.gq1.yahoo.com (98.137.11.164): icmp_seq=1 ttl=52 time=120 ms
--- yahoo.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 120.071/120.071/120.071/0.000 ms
If I login to the Dallas server that hosts 209.58.147.38 and use the `wg` command to try to see what the real IP of the peer 10.10.200.146 is, I'll get:
[root@dal-1 ~]# wg | grep -B4 -A4 10.10.200.146
peer: YYIoxxHPu6S2n0YiKQzELJmz8Axb4fkEuHgjoCIme2Y=
preshared key: (hidden)
endpoint: 64.42.181.228:59594
allowed ips: 10.10.200.146/32
latest handshake: 1 minute, 43 seconds ago
transfer: 42.32 KiB received, 250.76 KiB sent
persistent keepalive: every 25 seconds
So from the Dallas server's perspective, that client is connecting from the IP used for WireGuard on the Atlanta server.
What we're basically doing here is telling the system to only use hop1 to connect to hop2, then telling hop2 to send all traffic through it, except for the IP of hop1, because that needs to be routed through the main interface (otherwise recursive routing would happen and nothing would go out).
When you want to close the multihop tunnels, you would use `wg-quick down hop2` then `wg-quick down hop1`. It's important that you take down hop2 first, because if you take down hop1 first then no traffic will go anywhere since all traffic would still be redirecting to hop2, but hop1 was the only route to it.
That's also why you don't really need a firewall preventing direct access to hop2. But if you have other programs running that might be changing your routing table, for added protection, you could setup a few iptables rules to prevent any traffic from going directly to hop2's IP. Just replace enp0s3 with your main network interface, and 209.58.147.38 with whatever the second hop's IP is:
root@x:/etc/wireguard# iptables -A OUTPUT -o enp0s3 ! -d 209.58.147.38 -j ACCEPT
root@x:/etc/wireguard# iptables -A OUTPUT -o hop1 -j ACCEPT
root@x:/etc/wireguard# iptables -A OUTPUT -o enp0s3 -j DROP
Triple hop
To add a third hop to all of this, you would set AllowedIPs in hop1 to only connect to hop2, hop2 to only connect to hop3, and hop3 to send everything to it (excluding hop1 and hop2's IPs). You can actually do all of this multihop stuff in a single config, I was just using two configs in the above examples to make it easier to separate so I could better explain the steps.
In this triple hop example, I'll use Atlanta as the first hop, Bulgaria as the second, Dallas as the third (I'll turn off word wrap here since the subnet list gets pretty long, but there should be a scrollbar at the bottom that you can use to see the whole thing). Here's what the config would look like (with comments):
root@x:/etc/wireguard# cat triplehop.conf [Interface] PrivateKey = 4H5chAJHcdBGXhvizIFrs1VKYA6yvS67D6Uz8F38d0E= Address = 10.10.200.146 DNS = 10.31.33.8 [Peer] Presharedkey = 4aRLSgf/1AtPgPTQ+xYEP9eh2BY7hELR+Vk1LMBIT4o= PublicKey = qrZ3+Jp0y2+eYlOE0heVBfFzcHhuWJ31Y5UF/mHQLRA= # dallas.cstorm.is, the 3rd hop Endpoint = 209.58.147.38:443 # Everything through hop3, except for hop1 & hop2's IP. Generated with: # wget -qO- https://cryptostorm.is/wga?ip=37.120.152.238,64.42.181.244 AllowedIPs = 128.0.0.0/1, 0.0.0.0/3, 48.0.0.0/4, 40.0.0.0/5, 32.0.0.0/6, 38.0.0.0/7, 36.0.0.0/8, 37.128.0.0/9, 37.0.0.0/10, 37.64.0.0/11, 37.96.0.0/12, 37.112.0.0/13, 37.124.0.0/14, 37.122.0.0/15, 37.121.0.0/16, 37.120.0.0/17, 37.120.192.0/18, 37.120.160.0/19, 37.120.128.0/20, 37.120.144.0/21, 37.120.156.0/22, 37.120.154.0/23, 37.120.153.0/24, 37.120.152.0/25, 37.120.152.128/26, 37.120.152.192/27, 37.120.152.240/28, 37.120.152.224/29, 37.120.152.232/30, 37.120.152.236/31, 37.120.152.239/32, 96.0.0.0/3, 80.0.0.0/4, 72.0.0.0/5, 68.0.0.0/6, 66.0.0.0/7, 65.0.0.0/8, 64.128.0.0/9, 64.64.0.0/10, 64.0.0.0/11, 64.48.0.0/12, 64.32.0.0/13, 64.44.0.0/14, 64.40.0.0/15, 64.43.0.0/16, 64.42.0.0/17, 64.42.192.0/18, 64.42.128.0/19, 64.42.160.0/20, 64.42.184.0/21, 64.42.176.0/22, 64.42.182.0/23, 64.42.180.0/24, 64.42.181.0/25, 64.42.181.128/26, 64.42.181.192/27, 64.42.181.224/28, 64.42.181.248/29, 64.42.181.240/30, 64.42.181.246/31, 64.42.181.245/32 PersistentKeepalive = 25 [Peer] Presharedkey = 4aRLSgf/1AtPgPTQ+xYEP9eh2BY7hELR+Vk1LMBIT4o= PublicKey = 5JBGYHJx5cZMRWHot4yKd5fPuH7cvGupppO4p97WfQk= # bulgaria.cstorm.is, the 2nd hop Endpoint = 37.120.152.238:443 # dallas.cstorm.is, the 3rd hop AllowedIPs = 209.58.147.38 PersistentKeepalive = 25 [Peer] Presharedkey = 4aRLSgf/1AtPgPTQ+xYEP9eh2BY7hELR+Vk1LMBIT4o= PublicKey = EZZUsR5l+Oe47s5900Q1JamvMYF6HB2Dbs6+ZAhXAzU= # atlanta.cstorm.is, the 1st hop Endpoint = 64.42.181.244:443 # bulgaria.cstorm.is, the 2nd hop AllowedIPs = 37.120.152.238 PersistentKeepalive = 25
Starting it up should show:
root@x:/etc/wireguard# wg-quick up triplehop [#] ip link add triplehop type wireguard
[#] wg setconf triplehop /dev/fd/63
[#] ip -4 address add 10.10.200.146 dev triplehop [#] ip link set mtu 1420 up dev triplehop [#] resolvconf -a tun.triplehop -m 0 -x
[#] ip -4 route add 64.42.181.245/32 dev triplehop [#] ip -4 route add 37.120.152.239/32 dev triplehop [#] ip -4 route add 37.120.152.238/32 dev triplehop [#] ip -4 route add 209.58.147.38/32 dev triplehop [#] ip -4 route add 64.42.181.246/31 dev triplehop [#] ip -4 route add 37.120.152.236/31 dev triplehop [#] ip -4 route add 64.42.181.240/30 dev triplehop [#] ip -4 route add 37.120.152.232/30 dev triplehop [#] ip -4 route add 64.42.181.248/29 dev triplehop [#] ip -4 route add 37.120.152.224/29 dev triplehop [#] ip -4 route add 64.42.181.224/28 dev triplehop [#] ip -4 route add 37.120.152.240/28 dev triplehop [#] ip -4 route add 64.42.181.192/27 dev triplehop [#] ip -4 route add 37.120.152.192/27 dev triplehop [#] ip -4 route add 64.42.181.128/26 dev triplehop [#] ip -4 route add 37.120.152.128/26 dev triplehop [#] ip -4 route add 64.42.181.0/25 dev triplehop [#] ip -4 route add 37.120.152.0/25 dev triplehop [#] ip -4 route add 64.42.180.0/24 dev triplehop [#] ip -4 route add 37.120.153.0/24 dev triplehop [#] ip -4 route add 64.42.182.0/23 dev triplehop [#] ip -4 route add 37.120.154.0/23 dev triplehop [#] ip -4 route add 64.42.176.0/22 dev triplehop [#] ip -4 route add 37.120.156.0/22 dev triplehop [#] ip -4 route add 64.42.184.0/21 dev triplehop [#] ip -4 route add 37.120.144.0/21 dev triplehop [#] ip -4 route add 64.42.160.0/20 dev triplehop [#] ip -4 route add 37.120.128.0/20 dev triplehop [#] ip -4 route add 64.42.128.0/19 dev triplehop [#] ip -4 route add 37.120.160.0/19 dev triplehop [#] ip -4 route add 64.42.192.0/18 dev triplehop [#] ip -4 route add 37.120.192.0/18 dev triplehop [#] ip -4 route add 64.42.0.0/17 dev triplehop [#] ip -4 route add 37.120.0.0/17 dev triplehop [#] ip -4 route add 64.43.0.0/16 dev triplehop [#] ip -4 route add 37.121.0.0/16 dev triplehop [#] ip -4 route add 64.40.0.0/15 dev triplehop [#] ip -4 route add 37.122.0.0/15 dev triplehop [#] ip -4 route add 64.44.0.0/14 dev triplehop [#] ip -4 route add 37.124.0.0/14 dev triplehop [#] ip -4 route add 64.32.0.0/13 dev triplehop [#] ip -4 route add 37.112.0.0/13 dev triplehop [#] ip -4 route add 64.48.0.0/12 dev triplehop [#] ip -4 route add 37.96.0.0/12 dev triplehop [#] ip -4 route add 64.0.0.0/11 dev triplehop [#] ip -4 route add 37.64.0.0/11 dev triplehop [#] ip -4 route add 64.64.0.0/10 dev triplehop [#] ip -4 route add 37.0.0.0/10 dev triplehop [#] ip -4 route add 64.128.0.0/9 dev triplehop [#] ip -4 route add 37.128.0.0/9 dev triplehop [#] ip -4 route add 65.0.0.0/8 dev triplehop [#] ip -4 route add 36.0.0.0/8 dev triplehop [#] ip -4 route add 66.0.0.0/7 dev triplehop [#] ip -4 route add 38.0.0.0/7 dev triplehop [#] ip -4 route add 68.0.0.0/6 dev triplehop [#] ip -4 route add 32.0.0.0/6 dev triplehop [#] ip -4 route add 72.0.0.0/5 dev triplehop [#] ip -4 route add 40.0.0.0/5 dev triplehop [#] ip -4 route add 80.0.0.0/4 dev triplehop [#] ip -4 route add 48.0.0.0/4 dev triplehop [#] ip -4 route add 96.0.0.0/3 dev triplehop [#] ip -4 route add 0.0.0.0/3 dev triplehop [#] ip -4 route add 128.0.0.0/1 dev triplehop
After that, https://cryptostorm.is/test should say your IP is 209.58.147.37 (Dallas).
And as before, if you run tcpdump against the main interface, traffic will appear to be going to 64.42.181.244 (Atlanta). If I login to the Bulgaria server to try to get the real IP of the WireGuard client on 10.10.200.146, I would instead see the Atlanta server's WireGuard IP:
[root@bulgaria ~]# wg | grep -B4 -A4 10.10.200.146
peer: YYIoxxHPu6S2n0YiKQzELJmz8Axb4fkEuHgjoCIme2Y=
preshared key: (hidden)
endpoint: 64.42.181.228:51371
allowed ips: 10.10.200.146/32
latest handshake: 1 minute, 43 seconds ago
transfer: 42.32 KiB received, 250.76 KiB sent
persistent keepalive: every 25 seconds
And if I used tcpdump on the server to sniff the packets of 10.10.200.146, all I would see is traffic going to 209.58.147.38 (Dallas). All of the traffic would be encrypted at this point too, so the Bulgaria server can't see what the traffic is, only where it's going. If I login to the Dallas server, the 10.10.200.146 client would appear to be coming from 37.120.152.237 (Bulgaria's WireGuard IP):
[root@dal-1 ~]# wg | grep -B4 -A4 10.10.200.146
peer: YYIoxxHPu6S2n0YiKQzELJmz8Axb4fkEuHgjoCIme2Y=
preshared key: (hidden)
endpoint: 37.120.152.237:38084
allowed ips: 10.10.200.146/32
latest handshake: 1 minute, 30 seconds ago
transfer: 104.01 KiB received, 655.07 KiB sent
persistent keepalive: every 25 seconds
Septuple hop
You probably shouldn't do this. It'll be very slow. It increased my ping time to 8.8.8.8 by about 900ms. I'm just putting this here to show that it's possible. But I'm too lazy to setup each individual hop manually, so instead I repurposed the https://cryptostorm.is/wg_confgen.txt script to create a config with all the hops:
root@x:/etc/wireguard# cat hoppity.sh#!/bin/bash psk=4aRLSgf/1AtPgPTQ+xYEP9eh2BY7hELR+Vk1LMBIT4o= myip=10.10.200.146 DNS=10.31.33.8 declare -a nodes=( "austria:S5ymECx1eYP9g3CH9SSRKWC40TnfccBqjNjkC2Y6ljo=" "belgium:qdG2OTZYTcgUfvk96NYGy2q137AF6tlOsf1C7HHR6xo=" "brazil:Z+UMUQdQKUIXOtTwd2aF59mu2ZLk+Xsrh93Xu37Vhgc=" "bulgaria:5JBGYHJx5cZMRWHot4yKd5fPuH7cvGupppO4p97WfQk=" "montreal:w8+i77Jy0/rVVXe3jGa93Yu1nbAEZiysTJb9T4QsCiw=" "vancouver:oRDFg9PmkpiukA99BM0yewysFHJpDHdVcIhsqZLCTUk=" "czech:FB/YP7iTtOL4F1SyqpPlmLOqq53UgtCMxvvkwL3ikgs=" ) declare node_ips # dns lookup the hosts first for node in "${nodes[@]}"; do host=`echo $node | awk -F: '{print $1".cstorm.is"}'` echo -n "Looking up $host... " host_ip=`host $(echo $host) | awk '{print $NF}' | shuf -n1` echo $host_ip node_ips+=("$host_ip") done echo Generating config... cat > /etc/wireguard/bouncy.conf < > /etc/wireguard/bouncy.conf <
This script makes assumptions like: you have `wget` installed, and a `shuf` command, and a `host` command. Obviously you need to change the psk= line to your actual PSK, and myip= to your 10.10.x.x IP (both of which our https://cryptostorm.is/wireguard page generates). What this script does is, using the same node list format that confgen.sh uses, iterates through each host in the node list, resolves their IPs, then iterates through it again, placing each peer inside the WireGuard config file. It sets the AllowedIPs for each hop to the next hop's IP, until it reaches the last hop. For that one it uses https://cryptostorm.is/wga?ip= along with a comma separated list of all the endpoint IPs (except the last one). It then puts the output of that /wga page into AllowedIPs for the next hop.
After changing psk/ip, place the script in /etc/wireguard/ and do a `chmod +x hoppity.sh`, then run it with `./hoppity.sh`
It'll create a bouncy.conf WireGuard config that you can bring up with `wg-quick up bouncy`. In this example, it would bounce from Austria to Belgium to Brazil to Bulgaria to Montreal to Vancouver then finally to Czech. If you want it to go through different hops, use the node list format that the https://cryptostorm.is/wg_confgen.txt script uses ("nodename:nodepublickey").
Conclusion
Not that anyone at CS would do it, but theoretically if we wanted to match a client's real IP with their outgoing traffic, we could run tcpdump on all the servers in a multihop chain. The first hop to match the client's real IP and to get the second hop's IP, the second hop's server to figure out the third hop's IP, etc. etc. until we get to the final server to sniff the client's outgoing traffic. To prevent that theoretical situation from happening, you could always combine this type of multihop with another VPN provider that supports WireGuard. Connecting to them before us would mean we can't get your real IP, but we can see your outgoing traffic (which should be encrypted, so only the metadata), and they can get your real IP but not see your outgoing traffic. Connecting to us before them would mean we can see your real IP, but not your outgoing traffic (even the metadata), and they could see your outgoing traffic but not your real IP.