Tutorial: Enable Quantum-Resistant Encryption in Access Server with Post-Quantum Cryptography (PQC)
Enable post-quantum cryptography (PQC) in OpenVPN Access Server to protect VPN tunnels against future quantum computer attacks — covers configuring X25519MLKEM768 via tls-groups, FIPS-compatible algorithms (SecP256r1MLKEM768), client requirements, and verifying PQC key agreement in logs.
Overview
Post-Quantum Cryptography (PQC) provides quantum-resistant, or quantum-safe, cryptographic algorithms designed to withstand attacks from sufficiently powerful quantum computers.
A future quantum computer could potentially break widely used public-key cryptography based on RSA and elliptic curves using Shor's algorithm. This also creates a present-day harvest-now, decrypt-later risk, where an attacker records encrypted traffic now with the intent of decrypting it in the future when sufficiently capable quantum computing becomes available.
Access Server can use post-quantum key agreement for VPN connections when both the server and VPN client support it. With OpenSSL 3.5 or newer, the default post-quantum group is X25519MLKEM768, which combines the classical X25519 elliptic curve with ML-KEM (MLKEM), the NIST-standardized post-quantum key encapsulation mechanism.
In most supported configurations, Access Server and the VPN client can negotiate PQC automatically. This tutorial shows you how to:
Verify that your environment supports PQC.
Force post-quantum key agreement using the
tls-groupsdirective.Maintain compatibility with clients that don't yet support PQC.
Verify the negotiated key agreement in Access Server and client logs.
Configure PQC when Access Server is running in FIPS mode.
Tip
Post-quantum cryptography is also becoming increasingly relevant to zero trust and security requirements in regulated environments. For related architecture guidance, see Zero Trust Network Access.
Prerequisites
Before you begin, ensure you have:
Access Server installed on a Linux host with OpenSSL 3.5 or newer.
At the time of this writing, supported Linux distributions with OpenSSL 3.5 or newer include:
Ubuntu 26.04 LTS
Debian 13
RHEL 9 and compatible distributions
RHEL 10 and compatible distributions
An OpenVPN client that uses OpenSSL 3.5 or newer.
At the time of this writing, OpenVPN Connect v3 doesn't support OpenSSL 3.5. You can instead use a compatible OpenVPN Community client, such as:
OpenVPN 2 for Linux from the appropriate distribution software repository
Important
When using OpenVPN 2 on Linux, add the following directive to the connection profile so the client requests PQC:
tls-groups "X25519MLKEM768"
This additional profile configuration isn't required for OpenVPN GUI for Windows or Tunnelblick for macOS.
Admin Web UI access or console access with root privileges.
One or more users configured in Access Server.
Note
In our documentation, we use example IPv4 addresses and subnets reserved for documentation, such as 192.0.2.0/24, 198.51.100.0/24, and 203.0.113.0/24.
Ensure you replace them with valid IPv4 addresses and subnets for your network(s).
Before you begin
If both Access Server and the VPN client use OpenSSL 3.5 or newer, they can negotiate post-quantum key agreement without forcing a specific group. The configuration in this tutorial is primarily useful when you need to require PQC or explicitly control which TLS groups are permitted.
Test these changes in a non-production environment before deploying them to users.
Understand client compatibility before forcing PQC
If you configure Access Server to allow only a post-quantum group such as X25519MLKEM768, clients that don't support that group won't be able to connect.
An unsupported connection can fail with an OpenSSL error similar to: OpenSSL: error:0A000065:SSL routines::no suitable key share:
For example, if your users currently connect with OpenVPN Connect v3, forcing X25519MLKEM768 would prevent those clients from connecting.
To support both PQC-capable clients and clients that use traditional elliptic curve groups, configure both groups:
tls-groups "X25519MLKEM768:X25519"
Plan your migration accordingly before requiring PQC across a production deployment.
FIPS mode considerations
Access Server running in FIPS mode supports the following post-quantum groups:
SecP256r1MLKEM768SecP384r1MLKEM1024
If you're using FIPS mode, see:
Access Server and supported clients use X25519MLKEM768 for post-quantum key agreement by default. Use the tls-groups directive when you want to explicitly require this group.
You can configure it from the Admin Web UI or command line.
Admin Web UI
Sign in to the Admin Web UI.
Navigate to Advanced → OpenVPN Directives.
Under Server config directives, enter:
tls-groups X25519MLKEM768
This allows only
X25519MLKEM768, so clients that don't support this post-quantum group can't connect.To allow PQC-capable clients while maintaining compatibility with clients that support X25519, use this instead:
tls-groups "X25519MLKEM768:X25519"
Select Save and Restart.
Command line
Connect to the console and get root privileges.
To require
X25519MLKEM768, run:sacli --key "vpn.server.config_text" --value "tls-groups X25519MLKEM768" ConfigPut
To allow both
X25519MLKEM768and X25519 for compatibility with clients that don't support PQC, use:sacli --key "vpn.server.config_text" --value "tls-groups \"X25519MLKEM768:X25519\"" ConfigPut
Restart Access Server services:
sacli start
Download a connection profile and connect to Access Server with a supported client. After the VPN connection succeeds, verify that the connection negotiated X25519MLKEM768.
Verify from Access Server
Connect to the console and get root privileges.
Search the Access Server log for the negotiated key agreement:
grep "key agreement" /var/log/openvpnas.log
Example output:
[stdout#info] [OVPN 3] OUT: '2026-08-24 14:39:27 udp4:203.0.113.55:51371 Control Channel: TLSv1.3, cipher TLSv1.3 TLS_AES_256_GCM_SHA384, peer certificate: 384 bits ECsecp384r1, signature: ecdsa-with-SHA256, peer temporary key: 768 bits X25519MLKEM768, peer signing digest/type: ecdsa_secp384r1_sha384 ECDSA, key agreement: X25519MLKEM768'
Confirm that the output contains:
key agreement: X25519MLKEM768
Verify from the VPN client
Open the VPN client logs and locate the control-channel details.
Example:
Control Channel: TLSv1.3, cipher TLSv1.3 TLS_AES_256_GCM_SHA384, peer certificate: 384 bits ECsecp384r1, signature: ecdsa-with-SHA256, peer signing digest/type: ecdsa_secp384r1_sha384 ECDSA, key agreement: X25519MLKEM768
Confirm that the log contains:
key agreement: X25519MLKEM768
Use this configuration when you need SecP256r1MLKEM768 or SecP384r1MLKEM1024 instead of X25519MLKEM768.
Tip
If Access Server is running in FIPS mode, use one of these supported groups.
Ensure you configure the selected group on both Access Server and the VPN client. The examples below use SecP256r1MLKEM768. You can substitute SecP384r1MLKEM1024 where appropriate.
Step 1: Configure Access Server
You an set this up from the Admin Web UI or command line.
Admin Web UI
Sign in to the Admin Web UI.
Navigate to Advanced → OpenVPN Directives.
Under Server config directives, enter:
tls-groups SecP256r1MLKEM768
To allow PQC while maintaining compatibility with clients using
secp256r1, configure:tls-groups "SecP256r1MLKEM768:secp256r1"
Select Save and Restart.
Command line
Connect to the console and get root priviliges.
To require
SecP256r1MLKEM768, run:sacli --key "vpn.server.config_text" --value "tls-groups SecP256r1MLKEM768" ConfigPut
To allow both the post-quantum group and
secp256r1, run:sacli --key "vpn.server.config_text" --value "tls-groups \"SecP256r1MLKEM768:secp256r1\"" ConfigPut
Restart Access Server services:
sacli start
Step 2: Configure the VPN client
Download a new connection profile (
.ovpnfile).Open the connection profile in a text editor.
Add:
tls-groups SecP256r1MLKEM768
To allow both the post-quantum group and
secp256r1, use:tls-groups "SecP256r1MLKEM768:secp256r1"
Save the connection profile.
Step 3: Connect and verify the key agreement
Connect using the modified connection profile.
Connect to the Access Server console and get root privileges.
Check the Access Server logs for the key agreement line:
grep "key agreement" /var/log/openvpnas.log
Example output:
[stdout#info] [OVPN 3] OUT: '2026-08-24 14:39:27 udp4:203.0.113.55:51371 Control Channel: TLSv1.3, cipher TLSv1.3 TLS_AES_256_GCM_SHA384, peer certificate: 384 bits ECsecp384r1, signature: ecdsa-with-SHA256, peer temporary key: 768 bits X25519MLKEM768, peer signing digest/type: ecdsa_secp384r1_sha384 ECDSA, key agreement: SecP256r1MLKEM768'
Confirm that the log contains:
key agreement: SecP256r1MLKEM768
Verify the same value in the VPN client log:
Control Channel: TLSv1.3, cipher TLSv1.3 TLS_AES_256_GCM_SHA384, peer certificate: 384 bits ECsecp384r1, signature: ecdsa-with-SHA256, peer signing digest/type: ecdsa_secp384r1_sha384 ECDSA, key agreement: SecP256r1MLKEM768