F5 DNS/GTM External Monitor(EAV) with SNI support and response code check
The example DNS/GTM health monitor is for versions before 16.1 as BIG-IP supports SNI for default DNS/GTM HTTPS monitor in the latest version but if you have still not upgraded then this is for you!
I have used this monitor for XC Distributed Cloud as the HTTP LB share by default the same tenant IP address and SNI support is needed. You can order dedicated public IP addresses for each HTTP LB and enable "Default Load Balancer" ( https://my.f5.com/manage/s/article/K000152902 ) option but it will cost you extra 😉
The script is a modified version of External https health monitor for SNI-enabled pool as to handle response codes and to set the SNI globally for the entire pool and it's members.
- If you are uploading from Windows machine see External monitor fails to run as you could hit the bug.
- This could be needed for F5 DNS/GTM below 16.1 that do not support SNI in HTTPS monitors.
- The only mandatory variable is "SNI" that should be set in the external monitor config that references this uploaded bash script. The "URI" variable by default is set to "/" and "$2" variable by default is empty or 443, the default expected response code 200.
#!/bin/sh
# External monitoring script for checking HTTP status code
# $1 = IP (::ffff:nnn.nnn.nnn.nnn notation or hostname)
# $2 = port (optional; defaults to 443 if not provided)
# Default SNI to IP if not explicitly provided
node_ip=$(echo "$1" | sed 's/::ffff://') # Remove IPv6 compatibility prefix
SNI=${SNI:-"$node_ip"} # Assign sanitized IP to SNI
# Default variables
MON_NAME=${MON_NAME:-"MyExtMon$$"}
pidfile="/var/run/$MON_NAME.$1..$2.pid" # PID file path
DEBUG=${DEBUG:-0} # Enable debugging if set to 1
EXPECTED_STATUS=${EXPECTED_STATUS:-200} # Default HTTP status code to 200
URI=${URI:-"/"} # Default URI
DEFAULT_PORT=443 # Default port (used if $2 is unset)
# Set port to default if $2 is not provided
if [ -z "${2}" ]; then
PORT=${DEFAULT_PORT}
else
PORT=${2}
fi
# Kill old process if pidfile exists
if [ -f "$pidfile" ]; then
kill -9 -$(cat "$pidfile") > /dev/null 2>&1
fi
echo "$$" > "$pidfile"
# Perform the HTTP(S) request via single curl (fetch status code only)
status_code=$(curl -s -o /dev/null -w '%{http_code}' --connect-timeout 5 --resolve "${SNI}:${PORT}:${node_ip}" "https://${SNI}:${PORT}${URI}")
# Cleanup
rm -f "$pidfile" > /dev/null 2>&1
# Output server status based on HTTP status code match
if [ "$status_code" -eq "$EXPECTED_STATUS" ]; then
echo "up"
else
echo "down"
fi
# Debugging
if [ "$DEBUG" -eq 1 ]; then
echo "Debugging on..."
echo "SNI=${SNI}"
echo "URI=${URI}"
echo "IP=${node_ip}"
echo "PORT=${PORT}"
echo "MON_NAME=${MON_NAME}"
echo "STATUS_CODE=${status_code}"
echo "EXPECTED_STATUS=${EXPECTED_STATUS}"
echo "curl -s -o /dev/null -w '%{http_code}' --connect-timeout 5 --resolve ${SNI}:${PORT}:${node_ip} https://${SNI}:${PORT}${URI}"
fi
Updated Sep 10, 2025
Version 4.0Nikoolayy1
MVP
Joined October 15, 2019
No CommentsBe the first to comment