Forum Discussion

Brian_Burns_123's avatar
Brian_Burns_123
Icon for Nimbostratus rankNimbostratus
Mar 08, 2019

Need help with iRule and assigning server SSL profile

I am having difficulty assigning the server side SSL profile with an iRule that selectively requires client certificate authentication based on the URI. I have an API with two different URIs: “/external” and “/internal” on the same host. The “/external” API requires client certificate authentication and the “/internal” API requires windows authentication with no client certificate authentication.

I am using an iRule based on the “Selective Client Cert Authentication” posted by Colin Walker in 2008, and the “Client Certificate Request by URI with OCSP Checking” irule posted by hoolio in 2015.

Everything seems to work as expected, except when I assign the server side SSL profile during the SERVER_CONNECTED phase. The server side SSL profile that I am assigning through the iRule uses the same client certificate that the client side authenticates.

Based on the logs, it looks like it is assigning the correct server SSL profile, but the backend server does not see the client certificate in the SSL profile.

I've assigned the server SSL profile to a virtual server with a /32 source address for testing, and the server side SSL profile appears to work without any problems. I am able to verify the server sees the client certificate in the server SSL profile.

 

Code
when RULE_INIT {
     Log debug messages? (0=none, 1=minimal, 2=verbose, 3=everything)
    set ::ssl_debug 3
}

when CLIENT_ACCEPTED {
    set need_cert 0
    set log_prefix "client IP:port=[IP::client_addr]:[TCP::client_port]; VIP=[virtual name]"
    if {$::ssl_debug > 0}{log local0. "$log_prefix: New TCP connection to [IP::local_addr]:[TCP::local_port]"}
}

when CLIENTSSL_CLIENTCERT {
    if {$::ssl_debug > 0}{log local0. "$log_prefix: Cert count: [SSL::cert count], SSL sessionid: [SSL::sessionid]"}

    if {$need_cert == 1}{
        set subject_dn [X509::subject [SSL::cert 0]]
        set cert_hash [X509::hash [SSL::cert 0]]
        set cSSLSubject [findstr $subject_dn "CN=" 0 ","]
        log local0. "$log_prefix: Subject = $subject_dn, Hash = $cert_hash and $cSSLSubject."

        set Expected_hash [class match -value $cSSLSubject eq API_ClientCert_Thumb]

        if { $Expected_hash != $cert_hash } {
            if {$::ssl_debug > 0}{log local0. "Thumbprint does not matched api-service-auth. Expected Hash = $Expected_hash, Hash received = $cert_hash"}
            reject
        }
    }

    HTTP::release
}

when CLIENTSSL_HANDSHAKE {
    if {$need_cert == 1}{
        log local0. "$log_prefix: Cert count: [SSL::cert count], SSL sessionid: [SSL::sessionid]"
    }
}

when HTTP_REQUEST {
   if {$::ssl_debug > 0}{log local0. "$log_prefix: URI: [HTTP::uri], SSL session ID: [SSL::sessionid],\
      session lookup llength: [llength [session lookup ssl [SSL::sessionid]]],\
      string len: [string length [session lookup ssl [SSL::sessionid]]]\
      User-Agent: [HTTP::header User-Agent]"}

  if { [string tolower [HTTP::uri]] ends_with "/external" } {
    if { [SSL::cert count] <= 0 } {
      set need_cert 1
      HTTP::collect
      SSL::authenticate always
      SSL::authenticate depth 9
      SSL::cert mode require
      SSL::renegotiate
    } 
  }
}

 

Here is the code that assigns the server side SSL profile that does not appear to work.

 

when SERVER_CONNECTED {
    if {$need_cert == 0}{
        if {$::ssl_debug > 2}{log local0. "$log_prefix: Exiting event as \$need_cert is 0"}
        return
    }

    if {$need_cert == 1} {
        if {$::ssl_debug > 2}{log local0. "$log_prefix: Assigned Server Side SSL profile for api-service-ssl-auth"}

         This does not appear to assign the server side SSL profile
        SSL::profile api-service-ssl-auth
    }
}

 

Is there something I am missing?

Thanks in advance.

2 Replies

  • Hi, I am having a very similar issue. Is there any chance you may have found a fix for the problem above? ANy help would be appreciated

  • Hi

     

    Quick thought... Can you add an SSL::renegotiate after assigning SSL Serverside profile ?

     

    Yoann