Configure WireGuard VPNs with NetworkManager

wireguard

Photo excerpted from Thin Ethernet Ramble (TS 10:38) by High Treason

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:

  1. Install the required packages.
  2. Generate key pairs.
  3. 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:

Capture of UDP traffic between peers relying on WireGuard protocol

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.

FAQs and Guides

25 Comments

  1. Martin

    Can this method be used to connect to Mozilla VPN?

  2. I’d love to see another of these using systemd-networkd as well. Thanks for the write up!

  3. 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.

  4. Sergey

    Where’s the GUI?

  5. Martin

    Finally! 2 months ago this was impossible. Great work NetworkManager devs. Works on Fedora 33 for me.

  6. jack

    Great to see, i’ve been waiting for this !

  7. 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.

  8. Reiza

    I like to see a NetworkManager tutorial for more. BTW, good writing

  9. jonas bloch riisgaard

    which command prompt should be typed in Terminal to see the UDP and port listening ?

  10. 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

    • 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”).

  11. 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!)

    # Peer A (your gateway host)                                                                                                        
    # create the directory (if it doesn't exist)                                                                                        
    umask 077                                                                                                                          
    mkdir -p /etc/wireguard                                                                                                            

    # create config                                                                                                                    
    cat &lt;&lt; 'EOF' &gt; /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 &amp;&amp; firewall-cmd --zone=public --add-masquerade                            
    PostDown = firewall-cmd --zone=public --remove-port 51820/udp &amp;&amp; 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 &lt;&lt; 'EOF' &gt; /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
  12. Eric Nicholls

    That’s too much work. I will stay with OpenVPN until it becomes simpler to configure.

  13. 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.

  14. Devin Zuczek

    KDE has a UI for this, works great.

  15. I use a simple helper script to manage WireGuard connections with NetworkManager CLI.
    See https://gist.github.com/skipperTux/5bbc3d261c82c21bfee530d518a4bc38

  16. 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?

    • 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.

  17. 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!

  18. 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

    wg-quick

    it works as it is supposed to. But after switching to NM (

    wg-quick down wg0 &amp;&amp; nmcli con import type wireguard file /etc/wireguard/wg0.conf

    ) wireguard tunnel stops to work because of bad MTU.

    kvě 13 18:50:29 hal3042 nm-openvpn[3814]: tun packet too large on write (tried=1480,max=1450)

    It seems to me

    wg-quick

    is better to guess right MTU for

    wg0

    . Or it has better default.

Comments are Closed

The opinions expressed on this website are those of each author, not of the author's employer or of Red Hat. Fedora Magazine aspires to publish all content under a Creative Commons license but may not be able to do so in all cases. You are responsible for ensuring that you have the necessary permission to reuse any work on this site. The Fedora logo is a trademark of Red Hat, Inc. Terms and Conditions