Forum Discussion

Spela_317265's avatar
Spela_317265
Icon for Nimbostratus rankNimbostratus
Oct 25, 2017

iRule to redirect user with incorrect certificate to specific url

Hello,

 

I'm writing iRule, which sould redirect user to specific uri, if user don't have cert or have incorrect cert. Client ssl profile client authentication is set to "ignore". I want to redirect user with incorrect cert to "https://[HTTP::host]/index.php?id=14", which is the only uri, that works without cert auth. HTTP respond or redirect in event "when HTTP_REQUEST_SEND" does not work, but logging does ("No or invalid client Certificate!").

 

Browser response when I choose incorect cert:

 

" This site can’t provide a secure connection

 

sent an invalid response.

 

Try running Windows Network Diagnostics.

 

ERR_SSL_PROTOCOL_ERROR "

 

Code:

 

 when CLIENTSSL_CLIENTCERT {
  HTTP::release
  if { [SSL::cert count] < 1 } {
    log local0. "No client Certificate!"
     }
}

when HTTP_REQUEST {
   if { [HTTP::uri] ne "/index.php?id=14" }{
    if { [SSL::cert count] <= 0 } {
      HTTP::collect
      SSL::authenticate always
      SSL::authenticate depth 9
      SSL::cert mode require
      SSL::renegotiate
    }
  }
  if { [HTTP::uri] eq "/index.php?id=14" }{
  log local0. "uri eq id=14"
  pool XYZ-POOL
  }
}

when HTTP_REQUEST_SEND {
  clientside {
      if { [SSL::cert count] > 0 } {
      HTTP::header insert "X-SSL-Session-ID"        [SSL::sessionid]
      HTTP::header insert "X-SSL-Client-Cert-Status"    [X509::verify_cert_error_string [SSL::verify_result]]
      HTTP::header insert "X-SSL-Client-Cert-Subject"   [X509::subject [SSL::cert 0]]
      HTTP::header insert "X-SSL-Client-Cert-Issuer"    [X509::issuer [SSL::cert 0]]

      log local0. "http header insert completed"
    } 
    else { 
    log local0. "No or invalid client Certificate!"        
     HTTP::redirect "https://www.xyz.com/index.php?id=14"
    HTTP::respond 302 Location "https://[HTTP::host]/index.php?id=14"   
       }
  }
}

Best regards,

 

Spela

 

  • What is your logic for using event HTTP_REQUEST_SEND? Have you tried adding the code in HTTP_REQUEST and using HTTP::redirect

     

  • Hi Spela,

    you may take a look to the iRule below.

    The provided irule uses a slightly different approach to trigger the initial SSL session (aka. we ignore client certificates), SSL session renegotiation (aka. we request client certificates) and Client SSL Certificate verification (aka. we verify the client certificate instead of just counting the existence of (possible invalid?) client certificates).

    If the client is able to renegotiate the SSL session by using a valid client certificate it will be allowed to pass. And if the client is unable to renegotiate the SSL session by using a valid client certificate it receive the HTTP redirect to the error page and will also be able to view the error page...

    when CLIENT_ACCEPTED {
        set ssl_auth ""
    }
    when CLIENTSSL_HANDSHAKE {
        if { $ssl_auth ne "" } then {
            if { [SSL::verify_result] == 0 } then {
                set ssl_auth "success"
            } else {
                log local0.debug "SSL Verify Result: [X509::verify_cert_error_string [SSL::verify_result]]"
                set ssl_auth "failed"
            }
            HTTP::release
        }
    }
    when HTTP_REQUEST {
        if { [HTTP::uri] eq "/index.php?id=14" } then {
             HTTP::respond 200 content "access denied" "Content-Type" "text/html"
            pool XYZ-POOL
        } elseif { $ssl_auth eq "" } then {
            set ssl_auth "request"
            HTTP::collect
            SSL::cert mode request
            SSL::renegotiate
        }
    }
    when HTTP_REQUEST_SEND {
        clientside {
            if { $ssl_auth eq "success" } then {
                 Allow the request to pass...
            } else {
                HTTP::redirect "/index.php?id=14"
            } 
        }
    }
    

    To make this iRule work, you need to tweak your Client SSL Profile a little bit. Basically you have to configure the Client SSL Section so that the Profile will authenticate your clients by using your internal PKI infrastructure but with the only exception that you IGNORE the client certificates by default.

    ltm profile client-ssl www.domain.de {
        allow-expired-crl enabled
        app-service none
        authenticate always
        authenticate-depth 9
        ca-file MY-CA-Chain.crt
        cert default.crt
        cert-key-chain {
            default {
                cert default.crt
                key default.key
            }
        }
        chain none
        client-cert-ca MY-CA-Chain.crt
        crl-file none
        defaults-from clientssl
        inherit-certkeychain true
        key default.key
        passphrase none
        peer-cert-mode ignore
        renegotiation enabled
        retain-certificate true
    }
    

    Cheers, Kai