libdl and on Windows. Plugins can intercept script callbacks to extend authentication, logging, and connection handling.
Plugin architecture
Plugins are loaded at startup using the--plugin directive. Each plugin can register handlers for specific events in the OpenVPN lifecycle.
Supported hooks
Plugins can intercept the following script callbacks:up- After TUN/TAP device opendown- After TUN/TAP device closeroute-up- After routes are addedipchange- When remote IP changestls-verify- During TLS certificate verificationauth-user-pass-verify- For username/password authenticationclient-connect- When client connects (server mode)client-disconnect- When client disconnects (server mode)learn-address- When address is learned (server mode)
openvpn-plugin.h in the source distribution for detailed API documentation.
Loading plugins
Load a plugin using the--plugin directive:
Included plugins
auth-pam
Authenticate users against PAM using a split privilege execution model.# Server configuration
plugin /usr/lib/openvpn/plugins/openvpn-plugin-auth-pam.so login
# Require username/password
auth-user-pass-verify /bin/true via-env
The auth-pam plugin works even after privileges are dropped with
--user, --group, or --chroot.- PAM authentication with privilege separation
- Works after privilege drop (
--user/--group/--chroot) - Tested on Linux only
- Split privilege model for enhanced security
service-name parameter specifies which PAM service configuration to use (e.g., login, openvpn).
down-root
Execute down scripts with root privileges even after dropping privileges. Use case: When using--user and --group to drop privileges, the --down script normally runs with reduced privileges. This plugin allows the down script to run as root for cleanup tasks that require elevated permissions.
Configuration:
- Runs down scripts with root privileges
- Works after
--user/--group/--chroot - Not applicable on Windows
examples
A portable example plugin demonstrating the plugin API. Location:src/plugins/examples/ in the source distribution
Purpose:
- Demonstrates plugin API usage
- Shows portable plugin development (*nix and Windows)
- Serves as a template for custom plugins
Building plugins
From source distribution
The examples plugin uses a build script instead of a Makefile:
Custom plugin development
Create a custom plugin by implementing the plugin API defined inopenvpn-plugin.h:
Plugin vs script
Choose plugins over scripts when:Environmental variables
Plugins receive the same environmental variables as scripts. See scripting for details. Key variables include:common_name- Client’s certificate CNusername/password- Auth credentialstrusted_ip/trusted_port- Client’s addressifconfig_pool_remote_ip- Assigned VPN IPtime_unix- Connection timestamp
Plugin return codes
Plugins should return one of these codes:OPENVPN_PLUGIN_FUNC_SUCCESS- Operation successfulOPENVPN_PLUGIN_FUNC_ERROR- Operation failedOPENVPN_PLUGIN_FUNC_DEFERRED- Operation deferred (async)
Deferred authentication
Plugins can defer authentication decisions for async operations:if (args->type == OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY) {
// Start background authentication
start_async_auth(username, password, auth_control_file);
return OPENVPN_PLUGIN_FUNC_DEFERRED;
}
void background_auth(const char *user, const char *pass, const char *file) {
bool success = check_credentials(user, pass);
// Write result to control file
FILE *f = fopen(file, "w");
fprintf(f, "%d\n", success ? 1 : 0);
fclose(f);
}
Security considerations
Best practices
- Validate all input from environmental variables
- Drop privileges early if possible
- Use secure coding practices to prevent buffer overflows
- Audit plugin code before deployment
- Keep plugins updated with security patches
- Limit plugin functionality to what’s necessary
- Test thoroughly in development environments
Common vulnerabilities
- Buffer overflows - Validate string lengths
- Command injection - Sanitize inputs used in system calls
- Race conditions - Use proper locking for shared resources
- Memory leaks - Free allocated memory properly
- Path traversal - Validate file paths
Debugging plugins
Enable verbose logging:PLOG_ERR- ErrorsPLOG_WARN- WarningsPLOG_NOTE- NoticesPLOG_DEBUG- Debug messages