Can I use an iRule to perform the OCSP check and then, if OCSP fails for some reason, switch to an SSL profile that has CRL checking enabled so that CRL checking is performed?
That's actually a pretty good idea. Here's what you'd need to make this work:
-
An internal virtual server, pool, and monitor to load balance the actual remote OCSP resource(s).
-
An OCSP profile including a responder config that points to the above VIP, and the following iRule (applied directly to the profile). This is a slightly modified version of the built-in _sys_auth_ssl_ocsp iRule:
when RULE_INIT {
user-defined: name of OCSP server pool (behind OCSP VIP)
set static::OCSP_POOL "ocsp.domain.com.pool"
user-defined: name of client SSL profile with defined (static) CRL
set static::CRL_CLIENTSSL "myserver1.domain.com.crl"
user-defined: local debug
set static::LOCAL_DEBUG 1
}
when CLIENT_ACCEPTED {
if { [active_members $static::OCSP_POOL] < 1 } {
if { $static::LOCAL_DEBUG } { log local0. "OCSP pool is down - switching to local CRL" }
set localcrl 1
SSL::profile $static::CRL_CLIENTSSL
} else {
set tmm_auth_ssl_ocsp_sid 0
set tmm_auth_ssl_ocsp_done 0
}
set local_ip [IP::client_addr]
}
when CLIENTSSL_CLIENTCERT {
set local_cert_subj [X509::subject [SSL::cert 0]]
set local_cert_sn [X509::serial_number [SSL::cert 0]]
if { not ( [info exists localcrl] ) } {
set tmm_auth_ssl_ocsp_done 0
if {$tmm_auth_ssl_ocsp_sid == 0} {
set tmm_auth_ssl_ocsp_sid [AUTH::start pam default_ssl_ocsp]
if {[info exists tmm_auth_subscription]} {
AUTH::subscribe $tmm_auth_ssl_ocsp_sid
}
}
AUTH::cert_credential $tmm_auth_ssl_ocsp_sid [SSL::cert 0]
AUTH::cert_issuer_credential $tmm_auth_ssl_ocsp_sid [SSL::cert issuer 0]
AUTH::authenticate $tmm_auth_ssl_ocsp_sid
SSL::handshake hold
}
}
when CLIENTSSL_HANDSHAKE {
if { not ( [info exists localcrl] ) } {
set tmm_auth_ssl_ocsp_done 1
}
}
when AUTH_RESULT {
if { [info exists tmm_auth_ssl_ocsp_sid] and ( $tmm_auth_ssl_ocsp_sid == [AUTH::last_event_session_id] ) } {
switch [AUTH::status] {
"0" {
OCSP check good certificate
if { $static::LOCAL_DEBUG } { log local0. "OCSP check good certificate: Source: $local_ip - Subject: $local_cert_subj - Serial: $local_cert_sn" }
set tmm_auth_ssl_ocsp_done 1
SSL::handshake resume
}
"1" {
OCSP check revoked certificate
if { $static::LOCAL_DEBUG } { log local0. "OCSP check revoked certificate: Source: $local_ip - Subject: $local_cert_subj - Serial: $local_cert_sn" }
reject
}
default {
OCSP check failed or unknown status
if { $static::LOCAL_DEBUG } { log local0. "OCSP check failed or unknown status: Source: $local_ip" }
reject
}
}
}
}
-
Your application virtual server that has a standard client SSL profile (client certificate request/require and trusted authorities cert selected) and the OCSP authentication profile.
-
A second client SSL profile, identical to the first, but with a static CRL embedded.
The OCSP auth iRule simply switches to the other client SSL profile if there are no members in the OCSP pool. You'll want a good monitor on the OCSP pool, one that potentially makes OCSP calls with known good and revoked certificates. You'll also need a mechanism to update the static CRL on some regular interval. See:
https://devcentral.f5.com/questions/automaticlly-update-crl
On a side note, it's actually quite difficult with the (old) auth profile stuff to detect OCSP errors within the iRule, so it tends to be easier and more reliable to stand up a monitor that proactively maintains the state of the remote OCSP resource.