Forum Discussion
kridsana
Feb 07, 2018Cirrocumulus
iRule Choose pool base on SNI and disable ssl base on SNI
Hi
We have the need to select pool via irule but we don't want to decrypt all HTTPS traffic.
Can we do this? (This is outbound traffic)
We have list of URL in iRule Datagroup
...
Stanislas_Piro2
Feb 07, 2018Cumulonimbus
I changed the Kevin Stewart's irule to solve your issue (not tested, developed with tcl shell out of box)
Updated to add unset command and remove useless temp variables
when CLIENT_ACCEPTED {
TCP::collect
set default_pool [LB::server pool]
}
when CLIENT_DATA {
set payload [TCP::payload]
set payloadlen [TCP::payload length]
- tls_record_content_type : Reccord layer content-type (1 byte)
Handshake value is 22 (required for CLIENT_HELLO packet)
- tls_major_version : SSL / TLS version SSLv3 and TLS share major version value 3 (1 byte)
- tls_minor_version : SSL / TLS minor version. (1 byte)
SSLv3 value is 0 (doesn't support SNI, not valid in first condition)
TLS_1.0 value is 1
TLS_1.1 value is 2
TLS_1.2 value is 3
- tls_recordlen : Reccord layer content length (2 bytes) : must match payload length
TLS Hanshake protocol
- tls_action : Handshake action (1 byte) : CLIENT_HELLO = 1
- handshake length not stored in a variable (3 bytes)
- SSL / TLS handshake major version not stored in a variable (1 byte)
- SSL / TLS handshake minor version not stored in a variable (1 byte)
- hanshake random not stored in a variable (32 bytes)
- tls_sessidlen : handshake sessionID length (1 byte)
- handshake sessionID (length defined by sessionID length value, max 32-bit)
- CipherSuites length (2 bytes)
- CipherSuites (length defined by CipherSuites length value)
- Compression length (2 bytes)
- Compression methods (length defined by Compression length value)
- Extensions
- Extension length (2 bytes)
- list of Extensions records (length defined by extension length value)
- extension record type (2 bytes)
- extension record length (2 bytes)
- extension data (length defined by extension record length value)
SNI extension data format:
- SNI record length (2 bytes)
- SNI record data (length defined by SNI record length value)
- SNI record type (1 byte)
- SNI record value length (2 bytes)
- SNI record value (length defined by SNI record value length value)
If valid TLS 1.X CLIENT_HELLO handshake packet
if { [binary scan $payload cccScx37c tls_record_content_type tls_major_version tls_minor_version tls_recordlen tls_action tls_sessidlen] == 6 && \
($tls_record_content_type == 22) && \
($tls_major_version == 3) && ($tls_minor_version > 0) && \
($tls_action == 1) && \
($payloadlen == $tls_recordlen+5)} {
skip past the session id
set record_offset [expr {44 + $tls_sessidlen}]
skip past the cipher list
binary scan $payload @${record_offset}S tls_ciphlen
set record_offset [expr {$record_offset + 2 + $tls_ciphlen}]
skip past the compression list
binary scan $payload @${record_offset}c tls_complen
set record_offset [expr {$record_offset + 1 + $tls_complen}]
check for the existence of ssl extensions
if { ($payloadlen > $record_offset) } {
skip to the start of the first extension
binary scan $payload @${record_offset}S tls_extenlen
set record_offset [expr {$record_offset + 2}]
Check if extension length + offset equals payload length
if {$record_offset + $tls_extenlen == $payloadlen} {
for each extension
while { $record_offset < $payloadlen } {
binary scan $payload @${record_offset}SSx3S etype elen erlen
if { ($etype == 0) } {
if it's a servername extension read the servername
SNI record value start after extension type (2 bytes), extension record length (2 bytes), record type (2 bytes), record type (1 byte), record value length (2 bytes) = 9 bytes
binary scan $payload @[expr {$record_offset + 9}]A${erlen} tls_servername
set record_offset [expr {$record_offset + $elen + 4}]
break
} else {
skip over other extensions
set record_offset [expr {$record_offset + $elen + 4}]
}
}
}
} else {
log local0. "packet is not a valid TLS 1.X CLIENT_HELLO handshake"
reject
return
}
unset -nocomplain payload payloadlen tls_record_content_type tls_major_version tls_minor_version tls_recordlen tls_action tls_sessidlen record_offset tls_ciphlen tls_complen tls_extenlen etype elen erlen
if { [info exists tls_servername] } {
log local0. "tls_servername = ${tls_servername}"
switch [string tolower $tls_servername] {
"app1.company.com" {pool pool1}
"app2.company.com" {pool pool2}
default {pool $default_pool}
}
} else {
log local0. "packet is a valid TLS 1.X CLIENT_HELLO handshake but doesn't contain server name extension"
pool $default_pool
}
TCP::release
}
Recent Discussions
Related Content
DevCentral Quicklinks
* 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
Discover DevCentral Connects