Wireguard is the hip, new way to VPN :P
No, but seriously I wanted to try it out because it is super interesting and I think the direction it is going is awesome. Read about it on their website if you have not already.
What is cool about Wireguard is it integrates into the Linux networking stack so you have a lot of power over interactions with it. In other words, it is very easy to clone the interface into specific containers. Or just use it on your host.
If you are new to my blog, I HATEEEE installing things on my host. I run everything in containers. Wireguard is a kernel module. BUT guess what, literally anything can be run in a container. This post is going to go over how to install the Wireguard module by using a container and how to run the tools from a container as well.
UPDATE (April 2020): You might want to use Tailscale. It is simple to install and cross platform since it uses the go implementation of wireguard. Then you don’t have to mess with the kernel!
I will never forget this thread from 2017 ;) so glad to see the go implementation happen!
Soooooo waiting for the userspace portable Go implementation.
— Filippo Valsorda 🇮🇹 (@FiloSottile) June 21, 2017
Installing I wrote a Dockerfile for installing the kernel module.
You can run it with:
``` $ docker run --rm -it \ --name wireguard \ -v /lib/modules:/lib/modules \ -v /usr/src:/usr/src:ro \ r.j3ss.co/wireguard:install
```
This only works if you have your kernel headers installed in /usr/src and
your kernel allows kernel modules (CONFIG_MODULES=y). This will change your kernel modules on your
host since you are mounting that directory.
If you are like me and set CONFIG_MODULES=n then you can use my
kernel-builder Dockerfile
to build a custom kernel.
``` $ docker run --rm -it \ -v /usr/src:/usr/src \ -v /lib/modules:/lib/modules \ -v /boot:/boot \ --name kernel-builder \ r.j3ss.co/kernel-builder
```
That will pop you into a bash shell where you can run the following build script to build a specific kernel version.
```
```
That saves the vmlinuz to /boot (on your host, since you mounted that directory) where you can then update your initramfs
for the new image and add it to your bootloader if needed.
Using the tools
wg is the command for interacting with Wireguard. You can learn more about it
in their docs.
I put the tools in a container and added a bash alias for them:
``` $ type wg wg is a function wg () { docker run -it --rm --log-driver none -v /tmp:/tmp --cap-add NET_ADMIN --net host --name wg r.j3ss.co/wg "$@" }
```
Then you can run the following commands to try sending some packets through
Wireguard. The below steps come from the
following script
which is Copyright (C) 2015-2018 Jason A. Donenfeld. All Rights Reserved. GPL-2.0.
I merely added comments for the steps.
``` $ export WG_PRIVATE_KEY="$(wg genkey)"
$ exec 3<>/dev/tcp/demo.wireguard.com/42912
$ wg pubkey <<<"$WG_PRIVATE_KEY" >&3
$ IFS=: read -r status server_pubkey server_port internal_ip <&3
$ echo $status OK
$ sudo ip link del dev wg0 || true
$ sudo ip link add dev wg0 type wireguard
$ echo "$WG_PRIVATE_KEY" > /tmp/wg-privatekey
$ wg set wg0 private-key /tmp/wg-privatekey peer "$server_pubkey" allowed-ips 0.0.0.0/0 endpoint "demo.wireguard.com:$server_port" persistent-keepalive 25
$ sudo -E ip address add "$internal_ip"/24 dev wg0
$ sudo ip link set up dev wg0
$ export WG_HOST="$(wg show wg0 endpoints | sed -n 's/.\t(.):.*/\1/p')"
$ sudo -E ip route add $(ip route get $WG_HOST | sed '/ via [0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}/{s/^(. via [0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3})./\1/}' | head -n 1) $ sudo ip route add 0/1 dev wg0 $ sudo ip route add 128/1 dev wg0
```
Test it is routing!
``` $ curl https://httpbin.j3ss.co/ip {"origin":"163.172.161.0"}
```
And that’s all. Just thought it was kinda fun using this and now it is very easy to install :)