WireGuard on Alpine Linux with nftables
2019-10-12T08:09:47.720Z.
Changelog:
- 2019-10-18T16:07:23.705Z: Use reserved private network address.
- 2022-05-05T11:48:23.885Z: Updated for use on Alpine Linux 3.15.
- 2023-01-14T17:18:15.444Z: Updated for setup on Alpine Linux 3.17.
This article describes the installation and configuration of WireGuard on Alpine Linux (server) and iOS (client). Part of the setup is done using nftables. Once the setup is complete, the traffic from the client will go through the server before reaching the Internet (also known as "road warrior" setup).
The setup assumes the following:
- The VPN has the network address
10.0.0.0/24
. -
The server will be assigned with an IP address
10.0.0.1/24
within the VPN. -
The client will be assigned with an IP address
10.0.0.2/24
within the VPN. -
A network interface
wg0
on the VPN server will be used by WireGuard. -
The server connects to the Internet through the
eth0
interface.
Install WireGuard
You need to enable the community repository before installing WireGuard on
Alpine Linux. Edit /etc/apk/repositories
to enable the
repository.
Install the WireGuard packages:
apk update apk add wireguard-tools-wg
Enable IP forwarding
Enable IP forwarding by running:
sysctl -w net.ipv4.ip_forward=1
To make the settings permanent, create a configuration file under
/etc/sysctl.d/
. For example, create
/etc/sysctl.d/local.conf
with the following content:
net.ipv4.ip_forward=1
Configure WireGuard
WireGuard configuration files should be put under the
/etc/wireguard/
directory.
mkdir -p /etc/wireguard/
Now create the keypair used by WireGuard on the server:
cd /etc/wireguard/ wg genkey > server.key chmod 600 server.key wg pubkey < server.key > server.pub
The server.key
contains the server private key and
server.pub
contains the server public key.
Now create a pre-shared key used by WireGuard on the server and client.
wg genpsk > peer-01.psk
If there are multiple clients, create a pre-shared key for each of the client.
Create the configuration file of WireGuard on the server. Create a file at
/etc/wireguard/wg0.conf
with the following content:
[Interface] PrivateKey = AAAAA ListenPort = 20000 [Peer] PublicKey = BBBBB PresharedKey = CCCCC AllowedIPs = 10.0.0.2/32
In the Interface
section:
-
Set the
PrivateKey
property with the content ofserver.key
(i.e. server private key). -
Set the
ListenPort
with an unused port on the server.
In the Peer
section:
- Leave the
PublicKey
unset for the moment. -
Set the
PresharedKey
with the content ofpeer01.psk
(i.e. the pre-shared key between the server and peer). -
The
AllowedIps
is set with10.0.0.2/32
so that the client must connect from the specific (VPN) address, and traffic for the client will be directed to the same address.
Configuure network interface
Update /etc/network/interfaces
and add the following:
auto wg0 iface wg0 inet static address 10.0.0.1 netmask 255.255.255.0 pre-up ip link add dev wg0 type wireguard pre-up wg setconf wg0 /etc/wireguard/wg0.conf post-down ip link delete dev wg0
Configure nftables
In order for clients to reach the Internet through the server, nftables will be used to configure the source NAT.
If nftables has not been installed, run:
apk add nftables
Add a file /etc/nftables.d/wireguard.nft
with the following
content:
#!/usr/sbin/nft -f
# Configurations for WireGuard.
table inet filter {
chain input {
udp dport 20000 accept
}
chain forward {
iifname "eth0" oifname "wg0" accept;
iifname "wg0" oifname "eth0" accept;
}
}
table ip nat {
chain PREROUTING {
type nat hook prerouting priority filter; policy accept;
}
chain POSTROUTING {
type nat hook postrouting priority srcnat; policy accept;
oifname "eth0" masquerade
}
}
Run nft -f /etc/nftables.nft to load the new rules, and then nft list ruleset to check the configurations.
Run rc-update add nftables so that nftables will run and load the configurations when the system starts.
Configure VPN client
In WireGuard for iOS, create a new WireGuard tunnel.
In the interface section:
- Set the Name field with a preferred tunnel name.
- Click Generate keypair to generate the VPN client's private key and public key.
-
Set the Addresses field with the VPN client address, which is
10.0.0.2/32
. -
Set the DNS servers field with the preferred DNS server. For example,
set with
9.9.9.9
to use Quad9 DNS.
In the peer section:
- Set the Public key field with the server's public key.
-
Set the Preshared key field with the content of
peer01.psk
generated above (i.e. the pre-shared key between the server and peer). -
Set the Endpoint field with the IP address (or the domain name) and port
of the server. For example,
example.com:20000
. -
Set the Allowed IPs field with
0.0.0.0/0, ::/0
so that all traffic from the client will go to the server before reaching the Internet.
Activate VPN tunnel
Update the PublicKey
under the Peer
section of
/etc/wireguard/wg0.conf
on the server, set the value with the
public key of the VPN client.
On the server, run ifup wg0 to activate the interface. The client should be able to connect to the server, and all traffic will go through the server. On the client, you can visit website such as https://ifconfig.co/ to verify the IP address is the server's public IP address, instead of the client's public IP address.
You can run wg on the server to see the WireGuard statistics.
When needed, you can run ifdown wg0 on the server to deactivate the WireGuard interface.
References
- https://git.zx2c4.com/WireGuard/about/src/tools/man/wg.8
- https://www.wireguard.com/quickstart/#command-line-interface
- https://wiki.alpinelinux.org/wiki/Configure_a_Wireguard_interface_(wg)
- https://www.netfilter.org/projects/nftables/manpage.html
- https://wiki.nftables.org/wiki-nftables/index.php/Performing_Network_Address_Translation_(NAT)
- https://wiki.nftables.org/wiki-nftables/index.php/Scripting
- https://wiki.nftables.org/wiki-nftables/index.php/Atomic_rule_replacement
- https://log.kyaulabs.com/2020/03/wireguard_with_systemd_and_nftables