TLS Server Name Indication

Problem this snippet solves:

Extensions to TLS encryption protocols after TLS v1.0 have added support for passing the desired servername as part of the initial encryption negotiation. This functionality makes it possible to use different SSL certificates with a single IP address by changing the server's response based on this field. This process is called Server Name Indication (http://en.wikipedia.org/wiki/Server_Name_Indication).

It is not supported on all browsers, but has a high level of support among widely-used browsers. Only use this functionality if you know the bulk of the browsers accessing your site support SNI - the fact that IE on Windows XP does not precludes the wide use of this functionality for most sites, but only for now. As older browsers begin to die off, SNI will be a good weapon in your arsenal of virtual hosting tools.

You can test if your browser supports SNI by clicking here: https://alice.sni.velox.ch/

Supported Browsers: * Internet Explorer 7 or later, on Windows Vista or higher * Mozilla Firefox 2.0 or later * Opera 8.0 or later (the TLS 1.1 protocol must be enabled) * Opera Mobile at least version 10.1 beta on Android * Google Chrome (Vista or higher. XP on Chrome 6 or newer) * Safari 2.1 or later (Mac OS X 10.5.6 or higher and Windows Vista or higher) * MobileSafari in Apple iOS 4.0 or later (8) * Windows Phone 7 * MicroB on Maemo

Unsupported Browsers: * Konqueror/KDE in any version * Internet Explorer (any version) on Windows XP * Safari on Windows XP * wget * BlackBerry Browser * Windows Mobile up to 6.5 * Android default browser (Targeted for Honeycomb but won't be fixed until next version for phone users as Honeycomb will be reserved to tablets only) * Oracle Java JSSE

Note: The iRule listed here is only supported on v10 and above.

Note: Support for SNI was added in 11.1.0. See SOL13452 for more information.

How to use this snippet:

  1. Create a string-type datagroup to be called "tls_servername". Each hostname that needs to be supported on the VIP must be input along with its matching clientssl profile. For example, for the site "testsite.site.com" with a ClientSSL profile named "clientssl_testsite", you should add the following values to the datagroup.

    String: testsite.site.com
    Value: clientssl_testsite
    
  2. If you wish to switch pool context at the time the servername is detected in TLS, then you need to create a string-type datagroup called "tls_servername_pool". You will input each hostname to be supported by the VIP and the pool to direct the traffic towards. For the site "testsite.site.com" to be directed to the pool "testsite_pool_80", add the following to the datagroup:

    String: testsite.site.com
    Value: testsite_pool_80
    
  3. Apply the iRule below to a chosen VIP. When applied, this iRule will detect if an SNI field is present and dynamically switch the SSL profile and pool to use the configured certificate.

Important: The VIP must have a clientSSL profile AND a default pool set. If you don't set this, the iRule will likely break. There is also no real errorhandling for incorrect/inaccurate entries in the datagroup lists -- if you enter a bad value, it'll fail.

This allows you to support multiple certificates and multiple pools per VS IP address.

Published Mar 18, 2015
Version 1.0
  • Hi anyone,

     

    I have a question and in case to switch the traffic not just using SNI information, but the uri too, How can I change the code to this work ?. The flow of traffic it´ll be.

     

    The connection gets to VIP, on this VIP there´s 5 certificates, so the SNI it´ll be checked out to decrypt the data, on the same VIP there´s an Irule to redirect traffic using uri to different pools, after this the traffic must to be encrypt again because the server has the certificates too.

     

    Client ---- VIP:443 (5 certificates) SNI ->>> Irule redirect uri to pools ->>> | Certificates encrypt server side.

     

    Anyone can help me ?

     

  • Is there any reason to think that the code for examining TLS ClientHello would break with TLS 1.3? If not, we'd want to modify this as per below, right?

     

    from:

     

    switch $tls_version {
                        "769" -
                        "770" -
                        "771" {
    

    to:

     

    switch $tls_version {
                        "769" -
                        "770" -
                        "771" -
                        "772" {
    
  • @Chad : In TLS 1.3 Draft you can read this:

     

    legacy_record_version This value MUST be set to 0x0303 for all records generated by a TLS 1.3 implementation other than the ClientHello, where it MAY also be 0x0301 for compatibility purposes. This field is deprecated and MUST be ignored for all purposes. Previous versions of TLS would use other values in this field under some circumstances.

     

    And I saw that TLS 1.2 still send TLS 1.0 version in protocol version value of CLIENT_HELLO packet but send version 1.2 in handshake protocol version.

     

  • @stanislas

     

    Thanks, so you're saying that even with TLS 1.3, that TLS_version will be 771(Dec)/0x0303 and thus, the iRule should work unmodified with TLS 1.3.

     

  • CLIENT_HELLO version is 0x301 in TLS 1.2 and will still be 0x301 in TLS 1.3.

     

    Real tls version negotiation is in a new TLS extension in TLS 1.3

     

  • @chad, I tried my own code SNI based Pool selection without clientssl profile with firefox configured with TLS 1.3 support (draft 18).

     

    The CLIENT_HELLO had following values (seen with wireshark):

     

    • TLS record value : TLS 1.0
    • TLS Handshake version : TLS 1.2
    • supported versions extension:
      • TLS 1.3 (draft 18) 0x7f12
      • TLS 1.2 0x0303
      • TLS 1.1 0x0302
      • TLS 1.0 0x0301
    • server name : requested site

    the code extracted the server name value like in TLS 1.2 CLIENT_HELLO.

     

  • Hi Stan, I was going through a possible solution when i found this, can't ope the link and can't see your. Any chance you can re-share it please?

    Basically trying to set a variable at CLIENT_HELLO with SNI recieved and then load balance to specific pool based on that.

    Will appreciate your help.

    Regards,

    Ali