Core architecture overview
OpenVPN’s architecture follows a multi-layered event-driven design that separates control plane operations from data plane processing.Main event loop structure
The core of OpenVPN is built around a nested loop structure defined insrc/openvpn/openvpn.c:153:
Event loop implementation details
Event loop implementation details
The event loop is implemented with different functions based on the operational mode:
- Point-to-point mode: Uses
tunnel_point_to_point()for single tunnel management - Server mode: Uses
tunnel_server()for managing multiple client connections
- Timers and TLS operations via
pre_select() - I/O events via
io_wait() - Packet processing via
process_io()
Component layers
OpenVPN’s architecture consists of several distinct layers:- Control plane
- Data plane
- Network interface
Control channel processingThe control channel handles:
- SSL/TLS session establishment
- Key exchange and renegotiation
- Authentication and authorization
- Configuration push/pull
tls_multi_process() function, which determines whether to call TLS process for active or untrusted sessions.TUN/TAP virtual network interface
OpenVPN uses TUN/TAP virtual network devices to create the VPN tunnel. These devices exist on most platforms and provide the interface between OpenVPN and the operating system’s network stack.Device types
TUN vs TAP: OpenVPN with DCO (Data Channel Offload) supports Layer 3 (dev tun) only. TAP mode is only available in traditional userspace mode.
src/openvpn/tun.h:185:
Backend driver types
OpenVPN supports multiple backend drivers (src/openvpn/tun.h:43):
DRIVER_GENERIC_TUNTAP- Standard TUN/TAP driver on most Unix-like systemsDRIVER_DCO- Data Channel Offload (kernel-space packet processing)DRIVER_UTUN- macOS internal tun driverDRIVER_AFUNIX- AF_UNIX socket for external program integrationWINDOWS_DRIVER_TAP_WINDOWS6- Windows TAP driverDRIVER_NULL- Null driver for testing
With DCO enabled, data packets are processed directly in kernel space while OpenVPN userspace acts purely as a control plane application.
TUN/TAP operations
Key operations on TUN/TAP devices:Packet flow architecture
Understanding the packet flow is crucial to understanding OpenVPN’s architecture:Outgoing packet flow
- Application → writes packet to TUN/TAP interface
- OS kernel → delivers packet to OpenVPN via
read_tun() - OpenVPN → encrypts packet via
openvpn_encrypt() - OpenVPN → adds packet ID and HMAC
- OpenVPN → sends encrypted packet via UDP/TCP socket
- Network → delivers to remote peer
Incoming packet flow
- Network → receives encrypted packet via UDP/TCP socket
- OpenVPN → validates HMAC and packet ID
- OpenVPN → decrypts packet via
openvpn_decrypt() - OpenVPN → writes plaintext packet via
write_tun() - OS kernel → delivers to application via TUN/TAP interface
- Application → receives packet
Initialization sequence
OpenVPN follows a carefully orchestrated initialization sequence:-
Program-wide initialization (
init_static())- Initialize cryptographic library (OpenSSL/mbedTLS)
- Set up signal handling
- Initialize random number generators
-
Parse configuration (
parse_argv())- Read command-line options
- Parse configuration file
- Process plugin-contributed options
-
Early initialization (
init_early())- Initialize network context
- Load OpenSSL providers
- Set verbosity and mute levels
-
Context initialization (
context_init_1())- Set up TLS context
- Initialize management interface
- Query passwords if needed
-
Run tunnel (mode-dependent)
- Point-to-point:
tunnel_point_to_point() - Server:
tunnel_server()
- Point-to-point:
Signal handling
OpenVPN responds to various signals during operation:- SIGHUP - Restart with configuration reload (outer loop)
- SIGUSR1 - Soft restart without configuration reload (inner loop)
- SIGTERM/SIGINT - Graceful shutdown
- SIGUSR2 - Connection reset (P2P mode) or status output
P2P_CHECK_SIG() macro calls.
Memory and resource management
OpenVPN uses a garbage collector pattern for memory management:Data Channel Offload (DCO)
DCO support was added in OpenVPN 2.6.0+ for Linux and Windows, with the Linux
ovpn kernel module merged upstream in Linux 6.16.- Data packets are processed in kernel space
- Userspace OpenVPN acts as control plane only
- Significantly improved performance
- Lower CPU overhead
- Only AEAD ciphers supported (AES-GCM, ChaCha20-Poly1305)
--disable-dco to disable it.
Related documentation
- Tunneling modes - Point-to-point vs client-server modes
- Authentication - Authentication methods and mechanisms
- Encryption - Encryption and cipher information