Guide: WireGuard on OpenVZ/LXC VPS
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 wg-quick@wg0 systemctl start wg-quick@wg0
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 wg-quick@wg0
, 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
Daniel15 | https://d.sb/. List of all my VPSes: https://d.sb/servers
dnstools.ws - DNS lookups, pings, and traceroutes from 30 locations worldwide.
Comments
@Daniel i really appreciate you taking the time to post this, its exactly the sort of content that makes the community backbone stronger!
https://inceptionhosting.com
Please do not use the PM system here for Inception Hosting support issues.
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
Daniel15 | https://d.sb/. List of all my VPSes: https://d.sb/servers
dnstools.ws - DNS lookups, pings, and traceroutes from 30 locations worldwide.
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!
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 usingapt install./wireguard-tools_0.0.20191012-1_amd64.deb
. You do need to manually install updates in that case though.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.
The OpenVPN codebase is enormous though. Wireguard is significantly smaller, which also makes it easier to audit the entire codebase.
Daniel15 | https://d.sb/. List of all my VPSes: https://d.sb/servers
dnstools.ws - DNS lookups, pings, and traceroutes from 30 locations worldwide.
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...
Nvm got it working...
The all seeing eye sees everything...
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.
Daniel15 | https://d.sb/. List of all my VPSes: https://d.sb/servers
dnstools.ws - DNS lookups, pings, and traceroutes from 30 locations worldwide.
Hm, if using a NAT VPS, the endpoint would be my assigned NAT IPv4? And, what's the port number for?
Or should I set it to the official IP I'm NAT'ed behind?
Maybe I am confused as to the conceptual part?
(I haven't read all docs yet, just started playing for the first time right now, just compiled the binary.)
You use the external IP to one of the ports allocated to your NAT VPS that aren't in use. It'll be sent magically to your private IP.
My pronouns are asshole/asshole/asshole. I will give you the same courtesy.
For all my NAT VPSes, I'm using the IPv6 addresses (in general I use only IPv6 for inbound connections to NAT VPSes). You could use the IPv4 as long as you use a port number in your NAT port range, but I found it easier to use IPv6 so that every VPS can use the same port for WireGuard (makes my life easier when managing the configs).
For IPv6, wrap them in
[
and]
, eg this is a part of my config:or use domain names.
That port number is just one I made up or took from the WireGuard docs (can't remember). It can be anything as long as you're not using that UDP port for anything else. If you do use the NAT IPv4, it needs to be a port in your port range.
Daniel15 | https://d.sb/. List of all my VPSes: https://d.sb/servers
dnstools.ws - DNS lookups, pings, and traceroutes from 30 locations worldwide.
Hehe, I do understand how NAT and the port forwarding of my ports work ... So the
endpoint
here in the server config should just correspond to what I put in the client config, then ...(I assumed it would be enough to tell my NAT VPS wireguard config about the local IP, listen on i.e.
192.168.20.20:12345
, and then the client would be the one requiring<official IP>:12345
...)Makes sense. Thank you. Another question, a couple of my frequent (wifi) location don't have IPv6 at all. Can I somehow connect via IPv4 to my Wireguard node, and then have full IPv6 from there? The config you showed here assumes IPv6 all the way?
(Or maybe I should get some sleep, not thinking clearly now.)
BTW: Thanks! This is super helpful!
You could get a HE Tunnelbroker IPv6 tunnel and set that up on your laptop
I think it's possible (tunnelling 'public' IPv6 over WireGuard), not sure though. I just use it for a point-to-point VPN, connecting a bunch of VPSes together. Some VPN providers are using WireGuard now, so it should be doable.
Yeah, every internet connection I use frequently (home, work, phone) are all fully native IPv6, so I haven't had to worry about anything without IPv6 support.
Daniel15 | https://d.sb/. List of all my VPSes: https://d.sb/servers
dnstools.ws - DNS lookups, pings, and traceroutes from 30 locations worldwide.
My phone/LTE just offer CGNAT and no IPv6 ...
Got it working.
I've heard that CGNAT is relatively popular in various European countries, and in China. On the other hand, a lot of the American phone carriers are almost exclusively IPv6 now... T-Mobile is ~95% IPv6, using NAT64 to connect to legacy (IPv4-only) services.
Daniel15 | https://d.sb/. List of all my VPSes: https://d.sb/servers
dnstools.ws - DNS lookups, pings, and traceroutes from 30 locations worldwide.
(Got some help from this article too: https://angristan.xyz/how-to-setup-vpn-server-wireguard-nat-ipv6/)
Do you guys know if setting up L2TP/Ipsec, openswan or something is doable/will work on an OpenVZ7 NAT VPS? (Some routers don't speek Wireguard.)
Hi all, a little late to this thread but hopefully someone might be able to shed some light. The guide is great and much appreciated, I have managed to get wireguard-go running on a 128mb LES NAT VPS. As the VPS has a /64 IPV6 subnet assigned, would it be possible to assign a /80 IPV6 subnet to the wireguard interface and assign IPV6 addresses to my devices that way? My home network has IPV6 but my mobile network is IPV4 only. I've read the angristan.xyz guide, and I can get IPV6 NAT using ULAs working but this is not what I'm after.
I've managed to do this at home with a raspberry pi as the wireguard server. I had to add IPV6 routes for the wireguard subnets from the router to the raspberry pi for it to work. I think I can also install NDP Proxy Daemon on the raspberry pi instead but have not tried that yet as manually adding routes on the router worked and I left it at that.
On the VPS however, I used tcpdump to listen to IPV6 packets on wg0 and venet0. I can see traffic from my device to the VPS on wg0 (on the /80 subnet I assigned), and I can see traffic from venet0 going out, however there are no incoming packets on venet0. There are also no neighbor solicitation packets on venet0. How do I add a route for the /80 wireguard subnet? I thought the entire /64 subnet should be routed to the VPS but this does not seem to be the case. What am I missing here?
I‘d be interested as well
https://canvay.io - A simple webhosting platform
https://v6node.com - Affordable IPv6 only KVMs
Not 100% sure but I have a feeling this won't work on OpenVZ due to how it configures the network device, and you'll need to try it on KVM instead.
Daniel15 | https://d.sb/. List of all my VPSes: https://d.sb/servers
dnstools.ws - DNS lookups, pings, and traceroutes from 30 locations worldwide.
Thanks for this @Daniel
Ympker's Shared/Reseller Hosting Comparison Chart, Ympker's VPN LTD Comparison, Uptime.is, Ympker's GitHub.
@Daniel might be interesting to you: https://blog.cloudflare.com/boringtun-userspace-wireguard-rust/
Cloudflare built their own WireGuard userspace implementation in Rust called BoringTun.
Little bit of drama with them building their own instead of contributing directly to a WireGuard subproject, but there's an explainer in the comments from Cloudflare:
🦍🍌
When I was doing my initial prototyping, I couldn't get BoringTun working on OpenVZ: https://github.com/cloudflare/boringtun/issues/90. Seems like the issue I had was fixed though, I just haven't tried it again since Wireguard-go is working for me. I'd be interested in hearing whether anyone tries it out and how it compares to the Go implementation
Daniel15 | https://d.sb/. List of all my VPSes: https://d.sb/servers
dnstools.ws - DNS lookups, pings, and traceroutes from 30 locations worldwide.
I tried to do
wg-quick up wg0
but get this error:iptables v1.8.4 (nf_tables): Could not fetch rule set generation id: Invalid argument
any idea how to solve this?
my vps is OVZ7 container from InceptionHost
install iptables and/or 'touch /option.netfilter'
https://inceptionhosting.com
Please do not use the PM system here for Inception Hosting support issues.
I already tried the suggestion from knowledgebase section, but still getting that error.
wg-quick up wg0
[#] ip link add wg0 type wireguard
RTNETLINK answers: Operation not supported
[!] Missing WireGuard kernel module. Falling back to slow userspace implementation.
[#] wireguard-go wg0
INFO: (wg0) 2020/05/01 11:45:18 Starting wireguard-go version 0.0.20200320
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 10.123.0.1/24 dev wg0
[#] ip -6 address add fd42:42:42::1/80 dev wg0
[#] ip link set mtu 1420 up dev wg0
[#] iptables -t nat -A POSTROUTING -o venet0 -j MASQUERADE; ip6tables -t nat -A POSTROUTING -o venet0 -j MASQUERADE
iptables v1.8.4 (nf_tables): Could not fetch rule set generation id: Invalid argument
[#] ip link delete dev wg0`
Ah ok on actually reading your previous post it is likely that you are using a version of deb/ubuntu that expects nf_tables whole the host node kernel is actually el7 based, there was an article on using legacy rather than nf and I forgot the exact method, I will look it up when I get a minute, someone else I am sure will know so feel free to post.
it has been mentioned here before.
https://inceptionhosting.com
Please do not use the PM system here for Inception Hosting support issues.
Found the post: https://talk.lowendspirit.com/discussion/290/resolved-ufw-iptables-not-working-in-debian-10-minimal/p1
https://inceptionhosting.com
Please do not use the PM system here for Inception Hosting support issues.
@AnthonySmith thankyou. that solved the problem.
cool beans, KB updated.
https://inceptionhosting.com
Please do not use the PM system here for Inception Hosting support issues.