OpenWRT with WireGuard server which is connected through OpenVPN
Posted on July 18, 2024 • 5 minutes • 874 words
Table of contents
We setup a wireguard server on an OpenWRT router. We generate a setup file for the client. The wireguard server itself we connect through a VPN. The VPN itself can be socked through TOR (we don’t discuss this in the article).
Generate keys
umask go=
wg genkey | tee wgserver.key | wg pubkey > wgserver.pub
wg genkey | tee wgclient.key | wg pubkey > wgclient.pub
wg genpsk > wgclient.psk
Setup wireguard server
Note, wireguard server is actually a kernel module and there is no a special application to be run. The wireguard module exposes interface to ip link
with which one can create a device of type wireguard
.
In OpenWRT router we define a network interface with protocol of wireguard
.
uci -q delete network.styx;
uci set network.styx='interface';
uci set network.styx.proto='wireguard';
uci set network.styx.private_key='kKoONE1SO5x94fCJqrKV52mAxwIvgnpK7hAlPpt1R3I=';
uci set network.styx.listen_port='52820';
uci add_list network.styx.addresses='192.168.5.1/24';
uci -q delete network.wgclient`;
uci set network.wgclient='wireguard_styx';
uci set network.wgclient.public_key='9k5F5LsZKWR7wEqURgc4cVKTRgd31rayGtxSMrFYmgU='`;
uci set network.wgclient.preshared_key='ASsDWeoB8tdj5hTuPHNOocqnk7nNeSqt7s5y5aFn+XI=';
uci add_list network.wgclient.allowed_ips='192.168.5.2/32';
uci commit network`;
/etc/init.d/network reload`;
We defined interface styx
with listening port 52820
and assigned default gateway 192.168.5.1
with mask 255.255.255.0
. The private_key
was taken from wgserver.key
.
The network wgclient
allows only one host 192.168.5.2/32
. The public_key
was taken from wgclient.pub
and preshared_key
was taken from wgclient.psk
.
Setup wireguard client
On client (laptop) side, we use the following commands to setup wg0
device:
#!/bin/bash
ip link add dev wg0 type wireguard
# Set private key and IP address
wg set wg0 private-key <(echo +PiLMRXfFrIOMuiR7DK1XNj0QYkmQnGBszXrip1NKFA=)
ip address add 192.168.5.2/24 dev wg0
# Optional: Set DNS
# echo "nameserver 8.8.8.8" | resolvconf -a wg0
# Configure the peer
wg set wg0 peer Lp1/m57JlYM5UXVhfEUpV6RTXy5rIjcOPrgboRaP7gE= preshared-key <(echo ASsDWeoB8tdj5hTuPHNOocqnk7nNeSqt7s5y5aFn+XI=) endpoint 87.23.56.3:52820 allowed-ips 0.0.0.0/0 persistent-keepalive 25
# Bring up the interface
ip link set up dev wg0
We used private-key
taken from wgclient.key
and peer
taken from wgserver.pub
. The endpoint
is public IP of our router and the port is the one used for listening. If the OpenWRT router is connected to ISP router, we need to setup port forwarding for the port.
Setup OpenWRT firewall
To simplify testing, we just allow everything on the firewall:
nft flush ruleset
nft -f all-accept.nft
where all-accept.nft
is
table inet fw4 {
chain forward {
type filter hook forward priority filter; policy accept;
}
chain input {
type filter hook input priority filter; policy accept;
}
chain output {
type filter hook output priority filter; policy accept;
}
chain srcnat {
type nat hook postrouting priority srcnat; policy accept;
oifname "eth1" meta nfproto ipv4 masquerade
}
chain prerouting {
type filter hook prerouting priority filter; policy accept;
}
}
Now we can connect through wg0
on the client:
curl --interface w0 ipinfo.io
and we should get our router’s external ip.
Run OpenVPN on the router without default route change
We use mullvad open vpn setup file in which up
and down
directives are commented out. Then
openvpn --config mullvad_at_all.conf --route-nopull
We got the vpn on tun0
:
ifconfig
tun0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
inet addr:10.5.0.16 P-t-P:10.5.0.16 Mask:255.255.0.0
inet6 addr: fdda:d0d0:cafe:443::100e/64 Scope:Global
inet6 addr: fe80::5378:9544:a3c3:54b/64 Scope:Link
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1
RX packets:53 errors:0 dropped:0 overruns:0 frame:0
TX packets:64 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:500
RX bytes:5331 (5.2 KiB) TX bytes:8507 (8.3 KiB)
We can test the interface:
curl --interface tun0 ipinfo.io
Setting routing
We create styx
table for rule based routing:
echo '256 styx' >> /etc/iproute2/rt_tables
and add a default route to itthrough our vpn:
ip rule add default 10.5.0.16 dev tun0
The we create a rule which route the traffik from styx
interface to tun0
:
ip rule add from all iif styx lookup styx
Because forwarding policy in our firewall is accept
by default, we don’t need to explicitly allow the forwarding. However, we need masquerading, as always for interfaces which are used for external communication:
nft add rule inet fw4 srcnat oifname "tun0" meta nfproto ipv4 masquerade
Firewall with default drop policies
If firewall forwarding policy is default to drop
then we need to add:
nft add rule inet fw4 forward ct state established,related accept
nft add rule inet fw4 forward iifname "br-lan" oifname "eth1" accept
nft add rule inet fw4 forward iifname "styx" oifname "tun0" accept
If firewall input policy is defauly to drop
then we need to add:
nft add rule inet fw4 input iifname "lo" accept
nft add rule inet fw4 input ct state established,related accept
nft add rule inet fw4 input iifname "br-lan" accept
nft add rule inet fw4 input iifname "styx" accept
The interface lo
must be added for normal functioning. The interface br-lan
should be added to not lose access to the router through cable onlan ports.
The full firewall setup:
table inet fw4 {
chain forward {
type filter hook forward priority filter; policy drop;
ct state established,related accept
iifname "styx" oifname "tun0" meta nfproto ipv4 accept
iifname "br-lan" oifname "eth1" meta nfproto ipv4 accept
}
chain input {
type filter hook input priority filter; policy drop;
ct state established,related accept
iifname "lo" accept
iifname "br-lan" accept
}
chain output {
type filter hook output priority filter; policy accept;
}
chain srcnat {
type nat hook postrouting priority srcnat; policy accept;
oifname "eth1" meta nfproto ipv4 masquerade
oifname "tun0" meta nfproto ipv4 masquerade
}
chain prerouting {
type filter hook prerouting priority filter; policy accept;
}
}
Summary
Share
Tags
Counters