Hi Wlepkin,
you can pass a SNI value to you backend servers on multiple ways.
Scenario 1.) Use different Server SSL Profiles with appropiate (serverside) SNI values and switch the profiles on demand using an iRule and the SSL::profile command during the SERVER_CONNECTED event.
when HTTP_REQUEST {
switch -exact -- [string tolower [getfield [HTTP::host] ":" 1]] {
"site1.domain.tld" {
pool site1.domain.tld
set srv_ssl_profile "srv_profile_site1.domain.tld"
}
"site2.domain.tld" {
pool site2.domain.tld
set srv_ssl_profile "srv_profile_site1.domain.tld"
}
} default {
HTTP::respond 403 content "Access Denied"
}
}
when SERVER_CONNECTED {
if{ [info exists srv_ssl_profile] } then {
SSL::profile $srv_ssl_profile
}
}
Scenario 2.) Use an SNI relay iRule to copy the clientside SNI information (if available) into the serverside SSL protocol handshake.
when CLIENTSSL_HANDSHAKE {
if { [SSL::extensions exists -type 0] } then {
set tls_sni_extension [SSL::extensions -type 0]
} else {
set tls_sni_extension ""
}
}
when SERVERSSL_CLIENTHELLO_SEND {
if { $tls_sni_extension ne "" } then {
SSL::extensions insert $tls_sni_extension
}
}
Note: This technique will work very stable if the client provides a SNI record and the external and internal FQDN is identical.
Scenario 3.) Use an SNI injection iRule to insert a SNI record of your choice (e.g. based on HTTP::host or datagroups).
when HTTP_REQUEST {
set http_host [getfield [HTTP::host] ":" 1]
}
when SERVERSSL_CLIENTHELLO_SEND {
Compute a SNI extension record as defined in RFC 3546/3.1
- TLS extension = SNI = 0000
- TLS extension length (2 bytes)
- SNI record length (2 bytes)
- SNI record type = Hostname = 00 (1 bytes)
- SNI value length (2 bytes)
- SNI value (1 - X bytes)
Compute the length of the server SNI value
set sni_length [string length $http_host]
Convert server SNI value to hex
binary scan $http_host H* http_host_hex
Set TLS extension to 0000
set server_tls_sni_extension "0000"
Calculate the length of the TLS extension
append server_tls_sni_extension "[format %4.4X [expr { $sni_length + 5 }]]"
Calculate the length of the 1st SNI record
append server_tls_sni_extension "[format %4.4X [expr { $sni_length + 3 }]]"
Set 1st SNI record type to HOSTNAME.
append server_tls_sni_extension "00"
Calculate the length of the 1st SNI record value
append server_tls_sni_extension "[format %4.4X $sni_length]"
Add the SSL extension, 1st SNI record and 1st SNI value to serverside clienthello
SSL::extensions insert [binary format H* "$server_tls_sni_extension$http_host_hex"]
}
Note: This technique will work stable even in the case the client is unable to provide a SNI record and/or the internal/external FQDNs are different names .
Additional Note: Scenario 1.) allows you to validate the received CNAME/SAN attributes of the serverside SSL certificate via the "Authenticate Name" setting. The SNI relay/insert iRules are not able to overwrite the "Authenticate Name" SSL profile setting, to match the currently selected SNI value. So you have to use additional iRule code to verify the CNAME/SAN attributes of the server side certificates - if this is important for you. You may take a look to the link Stanislas has already provided for further details on CNAME/SAN verification...
https://devcentral.f5.com/questions/serverssl-sni-vhosts
Cheers, Kai