Forum Discussion

Stefan_Klotz's avatar
Stefan_Klotz
Icon for Cumulonimbus rankCumulonimbus
Apr 24, 2023
Solved

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" }
    
      }
    }

7 Replies

  • 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" }
    
      }
    }
    • Stefan_Klotz's avatar
      Stefan_Klotz
      Icon for Cumulonimbus rankCumulonimbus

      Dear Michael,
      thank you for your quick and useful response. This sounds indeed for an easy solution, at least for the iRule-option. But besides this, I'm still interested for an answer for the policy option. I mean which technical options do I have in regards to client-certificate verification? Is it really only the CN, which can be checked or other values like within iRules as well?

      Regards Stefan 🙂

      • Michael_Saleem's avatar
        Michael_Saleem
        Icon for MVP rankMVP

        Hi Stefan,

        I have checked this on TMOS v16 and it looks like you are correct. In a local traffic policy, you can only check the common name with the option of using 'index' to exactly specify which certificate you would like to check (e.g. the identity certificate or intermediate certificate that the client sends)

        root@(bigip-1)(cfg-sync In Sync)(Active)(/Common)(tmos)# create ltm policy Drafts/foo strategy first-match rules add { bar { ordinal 0 conditions add { 0 { ssl-cert ?
        Selectors
          common-name  Organization common-name specified in certificate
        Params
          index        Numeric index to match

         

  • Sorry for the late reply, but I'd like to inform you, that we have successfully implemented our requirement with the above mentioned iRule with a small difference.

    • As there needs to be a "default" clientSSL-profile configured directly on the VS, we decided to use here the more restrict one including the client-cert authentication.
    • Within the iRule we check the IP-whitelisting and if this is positive, we replace the clientSSL-profile to the one without client-cert authentication. So we are using no "else"-branch in the iRule as this is already the default from the VS-configuration.

    Thanks again for your help!

    Regards Stefan 🙂

  • That's great. Glad I could help. I also agree with those modifications you made - it simplifies the configuration.