VPN
Overview
kasad.com features a secure, private WireGuard tunnel. The kasad.com server will route requests on the tunnel out to the internet, making the tunnel usable as a VPN.
Structure
Tunnel Service
The WireGuard tunnel interface is wg0
. wg-quick(8)
is used to create the WireGuard tunnel and load configuration. It is automatically activated by the wg-quick@wg0.service
SystemD service.
WireGuard interface
The WireGuard interface is named wgvpn0
, although the interface name doesn't matter as long as it's configured properly on the server. The interface has the following configuration:
[Interface]
Address = 10.5.19.1/24
SaveConfig = false
ListenPort = 51194
PrivateKey = #############################################
## PEER LIST ##
# ...
Note: the keys in the snipped above have been hidden
IP Addressing
As can be seen in the configuration snippet, the WireGuard tunnel uses the IPv4 address subnet 10.5.19.0/24
. The tunnel does not use IPv6. In theory it could, but I have not bothered to set that up.
WireGuard listener
WireGuard listens on UDP port 51194. Outgoing UDP traffic is blocked by some network firewalls (notably my school's), so the kasad.com server has a firewall rule in place to redirect incoming traffic on UDP port 123 to 51194. Since UDP port 123 is used for NTP, it usually is not blocked for outgoing traffic.
nft(8)
rule to implement this:
table inet nat {
chain prerouting {
udp dport 123 redirect to :51194
}
}
Peers
Each device that connects to the interface has its own keypair and IP address(es).
IP Address quirk
The IP address for each peer can be specified in CIDR notation, but the range for each peer must be unique. This means you cannot assign the same subnet for all peers and allow them to choose their own addresses. You must give a single unique address to each peer or give each one a range of IP addresses that does not overlap with any other peer's range.
Peer Configuration
Each peer must be specified in the WireGuard interface's configuration. Unknown peers will not be allowed to connect.
[Peer]
PublicKey = #############################################
AllowedIPs = 10.5.19.2/32
Peer List
Device | IP Address(es) | Public key |
---|---|---|
Kian's laptop | 10.5.19.2 |
laT7XasKzIdTC5gy9jSS0PaKvdjEHEU3pQ/j2BYAujs= |
Kian's old phone | 10.5.19.3 |
tjNWCci8SQwxBcHPxIXjZkOX+K214d4WNsFV6MVuA1M= |
Kian's (current) phone | 10.5.19.4 |
Lvfk37+yv13mLGETIrBnbQD2Qw474Bpfr2KxZUMpn1Q= |
Home office desktop | 10.5.19.6 |
ALN7gfvfeswE2hwSfbRyWqsmZVPvsAa8TUaurHC9eG0= |
Usage as VPN
While a VPN doesn't technically have to route traffic out to the internet, that's what they're usually used for. The kasad.com WireGuard interface is configured to forward traffic to the outside world. To utilize this, simply set 10.5.19.1
as the router address in your network configuration when connected to the WireGuard tunnel.
VPN routing configuration on server
Two things must be enabled for VPN routing to work:
- IP forwarding must be enabled in the Linux kernel.
- Firewall rules must be in place to (a) allow forwarding and (b) perform SNAT/masquerading.
Kernel options
The file /etc/sysctl.d/20-ip-forward.conf
enabled IP forwarding in the kernel:
# Allow IPv4 forwarding
net.ipv4.ip_forward=1
# Allow "martian" packets on 'wgvpn0' interface.
# These are packets coming from an external interface but heading to a
# localhost destination. This is required for intercepting VPN DNS requests.
net.ipv4.conf.wgvpn0.route_localnet=1
Firewall rules
The portions of the nft(8)
rule file that apply to the VPN routing are displayed below. Omitted lines are marked with an ellipsis comment (# ...
).
table inet filter {
chain input {
# ...
iifname "wgvpn*" ip saddr 10.5.19.0/24 goto vpninput
}
chain vpninput {
accept
}
chain forward {
# ...
iifname wgvpn0 oifname ens3 accept
oifname wgvpn0 ct state established,related accept
}
}
table inet nat {
chain postrouting {
# ...
ip saddr 10.5.19.0/24 oifname ens3 masquerade
}
}
No Comments