Health Check DNS Load Balanced Web Servers
Consider example.com, which is load balanced with DNS using an ‘A’ record per server.
dig A example.com
example.com. 300 IN A 192.0.2.111 example.com. 300 IN A 192.0.2.222
Background
It’s uncommon to create TLS certificates with IPs as alternate names. So chances are that you‘ll need the actual domain name in order to fetch the page via HTTPS.
How to target a specific server?
Resolve the domain to a specific IP. Here are two ways of doing it, both timeout in two seconds.
curl
curl -so /dev/null --max-time 2 --head \ --write-out "%{http_code}" \ --resolve example.com:443:192.0.2.111 \ https://example.com
Or, with Node.js
import https from 'https' checkStatus('https://example.com', '192.0.2.111') .then(console.log) .catch(console.error) function checkStatus(url, ip) { return new Promise((resolve, reject) => { const ipFam = 4 const req = https.request(url, { method: 'HEAD', timeout: 2000, lookup(_, options, resolveDNS) { if (options.all) // Node 20+ resolveDNS(null, [{ address: ip, family: ipFam }]) else resolveDNS(null, ip, ipFam) } }, response => { resolve(response.statusCode) } ) req.on('error', reject) req.on('timeout', () => req.destroy()) req.end() }) }
Open Source
This health-check.mjs shows how to send an email on failure.
Other use
Bypassing a reverse proxy
For example, if Cloudflare® is proxying a server, you can see the original response sent by the origin server (you’ll need to tweak the method and response output).
Avoided alternatives
/etc/hosts or DNS zone file
Avoid changing the /etc/hosts file because it’s
system-wide, requires elevated privileges, and limits health checks
to be sequential. Also, it depends on nsswitch.conf.
The same goes for changing a zone file of a caching DNS
resolver like unbound.
Private Tunnels
Connecting via VPN or SSH wouldn’t be end-to-end health checks.
IP Address in the certificate’s SAN
Issuing certificates with an IP address in addition to the domain name it’s a needless expense if it’s only for health checking.
Skipping the hostname and certificate verification
For example, curl --insecure -L https://192.0.2.111