Stefan_Klotz
Apr 24, 2023Cumulonimbus
Client-Certificate and IP-Whitelisting via Policy or iRule?
We have a requirement to verify for a valid client-certificate (not expired and issued from a trusted CA), but also accept a bypass if the source-IP is trusted. I have the following questions for the two different configuration options:
Policy
- In the condition section for "SSL certificate" it says "common name with index", is this the number of the certificate (same as the iRule command "SSL::cert <index>")? Does this mean I can only verify the standard CN of it? In the documentation it's only mentioned "Inspects the properties of an SSL certificate", which sounds to me I can also verify e.g. issuer name, serial number of the issuer or expiration dates. So which value do I have to enter here? Or in other words, how can I check that the presented client-certificate is really issued from a trusted CA and not from a fake CA with the same CN?
- Assuming the first question can be answered positively, is it correct, that I simply create two rules based on "first match" to forward traffic (first rule for client-cert check, second rule for IP-whitelisting) and if none of the rules are matching, traffic will be blocked?
Assuming above mentioned policy-setup is not possible, I would configure the client-cert check within an iRule.
iRule
- Is the option "Trusted Certificate Authorities" from the clientSSL-profile used if I set "Client Certificate" to request? And if so, do I have to use any special iRule commands to do this?
- If the list of trusted CA from the clientSSL-profile can't be used within the iRule, which other commands best "simulate" this kind of check? I mean a string comparison for the issuer CN name is not a good option, because I can create my own CA, if I know the allowed CA-name. Is the serial number a better option? Or in other words, same question as above, how can I check that the presented client-certificate is really issued from a trusted CA and not from a fake CA with the same CN?
- The IP-whitelisting can be simply added in an else branch then, right?
Thank you!
Regards Stefan 🙂
I would approach this by having two separate client SSL profiles - one without client authentication (bypass) and one with client authentication (require). And then use an iRule to switch between them based on the source IP.
create ltm profile client-ssl CLIENTSSL-NO-CLIENT-AUTH defaults-from <PARENT CLIENT SSL PROFILE> cert-key-chain add { <CERT KEY CHAIN NAME> { cert <CERT NAME>.crt key <KEY NAME>.key chain <CA BUNDLE NAME>.crt } } create ltm profile client-ssl CLIENTSSL-CLIENT-AUTH defaults-from <PARENT CLIENT SSL PROFILE> cert-key-chain add { <CERT KEY CHAIN NAME> { cert <CERT NAME>.crt key <KEY NAME>.key chain <CA BUNDLE NAME>.crt } } peer-cert-mode require ca-file <ROOT CA NAME>.crt create ltm data-group internal DG-SSL-CLIENT-AUTH-BYPASS type ip records add { <WHITELISTED IP 1> <WHITELISTED IP 2> ... } when CLIENT_ACCEPTED { set DEBUG 0 set CLIENT_IP [IP::client_addr] if { [class match $CLIENT_IP equals DG-SSL-CLIENT-AUTH-BYPASS] } { # Skip SSL client authentication for whitelisted source IPs SSL::profile CLIENTSSL-NO-CLIENT-AUTH if { $DEBUG } { log local0. "$CLIENT_IP - SSL client authentication bypassed" } } else { # Enforce SSL client authentication for all other source IPs SSL::profile CLIENTSSL-CLIENT-AUTH if { $DEBUG } { log local0. "$CLIENT_IP - SSL client authentication enforced" } } }