We have a new VPN at work which works with WireGuard.
There are a lot of guides on the web like :
I’m going to present 2 cases:
- Home need: I need a VPN access for my phone and laptop in order to access block stuff in some situation. All the traffic goes throught the VPN. It’s the simplest case
- Work need: I need to access some ip or ip ranges but not all the traffic goes throught the VPN.
Home
Server
- Install of WireGuard. I’m on debian 10
- create a
/etc/apt/sources.list.d/backport.list
deb http://deb.debian.org/debian buster-backports main
apt update && apt install wireguard
reboot
. WireGuard consist of a kernel module which need to be loaded by the kernel. And unstable will upgrade you kernel to 4.19. that’s why. On ArchLinux for example you don’t need to reboot.
- create a
- Generate the key pair
cd /etc/wireguard
umask 077
wg genkey | tee privatekey | wg pubkey > publickey
- Fill the the file
/etc/wireguard/wg0.conf
.wg0
is the name of your interface it can be everything likewg10
or evenchambery
[Interface]
Address = 10.10.10.1/24
ListenPort = 51820
PrivateKey = <my private key>
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
PublicKey = <client pub key>
AllowedIPs = 10.10.10.2/32
Interface
means that you listen here. And a Peer
means a distant… Peer at the end of the
tunnel. You have to declare every peer in your VPN. Which mean that if you deploy wireguard as a VPN
concentrator for you company you will need some automation here !
There are some work going on to add dynamic IP to wireguard. Look at the idea here
The PostUp/PostDown
are here to NAT the private addresses to the address where the traffic goes
(generally, the internet). But in case you just want a tunnel to access internal stuff. You don’t need NAT.
- Start the service :
wg-quick up wg0
. - Once it works, enable the service in
systemd
, this way the interface get up when you start the system:systemctl enable wg-quik@wg0
Client
I’m on Arch, so I just have to do pacman -S wireguard
. Note that, Since kernel 5.6 (at this time
Arch runs on 5.6) integrate WireGuard. So pacman only download the tooling 😏. Pretty neat.
- Generate a key pair. Same way than on the server :
cd /etc/wireguard
umask 077
wg genkey | tee privatekey | wg pubkey > publickey
Then fill the /etc/wireguard/wg0.conf
[Interface]
PrivateKey = <Client Private Key>
Address = 10.10.10.2/32
DNS=10.10.10.1 # if you have a dns on the server !! if not, server of the machine will be the same as before.
[Peer]
PublicKey = <Client Public Key>
AllowedIPs = 0.0.0.0/0 # this specific address means all the traffic.
Endpoint=1.2.3.4/32 # The ip address of your server. can be an domain.
You can now launch !: wg-quick up wg0
And see status : wg show
.
Query (for example) ifconfig.io
:
curl https://ifconfig.io
The IP returned should be the one from your distant box endpoint.
Corp
At Camptocamp I needed a split tunneling. A VPN where only the traffic for our clients goes through the tunnel, not the whole traffic of my machine, it allow us to have a pretty small machine and bandwidth compared to what it should if all the traffic of all employees goes through it.
Server
The server configuration is the same as above
Client
What we want is to route through some route or ip range. The list of IP addresses I want is on git repo but it does not matter, it could anywhere.
Since AllowedIPs
cannot be set via shell script in the wgX.conf
, we will need to use
PostUp/PreDown
to:
- Add allowed ips to the peer.
- add the route in the routing table of the system. Wireguard doesn’t do this for you.
Set this script where you want, you’ll have to prive a $VPN_ROUTES
yourself ! This need
modifications.
#/bin/sh
set -e
UP_OR_DOWN=$1
WG_INTERFACE=$2
WG_PEERPUBKEY=$3
# this script expose a variable $VPN_ROUTES with all the endpoint that need
# to be added to route and AllowedIPs. You can curl your IPAM, maintain a list curl a gist on
# github. It's shell you can do whatever you want 😀 !
VPN_ROUTES="1.2.3.4/24 10.0.0.0/24"
# input like "join_by , A B C " output "A,B,C"
function join_by { local IFS="$1"; shift; echo "$*"; }
function add_routes() {
for route in $VPN_ROUTES; do
echo "ip route add $route"
ip ro add $route dev $WG_INTERFACE
done
}
function up_peer() {
wg set $WG_INTERFACE peer $WG_PEERPUBKEY allowed-ips $(join_by , $VPN_ROUTES)
add_routes
}
Then in /etc/wireguard/wg1.conf
[Peer]
PublicKey = <server pub key>
Endpoint = wg.example.com:12345
[Interface]
PrivateKey = <my private key>
Address = 10.2.3.4
PostUp = /path/to/my/wireguard/setup/route.sh up wg0 "<server pub key>"
Why does it need to set up the route ? If I set
AllowedIPs
to0.0.0.0/0
it works !
It works because wg-quick
will read the AllowedIPs
and create the route accordingly. Here we are setting up route via wg
which does only takes care of setting up the wireguard interface, not the routing.