TL;DR

System → Certificates → Certificate Revocation → pencil on the CRL the OpenVPN server uses → Lifetime (Days) = 730 → Save. Saving regenerates the CRL with valid dates. Then Status → Services → OpenVPN → Restart. Clients get back in without changing anything on their side.

If the GUI will not let you set a sane lifetime (versions before 2.7 / 23.01), first System → Patches (the System Patches package) → apply Fix for CRL expiration lifetime default and maximum values (a3c1589086ea67d25a28ec14ab95d7fd9ab25fa2), then the step above. Or upgrade pfSense: current versions already carry it.

The error

In the server log (Status → System Logs → OpenVPN) and on the client:

1
2
3
4
VERIFY ERROR: depth=0, error=CRL has expired: CN=client1, serial=3
OpenSSL: error:0A000086:SSL routines::certificate verify failed
TLS_ERROR: BIO read tls_read_plaintext error
TLS Error: TLS handshake failed

The clue is that every client fails at once. An expired certificate takes down one client; an expired CRL takes down the whole server, because it is checked on every handshake.

Why it happens

Two roads lead here:

  1. The CRL really expired. Every CRL has a nextUpdate; past that date OpenSSL treats it as invalid and OpenVPN rejects everyone. A CRL created years ago with a short lifetime and never touched ends up like this.
  2. The CRL was born expired. pfSense generated CRLs with a 9999-day default, which pushed them past 2050. X.509 encodes dates up to 2049 as UTCTime with a two-digit year, and pfSense wrote 50 where GeneralizedTime was due: OpenSSL reads it as 1950 and the CRL “expired” 75 years ago. That is Redmine bug #13424, and it explains why healthy installs started failing in 2022–2023 with nobody touching anything: CRLs regenerated by any change crossed 2050.

Netgate’s fix lowered the default lifetime to 730 days, capped the maximum (2050 on 64-bit, 2038 on 32-bit), and ships in current versions; for old ones it remained as a patch in the System Patches package.

Checking it

pfSense writes each OpenVPN server’s CRL into its configuration directory:

1
2
ls /var/etc/openvpn/server1/
openssl crl -in /var/etc/openvpn/server1/crl-verify -noout -lastupdate -nextupdate

A nextUpdate in the past, or a year of 1950, is the whole diagnosis.

Fix

  1. Identify which CRL the server uses: VPN → OpenVPN → Servers → edit → Peer Certificate Revocation list.
  2. Regenerate it: System → Certificates → Certificate Revocation → pencil on that CRL → Lifetime (Days) 730 → Save. Any save rewrites it with lastUpdate = now.
  3. Restart OpenVPN: Status → Services. OpenVPN re-reads crl-verify when it notices the change, but the restart saves you the wait.
  4. Check again with the openssl crl above.

On a version without the fix, between steps 1 and 2: System → Package Manager → install System_Patches → System → Patches → the patch shows up in the recommended list → Apply. Without it, the GUI writes 9999 again and the problem repeats as soon as you save.

Traps

  • Do not delete the CRL to “fix it”: without a CRL, the certificates you revoked become valid again. Edit it.
  • One CRL per CA: if you have several OpenVPN servers with different CAs, check each one.
  • Imported CRLs (from an external CA) cannot be regenerated from pfSense; request a new one from your CA and import it again.
  • 730 days run out too. Any revocation, CRL edit, or change to the OpenVPN server regenerates it; if you touch nothing for two years, you are back here. A calendar reminder is cheap.
  • Past 2038 on 32-bit hardware the other limit applies; in practice none of that gear should still be your firewall.

References: Certificate Revocation List Management in the Netgate documentation and Pasquale Fiorillo’s write-up.