Forum Discussion
Performing SSL Bypass for Forward Proxy Traffic based using an iRule capturing the SNI
Hey everyone!
I'm currently developing an iRule to exclude certain traffic from the "Full Proxy" Architecture by turning off the HTTP Profile and Client/Server SSL Profile for our SSL Forward Proxy. We are using the built in function in SWG but for some banking applications it still does not seem to work and the SWG's intelligence is getting in the way. We have been hit with a few bugs which we are currently resolving but in the mean time we need to have this iRule in place to create a workaround.
We would like a clean cut for some of the applications they have by adding them to a Data Group and building an iRule for this purpose.
Here is the current iRule:
when RULE_INIT {
set 1 to enable logging, 0 to disable
set static::debug 0
}
when CLIENT_ACCEPTED {
This iRule is meant to Passthrough SSL Connections for SWG in order to solve SSL issue. Based on Data Group List of IP addresses.
if { [class match [IP::local_addr] equals DG_SWG_SSL_Passthrough_IP] }
{
SSL::disable clientside
SSL::disable serverside
HTTP::disable
if {$static::debug}{log local0. "ir181017-1 - Client IP: {[IP::client_addr]} Server IP: {[IP::local_addr]}: - Match DataGroup DG_SWG_SSL_Passthrough_IP! Disabling SSL"}
}
}
when CLIENTSSL_CLIENTHELLO {
This iRule is meant to Passthrough SSL Connections for SWG in order to solve SSL issues. Based on Data Group List of FQDNs.
if {$static::debug}{log local0. "ir181017-2 - Client IP: {[IP::client_addr]} - Client Request Server SSL SNI: {[SSL::sni name]}"}
if { [class match [string tolower [SSL::sni name]] contains DG_SWG_SSL_Passthrough_FQDN] }
{
SSL::disable clientside
SSL::disable serverside
HTTP::disable
if {$static::debug}{log local0. "ir181017-3 - Client IP: {[IP::client_addr]} - Server SSL SNI: {[SSL::sni name]} - Match DataGroup DG_SWG_SSL_Passthrough_FQDN! Disabling SSL"}
}
}
The most relevant part of the iRule is the CLIENTSSL_CLIENTHELLO section. When logging the entries, we cannot see any SSL::sni in the logs. But when tcpdumping we can clearly see that there is Server Name Indication fields in the traffic.
Perhaps we are using the SSL::sni command wrong. Perhaps we can use the SSL::extension and have it return the SNI from there and we match against that instead?
- Stanislas_Piro2Cumulonimbus
Are you working in transparent or explicit mode?
- Kevin_StewartEmployee
Try this (in CLIENTSSL_CLIENTHELLO):
[SSL::extensions exists -type 0]
But also, configuring bypass data groups in the SSL Forward Proxy section of the client SSL profile doesn't work either?
- Stanislas_Piro2Cumulonimbus
To decode tls to extract servername, use this code!
This is an enhanced code based on Joël Moses code
- Stanislas_Piro2Cumulonimbus
Try this code (not tested) and change line 52 with data group name
when CLIENT_ACCEPTED { SSL::disable SSL::disable serverside TCP::collect set tls_servername "" } when CLIENT_DATA { Store TCP Payload up to 2^14 + 5 bytes (Handshake length is up to 2^14) set payload [TCP::payload 16389] set payloadlen [TCP::payload length] If valid TLS 1.X CLIENT_HELLO handshake packet if { [binary scan $payload cH4Scx3H4x32c tls_record_content_type tls_version tls_recordlen tls_handshake_action tls_handshake_version tls_handshake_sessidlen] == 6 && \ ($tls_record_content_type == 22) && ([string match {030[1-3]} $tls_version]) && \ ($tls_handshake_action == 1) && ($payloadlen == $tls_recordlen+5)} { skip past the session id set record_offset [expr {44 + $tls_handshake_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_extension_length set record_offset [expr {$record_offset + 2}] Check if extension length + offset equals payload length if {$record_offset + $tls_extension_length == $payloadlen} { for each extension while { $record_offset < $payloadlen } { binary scan $payload @${record_offset}SS tls_extension_type tls_extension_record_length if { $tls_extension_type == 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[expr {$tls_extension_record_length - 5}] tls_servername set record_offset [expr {$record_offset + $tls_extension_record_length + 4}] } else { skip over other extensions set record_offset [expr {$record_offset + $tls_extension_record_length + 4}] } } } } } unset -nocomplain payload payloadlen tls_record_content_type tls_recordlen tls_handshake_action tls_handshake_sessidlen record_offset tls_ciphlen tls_complen tls_extension_length tls_extension_type tls_extension_record_length tls_supported_versions_length tls_supported_versions if {$tls_servername equals "" || [class match $tls_servername equals "MyDG"] == 0} { SSL::enable SSL::enable serverside } TCP::release }
- Lon_377595Nimbostratus
.
- James_Hu_141729Historic F5 Account
Did SWG URL classification fail to identify the site as banking? Did you try using a custom category instead? Or was the SNI extraction itself not working in SWG?
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