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

Filter by:
  • Solution
  • Technology
code share


Problem this snippet solves:


You may or may not already have encountered a webserver that requires the SNI (Server Name Indication) extension in order to know which website it needs to serve you. It comes down to "if you don't tell me what you want, I'll give you a default website or even simply reset the connection". A typical IIS8.5 will do this, even with the 'Require SNI' checkbox unchecked.

So you have your F5, with its HTTPS monitors. Those monitors do not yet support SNI, as they have no means of specifying the hostname you want to use for SNI.

In comes a litle script, that will do exactly that.

Here's a few quick steps to get you started:

Download the script from this article (it's posted on pastebin: http://pastebin.com/hQWnkbMg, listed below and added as attachment). Import it under 'System' > 'File Management' > 'External Monitor Program File List'. Create a monitor of type 'External' and select the script from the picklist under 'External Program'. Add your specific variables (explanation below). Add the monitor to a pool and you are good to go.

A quick explanation of the variables:

METHOD (GET, POST, HEAD, OPTIONS, etc. - defaults to 'GET') URI ("the part after the hostname" - defaults to '/') HTTPSTATUS (the status code you want to receive from the server - defaults to '200') HOSTNAME (the hostname to be used for SNI and the Host Header - defaults to the IP of the node being targetted) TARGETIP and TARGETPORT (same functionality as the 'alias' fields in the original monitors - defaults to the IP of the node being targetted and port 443) DEBUG (set to 0 for nothing, set to 1 for logs in /var/log/ltm - defaults to '0') RECEIVESTRING (the string that needs to be present in the server response - default is empty, so not checked) HEADERX (replace the X by a number between 1 and 50, the value for this is a valid HTTP header line, i.e. "User-Agent: Mozilla" - no defaults) EXITSTATUS (set to 0 to make the monitor always mark te pool members as up; it's fairly useless, but hey... - defaults to 1)

There is a small thing you need to know though: due to the nature of the openssl binary (more specifically the sclient), we are presented with a "stdin redirection problem". The bottom line is that your F5 cannot be "slow" and by slow I mean that if it requires more than 3 seconds to pipe a string into openssl sclient, the script will always fail. This limit is defined in the variable "monitorstdinsleeptime" and defaults to '3'. You can set it to something else by adding a variable named 'STDINSLEEPTIME' and giving it a value. From my experience, anything above 3 stalls the "F5 script executer", anything below 2 is too fast for openssl to read the request from stdin, effectively sending nothing and thus yielding 'down'. When you enable debugging (DEBUG=1), you can see what I mean for yourself: no more log entries for the script when STDINSLEEPTIME is set too high; always down when you set it too low.

Kind regards,

Thomas Schockaert

Comments on this Snippet
Comment made 10-Dec-2015 by Paolo Di Liberto
Hi, this is really good, thanks! Due to a customer request, I did a little change on the script, allowing the user to use regexp to identity response codes. It is really basic, but it works. It is enough to change line 113 to: <code> if echo "$http_error_code" | egrep -q "$monitor_httpstatus"; then </code> You could assign a regexp to HTTPSTATUS (es. [2,3]0[0-3]) Thanks.
Comment made 14-Jun-2017 by RossVermette 307

FYI: I really like the script but had to make a few tweaks to make it work for me.

In line 13: added "sed" into the required_programs.

In line 109: Changed the "http_error_code" to use sed instead of awk, as the "http_content" was being returned into a single line, and the "$awk '{print $2}'" statement would only print the second word of the line. The line looks like this:

http_error_code=$(echo "$http_content" | $egrep "HTTP/1\.[0-1] " | $sed 's/.*HTTP\/1.[0-1] \([0-9][0-9][0-0]\).*/\1/')
Comment made 12-Jul-2017 by rst 0

Great script. Thanks! Just a little thing I noticed while looking at debug output: In line 161 it should probably read "HTTP Status" not "Receive String".

Comment made 06-Jun-2018 by RossVermette 307

Hey Thomas, Looking at line 105, and the "stdin redirection problem into openssl timing issue". What if you changed the command a little and used a "timeout" command with openssl and option of -ign_eof?

$http_content=`echo -e "$monitor_method $monitor_uri HTTP/1.1\r\nHost: $monitor_hostname\r\nConnection: close\r\n${monitor_header}\r" | timeout $monitor_stdin_sleeptime $openssl s_client -connect $monitor_targetip:$monitor_targetport -servername $monitor_hostname -ign_eof`