OpenBSD version: 7.1 (and some Ubuntu 22.04)
Arch:            Any
NSFP:            This might be one of the most stupid things i ever did.

« Part 1: Registrationless VPN <> Part 3: Adding IPv6 »

In the first part of this mini series, we took a look at making a wireguard web interface a bit more accepting of people who may not directly have a user account. A think with such a service is that, when analyzing network traces, one usually looks at things standing out. So to say, if a lot of people do a lot of things to a single port somewhere on the internet, that usually gets the attention of people with a dislike of things pinging rather quickly.

Making ports random

Wireguard is, in general, a rather forgiving protocol when it comes to accepting packets with funny destination ports. So with stuff listening on 192.0.2.1:51280 as per the previous part, we just have to do a tiny bit of iptables magic:

iptables -t nat -I PREROUTING -i eth0 -d 192.0.2.1/32 -p udp -m multiport --dports 1:51819,51821:65535  -j REDIRECT --to-ports 51820

This small command makes it happen that all packets arriving on any UDP port for the address Wireguard is listening on makes its path to the actual port Wireguard is listening on.

Making the webif randomize ports

With the iptables rule above in place (and remember to issue that after you started wg-ui, as–depending on whether you use --nat–it may flush your firewall rules upon start) we can now go about making wg-ui hand out random ports. Starting out, that is relatively simple: Instead of using the wgEndPoint specified in the code, we introduce a new variable wgCustPort that gets a random integer between 1 and 65535. At the same time, we no longer add the wireguard port to --wg-endpoint. This way, every time a user downloads a configuration file, they find themselves with a random port. Of course, users may want to change that port to something less suspicious (udp/53 DNS, or udp/443 QUIC). Therefore, we also let users know that they can do that.

To round things off, we also add some minor quality-of-ops features, specifically, we introduce --random-port-nat to enable the random port feature. If the switch is not supplied, wg-ui now just reuses the --wg-listen-port.

Restarting the service

So, all that’s left to do is hitting make build and restarting the service with:

./bin/wireguard-ui --wg-endpoint="192.0.2.1:51280" --wg-dns="192.0.2.53" --wg-allowed-ips=0.0.0.0/0 --listen-address="127.0.0.1:8080" --wg-keepalive="15" --auth-user-header="X-Request-ID" --client-ip-range="198.51.100.0/24" --wg-listen-port=51280 --random-port-nat &
iptables -t nat -I PREROUTING -i eth0 -d 192.0.2.1/32 -p udp -m multiport --dports 1:51819,51821:65535  -j REDIRECT --to-ports 51820

All done, all fancy, next up, IPv6.