If the F5 doesn't support the cryptography, you can't decrypt at the F5. And more importantly, you can't do SNI-based processing the easy way. Otherwise you could very easily build a CPM policy to load balance to different pools based on the SNI.
But since we're not talking about the easy way, I'll show you a harder way involving some layer 4 iRule parsing:
when CLIENT_ACCEPTED priority 300 {
set detect_handshake 1
TCP::collect
}
when CLIENT_DATA priority 200 {
binary scan [TCP::payload] H* orig
if { [binary scan [TCP::payload] cSS tls_xacttype tls_version tls_recordlen] < 3 } {
reject
return
}
768 SSLv3.0
769 TLSv1.0
770 TLSv1.1
771 TLSv1.2
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_handshake 0
}
}
}
"768" {
set detect_handshake 0
}
default {
set detect_handshake 0
}
}
if { ($detect_handshake) } {
skip past the session id
set record_offset 43
binary scan [TCP::payload] @${record_offset}c tls_sessidlen
set record_offset [expr {$record_offset + 1 + $tls_sessidlen}]
skip past the cipher list
binary scan [TCP::payload] @${record_offset}S tls_ciphlen
set record_offset [expr {$record_offset + 2 + $tls_ciphlen}]
skip past the compression list
binary scan [TCP::payload] @${record_offset}c tls_complen
set record_offset [expr {$record_offset + 1 + $tls_complen}]
check for the existence of ssl extensions
if { ([TCP::payload length] > $record_offset) } {
skip to the start of the first extension
binary scan [TCP::payload] @${record_offset}S tls_extenlen
set record_offset [expr {$record_offset + 2}]
read all the extensions into a variable
binary scan [TCP::payload] @${record_offset}a* tls_extensions
for each extension
for { set ext_offset 0 } { $ext_offset < $tls_extenlen } { incr ext_offset 4 } {
binary scan $tls_extensions @${ext_offset}SS etype elen
if { ($etype == 0) } {
if it's a servername extension read the servername
set grabstart [expr {$ext_offset + 9}]
set grabend [expr {$elen - 5}]
binary scan $tls_extensions @${grabstart}A${grabend} tls_servername_orig
set tls_servername [string tolower ${tls_servername_orig}]
set ext_offset [expr {$ext_offset + $elen}]
break
} else {
skip over other extensions
set ext_offset [expr {$ext_offset + $elen}]
}
}
}
}
if { ![info exists tls_servername] } {
This isn't TLS so we can't decrypt it anyway
SSL::disable clientside
SSL::disable serverside
} else {
log local0. "tls_servername = ${tls_servername}"
This is where you'd check a datagroup and disable SSL profiles as necessary
}
TCP::release
}
What you're looking at here is the standard iRule for SNI extraction at OSI layer 4 (TCP). At the end you see the clause that contains:
This is where you'd check a datagroup and disable SSL profiles as necessary
This is where you have access the SNI in the ${tls_servername} variable, and where you could do your pool processing. You must also do this in a Standard VIP configuration to ensure client side TCP completes before starting server side TCP.