Networking · Concept · 14 min read

WireGuard Explained: How 4,000 Lines of Code Replaced the VPN Stack

A key pair, a list of addresses, and no negotiation at all. Here is what WireGuard does, why it is faster than what came before, what it deliberately refuses to do for you, and the six configuration mistakes everybody makes once.

Written by Marko Ristic, Editor Updated Sep 8, 2026
4kLines of code, against hundreds of thousands for IPsec
2 minLongest gap between handshakes while traffic flows
25 sThe keepalive interval a peer behind NAT needs
UDPThe only transport, which is why it cannot pretend to be HTTPS
Short answer

WireGuard is a VPN protocol that builds an encrypted tunnel using public key cryptography, in about 4,000 lines of code. Each peer has a key pair. You give each one the other's public key and the addresses behind it, and traffic to those addresses goes down the tunnel. There is one handshake, one cipher, and no negotiation to get wrong.

  • A peer is a public key, and nothing else
  • AllowedIPs is the routing table and the access list
  • One cipher suite, so there is nothing to downgrade
  • Silent to anyone without a key, like a closed port
  • No user accounts, no DHCP, no TCP mode, by design
On this page

The designWhat makes it different

The older VPN protocols are frameworks. IPsec and OpenVPN both negotiate: which encryption cipher, which key exchange, which authentication method, which of a dozen options on each side. That flexibility is why those protocols interoperate with everything, and it is also why a misconfigured VPN tunnel can be weak while looking fine.

WireGuard removes the negotiation. The protocol has one key exchange, one encryption cipher, one hash and one way to authenticate. If a weakness is found in any of them, the answer is a new version of WireGuard rather than a configuration change, which its author has argued is the honest way to handle a broken primitive.

The size follows from that. IPsec across the kernel and its daemons runs to hundreds of thousands of lines of code. OpenVPN plus its OpenSSL dependency is comparable. WireGuard is around 4,000 lines of open source code, small enough for one person to read in a weekend and small enough to be audited seriously before it entered the Linux kernel.

The practical effect is that a WireGuard configuration file fits on a screen, and no part of it is a place where a wrong choice quietly weakens the encryption. That is most of why the protocol has spread as fast as it has.

KeysKeys, and how a peer is identified

Every WireGuard peer generates a key pair. The private key stays on the machine. The public key is handed to whoever needs to reach it, exactly like an SSH key, and the two keys together are the whole of WireGuard authentication.

There are no certificates, no certificate authority and no identity beyond the key. A WireGuard peer is its public key.

This is a deliberate simplification and it is the main security question organizations have to answer, because the protocol has no built in way to say "this user, from the directory, until their account is disabled". Key distribution and revocation are your problem, and at scale that means a management layer on top of WireGuard.

The upside is that no WireGuard key expires, nothing needs renewing at three in the morning, and there is no chain to validate.

AllowedIPsCryptokey routing, the idea that carries everything

This is the WireGuard concept people miss, and it is where the protocol's simplicity actually lives.

Each WireGuard peer entry has an AllowedIPs list, and that one setting does two jobs at once.

Outbound, it is a routing table. Data destined for an address in a peer's AllowedIPs is encrypted with that peer's key and sent to that peer. That is how the VPN tunnel decides where anything goes.

Inbound, it is an access control list. Data that arrives decrypted from a peer is dropped unless its source address is inside that peer's AllowedIPs. A WireGuard peer cannot claim to be an address it was not given, and that is the protocol's entire inbound security model.

Binding those two together is why WireGuard needs no separate firewall policy for the tunnel and no routing protocol inside it. It is also the setting people get wrong most often.

Setting AllowedIPs = 0.0.0.0/0 on a peer means "send everything to this peer and accept anything from it". That is what you want on a VPN client routing all its traffic through a server, and a serious mistake on a server entry for a single laptop.

The handshakeThe handshake, and why it is quiet

WireGuard runs over UDP on a single port, and the protocol says nothing at all to anyone who cannot prove they hold a key.

A WireGuard peer that receives data which does not authenticate does not reply. No error, no version banner, no response of any kind. To a port scanner a WireGuard VPN endpoint looks like a closed UDP port. That is a deliberate security decision, and it removes an entire category of attack that starts with finding the service.

The handshake itself happens every two minutes at most, and only when there is traffic. It gives both sides fresh encryption keys, so a compromised key does not decrypt yesterday's captured data.

Two things follow from that transport choice, and both separate WireGuard from older VPN protocols.

Roaming works. The server identifies a WireGuard client by its key, not by its address, so a phone moving from wifi to mobile data keeps the VPN connection. The first packet from the new address, correctly authenticated, updates where the server sends replies. No reconnection, no thirty second stall.

Idle tunnels send nothing. With no data to carry, WireGuard is silent, which is good for battery and bad for anything with a NAT table that forgets a connection. PersistentKeepalive = 25 sends a tiny packet every 25 seconds, and is required on any WireGuard peer behind NAT that has to stay reachable.

ConfigurationSetting one up

A WireGuard configuration is short enough to show in full, which is not true of any other VPN protocol in common use.

On the VPN server:

[Interface]
PrivateKey = <server private key>
Address = 10.8.0.1/24
ListenPort = 51820

[Peer]
PublicKey = <laptop public key>
AllowedIPs = 10.8.0.2/32

On the client laptop:

[Interface]
PrivateKey = <laptop private key>
Address = 10.8.0.2/24

[Peer]
PublicKey = <server public key>
Endpoint = vpn.example.com:51820
AllowedIPs = 10.8.0.0/24, 192.168.10.0/24
PersistentKeepalive = 25

That is a working WireGuard tunnel. The client reaches the 10.8.0.0/24 tunnel network and the 192.168.10.0/24 office network through it. Everything else goes out the laptop's normal connection, because it is not in AllowedIPs.

To send all client data through the VPN tunnel instead, the laptop's AllowedIPs becomes 0.0.0.0/0, and the server forwards and masquerades that traffic, which is one kernel setting and one firewall rule rather than anything WireGuard itself does.

The commands, in the order you need them. Generate a key pair, keeping the private key readable only by root:

umask 077
wg genkey | tee privatekey | wg pubkey > publickey

Bring the tunnel up and down, and set it to start at boot:

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

Read the live state, which is the first thing to look at when a VPN tunnel misbehaves:

sudo wg show

That last one prints, per peer, the last handshake time and the bytes sent and received. A recent handshake with zero bytes received means the tunnel is up and the routing is wrong. No handshake at all means the two ends never agreed, so check the keys, the endpoint and whether UDP is reaching the server.

PlatformsWhere you can run it

WireGuard runs on every platform that matters, and how it runs differs enough to be worth a table.

PlatformHow it runsWorth knowing
LinuxIn the kernel since 5.6The fastest WireGuard there is
WindowsA kernel driver, with an official appSet up by importing a config file
macOSAn app, from the App Store or HomebrewThe App Store version is sandboxed
iOS and AndroidAn official VPN appConfig imported by QR code
OpenWrt and routersA package or built inTurns a router into a site to site VPN
BSD and othersUserspace, in GoSlower, but the same protocol

Two practical notes. The mobile VPN apps read a configuration from a QR code, so setting up a phone means generating the config on the server and showing it as an image rather than typing WireGuard keys on a touchscreen.

And on every platform a WireGuard tunnel is a network interface like any other, so the operating system's own firewall and routing tools apply to it with nothing WireGuard specific involved.

The gapsWhat it deliberately leaves out

Knowing what WireGuard leaves out matters more than knowing what it includes, because these are the gaps you fill yourself.

No dynamic address assignment. WireGuard has no equivalent of DHCP. Every peer's tunnel address is written into the configuration on both sides, by hand or by whatever you build.

No user management. No accounts, no directory integration, no per user policy in the protocol. A WireGuard key is a key, and nothing more.

No push configuration. A WireGuard server cannot tell a client what routes to use. Both ends are configured independently and have to agree.

No obfuscation. WireGuard data is recognizable as WireGuard. In a country that blocks VPN protocols by signature that matters, and the answer is wrapping the secure tunnel inside something else.

No TCP mode. UDP only. On a network that permits only TCP on port 443 a WireGuard client does not connect at all, where an OpenVPN client would.

Every commercial WireGuard product exists to fill the first three gaps, and it is worth knowing you are buying management around the VPN rather than a better protocol.

PerformanceWhy it is fast, mechanically

Every WireGuard comparison leads with speed, and the reason is worth understanding rather than taking on faith. Four things make the protocol faster than the VPN protocols before it, and none of them is a trick.

It runs in the kernel. On Linux, WireGuard is a kernel module, so an encrypted packet never leaves kernel space, and that alone makes it faster than anything in userspace. OpenVPN runs in userspace, which means every packet crosses the kernel boundary twice.

That copying is a large part of why OpenVPN is the slowest of the three, and it is why the fast userspace implementations of WireGuard on other platforms do not quite match the Linux numbers.

The cipher was chosen for software. ChaCha20-Poly1305 is fast on processors without AES acceleration, which describes most phones and many small routers. On a modern server with AES instructions the gap narrows, but WireGuard has no slow case on any device.

There is no per packet state machine. A WireGuard packet is decrypted, checked against the peer's allowed addresses, and delivered. No session lookup of the kind IPsec does, no framing layer of the kind OpenVPN adds, which is why it is faster than both.

Handshakes are rare. Key agreement happens at most every two minutes and only when data is flowing, so the expensive cryptography is amortized across everything sent in between.

In independent testing WireGuard reaches several times the speed of OpenVPN on the same hardware and matches or beats IPsec, with noticeably lower latency than either of those protocols. On a small router that speed difference decides whether the VPN can saturate the line at all.

ProvidersCommercial VPN services, and what the protocol does not decide

Most people meet WireGuard through a commercial VPN service rather than a server of their own, and that changes which questions matter.

The WireGuard protocol gives you a fast, secure, modern encrypted VPN tunnel to whoever runs the other end. It says nothing about what that operator does with the traffic once it is decrypted. Privacy in a commercial VPN service is a policy and jurisdiction question, not a question about protocols, and no amount of good cryptography answers it.

One real technical wrinkle is worth knowing. WireGuard assigns each client a fixed tunnel address, written into the configuration on the server. A provider running it as designed therefore holds a table mapping every user to an address, which is exactly the record a privacy focused service does not want to keep.

The serious VPN providers solve this with systems that rotate or double blind that mapping, and the fact that they had to build something says WireGuard does not give privacy away for free.

For a WireGuard VPN you run yourself none of this applies. The other end of the tunnel is your own server, and the only devices holding keys are the ones you handed them to.

PitfallsWhere people go wrong

AllowedIPs too wide on the server. Giving a laptop 0.0.0.0/0 on the WireGuard server's peer entry tells the server to route everything to that client and to accept any source address from it. Use a /32 for a single device.

Two peers with overlapping AllowedIPs. The WireGuard routing table cannot hold the same address behind two peers. One of them silently stops working, and the configuration looks correct on both sides.

Forgetting the keepalive behind NAT. A site to site VPN where only one end has a public address needs PersistentKeepalive on the private end. Without it the tunnel works until it goes idle, then takes minutes to come back.

Expecting IP forwarding to be on. A server routing data between peers needs net.ipv4.ip_forward = 1. The tunnel comes up, the handshake succeeds, and nothing passes. This is the most common "WireGuard is broken" report, and it is not WireGuard.

Copying a private key between devices. Two devices with the same key fight over the same tunnel address, and their handshakes overwrite each other. Generate a WireGuard key per device, always.

Treating the key as the whole security story. Anyone holding the private key file is that peer. On a client laptop that means disk encryption and file permissions, because a WireGuard tunnel has no password on it.

ONE PEER ENTRY[Peer]PublicKey = abc...AllowedIPs = 10.8.0.2/32The last line does two jobs,and that is the whole ofWireGuard access control.OUTBOUND: A ROUTING TABLETraffic for 10.8.0.2 is encryptedwith this key and sent to this peer.Anything else takes another route.INBOUND: AN ACCESS CONTROL LISTA decrypted packet from this peer isdropped unless its source is 10.8.0.2.A peer cannot claim another address.Widen it to 0.0.0.0/0 and the server routes everything here and believes anything from it.Correct on a client sending all its traffic through a server. Wrong on a server entry for one laptop.
One peer entry, and the one line in it that routes outbound traffic and filters inbound traffic at the same time.

ComparisonWireGuard, OpenVPN and IPsec IKEv2, on what each one is actually better at

CriterionWireGuardOpenVPNIPsec IKEv2
Code size to auditTinyLargeVery large
Configuration complexityLowMediumHigh
Throughput on the same hardwareHighestLowestHigh
Handles roaming between networksYesReconnectsMostly
Runs over TCP 443 when neededNoYesNo
Built into mobile operating systemsNoNoYes
User accounts and directory loginNoYesYes
Cipher choiceNone, by designManyMany
Interoperates with vendor hardwareNoSometimesYes

The pattern: WireGuard is the fast, simple, auditable option. OpenVPN wins when the network is hostile and the connection has to look like HTTPS. IPsec wins when the tunnel has to terminate on somebody else's firewall.

FAQFrequently asked questions

What is WireGuard in simple terms?

A VPN protocol where each device has a key pair, you exchange public keys, and traffic to the addresses you list goes through a secure encrypted tunnel.

Is WireGuard faster than OpenVPN?

Yes, consistently. WireGuard runs in the Linux kernel, uses a cipher chosen for software speed, and does far less work per packet. The speed difference is large enough to see on the same hardware.

Is WireGuard secure?

The cryptography is modern and the code is small enough to have been audited properly. WireGuard security fails at key handling and configuration, not in the protocol itself.

What is AllowedIPs in WireGuard?

Both the routing table and the access control list for a peer. Outbound it decides what goes to that peer, inbound it decides what that peer is allowed to claim to be.

Does WireGuard hide that I am using a VPN?

No. The traffic is recognizable as WireGuard, though the endpoint answers nobody without a key. Hiding the protocol needs a wrapper around it.

Why does my tunnel drop when idle?

A NAT device between the peers dropped the mapping because nothing was sent. Add PersistentKeepalive = 25 on the peer behind NAT.

Can WireGuard use TCP?

No, UDP only. On a network that allows only TCP 443 a WireGuard client will not connect, and a tunnel wrapper is the usual workaround.

How do I revoke WireGuard access?

Remove the peer entry from the server's configuration and reload. There is no revocation list in the protocol, which is why key management at scale needs something on top.

Does WireGuard support IPv6?

Fully, on both the tunnel network and the outer transport, and one WireGuard VPN carries both at once.

How many peers can one WireGuard server handle?

Thousands. The per peer cost is small, and the practical limit is bandwidth and how you manage the keys, not the protocol.

Do I need a static IP on the VPN client?

No. Only the side being connected to needs a reachable endpoint. WireGuard clients roam freely, which is the point of identifying peers by key.

Why does my WireGuard handshake succeed but no traffic passes?

Almost always IP forwarding is off on the server, or AllowedIPs does not include the network being reached. Check those two before anything else, and read sudo wg show first.

Read next · Remote access VPN vs Proxy Whether you want a tunnel at all, before choosing which protocol builds it. Open this next13 min
Also worth reading
One packet a weekA short, illustrated explainer every Tuesday. No vendor pitches, unsubscribe in one click.