Why OpenVPN Is Giving Way to WireGuard
OpenVPN and IPsec have been staples for network administrators for years. However, their inherent drawback is a bloated codebase spanning hundreds of thousands of lines of code, resulting in high CPU usage and noticeable latency. Whenever you switch from Wi-Fi to cellular data, OpenVPN often takes 10–20 seconds to complete a handshake and reconnect.
WireGuard eliminates this hassle entirely. Its entire codebase consists of just under 4,000 lines, built directly into the Linux kernel starting from version 5.6. Real-world benchmarks demonstrate that WireGuard delivers 3–4 times the throughput of OpenVPN while saving around 30% battery on mobile devices. With an Ubuntu 22.04 or 24.04 VPS running on 1 vCPU / 1GB RAM, you can complete the entire setup in less than 10 minutes.
Core Concepts: How Does WireGuard Work?
Understanding how WireGuard operates under the hood will help you troubleshoot network issues rapidly:
- Cryptokey Routing Model: WireGuard treats every device as an equal Peer. Similar to SSH key authentication, each machine holds its own Public/Private Key pair. The server routes and decrypts packets directly based on the Public Key, eliminating tedious TLS handshakes and authentication steps.
- Direct Execution in Kernel Space: Data does not need to bounce back and forth between User Space and Kernel Space like OpenVPN’s TUN/TAP mechanism. As a result, latency is kept to a minimum and network interface bandwidth is fully utilized.
- Stateless Design: WireGuard does not transmit continuous keepalive packets unless there is active data to send. The server remains completely silent in response to random port scans across the Internet.
Step-by-Step Guide: Installing and Configuring WireGuard on Ubuntu
Step 1: Enable IP Forwarding
By default, Linux blocks packet forwarding between network interfaces. You must enable this feature so your VPS can route traffic to the Internet:
sudo sed -i -e '$a\net.ipv4.ip_forward = 1' /etc/sysctl.conf
sudo sed -i -e '$a\net.ipv6.conf.all.forwarding = 1' /etc/sysctl.conf
sudo sysctl -p
If the output shows net.ipv4.ip_forward = 1, the system has successfully applied the new configuration.
Step 2: Install Packages and Generate Server Keys
Install WireGuard along with the QR code generator utility for easy mobile device setup:
sudo apt update && sudo apt install -y wireguard qrencode
Create the working directory and generate the Server’s private/public key pair with secure permissions:
cd /etc/wireguard
umask 077
wg genkey | tee server_private.key | wg pubkey > server_public.key
You can view the key file contents using cat server_private.key. Never expose your Private Key to anyone.
Step 3: Identify Network Interface and Create Server Configuration
Find the primary network interface connected to the Internet by running:
ip -br link
Typically, the network interface is named eth0, ens3, or enp1s0. Be sure to use this exact name in the iptables firewall rules below.
Create the server configuration file at /etc/wireguard/wg0.conf:
sudo nano /etc/wireguard/wg0.conf
Paste the following configuration into the file (replacing the keys and network interface accordingly):
[Interface]
Address = 10.8.0.1/24, fd42:42:42::1/64
ListenPort = 51820
PrivateKey = <CONTENTS_OF_server_private.key>
SaveConfig = false
# Enable NAT when bringing up VPN and remove NAT when bringing down VPN (replace eth0 with your actual interface)
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ip6tables -A FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE; ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
Step 4: Configure Firewall and Start the Service
Open UDP port 51820 in UFW and start WireGuard via systemd:
sudo ufw allow 51820/udp
sudo ufw allow OpenSSH
sudo ufw enable
# Enable WireGuard to start on boot and run immediately
sudo systemctl enable --now wg-quick@wg0
Check the server status with the following command:
sudo wg show
If the terminal displays the wg0 interface along with port 51820 and the public key, your server is ready to accept incoming connections.
Step 5: Generate Client Configuration and QR Code
Generate a key pair for the first client device (for example, client1):
cd /etc/wireguard
wg genkey | tee client1_private.key | wg pubkey > client1_public.key
Add the Client information to the server configuration by editing /etc/wireguard/wg0.conf and appending the following block:
[Peer]
PublicKey = <CONTENTS_OF_client1_public.key>
AllowedIPs = 10.8.0.2/32, fd42:42:42::2/128
Apply the updated server configuration without restarting the service:
sudo wg addconf wg0 <(sudo wg-quick strip wg0)
Next, create the client configuration file client1.conf to import into the device:
[Interface]
PrivateKey = <CONTENTS_OF_client1_private.key>
Address = 10.8.0.2/24, fd42:42:42::2/64
DNS = 1.1.1.1, 8.8.8.8
[Peer]
PublicKey = <CONTENTS_OF_server_public.key>
Endpoint = <SERVER_PUBLIC_IP>:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25
To import the configuration on a phone, simply output the QR code in the terminal and scan it with the WireGuard mobile app:
qrencode -t ansiutf8 < client1.conf
Production Tips for Operating WireGuard
1. Fix Web Congestion and Stalling with MTU Tuning
If ping works reliably but large websites stall or load sluggishly, the root cause is often packet fragmentation due to an oversized MTU across multiple network hops. Lower the MTU in the Client configuration file:
[Interface]
MTU = 1360
An MTU value between 1360 and 1420 provides solid stability across most fiber-optic and 4G/5G mobile networks.
2. Prevent NAT Connection Drops with PersistentKeepalive
Many Wi-Fi routers and mobile carriers using CGNAT automatically flush idle NAT state tables after 30 seconds of inactivity. Adding PersistentKeepalive = 25 to the Client’s [Peer] section sends a lightweight probe packet every 25 seconds. This keeps the NAT tunnel open and ensures you receive push notifications instantly.
3. Full Tunnel vs. Split Tunnel
Depending on your workflow requirements, adjust the AllowedIPs directive in the Client file:
- Full Tunnel (
AllowedIPs = 0.0.0.0/0, ::/0): All web browsing and file traffic routes through the VPS. This setup is strongly recommended when connected to untrusted public Wi-Fi in cafes or hotels. - Split Tunnel (
AllowedIPs = 10.8.0.0/24): Only traffic destined for the internal VPN subnet routes through the tunnel, while normal Internet browsing uses your native connection. This saves VPS bandwidth and maintains maximum browsing speeds.
Summary
WireGuard proves that a secure networking solution doesn’t need to be complex or bloated. With just a few commands to generate keys and configure iptables routing, you get a blazingly fast, private encrypted tunnel. Properly tuning your MTU and Keepalive settings right from the start ensures a seamless VPN experience across all your devices.

