Learn F5 Technologies, Get Answers & Share Community Solutions Join DevCentral

Filter by:
  • Solution
  • Technology
code share

TLS server_name extension based routing without clientssl profile

Problem this snippet solves:

Some configuration requires to not decrypt SSL traffic on F5 appliances to select pool based on HTTP Host header.

I found a useful irule and this code keeps the structure and most of binary commands of it. I'm not sure if the first author was Kevin Stewart or Colin Walker. thanks both of them to have provided such code.

I worked to understand it reading TLS 1.2 RFC 5246 and TLS 1.3 draft-23 and provided some enhancements and following description with irule variables references. According to TLS 1.3 draft-23, this code will still be valid with next TLS version.

the following network diagram shows one use cases where this code will help.

Image Text

This diagram show how this code works based on the tls_servername_routing_dg Datagroup values and detected server name and TLS versions detected in the CLIENT_HELLO packet.

Image Text

For performances reasons, only the first TCP data packet is analyzed.

Versions :

1.1 : Updated to support TLS version detection and SSL offload feature. (05/03/2018)

1.2 : Updated to support TLS Handshake Failure Messages instead of reject. (09/03/2018)

1.3 : Updated to support node forwarding, logs only for debug (disabled with static variable), and changed the Datagroup name to tls_servername_routing_dg. (16/03/2018)

1.4 : Added 16K handshake length limit defined in RFC 1.2 in variable payload. (13/04/2018)

1.5 : Added supported version extension recursion, to bypass unknown TLS version if a known and allowed version is in the list. This correct an issue with Google chrome which include not documented TLS version on top of the list. (30/04/2018)

How to use this snippet:

create a virtual server with following configuration:

  • type : Standard
  • SSL Profile (client) : Only if you want to enable SSL offload for some pools
  • irule : code bellow

create all objects used in following datagroup (virtual servers, pools)

create a data-group named tls_servername_routing_dg.

  • if you want to forward to pool, add the value pool NameOfPool
  • if you want to forward to pool and enable SSL Offload (ClientSSL profile must be enabled on virtual server), add the value pool NameOfPool ssl_offload
  • if you want to forward to virtual server, add the value virtual NameOfVirtual
  • if you want to forward to an IP address, add the value node IPOfServer, backend server will not be translated
  • if you want to reject the connection with RFC compliant handshake_failure message, add the value handshake_failure
  • if you want to reject the connection, add the value reject
  • if you want to drop the connection, add the value drop

The defaultvalue keyword is search if there is no TLS server name extension or if TLS server name extension is not found in the data group. here is an example:

ltm data-group internal tls_servername_routing_dg {
    records {
        app1.company.com {
            data "virtual vs_app1.company.com"
        }
        app2.company.com {
            data "pool p_app2"
        }
        app3.company.com {
            data "pool p_app3 ssl_offload"
        }
        app4.company.com {
            reject
        }
        default {
            data "handshake_failure"
        }
    }
    type string
}
Comments on this Snippet
Comment made 12-Feb-2018 by Mel Cey 0

Thanks so much for publishing this - I am working on a similar issue where SSL is terminated behind the Bigip and want to distribute the traffic to certain pools depending on the Host header.

We started with an iRule based on this one: https://devcentral.f5.com/questions/match-ssl-sni-and-redirect-ssl-traffic-without-ssl-termination

From time to time we get errors:

<CLIENT_DATA> - bad option "-28159": must be -exact, -glob, -regexp, or -- while executing "switch $tls_version { "769" - "770" - "771" { if { ($tls_xacttype == 22) }...'

Which have lead to further investigations including the suggestion that we should limit the TCP:collect based on the possibility of causing the tmm to crash if the scan doesn't find what it needs and reads too much data.

https://support.f5.com/csp/article/K6578

https://support.f5.com/csp/article/K13387

I was wondering if this is a concern as there's an open TCP:collect here. So basically, my question is - in this iRule should the TCP:collect be limited to a certain number of bytes, and if so, how many would be enough to ensure that we can reach the SNI value?

Again - thanks for sharing this, it's super helpful.

-M

0
Comment made 12-Feb-2018 by Stanislas Piron 10464

@Mel : your issue is not a collect size issue but a non tls packet deciding issue

The returned value of binary command is -28159 which is not a valid tls version yet (a signed to unsigned convertion may be done)

Then after this decoding, the value is checked within switch command which handle any value starting with dash as a parameter : -28159 is not a valid parameter.

You can replace the switch command with

switch —- $tls_version    

Or use this code which does not the same test.

0
Comment made 06-Aug-2018 by kazeem yusuf 212

Hello Stanislas, I need help on decrypting https enrichment problem. The Scenario is an https virtual server terminating https to backend pool on http. We have clients sending https enriched requests to certificates terminated on F5. (the enrichment is embedded on a tls extensionvalue in CLIENT HELLO)

However, because the certificate loaded ON F5 uses standard "server hello" settings, the ssl handshake fails.

1.Is it possible to have the data on client hello included in request sent to backend server.

  1. Is there an irule that can be included on F5 that can be used to create tls extension values. ( i worked on an irule using CLIENTSSL_CLIENTHELLO but haven't gotten headway).

when CLIENTSSL_CLIENTHELLO { set my_ext "Hello world!" set my_ext_type 17516 SSL::extensions insert [binary format S1S1a* $my_ext_type [string length $my_ext] $my_ext] }

Looking forward to hearing from you.

0
Comment made 06-Aug-2018 by kazeem yusuf 212

Image Text

0
Comment made 06-Aug-2018 by Stanislas Piron 10464

@kazeem

  1. This snippet doesn't manage virtual servers terminating SSL on F5, So please only add comments here related to the code above. If there is no answer on the question you posted in "Answer section", try to update it with your new search (the irule you posted here for example)
  2. Devcentral is a forum where experts helps others during free time. please don't contact me with linkedIn if I don't answer here.

Regards,

Stanislas

0
Comment made 06-Aug-2018 by kazeem yusuf 212

My apologies StanislaS, i have updated the irule on this question ON DEVCENTRAL page i created as advised.

0
Comment made 5 months ago by Walter Kacynski 978

What is the advantage of using these two statements?

    set ssldisable "SSL::disable"
    set sslenable "SSL::enable"
0
Comment made 5 months ago by Stanislas Piron 10464

If virtual server doesn't have a clientssl profile, assigning an irule with SSL::disable command is not possible.

to allow to use this command only if clientssl profile is assigned, i set a variable with the command and evaluate the command

if { [PROFILE::exists clientssl] } {
    # We have a clientssl profile attached to this VIP but we need
    # to find an SNI record in the client handshake. To do so, we'll
    # disable SSL processing and collect the initial TCP payload.
    set ssldisable "SSL::disable"
    set sslenable "SSL::enable"
    eval $ssldisable
} 

[PROFILE::exists clientssl] is true only if the virtual server have a clientssl profile assigned.

1
Comment made 5 months ago by Walter Kacynski 978

Now that is tricky!

0