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).