Guide: WireGuard on OpenVZ/LXC VPS

DanielDaniel OG
edited November 2019 in Technical

I posted something like this somewhere in the old forum (and on my blog), but figured it was worth reposting in this new forum.

WireGuard is an exciting, new, extremely simple VPN system that uses state-of-the-art cryptography. Its Linux implementation runs in the kernel, which provides a significant performance boost compared to traditional userspace VPN implementations

The WireGuard kernel module is great, but sometimes you might not be able to install new kernel modules. One example scenario is on a VPS that uses OpenVZ or LXC. For these cases, we can use wireguard-go, a userspace implementation of WireGuard. This is the same implementation used on MacOS, Windows, and the WireGuard mobile apps. This implementation is slower than the kernel module, but still plenty fast.

This post focuses on Debian, however the instructions should mostly work on other Linux distros too.

Install WireGuard Tools

We need to install the WireGuard tools (wg-quick). On Debian, you can run this as root:

echo "deb http://deb.debian.org/debian/ unstable main" > /etc/apt/sources.list.d/unstable.list
printf 'Package: *\nPin: release a=unstable\nPin-Priority: 90\n' > /etc/apt/preferences.d/limit-unstable
apt update
apt install wireguard-tools --no-install-recommends

(see the WireGuard site for instructions if you're not on Debian)

Install Go

Unfortunately, since wireguard-go is not packaged for Debian, we need to compile it ourselves. To compile it, we first need to install the latest version of the Go programming language (currently version 1.13.4).

cd /tmp
wget https://dl.google.com/go/go1.13.4.linux-amd64.tar.gz
tar zvxf go1.13.4.linux-amd64.tar.gz
sudo mv go /opt/go1.13.4
sudo ln -s /opt/go1.13.4/bin/go /usr/local/bin/go

Now, running go version should show the version number.

Compile wireguard-go

Now that we've got Go, we can download and compile wireguard-go. Download the latest release version:

cd /usr/local/src
wget https://git.zx2c4.com/wireguard-go/snapshot/wireguard-go-0.0.20191012.tar.xz
tar xvf wireguard-go-0.0.20191012.tar.xz
cd wireguard-go-0.0.20191012

If you are on a system with limited RAM (256 MB or lower), which you probably are if you're on this forum, you will need to do a small tweak to the wireguard-go code to make it use less RAM. Open device/queueconstants_default.go and replace this:

MaxSegmentSize             = (1 << 16) - 1 // largest possible UDP datagram
PreallocatedBuffersPerPool = 0 // Disable and allow for infinite memory growth

With these values (taken from device/queueconstants_ios.go):

MaxSegmentSize             = 1700
PreallocatedBuffersPerPool = 1024

This will make it use a fixed amount of RAM (~20 MB max), rather than allowing memory usage to grow infinitely.

Now we can compile it:

make
# "Install" it
sudo cp wireguard-go /usr/local/bin

Running wireguard-go --version should work and show the version number.

If you have multiple VPSes that use the same OS version and architecture (eg. Debian 10, 64-bit), you can compile it on one of them and then just copy the wireguard-go binary to all the others.

Configuration

wg0.conf

You'll need to configure /etc/wireguard/wg0.conf to contain the configuration for your peer. This post won't go into significant detail about this; please refer to another general WireGuard guide (like this one) for more details. The basic jist is that you need to run:

wg genkey | tee privatekey | wg pubkey > publickey

to generate a public/private key pair for each peer, then configure the [Interface] with the private key for the peer, and a [Peer] section for each peer that can connect to it.

Your wg0.conf should end up looking something like:

[Interface] 
Address = 10.123.0.2
PrivateKey = 12345678912345678912345678912345678912345678
ListenPort = 51820

[Peer] 
PublicKey = 987654321987654321987654321987654321987654321
AllowedIPs = 10.123.0.1/32
Endpoint = 198.51.100.1:51820

systemd

We need to modify the systemd unit to pass the WG_I_PREFER_BUGGY_USERSPACE_TO_POLISHED_KMOD flag to wireguard-go, to allow it to run on Linux. Open /lib/systemd/system/[email protected], find:

Environment=WG_ENDPOINT_RESOLUTION_RETRIES=infinity

and add this line directly below:

Environment=WG_I_PREFER_BUGGY_USERSPACE_TO_POLISHED_KMOD=1

Finally, enable and start the systemd service:

systemctl enable [email protected]
systemctl start [email protected]

Enabling the systemd service will connect the VPN on boot, and starting the systemd service will connect it right now.

You're Done

Now, everything should be working! You can check the status of wg-quick by running systemctl status [email protected], which should return something like:

[email protected] - WireGuard via wg-quick(8) for wg0 
   Loaded: loaded (/lib/systemd/system/[email protected]; enabled; vendor preset: enabled) 
   Active: active (exited) since Mon 2019-07-01 06:30:30 UTC; 1 day 22h ago 

Running wg will give you a list of all the peers, and some details about them:

interface: wg0
  public key: 987654321987654321987654321987654321987654321
  private key: (hidden)
  listening port: 38917

peer: 987654321987654321987654321987654321987654321
  endpoint: 198.51.100.1:51820
  allowed ips: 10.123.0.1/32
  latest handshake: 1 day, 22 hours, 59 minutes, 34 seconds ago
  transfer: 2.75 KiB received, 2.83 KiB sent
Tagged:

Comments

  • AnthonySmithAnthonySmith AdministratorHosting Provider

    @Daniel i really appreciate you taking the time to post this, its exactly the sort of content that makes the community backbone stronger!

    Inception Hosting - we surveyed 100 people and asked them what a fat husband may hide from his wife in his belly button, the 3rd most popular answer was: "Jewelry"

  • AnthonySmith said: i really appreciate you taking the time to post this, its exactly the sort of content that makes the community backbone stronger!

    I'm happy to help! :)

    In case anyone doesn't want to compile wireguard-go themselves for some reason, here's a version I built on a 64-bit machine running Debian 10: https://d.ls/wireguard/wireguard-go-v0.0.20191012. Do prefer compiling it yourself though

  • Thanks @Daniel, I didn't know you were an active user on here, I posted a link to your guide last week:

    https://talk.lowendspirit.com/discussion/comment/3897#Comment_3897

    Notes from me:

    • Pinning the unstable Debian repo to get the wireguard-tools package in a 128MB LES NAT VPS gave me "failed to fork" errors with apt commands. Switching to Anthony's new slimline Ubuntu 18.04 template meant I could use the Wireguard PPA instead, which doesn't use as much resources. Pinning the unstable repo might work fine on the new 256MB plans though...

    • Compiling the wireguard-go binary is much better done on a local machine with more resources than a LES box (be sure to make the necessary adjustments detailed to keep RAM usage low!) Once it spits out the binary, push it onto your LES box with SCP/SFTP etc., copy it to /usr/local/bin and make it executable

    I've got this setup working nicely on one of Ant's UK 128MB NAT VPSes, and even though Wireguard is the userspace go implementation, speeds have been better than OpenVPN for me. Of course, OpenVPN is older and much more thoroughly historically audited compared to Wireguard (but that's a digression for someone else to take up).

    And thanks again @Daniel! Yours was the most comprehensive guide I found to get Wireguard working on OpenVZ!

  • greensysadmin said: Pinning the unstable Debian repo to get the wireguard-tools package in a 128MB LES NAT VPS gave me "failed to fork" errors with apt commands.

    Interesting! I didn't have any issues with it on my MrVM 128 MB NAT VPS. Another alternative is to just manually download the .deb from https://packages.debian.org/sid/amd64/wireguard-tools/download (for example by using wget) and install it using apt install./wireguard-tools_0.0.20191012-1_amd64.deb. You do need to manually install updates in that case though.

    greensysadmin said: Compiling the wireguard-go binary is much better done on a local machine with more resources than a LES box (be sure to make the necessary adjustments detailed to keep RAM usage low!)

    That's a good suggestion. Having said that, Wireguard-go is very light so compilation generally takes less than a minute, and I didn't have any issues with it on a 256 MB VPS. I did it on one VPS and then scp'd it to several others.

    greensysadmin said: Of course, OpenVPN is older and much more thoroughly historically audited

    The OpenVPN codebase is enormous though. Wireguard is significantly smaller, which also makes it easier to audit the entire codebase.

  • Has anyone done a "start wireguard on host then move to LXC container" configuration?

    There is a tutorial on wireguard's website but I wonder if there is an LXC-kosher way of doing it.

    The all seeing eye sees everything...

  • @terrorgen said:
    Has anyone done a "start wireguard on host then move to LXC container" configuration?

    There is a tutorial on wireguard's website but I wonder if there is an LXC-kosher way of doing it.

    Nvm got it working...

    The all seeing eye sees everything...

  • terrorgen said: Has anyone done a "start wireguard on host then move to LXC container" configuration?

    I haven't tried that yet, but it's something I'm interested in looking into. WireGuard's docs aren't very clear at the moment... But that's understandable, as far as I know it's mostly one guy (the creator, Jason Donenfield) writing most of the code and the docs. Pretty impressive.

    Thanked by mfs terrorgen
Sign In or Register to comment.