WireGuard

最後更新: 2024-08-23

目錄

 


WireGuard 簡介

 

WireGuard securely encapsulates IP packets over UDP.

核心

WireGuard interface

It works by adding a network interface (wg0, wg1, etc), like eth0 or wlan0, called.

Cryptokey Routing

Each network interface has a private key and a list of peers.
Each peer has a public key.
Public keys with a list of tunnel IP addresses that are allowed inside the tunnel.(AllowedIPs)

Public key must be unique between multiple peers on the same tunnel. Otherwise,
 traffic to the conflicting networks will only be routed to the last peer in the list.

優點

Minimal Attack Surface

It is meant to be easily implemented in very few lines of code,
 and easily auditable for security vulnerabilities.

High Performance

WireGuard lives inside the Linux kernel

Simple & Easy-to-use

At the heart of WireGuard is a concept called Cryptokey Routing
simply match on "is it from this IP? on this interface?

Ready for Containers

Known Limitations

  • WireGuard does not focus on obfuscation
  • WireGuard explicitly does not support tunneling over TCP
  • WireGuard uses ChaCha20Poly1305
    (does not support hardware encryption devices)

Other Project

 


Clients

 

Windows 's client

https://download.wireguard.com/windows-client/

 


Linux Installation

 

# U22

apt install wireguard

apt install iptables            # wg-quick 要用到 iptables-restore

Depends

  • wireguard-modules / wireguard-dkms
  • wireguard-tools

# RHEL(7,8)@EPEL: kmod-wireguard wireguard-tools

dnf install wireguard-tools

 


Kernel Module

 

# module 在 linux-modules-6.5.0-41-generic package 內

modprobe wireguard

U22

# 調用 dkms 去 compile kernel module

apt install wireguard-dkms

有機會遇到沒有 linux-headers 的情況

場景:

系統行緊的 Kernel 係 linux-image-5.15.0-58-generic, 但沒有對應的 linux-headers

原因係當前最新的 Kernel 是 linux-image-5.15.0-112-generic

它對應 linux-headers-5.15.0-112-generic

 


建立 keys

 

Private & Public key (PublicKey, PrivateKey)

wg genkey > private.key

chmod 640 private.key

wg pubkey < private.key > public.key

PSK (PresharedKey)

# 256 bits base64-encoded string (44 alphanumeric characters)

wg genpsk > psk.key

chmod 640 psk.key

 


Setup

 

1) 建立 NIC

ip link add dev wg0 type wireguard

2) 設定雙方 IP

ip address add dev wg0 192.168.2.1/24

OR

ip address add dev wg0 192.168.2.1 peer 192.168.2.2

3) Configure NIC

方式 A

Default Port: 51820/udp

wg set wg0 \
listen-port 51820 \
private-key /path/to/private-key \
peer R.R.R.R \
allowed-ips 192.168.88.0/24 \
endpoint R.R.R:R:51820

方式 B

wg setconf wg0 wg0.conf

方式 C

wg-quick up wg0

4) Checking

wg [show]

interface: wg0
  public key: ...
  private key: (hidden)
  listening port: 48917

peer: ...
  preshared key: (hidden)
  endpoint: R.R.R.R:51820
  allowed ips: 10.0.31.0/24

wg showconf <interface> # output 的是 config file 的內容. 可能保存成 config file

 


Options

 

必要的 settings

Address = Your.internal.IP.address

AllowedIPs

The Tunnel address, and any additional networks which should be routed across the VPN in a comma-separated list.
This could be a LAN subnet (e.g. 10.6.0.0/24) or
We use 0.0.0.0/0 to route all traffic, including Internet traffic, across the tunnel.

Optional Settings

PersistentKeepalive = 10

a keepalive packet is sent to the server endpoint once every interval seconds.

DNS = 10.0.31.1

Domain Name Server, used to resolve hostnames to IPs for VPN clients

用 internal dns server 可以防止 DNS 解釋漏出

MTU = 1440

Run Script

  • PostUp =
  • PostDown =

PresharedKey

PresharedKey = /path/to/file

A base64 preshared key generated by wg genpsk.

This option adds an additional layer of symmetric-key cryptography
to be mixed into the already existing public-key cryptography,
for post-quantum resistance.

 


Config File

 

[Interface]
PrivateKey = ABCDE...
Address = 10.0.31.11
SaveConfig = true
ListenPort = 51820

[Peer]
PublicKey = FGHIJ...
PresharedKey = KLMNO...
Endpoint = R.R.R.R:51820
AllowedIPs = 10.0.31.0/24, 192.168.31.0/24
PersistentKeepalive = 10

SaveConfig

true => the configuration is saved from the current state of the interface upon shutdown

ListenPort

如果沒有設定, 那會隨機 listen 一個 UDP port

 


Scripts(PreUp, PostUp, PreDown, PostDown)

 

Usage

  • The script snippets which will be executed by bash
  • The special string "%i" is expanded to INTERFACE
  • Each one may be specified multiple times

e.g.

[Interface]
PostUp = /etc/wireguard/%i/postup.sh %i
PostDown = /etc/wireguard/w%i/postdown.sh %i

postup.sh

#!/bin/bash

LAN=192.168.123.0/24
WG_SUBNET=10.0.31.0/24
MASQUERADE_IF=br0

WG_IF=$1
if [ -z $WG_IF ]; then echo "No WG_IF" && exit 1; fi

iptables -t nat -I POSTROUTING -o $MASQUERADE_IF -j MASQUERADE -s $WG_SUBNET

# Add a WIREGUARD_wg0 chain to the FORWARD chain
CHAIN_NAME="WIREGUARD_$WG_IF"
iptables -N $CHAIN_NAME
iptables -A FORWARD -j $CHAIN_NAME

# Accept related or established traffic
iptables -A $CHAIN_NAME -o $WG_IF -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

# Accept traffic from any Wireguard IP address connected to the Wireguard server
iptables -A $CHAIN_NAME -s $WG_SUBNET ! -d $LAN -i $WG_IF -j ACCEPT

# Reject everything else coming through the Wireguard interface
iptables -A $CHAIN_NAME -i $WG_IF -j REJECT

# Return to FORWARD chain
iptables -A $CHAIN_NAME -j RETURN

postdown.sh

#!/bin/bash

WG_SUBNET=10.0.31.0/24
MASQUERADE_IF=br0

WG_IF=$1
if [ -z $WG_IF ]; then echo "No WG_IF" && exit 1; fi

CHAIN_NAME="WIREGUARD_$WG_IF"
iptables -t nat -D POSTROUTING -o $MASQUERADE_IF -j MASQUERADE -s $WG_SUBNET

# Remove WG FORWARD CHAIN
iptables -D FORWARD -j $CHAIN_NAME
iptables -F $CHAIN_NAME
iptables -X $CHAIN_NAME

 


Auto Start By systemd

 

/etc/wireguard/wg0.conf                          # 要有設定好的 config file

systemctl enable [email protected] --now

systemctl status wg-quick@wg0

Remove Service

systemctl disable [email protected] --now

find /etc/systemd/system -name wg-quick@*

rm -f /etc/systemd/system/multi-user.target.wants/[email protected]

systemctl daemon-reload

 


Summary

 

Diagram

LAN: 192.168.31.0/24
      |
    Server       <-51820/udp-      Client
10.0.31.254            Tunnel      10.0.31.11 

Client Config(wg0.conf)

[Interface]
PrivateKey = ABCDE...
Address = 10.0.31.11

[Peer]
PublicKey = FGHIJ...
PresharedKey = KLMNO...
Endpoint = R.R.R.R:51820
AllowedIPs = 10.0.31.0/24, 192.168.31.0/24
PersistentKeepalive = 10

 


Debug

 

Server

tcpdump -n -i eth0 port 51820

Client

nc -u x.x.x.x 51820

 


Install wireguard on LXC CT

 

To install a package without installing its dependencies

由於 wireguard 依然 wireguard-modules / wireguard-dkms

但在 LXC 內它們是沒有用的 (因為它們係 Kernel Module 來)

所以我們可以使用 "--no-install-recommends" 略過

apt install --no-install-recommends wireguard-tools

 


ufw settings

 

# Forward traffic to LXC CT(192.168.200.18)

Internet <-> ens160[HOST]br0 <-> CT

ufw route allow in on br0 out on ens160 from 192.168.200.0/24             # LXC 上網

ufw route allow in on ens160 to 192.168.200.18 port 51820 proto udp    # wireguard vpn traffic

/etc/ufw/before.rules

*nat

:POSTROUTING ACCEPT [0:0]
-F POSTROUTING
-A POSTROUTING -s 192.168.200.0/24 -o ens160 -j MASQUERADE

:PREROUTING ACCEPT [0:0]
-F PREROUTING
-A PREROUTING -i ens160 -p udp --dport 51820 -j DNAT --to-destination 192.168.200.18

COMMIT

 


Reload Settings

 

需要 "wg-quick strip" 與 "wg syncconf" 配合完成

wg-quick strip

output a configuration file with all wg-quick specific options removed,

應用: reloading configuration files without disrupting active sessions

e.g.

wg syncconf wg0 <(wg-quick strip wg0)

wg syncconf

wg syncconf wg0 wg0.conf

Like setconf, but reads back the existing configuration first and
 only makes changes that are explicitly different between the configuration file and the interface.

 

 


Peer 互連

 

當 Peer1 及 Peer2 連通 Server 後, 它們就可以互通

Diagram

      /-- Peer1
Server
      \-- Peer2

在 server 上的 wg0.conf

# Server
[Interface]
Address = 10.0.31.1
ListenPort = 51820

# Peer 1
[Peer]
Endpoint = peer1.domain:51820
AllowedIPs = 10.0.31.11/32

# Peer 2 (mobile)
[Peer]
AllowedIPs = 10.0.31.12/32

 * Server 必須有 ListenPort

 * 由於 mobile 沒有 public 的 wan ip, 所以沒有 Endpoint 設定

 


Other

 

 

 

Creative Commons license icon Creative Commons license icon