SNI Routing with DNS Lookup

SNI (Server Name Indication) is an extension of the TLS protocol that is used by the client to indicate the hostname it is attempting to connect to at the start of the SSL handshake. 

In the case of the BIG-IP the SNI can be used to select which client SSL profile should be applied to the ingress traffic but it requires at least one client SSL profile to be attached to the virtual server. In other words the SSL data must still be decrypted.

This iRule which is suitable for some SSLO use cases does not require SSL traffic to be terminated (i.e. decrypted) on the BIG-IP.  It only needs a generic SSL persistence profile to be attached to the virtual server and this just to circumvent MCP validation issues. Once the CLIENTSSL_CLIENTHELLO iRule event is triggered, the SNI can then be determined and used to steer traffic.

In this example below, once the SNI is found, an attempt is made to resolve it using DNS and then route the request using the BIG-IP to a gateway which could (in the case of SSLO) be a Secure Web Gateway device.

Note

  1. SSL::extensions -type <extension type value> returns the opaque extension byte array corresponding to the specified extension type value, or an empty string if not found.  Extension Type 0 is the server name.
  2. The "node" command is useful if you want to send traffic to a specific IP/port combination that is not defined as a pool member

iRule

[root@sslo:Active:Standalone] config # tmsh list ltm rule bluecoat
ltm rule bluecoat {
when RULE_INIT {
set static::resolver "8.8.8.8"
}
when CLIENT_ACCEPTED {
HTTP::disable
}
when CLIENTSSL_CLIENTHELLO {
set s_sni "NULL"
set sni_exists [SSL::extensions exists -type 0]
if {$sni_exists} {
binary scan [SSL::extensions -type 0] @9a* s_sni
log local0. "sni: $s_sni"
if { [catch "RESOLV::lookup @$static::resolver -a ${s_sni}" addrs] } {
log local0. "DNS resolution error"
reject
}
else {
log local0. "Resolved: [lindex ${addrs} 0]"
node [lindex ${addrs} 0] [TCP::local_port]
}
}
}
}

Published Jan 31, 2022
Version 1.0
  • Hi Peter,

    your [catch "...do something..." addr] command allows double-substitution. Special crafted SNI records will be able to hijack or crash your LTM. You may test my observation by manually overwriting the value of ${s_sni} to "www.\[{log}ups!?!\].de". It should add a harmless log line to your log...

    Cheers, Kai

  • Nice! RESOLV::lookup is a great command to trigger dns resolver without any DNS/GTM license or this may help with DNS caching issues and EDNS0 extension that has the real client ip address as they seem to not work so well. The only issue I have seen is that the network resolver seems to not be able to use an F5 Virtual Servers/VS that is on the same device as it replies come from 127.0.0.1 as it is a local communication. I am sharing this just to keep a note as maybe in some versions there is no such issue.