Extracting the SNI server name
Problem this snippet solves:
The following LTM iRule code snippet helps to lookup incoming connections for using server name indication (aka SNI).
A TLS extension may contain an information about the server name the client wants to talk to.
Based on the information the server may pick a matching SSL certificate or a proxy may create one in real-time.
The code below uses the SSL::extensions function to lookup the SSL client hello message for the SNI extension.
The information is stored in the variable sni_name and its value will be logged conditionally by using the ternary operator.
(The ternary operator is a shortcut to simple if-then-else constructs.)
How to use this snippet:
Create a virtual server in standard mode and assign a client-ssl profile to make sure the SSL connection is terminated on your BIG-IP.
Use the iRule below as a resource of your virtual server to determine the usage of SNI in the client hello message during the SSL handshake.
You may test your results by using the openssl s_client utility, i.e.:
$ openssl s_client -connect <virtual-ip>:<port> -servername <hostname.domain>
Lookup the /var/log/ltm file for related log messages by using (and stop it with CTRL-C):
$ tail -f /var/log/ltm
Code :
when CLIENTSSL_HANDSHAKE { if { [SSL::extensions exists -type 0] } { # optionally lookup all SNI headers (typically not required) binary scan [SSL::extensions -type 0] {SSScSA*} ext_type ext_len sni_list_len sni_name_type sni_name_len sni_name log local0. "sni info: ${ext_type} ${ext_len} ${sni_list_len} [expr { ${sni_name_type} & 0xff }] ${sni_name_len} ${sni_name}" # skip the SNI headers instead to save memory binary scan [SSL::extensions -type 0] {@9A*} sni_name log local0. "sni name: ${sni_name}" } # use the ternary operator to return the servername conditionally log local0. "sni name: [expr {[info exists sni_name] ? ${sni_name} : {not found} }]" }
Tested this on version:
12.1