User:Equinox/WireGuard

From BitFolk
Jump to navigation Jump to search


STOP !!!!!

This is a first draft! If you're a hardy network type who can recover from errors / omissions in this page then go for it (and fix this page!)



You read the bit about STOP above, didn't you.. WireGuard is part of the Linux kernel and is minimal and lightweight, gaining what can be interpreted as approval by Linus Torvalds himself. WireGuard is almost symmetrical in operation so there aren't really servers and clients, just peers. It operates over the UDP protocol and while there is an initial handshake when "connecting", nothing is transmitted between the peers unless necessary. (There is a keep-alive option to defeat NAT gateway timeouts). WireGuard is fast: It can saturate my home broadband connection where OpenVPN could not.

This WireGuard guide section was created using Debian 12 and 'wg-quick' at both ends of the VPN. As they say, YMMV - use what you can, adapt where necessary. Let's stick to the example requirements set above for this guide. (WireGuard can be used in other configurations, for example, to route everything through the VPN except the VPN traffic itself).

Server Setup

# apt install wireguard
# cd /etc/wireguard
# wg genkey > server-private-key
# wg pubkey < server-private-key > server-public-key
# wg genpsk > shared-secret-key   # Optional for improved security

Edit /etc/wireguard/wg0.conf

[Interface]
PrivateKey = # Insert the contents of the file server-private-key generated above
ListenPort = # Pick an empty UDP port to listen on. Remember to open it in your firewall
Address = 10.254.1.254/32
Address = 2a0a:1100:1018:1::fe/128

Client Setup

# apt install wireguard
# cd /etc/wireguard
# wg genkey > client-private-key
# wg pubkey < client-private-key > client-public-key

Edit /etc/wireguard/wg0.conf

[Interface]
PrivateKey = # Insert the contents of the file client-private-key generated above
Address = 10.254.1.1/24
Address = 2a0a:1100:1018:1::1/64

Now we have a wg0 interface defined on both ends with statically assigned IPv4 and IPv6 addresses.

Add the Client Information to the Server

Append the following to the server /etc/wireguard/wg0.conf, inserting your generated information where appropriate:

# Client Name
[Peer]
PublicKey = # Insert contents of client-public-key generated in Client Setup
# PresharedKey = # Uncomment and insert contents of shared-secret-key generated in Server Setup - if you did
AllowedIPs = 10.254.1.0/24  # Source IPv4 addresses from the client side allowed to transmit to the server
AllowedIPs = 2a0a:1100:1018:1::/64 # Source IPv6 addresses from the client side allowed to transmit to the server

Add the Server Information to the Client

Append the following to the client /etc/wireguard/wg0.conf, inserting your generated information where appropriate:

# Your VPS Name
[Peer]
PublicKey = # Insert contents of server-public-key generated in Server Setup
# PresharedKey = # Uncomment and insert contents of shared-secret-key generated in Server Setup - if you did
Endpoint = 85.119.82.121:PORT-NUMBER # Replace PORT-NUMBER with the UDP port number you chose in Server Setup ListenPort
# PersistentKeepalive = 170  # Uncomment and choose a timeout in seconds for keepalive packets - Necessary if the client is behind NAT
AllowedIPs = 0.0.0.0/0, ::/0   # Allow any IP from the server side to transmit to the client

Start The VPN

Run on both sides:

# systemctl daemon-reload             # Have systemd find the new wg0.conf files
# systemctl start wg-quick@wg0
# systemctl enable wg-quick@wg0       # Optional - start VPN at startup

If all went well you should now have a working tunnel. Confirm by running:

# wg

If both sides have a reasonable looking "latest handshake" line then the tunnel is up.

The wg-quick scripts automatically set up routes / default routes based on the contents of the wg0.conf files, so at this point you can test the link by pinging addresses from either side.

Two further things may/will need to be configured to allow full routing...

Enable IP Forwarding

Edit /etc/sysctl.conf, or a local conf file in /etc/sysctl.d/ and enable IPv4 and/or IPv6 forwarding

net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1

Reload the kernel variables:

systemctl reload procps

WireGuard Max MTU Size

If some websites don't work properly over IPv6 (Netflix) you may be running into MTU size problems. If using nftables, this can be entirely fixed with the following line in the forward table:

oifname "wg0" tcp flags syn tcp option maxseg size set rt mtu


Enable Forwarding In Your Firewall

You will have to figure out how to do this for your flavour of firewall. If you happen to be using nftables, the following snippet is an example (by no means a full config!) of how to forward IPv6 back and forth. This snippet allows all outbound traffic but throws incoming traffic to the table "ipv6-incoming-firewall" for further filtering. (For testing you could just "accept" but don't leave it like that!)

chain ip6-forwarding {
    type filter hook forward priority 0; policy drop;

    oifname "wg0" tcp flags syn tcp option maxseg size set rt mtu

    ip6 saddr 2a0a:1100:1018:1::/64 accept
    ip6 daddr 2a0a:1100:1018:1::/64 jump ipv6-incoming-firewall
}

Useful Information / Commands

Status of all WireGuard interfaces:

# wg

wg-quick is a higher level system to manage wg, wg being the low level kernel-based part. The wg0.conf files made above are a hybrid format with some options targeted at wg-quick and some at wg. When wg-quick talks to wg it strips any wg-quick only options from the config before submitting it.

There are useful wg-quick options that can be added to wg0.conf, particularly this one:

PostUp = /etc/wireguard/wg0-postup.sh

... into which you can write any complex routing setup you like.

Android Client

To add an Android client using a QR code to scan for configuring it, create a fully configured android-client.conf file for your new Android client just as a client wg0.conf was created above. Install qrencode and then:

# qrencode -t png -o qr-code.png -r android-client.conf