How to Set Up Monitoring When Your Host Blocks Ping and ICMP
To monitor a website when the host blocks ping, stop treating ICMP as your health signal and check the thing your visitors actually use: a TCP connection and an HTTP response. A host that silently drops ICMP echo requests is usually still answering on port 443, and that answer is a far better uptime signal than a reply from the kernel's network stack.
This matters because ICMP is easy to block and easy to deprioritise. Many providers filter it at the edge, rate limit it, or drop it under load, so a failed ping tells you almost nothing about whether your site is serving pages. Worse, some hosts answer pings from their routers while the web server behind them is down, which gives you the opposite problem: a green check on a broken site. Monitoring website availability when a host blocks ping means moving your probes up the stack.
Why ICMP gets dropped, and why that is fine
ICMP echo is a separate protocol from TCP. It has no ports, no handshake, and no notion of a web server. A firewall rule like iptables -A INPUT -p icmp --icmp-type echo-request -j DROP kills it without touching anything your users do. Some networks also filter it to reduce scan noise or because of policy. None of that affects a listener on port 443.
The practical consequence is that any monitor built around ping or a raw ICMP socket will report your host as down while it is happily serving traffic. The fix is to probe a port and, ideally, an application response. A TCP connect to the right port proves something is listening. An HTTP request proves the application is answering and, if you check the status code and body, that it is answering correctly.
Probe the port, not the host
Start with a TCP check. It completes the three way handshake, so a success means a process accepted the connection. From a shell you can do this with nc or curl. The -z flag tells netcat to scan without sending data, and -w sets a timeout so a blackholed packet does not hang your check.
$ nc -zv -w 5 example.com 443
Connection to example.com 443 port [tcp/https] succeeded!
If that succeeds but a browser fails, the problem is above the transport layer, which is exactly the kind of thing a ping monitor would never have caught. If it fails with a timeout rather than a refusal, you are probably looking at a firewall dropping packets rather than a closed port, and that distinction is worth logging.
For anything you will run on a schedule, use curl and inspect both the exit code and the HTTP status. The -o /dev/null discards the body, -s silences progress, -S still shows errors, and -w prints the fields you care about.
$ curl -sS -o /dev/null -w '%{http_code} %{time_connect} %{time_total}\n' \
--max-time 10 https://example.com/health
200 0.041 0.187
A 200 with a sensible connect time is a healthy result. A 000 means curl never got a response at all, which is your down signal. A 5xx means the server is up but the application is unhappy, and you should treat those differently in your alerting so you do not page someone for a transient backend error at the same severity as a total outage.
Check the header, not just the status code
Status codes lie in both directions. A captive portal, a CDN error page, or a misconfigured proxy can return 200 with content that is not your site. If you control the application, add a small endpoint that returns a known string and check for it. If you do not, check a response header you know your stack emits, such as Server or a cache header, and confirm it is present.
$ curl -sSI --max-time 10 https://example.com/ | head -n 5
HTTP/2 200
server: nginx
content-type: text/html; charset=utf-8
cache-control: no-cache
Matching on a header is brittle if your host or CDN rewrites it, so prefer a body check against a string you control. The point is to make the probe assert something about the response rather than merely that bytes arrived.
Configure your monitor to avoid false alarms
Most false alarms come from three sources: timeouts that are too tight, a single vantage point, and alerting on one failed check. Set your timeout above the worst normal latency you have measured, not at the average. Require several consecutive failures before alerting, and probe from more than one network if you can, because a route problem between one monitor and your host is not the same as your site being down.
If you run your own checks, a short script with a retry loop is enough. The shape below retries a few times and only reports failure when every attempt fails, which removes most single packet loss noise.
#!/bin/sh
for i in 1 2 3; do
code=$(curl -sS -o /dev/null -w '%{http_code}' --max-time 10 https://example.com/health)
[ "$code" = "200" ] && exit 0
sleep 5
done
echo "down: last status $code" >&2
exit 1
Run that from cron or a timer, and have it exit non zero so your existing alerting picks it up. Keep the check interval and the retry window in mind together: a check every minute with three retries and a five second gap means you will not alert until roughly three minutes of failure, which is usually the right trade for a site that is not handling payments.
What to do next
Pick one URL that exercises your application, not just your web server, and point a TCP or HTTP check at it with a timeout you have measured rather than guessed. Run it from two locations if you can, require more than one failure before alerting, and log the status code and connect time on every check so you can tell a network problem from an application problem after the fact. Then leave ICMP out of it entirely, because a host that drops ping has told you nothing about whether your site is up.
