Virtual Private Networks (VPNs) are used extensively. Nowadays there are different solutions available which allow users access to any kind of resource while maintaining their confidentiality and privacy.
Lately, one of the most commonly used VPN protocols is WireGuard because of its simplicity, speed and the security it offers. WireGuard’s implementation started in the Linux kernel but currently it is available in other platforms such as iOS and Android among others.
WireGuard uses UDP as its transport protocol and it bases the communication between peers upon Critokey Routing (CKR). Each peer, either server or client, has a pair of keys (public and private) and there is a link between public keys and allowed IPs to communicate with. For further information about WireGuard please visit its page.
This article describes how to set up WireGuard between two peers: PeerA and PeerB. Both nodes are running Fedora Linux and both are using NetworkManager for a persistent configuration.
WireGuard set up and networking configuration
You are only three steps away from having a persistent VPN connection between PeerA and PeerB:
- Install the required packages.
- Generate key pairs.
- Configure the WireGuard interfaces.
Installation
Install the wireguard-tools package on both peers (PeerA and PeerB):
$ sudo -i # dnf -y install wireguard-tools
This package is available in the Fedora Linux updates repository. It creates a configuration directory at /etc/wireguard/. This is where you will create the keys and the interface configuration file.
Generate the key pairs
Next, use the wg utility to generate both public and private keys on each node:
# cd /etc/wireguard # wg genkey | tee privatekey | wg pubkey > publickey
Configure the WireGuard interface on PeerA
WireGuard interfaces use the names: wg0, wg1 and so on. Create the configuration for the WireGuard interface. For this, you need the following items:
- The IP address and MASK you want to configure in the PeerA node.
- The UDP port where this peer listens.
- PeerA’s private key.
# cat << EOF > /etc/wireguard/wg0.conf [Interface] Address = 172.16.1.254/24 SaveConfig = true ListenPort = 60001 PrivateKey = mAoO2RxlqRvCZZoHhUDiW3+zAazcZoELrYbgl+TpPEc= [Peer] PublicKey = IOePXA9igeRqzCSzw4dhpl4+6l/NiQvkDSAnj5LtShw= AllowedIPs = 172.16.1.2/32 EOF
Allow UDP traffic through the port on which this peer will listen:
# firewall-cmd --add-port=60001/udp --permanent --zone=public # firewall-cmd --reload success
Finally, import the interface profile into NetworkManager. As a result, the WireGuard interface will persist after reboots.
# nmcli con import type wireguard file /etc/wireguard/wg0.conf Connection 'wg0' (21d939af-9e55-4df2-bacf-a13a4a488377) successfully added.
Verify the status of device wg0:
# wg interface: wg0 public key: FEPcisOjLaZsJbYSxb0CI5pvbXwIB3BCjMUPxuaLrH8= private key: (hidden) listening port: 60001 peer: IOePXA9igeRqzCSzw4dhpl4+6l/NiQvkDSAnj5LtShw= allowed ips: 172.16.1.2/32 # nmcli -p device show wg0 =============================================================================== Device details (wg0) =============================================================================== GENERAL.DEVICE: wg0 ------------------------------------------------------------------------------- GENERAL.TYPE: wireguard ------------------------------------------------------------------------------- GENERAL.HWADDR: (unknown) ------------------------------------------------------------------------------- GENERAL.MTU: 1420 ------------------------------------------------------------------------------- GENERAL.STATE: 100 (connected) ------------------------------------------------------------------------------- GENERAL.CONNECTION: wg0 ------------------------------------------------------------------------------- GENERAL.CON-PATH: /org/freedesktop/NetworkManager/ActiveC> ------------------------------------------------------------------------------- IP4.ADDRESS[1]: 172.16.1.254/24 IP4.GATEWAY: -- IP4.ROUTE[1]: dst = 172.16.1.0/24, nh = 0.0.0.0, mt => ------------------------------------------------------------------------------- IP6.GATEWAY: -- -------------------------------------------------------------------------------
The above output shows that interface wg0 is connected. It is now able to communicate with one peer whose VPN IP address is 172.16.1.2.
Configure the WireGuard interface in PeerB
It is time to create the configuration file for the wg0 interface on the second peer. Make sure you have the following:
- The IP address and MASK to set on PeerB.
- The PeerB’s private key.
- The PeerA’s public key.
- The PeerA’s IP address or hostname and the UDP port on which it is listening for WireGuard traffic.
# cat << EOF > /etc/wireguard/wg0.conf [Interface] Address = 172.16.1.2 SaveConfig = true PrivateKey = UBiF85o7937fBK84c2qLFQwEr6eDhLSJsb5SAq1lF3c= [Peer] PublicKey = FEPcisOjLaZsJbYSxb0CI5pvbXwIB3BCjMUPxuaLrH8= AllowedIPs = 172.16.1.254/32 Endpoint = peera.example.com:60001 EOF
The last step is about importing the interface profile into NetworkManager. As I mentioned before, this allows the WireGuard interface to have a persistent configuration after reboots.
# nmcli con import type wireguard file /etc/wireguard/wg0.conf Connection 'wg0' (39bdaba7-8d91-4334-bc8f-85fa978777d8) successfully added.
Verify the status of device wg0:
# wg interface: wg0 public key: IOePXA9igeRqzCSzw4dhpl4+6l/NiQvkDSAnj5LtShw= private key: (hidden) listening port: 47749 peer: FEPcisOjLaZsJbYSxb0CI5pvbXwIB3BCjMUPxuaLrH8= endpoint: 192.168.124.230:60001 allowed ips: 172.16.1.254/32 # nmcli -p device show wg0 =============================================================================== Device details (wg0) =============================================================================== GENERAL.DEVICE: wg0 ------------------------------------------------------------------------------- GENERAL.TYPE: wireguard ------------------------------------------------------------------------------- GENERAL.HWADDR: (unknown) ------------------------------------------------------------------------------- GENERAL.MTU: 1420 ------------------------------------------------------------------------------- GENERAL.STATE: 100 (connected) ------------------------------------------------------------------------------- GENERAL.CONNECTION: wg0 ------------------------------------------------------------------------------- GENERAL.CON-PATH: /org/freedesktop/NetworkManager/ActiveC> ------------------------------------------------------------------------------- IP4.ADDRESS[1]: 172.16.1.2/32 IP4.GATEWAY: -- ------------------------------------------------------------------------------- IP6.GATEWAY: -- -------------------------------------------------------------------------------
The above output shows that interface wg0 is connected. It is now able to communicate with one peer whose VPN IP address is 172.16.1.254.
Verify connectivity between peers
After executing the procedure described earlier both peers can communicate to each other through the VPN connection as demonstrated in the following ICMP test:
[root@peerb ~]# ping 172.16.1.254 -c 4 PING 172.16.1.254 (172.16.1.254) 56(84) bytes of data. 64 bytes from 172.16.1.254: icmp_seq=1 ttl=64 time=0.566 ms 64 bytes from 172.16.1.254: icmp_seq=2 ttl=64 time=1.33 ms 64 bytes from 172.16.1.254: icmp_seq=3 ttl=64 time=1.67 ms 64 bytes from 172.16.1.254: icmp_seq=4 ttl=64 time=1.47 ms
In this scenario, if you capture UDP traffic on port 60001 on PeerA you will see the communication relying on WireGuard protocol and the encrypted data:
Conclusion
Virtual Private Networks (VPNs) are very common. Among a wide variety of protocols and tools for deploying a VPN, WireGuard is a simple, lightweight and secure choice. It allows secure point-to-point connections between peers based on CryptoKey routing and the procedure is very straight-forward. In addition, NetworkManager supports WireGuard interfaces allowing persistent configurations after reboots.
Martin
Can this method be used to connect to Mozilla VPN?
Steven
I’d love to see another of these using systemd-networkd as well. Thanks for the write up!
Ray
I’ve been using this setup for a while.
I do have an issue however. I set up my connection to use a specific DNS server for certain domains. Once in a while the system just stops using that DNS server. Restarting the wireguard connection fixes it.
So it seems like something is overwriting the DNS configuration. But I don’t know what. It doesn’t appear to be anything triggered by what I am doing, I can be using a web browser hitting sites on my VPN when suddenly it happens.
If anyone has any advice, it would be appreciated.
setenforce 1
Hi,
I’m using something like this :
resolvectl dns wlp0s20f3 “1.1.1.1#one.one.one.one 1.0.0.1#one.one.one.one 2606:4700:4700::1111#one.one.one.one 2606:4700:4700::1001#one.one.one.one”
resolvectl domain wlp0s20f3 ~.
resolvectl dnsovertls wlp0s20f3 yes
resolvectl dnssec wlp0s20f3 yes
resolvectl dns enp0s13f0u3u1 “1.1.1.1#one.one.one.one 1.0.0.1#one.one.one.one 2606:4700:4700::1111#one.one.one.one 2606:4700:4700::1001#one.one.one.one”
resolvectl domain enp0s13f0u3u1 ~.
resolvectl dnsovertls enp0s13f0u3u1 yes
resolvectl dnssec enp0s13f0u3u1 yes
resolvectl dns wg1 10.0.0.1 10.0.0.2
resolvectl domain wg1 example.com
resolvectl dnsovertls wg1 no
resolvectl dnssec wg1 no
Do you use something similar?
I don’t have any issue as long as I don’t restart the Networking / disconnect reconnect the Wi-Fi.
Ray
Thanks for the reply.
No, I am setting the DNS resolution via Network Manager:
nmcli connection modify wg0 ipv4.dns-search custom.domain1.com,customdomain2.com
My setup is based on https://blogs.gnome.org/thaller/2019/03/15/wireguard-in-networkmanager/
I will look into resolvectl to see if it can help me though.
Sergey
Where’s the GUI?
Felix Kaechele
For Gnome it’s in the works: https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/982
Devin Zuczek
KDE has one.
Martin
Finally! 2 months ago this was impossible. Great work NetworkManager devs. Works on Fedora 33 for me.
jack
Great to see, i’ve been waiting for this !
Sergey
Also. How to make exceptions ?
I am forced to have many subnets in the configuration to specify that only they need to be rotated.
So that my local network and the internet do not go through vpn.
Reiza
I like to see a NetworkManager tutorial for more. BTW, good writing
jonas bloch riisgaard
which command prompt should be typed in Terminal to see the UDP and port listening ?
Gregory Bartholomew
Does
not work?
jonas bloch riisgaard
after typing if config which IP address should I choose to make peer2peer between. Is it the “Inet” or “broadcast” I see in the terminal after following: https://www.wireguard.com/quickstart/
I do not find the ip address 192.168.2.1/24
for typing in
Does the / between 1/24 means the numbers of Subnetmasks.
Can somebody please help
Gregory Bartholomew
You are interested in the “inet” address. BTW, ifconfig is deprecated. Use ip address list instead. The slash is just a separator. The number after the slash indicates the number of bits (starting from the highest order) to use to form the subnet mask (i.e. “24” is a shorter way of writing “255.255.255.0”).
Renich Bon Ćirić
Thank you for the article! Really good to give some exposure to wireguard.
IMHO, it’s better to use wg-quick to setup and verify it works so you can, later on, to import it with nmcli.
Here’s a quick script to setup Peer A as a gateway and Peer B as a client (kind of a VPN of sorts, but with WireGuard!)
# create the directory (if it doesn't exist)
umask 077
mkdir -p /etc/wireguard
# create config
cat << 'EOF' > /etc/wireguard/wg0.conf
[Interface]
Address = 192.168.200.1/24 # some private address/network.
PrivateKey = QOQwOjFhRQlPGV0R+oJ6mQboA3PHGoGEBxRRD9evXXE=
ListenPort = 51820 # The port where you want to listen for connections.
# Post up and down actions
PostUp = firewall-cmd --zone=public --add-port 51820/udp && firewall-cmd --zone=public --add-masquerade
PostDown = firewall-cmd --zone=public --remove-port 51820/udp && firewall-cmd --zone=public --remove-masquerade
# Allowed peers
[Peer]
AllowedIPs = 192.168.200.2/32 # IP to allow for Peer B.
PublicKey = aPkGZq/RAVJvAtEgoaSqX8DTJwPGlp0tVR7kSW3QTDs=
EOF
# either set it up
wg-quick up wg0
# or import it and activate it
nmcli connection import type wireguard file /etc/wireguard/wg0.conf
nmcli connection up wg0
# Peer B (your client host)
# create the directory (if it doesn't exist)
umask 077
mkdir -p /etc/wireguard
# create config
cat << 'EOF' > /etc/wireguard/wg0.conf
[Interface]
PrivateKey = mAIjTzYpdyGnQRBATsfrM50O2w+Eo1pYHnQPknhcilg=
Address = 192.168.200.2/32 # the address you're allowed on in Peer A.
DNS = 8.8.8.8, 8.8.4.4, 1.1.1.1, 1.0.0.1 # DNS settings. You can use whatever you prefer.
[Peer]
PublicKey = HdDeIa/WqALjAh3+NgfrXHaUAsWdoKEzNvJ11SyXMUI=
Endpoint = web1.woralelandia.com:51820 # you can use either a domain name or IP address.
AllowedIPs = 0.0.0.0/0 # yeah, allow the Internet through this one.
EOF
# either set it up
wg-quick up wg0
# or import it and activate it
nmcli connection import type wireguard file /etc/wireguard/wg0.conf
nmcli connection up wg0
Eric Nicholls
That’s too much work. I will stay with OpenVPN until it becomes simpler to configure.
jack
a different topologyPlease?
the peerA to peerB configuration, very nice.
how about a different topo.
i have a simple static ip with host(fedora) serving http & https behind routers.
i want a tunnel such that all internet traffic is run through WG.
Devin Zuczek
KDE has a UI for this, works great.
christoph
I use a simple helper script to manage WireGuard connections with NetworkManager CLI.
See https://gist.github.com/skipperTux/5bbc3d261c82c21bfee530d518a4bc38
Rodehoed
Hi,
I tried WG last week. One thing which put me back to openVpn. The wg0 interface is always up when started. Even when the peer connection is not. The up status is also seen in network manager and is confusing.
Maybe I’m doing something wrong or missing something?
Gregory Bartholomew
I think it is normal for the status of wg0 on the client to be independent of the status of the peer. I use the wg command to check if packets are being received from the peer.
Grayson
Is that a radio in the header picture? Maybe hooking up an antenna? Haha, that’s the first thing I noticed. Thanks for the good article, Wireguard is awesome!
jask
I found interesting problem. I have small wireguard network with one central node (server). I use it to provide access to these nodes which are not accessible from the Internet. And I also use my company’s openVPN which pushes default route to my laptop. As long as I setup with
it works as it is supposed to. But after switching to NM (
) wireguard tunnel stops to work because of bad MTU.
It seems to me
is better to guess right MTU for
. Or it has better default.