WireGuard — Secure VPN Tunnel

Published

July 9, 2026

Modified

July 9, 2026

Keywords

Terminal, Security, Network

Overview

WireGuard1 is a modern VPN protocol that creates encrypted tunnels between peers using state-of-the-art cryptography. Unlike legacy solutions such as OpenVPN or IPsec, it is designed to be faster, simpler, and easier to audit — the entire codebase fits in roughly 4,000 lines of C.

WireGuard operates over UDP and establishes connections only when traffic needs to flow, keeping idle tunnels silent. Each peer is identified by a public key, similar to SSH, eliminating the complexity of certificate authorities and pre-shared keys. It supports both peer-to-peer and server-client topologies, making it suitable for everything from remote access to site-to-site networking.

WireGuard vs SSH-Based Alternatives

SSH tunneling has long been the go-to method for quickly creating secure connections. Tools like sshuttle2 extend this idea by intercepting traffic at the network layer and proxying it over SSH, acting as a poor man’s VPN without requiring admin access on the remote side. Yet both approaches share a fundamental limitation: they tunnel everything over a single SSH connection.

Dimension SSH Tunnel sshuttle WireGuard
Layer Application (port forwarding) Network-layer interception proxied over SSH Network layer (kernel TUN device)
Scope Single host or specific forwarded ports Entire subnets routed through one SSH session Entire subnets; full mesh between peers
Performance Userspace encryption; per-port connections degrade under load Single SSH connection becomes a bottleneck; TCP-over-TCP latency Kernel-mode crypto; near-wire-speed throughput
Topology Client-server only Client-server only Peer-to-peer and server-client; any peer can initiate
Admin required No No on the remote side Yes, to install and configure WireGuard
DNS Manual forwarding or -D SOCKS proxy Built-in DNS tunneling over SSH Routes DNS like any other traffic

When you need quick access to a remote network without admin privileges, sshuttle is the practical choice. It intercepts traffic destined for specified subnets and forwards it over SSH, handling DNS automatically. The drawback is that all traffic funnels through a single SSH connection — if that connection drops, everything goes down. Performance suffers under heavy load because SSH encrypts in userspace and stacks TCP over TCP.

WireGuard handles multi-host networking naturally. Every peer on the tunnel can reach every other peer directly, with no hub-and-spoke bottleneck. The trade-off is that you need to deploy and configure WireGuard on both ends — it does not reuse your existing SSH keys or daemon.

Installation

The WireGuard kernel module is included in the mainline Linux kernel since version 5.6, so every current Fedora release has it built in. You only need the userspace tools to manage tunnels and handle configuration.

Install the package from the default repositories:

sudo dnf install -y wireguard-tools
Binary Purpose
wg Configure and inspect WireGuard interfaces
wg-quick Bring interfaces up or down using a configuration file

Verify the installation and confirm the kernel module is available:

wg --version
modprobe wireguard
lsmod | grep wireguard

The modprobe command loads the module immediately. The lsmod output confirms it is active and ready before you create any tunnel interfaces.

On Fedora Workstation, you can also manage WireGuard through NetworkManager, which integrates with GNOME’s network settings panel. Import an existing configuration file with:

sudo nmcli connection import type wireguard file /etc/wireguard/wg0.conf

This approach is optional. The wg-quick method works on both servers and desktops and gives you more control over the tunnel lifecycle.

Usage

Key Generation

Each peer in a WireGuard tunnel needs a private key and a corresponding public key. The keys are 32-byte values encoded in base64, derived from the Curve25519 elliptic curve3.

Generate a private key:

wg genkey

Derive the matching public key from it:

wg genkey | wg pubkey

Generates both keys at once, saving the private key to a file while piping it through wg pubkey:

wg genkey | tee private.key | wg pubkey > public.key
chmod 600 private.key

Configuration

Once the client has generated its key pair, share only the public key with the server. The private key stays on the client machine and never leaves it. On the server, register the client as a peer by adding a [Peer] block to /etc/wireguard/wg0.conf:

[Peer]
PublicKey = <client-public-key>
AllowedIPs = 10.0.0.2/32

The PublicKey field authenticates the client. The AllowedIPs field assigns the client a tunnel IP address and defines which traffic from that IP is accepted. Use a /32 CIDR mask for individual hosts.

Apply the change without disrupting existing peers:

sudo wg set wg0 peer <client-public-key> allowed-ips 10.0.0.2/32
sudo wg-quick save wg0

The wg set command updates the live interface immediately. The wg-quick save command persists the runtime configuration back to the config file so it survives a reboot.

Create the client configuration file at /etc/wireguard/wg0.conf on the client machine4:

[Interface]
Address = 10.0.0.2/24
PrivateKey = <client-private-key>
DNS = 1.1.1.1

[Peer]
PublicKey = <server-public-key>
Endpoint = <server-ip>:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25

The Endpoint field specifies the server’s reachable address and port. The AllowedIPs = 0.0.0.0/0, ::/0 directive routes all IPv4 and IPv6 traffic through the tunnel. For split tunneling, replace it with specific CIDR ranges such as 10.0.0.0/24. The PersistentKeepalive setting sends a heartbeat every 25 seconds to keep NAT mappings alive when idle.

Start the tunnel on the client:

sudo wg-quick up wg0
sudo systemctl enable wg-quick@wg0

Verify the connection with sudo wg. The output shows peer status, data transfer counters, and the time since the last handshake.