Repository navigation
Security
CVE-2026-105390 — a locking flaw allowed a local user with access to the driver's device to cause a system deadlock and denial of service, hanging the host until it was power-cycled.
Every earlier release is affected. Users on the 1.x branch should move to 1.3.4, which carries the same fix.
Performance
ovpn-dco-win now spreads the data channel over the machine's cores. Before, a tunnel's encryption, decryption and sending each ran on a single core, so throughput hit a one-core ceiling no matter how many cores the machine had.
Transmit
- Per-CPU encryption workers (#160). The packet queue thread now only copies packets. Encryption and sending happen on up to 8 per-CPU workers. Each inner flow is hashed to one worker, so its packets stay in order. One tunnel no longer tops out at one core's worth of encryption.
- Workers stay off the busy cores. No worker runs on the core where the network card receives the tunnel, or on the driver's own queue-thread core. A flow that landed there used to slow the whole tunnel to about half speed.
- Steady packet ids under load. Each worker sends after every 128 packets, so a stalled vCPU can no longer push its packets outside the receiver's replay window.
- Less per-packet overhead. Transmit buffers keep their memory descriptors (MDLs) instead of allocating them per packet, which removes cross-core contention on every send.
- Bounded memory. Packets in flight are capped (#161); past the cap new packets are dropped instead of growing the buffer pool.
Receive
- Parallel decryption. Received packets are decrypted by per-core workers in batches, then delivered to the network stack in arrival order. Inner TCP connections therefore see no reordering, and replay protection is unchanged.
TCP transport
- One write per pass. A pass's data packets are sent as one stream write of up to 64 KB, instead of one socket send per packet. That per-packet cost was most of the transmit thread's time, and TCP uploads are about 2.5× faster.
Core placement
- A home core for the queue threads. The driver notes which core the network card delivers the tunnel to, and keeps its receive and transmit threads on a different, nearby core. Before, whether a connection ran at full speed depended on where the scheduler happened to put these threads. This applies to clients, and to servers whose traffic comes mostly from one peer (for example site-to-site); on a server with many peers the threads go anywhere, as before.
Measured on AWS (c6i.4xlarge, Windows Server 2025, OpenVPN 2.7.7, AES-256-GCM; iperf3 inside the tunnel, Mbit/s, median of 3 × 30 s, two interleaved runs per build):
| 2.8.7 | 2.8.13 | ||
|---|---|---|---|
| Windows client, UDP, upload (4 conn) | 5121 | 7384 | +44% |
| Windows client, UDP, download (4 conn) | 6065 | 7199 | +19% |
| Windows client, TCP, upload (1 conn) | 2403 | 6169 | +157% |
| Windows client, TCP, upload (4 conn) | 2322 | 5202 | +124% |
| Windows server → Linux client, UDP (4 conn) | 4701 | 7131 | +52% |
| Windows ↔ Windows, UDP (4 conn) | 5164 | 7278 | +41% |
About 7.4 Gbit/s is the most a single tunnel can carry on this network, whichever OS is at either end, because AWS limits each UDP flow to about 8 Gbit/s. With 2.8.13 a Windows tunnel reaches that ceiling.
Fixes
- Slow connection setup and renegotiation (#149). A control packet stayed pending until its network send completed, and OpenVPN dropped the next packets of the same TLS flight while it waited, so every lost packet cost a retransmit timeout. On a test server a handshake took 6.5 s instead of 0.05 s.
- Control writes are bounded. A control write completes as soon as its data is copied, so a fast writer could pile up sends faster than the network completed them. Past 1024 control writes in flight, a write now waits for its send.
- Data channel epoch keys (OpenVPN 2.7
aead-epoch):- the send key now rotates when the packet counter is exhausted;
- the send counter resets when the peer moves to a new epoch;
- re-keying no longer leaks the slot's future and retiring keys;
- the future-key window is 4, as in OpenVPN 2.7. It isn't negotiated, so peers with different window sizes still interoperate.
- Receive: datagrams that arrive in several pieces on different processors no longer share one reassembly buffer.
Diagnostics
- Decryption failures say why: a packet from an epoch already retired (normal after a peer id is reused), one too far ahead to derive a key for, or a failed authentication tag.
- Logs about key installs, key swaps, peer deletion and floats now say which peer they concern.
Full Changelog: 2.8.7...2.8.13