Forum Discussion
Catch specific SSL errors/failures???
One of the requirements that I've been given is to try and catch certain SSL errors and return a more friendly error page, rather than the browser default...
A couple of the examples that have come up so far are:
* A User attempting to connect to a VIP that is enforcing client SSL certficiates but doesn't have a valid Client SSL certificate installed...
* A user attempting to connect to a VIP with an expired Client SSL certificate
* A user connecting with a very old SSL Version or Cipher...
Now the last one is nice and easy as there's plenty of reference code on the Wiki...
However I'm struggling with 1 & 2 above...
Any pointers or ideas???
Cheers
Gav
- nitassEmployee
not sure whether SSL::verify_result is usable.
SSL::verify_result wiki
http://devcentral.f5.com/wiki/iRules.SSL__verify_result.ashx
[root@ve1023:Active] ca2012 b virtual bar list virtual bar { snat automap pool foo destination 172.28.19.79:443 ip protocol 6 rules myrule profiles { http {} myclientssl { clientside } tcp {} } } [root@ve1023:Active] ca2012 b pool foo list pool foo { members 200.200.200.101:80 {} } [root@ve1023:Active] ca2012 b profile myclientssl list profile clientssl myclientssl { defaults from clientssl ca file "chain.crt" peer cert mode request } [root@ve1023:Active] ca2012 b rule myrule list rule myrule { when HTTP_REQUEST { if {[SSL::verify_result]} { HTTP::respond 403 content [X509::verify_cert_error_string [SSL::verify_result]] } } } [root@ve1023:Active] ca2012 curl -ik https://172.28.19.79 HTTP/1.0 403 Forbidden Server: BigIP Connection: Keep-Alive Content-Length: 32 application verification failure [root@ve1023:Active] ca2012 curl -ik https://172.28.19.79 --cert certs/client.crt --key certs/client.key HTTP/1.1 200 OK Date: Mon, 16 Jan 2012 17:32:45 GMT Server: Apache/2.2.3 (CentOS) Last-Modified: Fri, 11 Nov 2011 14:48:14 GMT ETag: "4183e4-3e-9c564780" Accept-Ranges: bytes Content-Length: 62 Set-Cookie: BROWSER=MOZILLA%20INTERNET_EXPLORER%20CHROME; path=/ Content-Type: text/html; charset=UTF-8 ...
- hooleylistCirrostratusOne of the keys to this working is that you need to change the client cert mode from require to request. This allows LTM to complete the SSL handshake without a valid client cert.
- GavinW_29074NimbostratusAaron/Nitass
- nitassEmployee
You should probable also add a check that [SSL::cert 0] ne "" before checking SSL::verify_result doesn't return 0 for an invalid cert. since it does not return 0, bigip should respond with 403, shouldn't it?
[root@ve1023:Active] ssl curl -ik https://172.28.19.79 --cert ssl.crt/default.crt --key ssl.key/default.key HTTP/1.0 403 Forbidden Server: BigIP Connection: Keep-Alive Content-Length: 23 self signed certificate
- GavinW_29074NimbostratusSorry for the weird formatting on the above 2 posts... I've tried several edit's to get it correct, but it's having none of it...
- hooleylistCirrostratusThat looks like a good start Gavin. Can you try moving the ifile command to RULE_INIT and use subst to force evaluation of the variable?
- GavinW_29074NimbostratusDouble post...
- GavinW_29074Nimbostratus
Aaron
Did try putting code tags in, but just kept breaking... I guess could be due to the HTML tags in the include page...
I tried adding your line to the RULE_INIT block, but got the following error:
Jan 18 13:57:24 tmm err tmm[9144]: 01220001:3: TCL error: /Common/Catch_SSL_Errors - can't read "failure_result": no such variable while executing "subst [ifile get error_page_html]"
Jan 18 13:57:24 tmm err tmm[9144]: 01220006:3: RULE_INIT for rule /Common/Catch_SSL_Errors failed
However that did send me in the right direction... I've kept the error_page variable in the HTTP_REQUEST block, and have wrapped it inside a 'subst' tag on the HTTP::respond lines... E.g:
HTTP::respond 403 content [subst $error_page] "Content-Type" "text/html" "Connection" "Close"
I did try the code without the SSL::cert count, and it returns a result code of 50 - 'X509_V_ERR_APPLICATION_VERIFICATION: application verification failure'. I chose to wrap it in a count as it gives me an easy way of picking out where they don't have a client cert, as that's our typical failure method. Plus it saves some processing time I guess...
Latest copy of the rule is below...
Going back to your suggestion of putting the 'ifile get' in the RULE_INIT section, are there any advantages/disadvantages of this?
Cheers
Gav
when RULE_INIT {
Debug Loggingset static::CatchSSLErrorsDebug 1Get the Error Page HTMLset static::error_page [ifile get error_page_html]}
v10.1 or higher
Redirect any client HTTP request with no client certificate or with a cert which is not correctly
validated against the trusted root certificate specified in the client SSL profile.
when HTTP_REQUEST priority 10 {
if {$static::CatchSSLErrorsDebug == 1} { log local0. "CatchSSLErrors HTTP Request:" }Return the Logo if requested.if { [HTTP::uri] ends_with "logo-act.png" } {if {$static::CatchSSLErrorsDebug > 0} { log local0.info "Returning Logo..." }HTTP::respond 200 content [ifile get act_logo_png] "Content-Type" "image/png" "Connection" "Close"event disablereturn}Hide the SSL:: command's from the iRule parserso the iRule can be used on a non-client SSL VSset cipher_cmd "SSL::cipher version"set count_cmd "SSL::cert 0"set verify_cmd "SSL::verify_result"set failure_cmd "X509::verify_cert_error_string"Get the error pageset error_page [ifile get error_page_html]Check if the client used an SSL cipher and it's not "none"if {not ([catch {eval $cipher_cmd} result]) && $result ne "none"}{Client did use a cipherif {$static::CatchSSLErrorsDebug == 1} { log local0.info "SSL Connection initiated... Verifying client certificate." }catch {eval $count_cmd} count_resultif {$static::CatchSSLErrorsDebug == 1} { log local0.info "SSL::cert returned the following output... '$count_result'" }if {$count_result ne ""} {if {$static::CatchSSLErrorsDebug == 1} { log local0.info "Client cert presented. Verifying..." }catch {eval $verify_cmd} verify_resultif { $verify_result == 0 } {Client Cert present and verified successfully.if {$static::CatchSSLErrorsDebug == 1} { log local0.info "SSL::Verify_result was OK... '$verify_result' Continuing..." }return} else {Client cert verification error.if {$static::CatchSSLErrorsDebug == 1} { log local0.info "SSL::Verify_result was NOT OK... '$verify_result'" }Get failure reasoncatch {eval $failure_cmd $verify_result } failure_resultif {$static::CatchSSLErrorsDebug == 1} { log local0.info "X509::verify_cert_error_string value is... '$failure_result'" }HTTP::respond 403 content [subst $error_page] "Content-Type" "text/html" "Connection" "Close"event disablereturn}} else {if {$static::CatchSSLErrorsDebug == 1} { log local0.info "No Client cert presented. Returning error page..." }Return failure page. No Client cert presented...set failure_result "No client certificate present"HTTP::respond 403 content [subst $error_page] "Content-Type" "text/html" "Connection" "Close"event disablereturn}} else {Client did not use a cipherif {$static::CatchSSLErrorsDebug == 1} { log local0.info "Non-SSL Connection initiated... Continuing..." }return}}
- hooleylistCirrostratusSorry, $failure_result is calculated at runtime, so your solution of calling subst at runtime is perfect. You should be able to get the ifile contents in RULE_INIT using 'set static::error_page [ifile get error_page_html]' and then call subt against that with HTTP::respond:
- GavinW_29074NimbostratusAaron
Recent Discussions
Related Content
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com