Forum Discussion

Walker_111918's avatar
Walker_111918
Icon for Nimbostratus rankNimbostratus
Apr 24, 2012

Change SSL::profile depending on user-agent

Is it possible to change the SSL::profile depending on user-agent? I tried something like this:

 

 

fingerprint_sha hase 3 states:

 

0: not set

 

1: sha1

 

2: sha256

 

set fingerprint_sha 0

 

}

 

when HTTP_REQUEST {

 

if { $fingerprint_sha == 0 } {

 

if {[HTTP::header User-Agent] contains "Paul"} {

 

log local0.info "Paul"

 

set fingerprint_sha 1

 

} else {

 

log local0.info "nicht Paul"

 

set fingerprint_sha 2

 

SSL::profile profile2

 

}

 

}

 

}

 

 

The problem is that I couldn't user SSL::Profile in HTTP_REQUEST event. Does anyone have any ideas on it?

 

5 Replies

  • Hi Walker,

     

     

    What's your goal for this? If you provide more detail we can try to suggest an alternative.

     

     

    It's too late to change the client SSL profile for the current SSL session in HTTP_REQUEST as the session has already been established.

     

     

    Aaron
  • Our problem is, that we would like to use ssl-certificates with sha256. Windows XP with service pack 2 have an error so they could'nt finish the ssl-handshake with a sha256-certificate. My idea was that i try to start with a certifikate with sha1. If i know that the user doesn't use Windows XP with service pack 2 i would like to change the certificate to the sha256.
  • Here's an idea.

     

     

    Windows XP doesn't present the SSL SNI field when setting up an SSL/TLS session. It's not a totally precise way to identify Windows XP (it will also get other browsers that don't send an SNI field), but it would let you switch the profile after the initial client SSL request -- which is absolutely possible. I wrote an iRule that switches pools and SSL profiles based on the SNI hostname:

     

     

    https://devcentral.f5.com/wiki/iRules.TLS-ServerNameIndication.ashx

     

     

    A modification to this rule could replace the default sha256-cert containing profile with the sha1 profile for browsers that don't seem to present SNI. That would include all XP users but present the "more secure" default cert for Vista/Win7. I'll see if I can find some time to try this.
  • I've not been able to fully verify syntax (let me know), but I think this might work for your purposes:

    when RULE_INIT {
    set static::alternate_profile_for_non_sni "clientssl_mysite_xp"
    }
    
    when CLIENT_ACCEPTED {
    if { [PROFILE::exists clientssl] } {
    set detect_non_sni 1
    SSL::disable
    TCP::collect
    } else {
    log local0. "This iRule is applied to a VS that has no clientssl profile."
    set detect_non_sni 0
    }
    }
    
    when CLIENT_DATA { 
    if { ($detect_non_sni) } {
    binary scan [TCP::payload] cSS tls_xacttype tls_version tls_recordlen
    switch "$tls_version" {
    "769" -
    "770" -
    "771" {
    if { ($tls_xacttype == 22) } {
    binary scan [TCP::payload] @5c tls_action
    if { not (($tls_action == 1) && ([TCP::payload length] > $tls_recordlen)) } {
    set detect_non_sni 0
    }
    }
    }
    default {
    set detect_non_sni 0
    }
    }
    if { ($detect_non_sni) } {
    set record_offset 43
    binary scan [TCP::payload] @${record_offset}c tls_sessidlen
    set record_offset [expr {$record_offset + 1 + $tls_sessidlen}]
    binary scan [TCP::payload] @${record_offset}S tls_ciphlen
    set record_offset [expr {$record_offset + 2 + $tls_ciphlen}]
    binary scan [TCP::payload] @${record_offset}c tls_complen
    set record_offset [expr {$record_offset + 1 + $tls_complen}]
    if { ([TCP::payload length] >= $record_offset) } {
    binary scan [TCP::payload] @${record_offset}S tls_extenlen
    set record_offset [expr {$record_offset + 2}]
    binary scan [TCP::payload] @${record_offset}a* tls_extensions
    for { set x 0 } { $x < $tls_extenlen } { incr x 4 } {
    set start [expr {$x}]
    binary scan $tls_extensions @${start}SS etype elen
    if { ($etype == "00") } {
    set grabstart [expr {$start + 9}]
    set grabend [expr {$elen - 5}]
    binary scan $tls_extensions @${grabstart}A${grabend} tls_servername
    set start [expr {$start + $elen}]
    } else {
    set start [expr {$start + $elen}]
    }
    set x $start
    }
    if { ([info exists tls_servername] ) } {
    SSL::enable
    } else {
    set ssl_profile_enable "SSL::profile $ssl_profile"
    catch { eval $ssl_profile_enable }
    SSL::enable
    }
    } else {
    SSL::enable
    }
    set detect_non_sni 0
    TCP::release
    } else {
    set detect_non_sni 0
    SSL::enable
    TCP::release
    }
    }
    }
    

    This is modified from the SNI switching iRule and looks big and ugly, but it's really quite simple. If it does not find an SNI field in the client's first handshake, it switches the SSL profile to the alternate one named in RULE_INIT. Otherwise, it passes the connection through using whatever was previously set (so your SHA256 cert should be on the default clientssl profile).