Safeguard
Supply Chain Security•

OpenVPN Explained: TLS Control Channel, Data Channel and Hardening

OpenVPN runs a TLS control channel and a separate encrypted data channel over one UDP or TCP connection. How both work, what changed in 2.6, and hardening.

Safeguard Security Team
43 min read

OpenVPN is an open source VPN protocol that carries IP packets or Ethernet frames through an encrypted tunnel over a single UDP or TCP connection, by default on port 1194. Inside that connection it runs two channels: a TLS control channel that authenticates the peers with certificates and agrees keys, and a separate data channel that encrypts tunnel traffic with those keys using AES-GCM or ChaCha20-Poly1305.

That split is the whole story of OpenVPN's security. TLS does the hard part, the handshake and the identity checks, and OpenVPN's own lightweight packet format does the fast part, moving traffic. Most hardening advice is about one side of the split or the other: which TLS settings protect the handshake, which keys wrap the control channel before TLS even starts, and which data ciphers may be negotiated. Below: both channels on the wire, the control channel wrappers, cipher negotiation from 2.4 to 2.7, weakness classes as concepts, and defender checks. Facts come from the OpenVPN 2.6 reference manual, the project's source repository and wire protocol draft, the community wiki, the IETF RFCs and the IANA registry, all fetched on 23 October 2026.

Key takeaways

  • OpenVPN has no IETF standard. The protocol is defined by the open source implementation, its reference manual and a wire protocol document the project itself marks as "work in progress". Port 1194 over UDP and TCP has been registered to OpenVPN with IANA since November 2004.
  • One connection carries both channels. The first byte of every packet (the third byte over TCP) holds a 5 bit opcode and a 3 bit key ID that say which channel and which key generation the packet belongs to.
  • The control channel tunnels a normal TLS session (TLS 1.2 minimum by default since 2.6.0, TLS 1.3 when both sides support it) over OpenVPN's own reliability layer, so TLS works over UDP. Data channel keys come from the TLS keying material exporter defined in RFC 5705.
  • tls-auth adds an HMAC to every control packet, tls-crypt encrypts and authenticates control packets with a shared key, and tls-crypt-v2 gives every client its own wrapping key. All three let a server drop unauthenticated packets before any TLS code runs.
  • Since 2.5, data-ciphers is the list of allowed data ciphers and the server picks the first one the client also supports. The 2.6 default is AES-256-GCM, AES-128-GCM and ChaCha20-Poly1305. BF-CBC is no longer accepted by default and cipher is ignored in TLS mode.
  • OpenVPN 2.6 added data channel offload (DCO), a kernel module that moves encryption of tunnel packets out of user space on Linux. DCO requires AEAD data ciphers.
  • The weakness classes to design out are deprecated ciphers and compression, clients that do not check the server certificate's role (remote-cert-tls server), TCP tunnels carrying TCP traffic, and a management interface reachable from the network.

What OpenVPN is for, the layer and the standard

OpenVPN solves the problem of joining a remote device or a remote network to a private network across an untrusted one. A laptop connects to a company network, two offices join their LANs, or a cloud subnet reaches an on premises one. It does this by creating a virtual network interface on each side, a tun device for routed IP traffic or a tap device for bridged Ethernet frames, reading packets from that interface, encrypting them, and sending them to the peer inside ordinary UDP datagrams or a TCP stream.

So OpenVPN is a tunnelling protocol that runs over the transport layer, carrying network layer packets (or link layer frames in tap mode) inside UDP or TCP, which is why it crosses NAT more easily than protocols with their own IP protocol number.

The defining documents

There is no RFC for OpenVPN. The project's wire protocol document, published from the OpenVPN/openvpn-rfc repository, opens with a warning that it "should not considered a complete or correct documentation of the OpenVPN protocol yet" and tells implementers to check the current implementations. It describes OpenVPN as an SSL/TLS based VPN "first released in 2001". In practice the protocol is defined by three things:

DocumentWhat it definesStatus on 23 Oct 2026
OpenVPN 2.6 reference manual (openvpn.net, mirrored from doc/man-sections in the source tree)Every option, its default and its security notes2.6 is the previous stable branch
OpenVPN wire protocol draft (openvpn.github.io/openvpn-rfc)Packet formats, opcodes, key derivation, epoch keysMarked work in progress
Changes.rst in the source repositoryWhat each release added, deprecated or removedCurrent through 2.6.23 and 2.7.x
RFC 8446 (TLS 1.3, August 2018) and RFC 5246 (TLS 1.2)The TLS session carried inside the control channelStandards Track
RFC 5705 (Keying Material Exporters for TLS, March 2010)How data channel keys are exported from the TLS sessionStandards Track, updated by RFC 8446
IANA service name and port registryopenvpn on 1194/udp and 1194/tcp, registered 2004-11Assigned

The 2.6 manual adds that 1194 "represents the official IANA port number assignment for OpenVPN and has been used since version 2.0-beta17. Previous versions used port 5000 as the default."

Where TLS fits in

The control channel is a real TLS session. OpenVPN does not invent its own handshake; it hands the bytes to OpenSSL or mbed TLS and lets that library run TLS 1.2 or TLS 1.3. RFC 8446 matters here because TLS 1.3 removed static RSA and plain Diffie-Hellman key exchange, encrypted every handshake message after the ServerHello, and defined the exporter secret that OpenVPN uses to derive data channel keys. If you want the TLS 1.3 handshake itself step by step, our posts on what TLS is and the TLS 1.3 handshake cover it; this post treats TLS as a black box and focuses on what OpenVPN wraps around it.

How OpenVPN works on the wire

One connection, two channels

OpenVPN's own cryptographic layer overview draws the design as a multiplexer. On one side, TLS sits on top of a reliability layer, optionally wrapped by the tls-auth HMAC. On the other, tunnel IP packets are encrypted and authenticated directly. Both streams merge into one UDP or TCP connection:

TLS session --> reliability layer --> tls-auth / tls-crypt wrap --\
                                                                   >-- multiplexer --> UDP or TCP
Tunnel IP packets --> encrypt + authenticate (data channel) ------/

The page explains the reason: TLS was designed for a reliable transport, so OpenVPN gives TLS one, while tunnel packets travel "without any reliability layer" so that, over UDP, IP packets are never stuck behind retransmissions. "The reliability and authentication layers are completely independent of one another." The same page still describes Blowfish as the default cipher, which reflects old releases; the architecture is unchanged, but use the 2.6 manual for current defaults.

The common header: opcode and key ID

Every OpenVPN packet starts with one byte that holds a 5 bit opcode and a 3 bit key ID. Over UDP that byte is the first byte of the datagram. Over TCP each packet is prefixed by a 16 bit length field in network byte order, so the opcode is the third byte. The wire protocol draft lists the opcodes:

OpcodeNameChannelStatus
1, 2CONTROL_HARD_RESET_CLIENT_V1, CONTROL_HARD_RESET_SERVER_V1ControlObsolete
3CONTROL_SOFT_RESET_V1ControlCurrent, starts a key renegotiation
4CONTROL_V1ControlCurrent, carries TLS records
5ACK_V1ControlCurrent, acknowledgements only
6DATA_V1DataDeprecated, no peer ID
7, 8CONTROL_HARD_RESET_CLIENT_V2, CONTROL_HARD_RESET_SERVER_V2ControlCurrent, start a session
9DATA_V2DataCurrent, 24 bit peer ID
10CONTROL_HARD_RESET_CLIENT_V3ControlCurrent, session start with tls-crypt-v2
11CONTROL_WKC_V1ControlCurrent, control packet with wrapped client key
12, 13CONTROL_OOB_V1, CONTROL_OOB_WKC_V1ControlOut of band messages
14CONTROL_DATA_V1ControlUnreliable control data using the data channel cipher

The key ID ranges from 0 to 7. The first TLS session uses key ID 0; each renegotiation increments it, and after 7 it wraps to 1, never back to 0. That lets old and new keys coexist during a renegotiation without ambiguity.

Control channel packet layout

The draft defines the fields in order. Fields marked "wrap" are only present when tls-auth adds its HMAC:

FieldSizeMeaning
pkt_len16 bitsPacket length, TCP only
opcode and key_id5 + 3 bitsPacket type and key generation
own_session_id64 bitsRandom ID for this side's session; RECOMMENDED to be 64 random bits
HMAC (wrap)128 to 512 bitstls-auth signature; length set by the digest
replay_packet_id (wrap)64 bitsReplay counter: 32 bit time plus 32 bit counter
acked_pktid_len8 bitsNumber of acknowledgements in this packet
acked_pktid_list32 bits eachControl packet IDs being acknowledged
peer_session_id64 bitsRemote session ID, present only when acknowledging
packet_id32 bitsSequence number of this control packet; ACK_V1 has none
payloadvariableUsually a TLS record

Control packet IDs start at 0 and must be "sequential without gaps". A retransmission reuses the packet ID but gets a new replay ID. Unlike TCP, acknowledgements are not cumulative: each ACK confirms exactly one packet, an ACK_V1 usually carries up to 8 and other packets up to 4.

The connection sequence

Putting the opcodes together, a client to server connection with tls-crypt or tls-auth looks like this:

Client                                              Server
  |-- CONTROL_HARD_RESET_CLIENT_V2 (key_id 0) --------->|  wrapped: dropped here if HMAC/tag is wrong
  |<-------------------- CONTROL_HARD_RESET_SERVER_V2 --|  2.6+ server: session ID is an HMAC cookie
  |-- ACK_V1 / CONTROL_V1 (TLS ClientHello) ----------->|  three-way reset handshake complete
  |<-------------------- CONTROL_V1 (TLS ServerHello..) |
  |-- CONTROL_V1 (TLS Finished, client certificate) --->|  TLS 1.2 or 1.3 inside CONTROL_V1
  |<-------------------- CONTROL_V1 (TLS Finished) -----|
  |-- CONTROL_V1 [key exchange: OCC string,          -->|  username/password if configured,
  |               username, password, peer info]        |  IV_CIPHERS, IV_PROTO, IV_VER ...
  |<-------------------- CONTROL_V1 [key exchange] -----|
  |-- CONTROL_V1 [PUSH_REQUEST] ----------------------->|  (2.5+ servers may push without waiting)
  |<-------------------- CONTROL_V1 [PUSH_REPLY: cipher, peer-id, routes, ifconfig ...]
  |   both sides export data keys from TLS (RFC 5705 label "EXPORTER-OpenVPN-datakeys")
  |== DATA_V2 (peer_id, packet_id, AEAD ciphertext) ==>|
  |<================================= DATA_V2 =========|
  |   ... after reneg-sec (default 3600 s) ...
  |-- CONTROL_SOFT_RESET_V1 (key_id 1) --------------->|  new TLS session, old key kept for tran-window

With tls-crypt-v2, the first client packet is CONTROL_HARD_RESET_CLIENT_V3 and carries the client's wrapped key so the server can unwrap it before replying.

The reliability layer, and UDP versus TCP

Over UDP, OpenVPN's control channel retransmits unacknowledged packets itself, which is what lets a TLS session survive packet loss. Data packets have no retransmission at all. Over TCP, the operating system's TCP stack provides reliability for everything, including tunnel packets. The manual's proto entry is direct about the trade off: "OpenVPN is designed to operate optimally over UDP", and TCP "will usually be somewhat less efficient and less robust when used over unreliable or congested networks." The default is proto udp. TCP mode needs one side to be tcp-server and the other tcp-client.

The key exchange message and data channel keys

After the TLS handshake, each side sends a key exchange message inside the TLS session. It starts with four zero bytes and a method byte of 2, then random fields used only by legacy peers, then the OCC options string, an optional username and password, and the peer info string. Peer info is a list of VAR=VALUE lines such as IV_VER, IV_PLAT, IV_PROTO (a bit field of supported protocol extensions) and IV_CIPHERS (the client's allowed data ciphers).

Modern peers derive 256 bytes of data channel key material with the RFC 5705 exporter, using the label EXPORTER-OpenVPN-datakeys. That block splits into four 64 byte parts: an encryption key and an authentication key for each direction. Older peers that cannot export keys fall back to a TLS 1.0 style PRF built on MD5 and SHA-1, which the draft calls deprecated and says should only be implemented for compatibility.

Data channel packets

The common data packet today is DATA_V2 with an AEAD cipher:

FieldSizeMeaning
opcode and key_id8 bits9 (DATA_V2) and the key generation
peer_id24 bitsLets the server find the session when a client's address changes
packet_id32 bitsCounter, part of the nonce, used for replay protection
authentication tag128 bitsAEAD tag (at the front in this format)
encrypted payloadvariableThe tunnelled IP packet or Ethernet frame

For AES-GCM and ChaCha20-Poly1305 the 96 bit nonce is the 32 bit packet ID plus 64 implicit bits taken from the data channel key. The opcode, key ID, peer ID and packet ID are all covered by the tag, so a forged peer ID fails authentication. Receivers enforce a sliding replay window: a packet with a counter already seen, or too far below the highest seen, is dropped.

The older CBC format puts an HMAC and an explicit IV in front of the ciphertext. The manual's auth entry notes that OpenVPN uses encrypt-then-MAC for CBC, "which prevents padding oracle attacks", and that the auth digest is ignored for the data channel when an AEAD cipher is in use.

OpenVPN 2.7 introduced a newer AEAD format with the tag at the end, 64 bit packet IDs split into a 16 bit epoch and a 48 bit counter, and an XOR-built nonce. Epoch keys let a peer switch to a fresh key automatically when a cipher's usage limit is near, in the same spirit as TLS 1.3 and DTLS 1.3.

Peer ID and floating clients

OpenVPN 2.4 added DATA_V2 and the peer ID so a client can "float". If a phone moves from Wi-Fi to mobile data, its source address and port change, but its DATA_V2 packets still carry the same peer ID. The server verifies the tag, then updates the client's address, without a new TLS handshake. The draft adds a rule: the server must make sure a float "does not clobber a pre-existing client".

Renegotiation

Data channel keys are renewed by running a fresh TLS session inside the existing connection. reneg-sec defaults to 3600 seconds; on servers the effective value is randomised between 90 and 100 percent of it, to spread load. reneg-bytes and reneg-pkts can trigger it on volume instead, and whichever side reaches its limit first starts the renegotiation. tran-window (default 3600 seconds) lets the old key keep working while the new one comes up, so traffic does not stall.

What tls-auth, tls-crypt and tls-crypt-v2 add

TLS needs several round trips before it can authenticate anyone. Until then, the server spends memory and CPU on a stranger and exposes its whole TLS library to that stranger's packets. The 2.6 manual describes tls-auth as an "HMAC firewall" on the OpenVPN port: control packets with a bad HMAC "can be dropped immediately without response". The three options are layers on the control channel only; they never replace certificates.

tls-auth

Every control packet gets an HMAC computed with a pre-shared static key, plus a 64 bit replay counter. The digest follows auth (SHA1 by default), so the HMAC is 20 bytes with SHA1 and 64 bytes with SHA512. Each direction uses a different key, which is why tls-auth has a direction parameter (0 on one side, 1 on the other). The packets themselves are not encrypted, so an observer still sees certificates in TLS 1.2 handshakes. The community hardening page notes that tls-auth protected servers against Heartbleed (CVE-2014-0160) for attackers who did not have the key, but "offers no protection at all in the event of a complete cryptographic break".

tls-crypt

tls-crypt encrypts and authenticates every control packet with a pre-shared key: AES-256-CTR for encryption and HMAC-SHA256 for authentication, in a synthetic IV construction where the IV is taken from the HMAC tag. That design resists nonce reuse, which matters because a shared key may protect millions of packets across all clients. The manual lists three benefits: it hides the certificate used for the TLS connection, it makes OpenVPN traffic harder to identify, and it gives "poor-man's" post-quantum protection against attackers who never learn the key (without forward secrecy). It needs no direction parameter.

The manual also sets a lifetime: the key should protect no more than 2^48 control messages in each direction, which works out to "8171 years divided by the number of users" at one renegotiation per minute, so 1,000 users should rotate at least every eight years.

tls-crypt-v2

tls-auth and tls-crypt share one key across every client. If any client device is lost, the key is lost, and anyone holding it can reach the server's TLS stack again. tls-crypt-v2, added in 2.5, gives each client its own control channel key (Kc). The server never stores those keys. Instead, each client also holds a copy of its key wrapped with the server key (WKc) and sends it in the first packet; the server unwraps it, optionally checks metadata such as a timestamp or a certificate serial, and can reject the client before any TLS processing. Servers can run tls-crypt-v2 alongside tls-auth or tls-crypt during a migration.

OpenVPN 2.6 added a cookie based stateless three-way handshake. The tls-crypt-v2 option takes force-cookie to accept only clients that support it, or allow-noncookie, which is "(currently)" the default, to accept older clients.

Side by side

OptionProtectsKey scopeHides certificateAdded
NoneTLS onlyn/aNo (TLS 1.2 sends it in clear)n/a
tls-authIntegrity and replay protection of control packetsOne shared key, per directionNoLong standing; freeform passphrase files dropped in 2.4
tls-cryptConfidentiality, integrity, replay protection of control packetsOne shared keyYes2.4
tls-crypt-v2Same as tls-crypt, per client, with metadata checksOne key per client, wrapped by a server keyYes2.5

How data channel ciphers are negotiated

Negotiation has changed in every release since 2.4, and most interoperability trouble comes from mixing generations.

OpenVPN 2.4 (December 2016) introduced Negotiable Crypto Parameters (NCP). A client that sent IV_NCP=2 was telling the server it supported AES-256-GCM and AES-128-GCM, and the server pushed one, by default AES-256-GCM. The list was configured with ncp-ciphers. 2.4 still accepted BF-CBC when nothing was configured.

OpenVPN 2.5 (October 2020) renamed ncp-ciphers to data-ciphers and made the server choose properly: clients now send their whole list in IV_CIPHERS, and the server picks "the first cipher in that list that is also in the client's data-ciphers list". If nothing matches, the client is rejected with this message, quoted from the manual:

AUTH: Received control message: AUTH_FAILED,Data channel cipher negotiation failed (no shared cipher)

2.5 also added ChaCha20-Poly1305 to the data channel and, by default, accepted only AES-256-GCM and AES-128-GCM. BF-CBC now had to be listed explicitly.

OpenVPN 2.6 (January 2023) made these changes, all from the 2.6.0 release notes and manual:

  • data-ciphers defaults to AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305 when ChaCha20-Poly1305 is available.
  • A cipher can be prefixed with ? to mark it optional if the TLS library may not support it.
  • cipher is ignored in TLS mode and only matters for the deprecated static key mode. It is no longer silently appended to data-ciphers; that only happens with compat-mode set to 2.4.x or lower.
  • tls-version-min defaults to 1.2, and allow-compression defaults to no.
  • ncp-disable was removed, and static key mode (secret) was deprecated.
  • Default configurations no longer connect to 2.3.x or older peers. compat-mode restores older defaults when you truly need them, and the manual warns it "can lower security or disable features like data-channel offloading".
  • data-ciphers-fallback exists only for peers with no negotiation at all, such as 2.3 builds made with enable-small.

Data channel offload in 2.6

OpenVPN 2.6.0 added data channel offload (DCO). With the ovpn-dco kernel module on Linux, "data packets are directly processed and forwarded in kernel space" and "the userspace openvpn program acts purely as a control plane application". On Windows the default driver became ovpn-dco (dco-win). The manual says DCO is used opportunistically when the configuration and kernel allow it, and that it "requires data-ciphers to only contain AEAD ciphers (AES-GCM and Chacha20-Poly1305)". disable-dco turns it off, which is mainly needed for clients older than 2.4.

DCO changes where the code that encrypts your tunnel lives. With it, that code is a kernel module; without it, it is the user space process linked to OpenSSL or mbed TLS. Both are things you patch, but through different channels.

What 2.7 changed

OpenVPN 2.7.0 shipped on 11 February 2026 and is now the stable branch. Its release notes say the DCO module is being merged into the main Linux kernel under the new name ovpn, and 2.7 only supports that new API. 2.7 also enforces AES-GCM usage limits "with the same confidentiality margin as TLS 1.3", adds the epoch data format described above, removes static key mode by default (it can be re-enabled with allow-deprecated-insecure-static-crypto until 2.8), stops compressing outgoing data, and enforces the block-local flag on Windows with firewall filters for "stronger protection against TunnelCrack-style attacks".

Versions and history

BranchFirst releaseNotable protocol and security changesSupport status (community wiki)
2.111 Dec 2009TLS 1.0 onlyUnsupported since Nov 2011
2.221 Apr 2011Unsupported since Nov 2015
2.32 Jan 2013Later 2.3.x releases add TLS version negotiation and tls-version-minUnsupported since June 2021
2.426 Dec 2016NCP cipher negotiation, AES-GCM data channel, DATA_V2 and peer ID floating, tls-crypt, ECDH and ECDSA suitesUnsupported since March 2023
2.527 Oct 2020data-ciphers, ChaCha20-Poly1305, tls-crypt-v2, BF-CBC off by default, compression risk warnings, client-cert-not-required removedUnsupported since July 2025
2.625 Jan 2023DCO, TLS 1.2 minimum, compression off by default, cipher ignored in TLS mode, secret deprecated, stateless cookie handshake, peer-fingerprint alternative to a full PKI, connect-freq-initial reflection limitOld stable; security fixes until August 2027, end of life August 2028
2.711 Feb 2026Upstream kernel ovpn DCO, epoch data keys, AES-GCM usage limits, static key mode removed by default, no outgoing compression, multi-socket serversCurrent stable

The latest releases on GitHub at the time of writing are 2.7.8 (7 October 2026) and 2.6.23 (23 September 2026). Static key mode, the oldest way to run OpenVPN, has been on its way out across three releases: deprecated in 2.6, off by default in 2.7, and scheduled for removal in 2.8.

Security properties and weakness classes

What OpenVPN guarantees, and what it does not

PropertyIn TLS mode with AEAD data ciphersNotes
Confidentiality of tunnel trafficYesAES-GCM or ChaCha20-Poly1305 with keys exported from TLS
Integrity and authenticity of tunnel packetsYesAEAD tag covers header fields and payload
Replay protectionYesSliding window on the packet ID
Forward secrecyYesFrom the ephemeral TLS key exchange; static key mode has none
Server authenticationOnly if the client checks the certificate properlyCA check alone is not enough, see below
Client authenticationCertificates, and optionally username and password or a script or pluginverify-client-cert none puts everything on the password check
Hiding that the traffic is OpenVPNPartly, with tls-cryptPacket sizes, timing and the port remain visible
Availability under floodsImproved with tls-auth, tls-crypt, tls-crypt-v2 and 2.6 cookiesNot a DDoS defence by itself
Protection of traffic outside the tunnelNoRouting and DNS on the client decide what enters the tunnel

Deprecated ciphers and 64 bit block sizes

Old configurations often name cipher BF-CBC, DES-CBC or other 64 bit block ciphers. The manual ties reneg-bytes to the SWEET32 attack class: with a block size under 128 bits, OpenVPN renegotiates every 64 MB by default. The concept is simple: a small block size runs out of safe output long before a modern tunnel runs out of traffic. OpenSSL 3.0 no longer offers Blowfish without loading the legacy provider, so these configurations also tend to break during operating system upgrades. The fix is to remove them from data-ciphers and move every peer to AEAD.

Compression before encryption

The manual is blunt: compression is "generally not recommended" and tunnels that use it are susceptible to the VORACLE attack vector. The concept is the same one behind CRIME and BREACH in TLS. If an attacker can influence part of the plaintext and observe the size of the encrypted packets, compression turns size differences into information about the secret parts. OpenVPN 2.5 started accepting compressed packets without compressing outgoing ones by default, 2.6 set allow-compression no by default, and 2.7 never compresses on send. The leftover risk is old configurations with comp-lzo or compress lz4, and servers that push compression to clients.

Missing certificate role checks

A client that only checks "is this certificate signed by my CA" will accept any certificate from that CA, including another client's. The manual describes the result as "a man-in-the-middle attack where an authorized client attempts to connect to another client by impersonating the server". The defence is to require the server role: remote-cert-tls server checks the key usage and the extended key usage "TLS Web Server Authentication". Alternatives are verify-x509-name, peer-fingerprint or a tls-verify script. On the server, remote-cert-tls client does the reverse.

The wire protocol draft adds a second rule: enforce certificate authentication against a CA you control. Using a public CA "will reduce the security of the tunnel dramatically". The manual's warning on verify-x509-name ... name-prefix says the same: never use a name prefix when certificates are signed by a third party.

Static key mode

Static key mode (secret) uses one pre-shared key for the data channel with no TLS and no key exchange. The manual says that if an attacker steals the key, "everything that was ever encrypted with it is compromised", and the wire draft adds that it cannot use AES-GCM because IV uniqueness cannot be guaranteed. That is why it was deprecated in 2.6 and disabled by default in 2.7. For small setups the project points to peer-fingerprint, which lets two peers trust each other's self-signed certificates by SHA-256 fingerprint without running a CA.

TCP tunnels carrying TCP traffic

When OpenVPN runs over TCP and the tunnel carries TCP connections, two independent sets of retransmission timers are stacked. A loss on the outer connection stalls everything inside it, and the inner connections, seeing delay, retransmit too and add more traffic to a congested path. The manual links an archived article on the problems of tunnelling IP over TCP and recommends UDP unless something blocks it. This is a performance and availability weakness rather than a confidentiality one, but under load it looks like an outage. Our TCP explainer covers the retransmission and congestion behaviour underneath.

An exposed management interface

The management interface lets another program control a running OpenVPN process: list and kill clients, answer password prompts, change state. The manual marks management IP port without a password file as "(INSECURE)" and warns: "Any user who can connect to this TCP IP:port will be able to manage and control (and interfere with) the OpenVPN process." Even the Unix socket form is reachable by any local process by default unless management-client-user or management-client-group restricts it. The weakness is not in the protocol; it is a control port that, if bound to a routable address, hands the tunnel to whoever reaches it.

Handshake floods and reflection

Any UDP service that answers an unauthenticated first packet with a larger or repeated reply can be abused for reflection. OpenVPN 2.6 replaced per-client state on the first packet with an HMAC cookie in the server's session ID, which the release notes say "eliminates the amplification and resource exhaustion attacks", and it rate limits replies to initial packets with connect-freq-initial (100 per 10 seconds by default). Wrapping the control channel with tls-auth, tls-crypt or tls-crypt-v2 means unauthenticated packets get no reply at all.

A hostile or compromised server

Clients trust servers to push routes, DNS settings and options. A server that is compromised can push routes that capture more traffic than intended, or values that client code must parse safely. CVE-2024-5594, published on cve.org on 6 January 2025, is an example of the parsing class: OpenVPN before 2.6.11 did not sanitise PUSH_REPLY messages, so a malicious server could inject unexpected data into client logs. The general lesson is that the client side of a VPN is also an attack surface, and pull-filter exists so clients can refuse pushed options they never want.

Implementation bugs

The project's security announcements page lists dozens of CVEs, many of them in Windows helper services and drivers rather than in the protocol. Two show how protocol features become bug surfaces. CVE-2025-2704 let a remote attacker crash OpenVPN servers 2.6.1 through 2.6.13 that used tls-crypt-v2 by corrupting and replaying early handshake packets; the 2.6.14 release notes say a valid client key or observation of a handshake with one was needed, and no data was leaked. CVE-2026-84790, published 13 October 2026, lets authenticated users of OpenVPN 2.7_alpha1 through 2.7.7 impersonate others via a crafted certificate subject field, according to its cve.org record. Code that parses packets around authentication is where severe bugs tend to live, which is why the control channel wrappers matter.

Secure configuration, with defender-side check commands

Only run the commands below against systems you own or are authorised to test. Every option is documented in the OpenVPN 2.6 reference manual; the operating system commands come from their own manual pages.

A hardened 2.6 server baseline

These are configuration file lines, which drop the leading dashes used on the command line:

# Transport
proto udp
port 1194

# TLS control channel
tls-version-min 1.2
remote-cert-tls client
tls-crypt-v2 /etc/openvpn/server/tc2-server.key force-cookie
crl-verify /etc/openvpn/server/crl.pem

# Data channel: AEAD only (also required for DCO)
data-ciphers AES-256-GCM:AES-128-GCM:?CHACHA20-POLY1305

# Compression stays off (2.6 default, stated explicitly)
allow-compression no

# Operations
management /run/openvpn/server.sock unix /etc/openvpn/server/mgmt.pw
status /run/openvpn/server.status 60
status-version 2
user nobody
group nogroup
persist-key
persist-tun

Use force-cookie only when every client runs 2.6 or later. On the client, the counterpart lines are remote-cert-tls server, a matching tls-crypt-v2 client key, and preferably verify-x509-name with the exact server name so that a valid but different server certificate is refused.

What to leave out: cipher (ignored in TLS mode), ncp-disable (removed), comp-lzo and compress (deprecated), secret (deprecated, removed by default in 2.7), compat-mode unless you have a dated plan to retire old peers, duplicate-cn (lets several clients share one certificate, which hides a stolen one), and verify-client-cert none unless the password check is strong and audited.

Generate per-client control channel keys

From the manual's genkey section. The server key is generated once; each client key is generated from it:

openvpn --genkey tls-crypt-v2-server v2crypt-server.key
openvpn --tls-crypt-v2 v2crypt-server.key --genkey tls-crypt-v2-client v2crypt-client-1.key

Distribute each client key once, with the client's certificate. If a device is lost, revoke its certificate in the CRL; its tls-crypt-v2 key only gets an attacker as far as the TLS handshake, where the revoked certificate fails.

Check what your build supports

These standalone options print what the local build and its crypto library offer, from the manual's encryption options section:

openvpn --show-ciphers    # data channel ciphers usable in data-ciphers
openvpn --show-digests    # digests for auth (and tls-auth HMAC)
openvpn --show-tls        # TLS cipher suites, most preferred first
openvpn --show-groups     # elliptic curves and groups for tls-groups

If AES-256-GCM, AES-128-GCM or ChaCha20-Poly1305 are missing from show-ciphers, the crypto library is too old or restricted, and negotiation will fail or fall back.

Check the negotiated data cipher for each client

With status-version 2, the server status file includes a "Data Channel Cipher" column for every connected client, alongside the common name, real and virtual addresses and peer ID. Read it on the server:

cat /run/openvpn/server.status

Any client showing a CBC cipher is an old peer or a peer forced by compat-mode; any client showing BF-CBC needs attention now.

Check the server certificate's role and expiry

remote-cert-tls server only works if the server certificate actually carries the server extended key usage. The OpenSSL x509 command prints extensions selected with -ext:

openssl x509 -in server.crt -noout -subject -enddate -ext keyUsage,extendedKeyUsage

The output should show "TLS Web Server Authentication" for the server certificate and "TLS Web Client Authentication" for client certificates.

Check what is listening

ss from iproute2 lists listening sockets with their owning process (-l listening, -u UDP, -t TCP, -n numeric, -p processes):

sudo ss -ulnp | grep openvpn   # the tunnel port, normally udp 1194
sudo ss -tlnp | grep openvpn   # should show nothing unless you run TCP mode or a TCP management port

If a management port appears on anything other than 127.0.0.1, or appears at all when you use a Unix socket, fix it before anything else.

Audit configuration files for deprecated options

A plain search across your configuration directory finds the lines the 2.6 and 2.7 release notes deprecate or remove:

grep -rnE '^\s*(cipher|ncp-ciphers|ncp-disable|comp-lzo|compress|secret|compat-mode|duplicate-cn|verify-client-cert|management|tls-version-min|tls-cert-profile)\b' /etc/openvpn/

Review each hit against the manual. tls-cert-profile deserves a look in particular: its default is legacy, which accepts SHA-1 signed certificates and RSA 2048 bits or more, and the manual says OpenVPN "will migrate to 'preferred' as default in the future. Please ensure that your keys already comply."

Log and alert

Keep the server log at the default verbosity or above, ship it off the host, and alert on repeated AUTH_FAILED, on TLS errors from a single source, and on clients connecting with a cipher outside your list. Revoke certificates through the CRL configured with crl-verify, and remember the community hardening page's advice to generate a CRL upfront even when it is empty, because adding the option later needs a restart.

Where the OpenVPN code lives in your software

The openvpn daemon on a VPN server is easy to find. The OpenVPN code you forget about is elsewhere: container images that bundle a client for site to site links, appliance firmware, CI runners that join a private network to deploy, desktop builds that ship an OpenVPN 3 based client library, and the OpenSSL or mbed TLS library underneath all of them. A fully patched server can still talk to a client built on a library from three years ago.

That is the honest connection to Safeguard. Software composition analysis, generally available, inventories transitive dependencies in repositories and container images, so the OpenVPN package and the TLS library it links show up with their versions. SBOM generation and analysis in SPDX and CycloneDX, vulnerability management with EPSS and CISA KEV enrichment, reachability analysis and container scanning, all generally available, help you find and rank OpenVPN and TLS library findings when an advisory lands. Safeguard does not inspect, filter or terminate VPN traffic, and it does not audit server.conf; the checks above remain your job.

When to use OpenVPN versus WireGuard or IPsec

All three are mature. The choice is mostly about where they run, how they authenticate and what you already operate. The WireGuard facts below come from wireguard.com and the IKEv2 facts from RFC 7296 (October 2014). Our comparison posts on WireGuard vs OpenVPN and IPsec vs OpenVPN go deeper on the trade offs, and how to set up a VPN with WireGuard walks through a WireGuard build.

Use case or propertyOpenVPNWireGuardIPsec with IKEv2
TransportUDP (default) or TCP, port 1194 by default, any port possibleUDP onlyIKE on UDP 500 and 4500; ESP for data
AuthenticationX.509 certificates via TLS, plus optional username, password, plugins and challenge responseStatic public keys per peerCertificates, EAP or pre-shared keys
CryptographyNegotiated: TLS suites for control, data-ciphers for dataFixed set: Curve25519, ChaCha20-Poly1305, BLAKE2sNegotiated through IKE proposals
Works through restrictive firewalls or proxiesYes, TCP mode and HTTP proxy supportOnly where UDP is allowedNeeds UDP 500 and 4500 or ESP allowed
Per-user identity and policy at the serverStrong: certificate names, scripts, pushed per-client configPer-key only; user identity handled outside the protocolStrong with EAP and certificates
Configuration surfaceLarge; many options to get wrongSmallLarge; many proposals to get wrong
Operational costRun a CA, distribute configs and keysDistribute public keys, manage addressesRun a CA or EAP backend; interoperability testing across vendors
Typical fitRemote access with user directories, networks that block UDP, mixed client platformsSite to site and device meshes where UDP is openStandard site to site links and native operating system clients

If you need TCP fallback, per-user authentication through an existing directory, or pushed per-client policy, OpenVPN remains a natural choice. If you control both ends and UDP is open, a smaller fixed protocol is easier to audit and to run.

Common mistakes

  • Keeping cipher AES-256-CBC in a 2.6 config and believing it sets the data cipher. In TLS mode it is ignored. data-ciphers decides, and the status file shows what was actually negotiated.
  • Leaving compat-mode in place after the old clients are gone. It turns old, weaker defaults back on and can disable DCO.
  • Checking only the CA on the client. Without remote-cert-tls server, verify-x509-name or peer-fingerprint, any certificate from your CA, including a client's, can pose as the server.
  • Issuing certificates from a public CA. Anyone who can get a certificate from that CA becomes a candidate impersonator. Use a private CA or fingerprints.
  • Treating tls-auth as encryption. It authenticates control packets; it does not hide them. tls-crypt or tls-crypt-v2 encrypts them.
  • Sharing one tls-crypt key across thousands of users for years. The key is only as safe as the least protected device. Per-client tls-crypt-v2 limits the damage of a lost laptop.
  • Re-enabling compression to save bandwidth. Most tunnel traffic is already encrypted or compressed, and compression before encryption is the VORACLE class of leak.
  • Binding the management interface to a routable address without a password file. Use a Unix socket with restricted ownership, or 127.0.0.1 with pw-file.
  • Allowing duplicate-cn. One certificate on many devices makes a stolen certificate indistinguishable from a legitimate one.
  • Running TCP mode by default. Use UDP unless something in the path blocks it; TCP over TCP suffers under loss.
  • Forgetting the client side. Old clients bundled in images and appliances still negotiate weak ciphers or carry parsing bugs long after the server is updated.

FAQ

What port does OpenVPN use?

UDP 1194 by default. IANA has registered port 1194 for OpenVPN on both UDP and TCP since November 2004. You can run OpenVPN on any other port. Versions before 2.0-beta17 used port 5000.

Is OpenVPN encrypted?

Yes, in TLS mode both channels are protected. The control channel is a TLS 1.2 or TLS 1.3 session, and the data channel encrypts every tunnel packet with keys exported from that session, using AES-GCM or ChaCha20-Poly1305 by default in 2.6. Encryption only covers what the client routes into the tunnel.

Does OpenVPN use TLS or its own protocol?

Both. It uses standard TLS, from OpenSSL or mbed TLS, for authentication and key agreement, carried inside OpenVPN's own control packets with a reliability layer so it can run over UDP. Tunnel traffic does not travel as TLS records; it uses OpenVPN's lighter data channel format.

Is OpenVPN UDP or TCP?

Either. UDP is the default and the manual says OpenVPN "is designed to operate optimally over UDP". TCP mode exists for networks that block UDP or force traffic through a proxy, at a cost in efficiency and resilience on lossy links.

What is the difference between tls-auth and tls-crypt?

tls-auth adds an HMAC signature to every control channel packet so the server can drop packets from anyone without the key. tls-crypt does that and also encrypts the control packets, which hides the certificate and makes the traffic harder to fingerprint. tls-crypt-v2 does the same with a separate key per client.

What ciphers does OpenVPN 2.6 use by default?

The default data-ciphers list is AES-256-GCM, AES-128-GCM and ChaCha20-Poly1305 when the crypto library supports it. The server picks the first cipher in its own list that the client also offers. The TLS cipher suites for the control channel come from the TLS library's defaults, with TLS 1.2 as the minimum version.

What is OpenVPN data channel offload?

DCO, added in OpenVPN 2.6, moves encryption and forwarding of tunnel packets into a kernel module (ovpn-dco on Linux, dco-win on Windows), leaving the user space process to handle only the control channel. It requires AEAD data ciphers. In 2.7 the Linux module is the upstream ovpn driver.

Is OpenVPN still secure in 2026?

The protocol design is sound when configured with TLS mode, AEAD ciphers, no compression, proper certificate role checks and a wrapped control channel, and both the 2.7 and 2.6 branches receive security fixes. Most real exposure comes from old configurations, old clients and unpatched implementations rather than from the protocol.

OpenVPN vs WireGuard: which should I use?

WireGuard is smaller, UDP only, uses a fixed set of modern algorithms and identifies peers by public key. OpenVPN is larger and more configurable, works over TCP and proxies, and integrates with certificates and user directories. Choose WireGuard when you control both ends and UDP is open; choose OpenVPN when you need per-user authentication, TCP fallback or pushed per-client policy.

What is VORACLE?

VORACLE is the name the OpenVPN manual uses for compression attacks on VPN tunnels. When data is compressed before encryption, the size of encrypted packets can reveal information about secret content if an attacker can influence other parts of the plaintext. OpenVPN 2.6 disables compression by default and 2.7 never compresses outgoing traffic.

Fix it without waiting for upstream

Most OpenVPN advisories are fixed in the openvpn package, the DCO kernel module or the TLS library underneath, and the copies that linger longest are the ones bundled into images, appliances and client builds. Closing that gap is a dependency problem as much as a VPN problem.

Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.

1. Autonomous remediation: pull requests, not tickets

When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation covers eight categories, including dependencies, licenses, security posture and findings. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.

2. Gold Open Source: the safe version in seconds, free

gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds. The safeguard-sh/gold-scan-action GitHub Action can fail a build on a known exploited vulnerability, on any known vulnerability, or never, so a version you have just removed cannot quietly come back in next week's merge.

3. Gold Registry: start from components that are already fixed

registry.safeguard.sh provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs, zero malware and a completed license check, with SLSA L3 or higher provenance, a Sigstore signature and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.

When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. This fork and patch flow is in early access today, so ask which packages it covers before you plan around it.

Your situationWhat to use
A fixed version existsAutonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version
You need to know today whether you are affectedGold Open Source lookup and "Am I affected?" checker, free and without login
You want vulnerable versions to stop shippingThe Gold scan GitHub Action in CI, plus Safeguard policies and gates
Upstream has no fix yet, or will not ship oneA custom Gold request; fork and patch (early access)
You want to start clean on new projectsPull hardened components and images from Gold Registry

One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.

See how Safeguard would help

These demos show dependency, scanning and approval workflows, not VPN monitoring. You can download Safeguard and follow the CLI docs to try them on your own projects.

This demo is a real CLI session: install, open the interactive terminal, ask it to fix the lodash CVE in a repository, and watch it read the finding and advisory, ask before each command, move lodash to 4.17.21, run npm install and npm test with approval, and print a summary without pushing anything. The same approve each step flow applies when the component to bump is the OpenVPN package or the TLS library pinned in a Dockerfile or manifest.

Click through it at your own pace, or open it full screen.

This demo connects Claude to the Safeguard MCP server with OAuth and lets you choose which tools Claude can use. Once connected, you can ask in plain language which of your projects or images include a particular OpenVPN or OpenSSL version, and get the answer from your own scan data rather than from memory.

Click through it at your own pace, or open it full screen.

This demo is a real Android session: send work to a computer running the CLI, then approve the command on the phone with Allow once, Allow for turn or Deny. If an OpenVPN advisory lands while you are away from your desk, the same flow lets you start the dependency update on your workstation and approve each step from your phone.

Click through it at your own pace, or open it full screen.

Quick check

Your 2.6 server config says cipher AES-256-CBC. Which cipher do clients actually use?

Not necessarily AES-256-CBC. In OpenVPN 2.6 the cipher option is ignored in TLS mode. The server picks the first cipher in its data-ciphers list that the client also supports, which by default is AES-256-GCM. Check the Data Channel Cipher column in a status-version 2 status file to see what each client really negotiated.

Your clients verify the server against your private CA. Is that enough to stop impersonation?

No. Any certificate your CA issued, including another client's, passes a CA-only check. Add remote-cert-tls server so the client requires the server extended key usage, and ideally verify-x509-name with the server's exact name or peer-fingerprint for small setups.

Sources

Last reviewed: 23 October 2026. OpenVPN defaults change between releases; confirm against the manual for the version you run.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.