The story of how we (eventually) found our missing firewall rule
I recently shared a war story about how we had load problems on a new web server but not an older one because of a missing firewall rule. In a comment, Aristotle Pagaltzis asked how we'd realized that we had a missing firewall rule. This is a good question, because the sequence of events involves a certain amount of luck and coincidence. So here's that story, which may be a useful example of system administration in action in practice (ie, it's kind of messy).
When we first deployed our new web server for a highly in-demand data set, Apache wasn't configured for very many concurrent connections and was immediately overloaded with HTTP requests, but we mostly shrugged. Because this upset our monitoring system and I did want to monitor the web server at least a bit, I turned up the Apache connection limits to an absurd number. This was mostly enough, and the web server's outgoing bandwidth jumped up to 1G wire rates, which at the time I thought was fine. Soon after that, an apparently unrelated machine began to have NFS performance problems, and after some work we realized that it was on the same 1G switch as the highly active web server and its network traffic was getting crowded out.
In a rush to limit the web server's bandwidth usage so the much more
important other machine would stop having NFS problems, I hastily
added some tc based bandwidth limits by hand, and by this I mean that I typed
'tc'
commands in a shell session. A few days later, we worked out how to
make mod_qos based limits work in Apache itself. One of the limits we imposed and
fiddled with was a limit on the number of concurrent connections from
a single IP address, which had a much bigger effect than I expected.
The Apache error log showed that some IPs were hitting it quite a lot,
and our metrics system said the number of concurrent Apache requests
dropped dramatically afterward (to about half what they'd been
before).
After the dust settled from the immediate crisis, we needed to decide
if we were going to make the tc-based limits a
permanent part of the machine's configuration (making it the first
machine officially using tc in production, and we'd have to
write something to install them on system startup) or if we'd rely
entirely on mod_qos. While considering the tradeoffs involved, I
remembered that we had a general purpose 'block brute force things'
system on our perimeter firewall, so we
should probably make it apply to HTTP and HTTPS requests to our new
web server for extra insurance. Immediately after I did this, our
metrics system showed another major drop in concurrent Apache
connections (shrinking by half again).
(The perimeter firewall's system has a list of IP addresses that it applies the HTTP and HTTPS limits to, and the new web server, with a new IP address, wasn't in the list (until I added it).)
That major drop from the firewall rule was what sparked my realization
of what was different that would explain why our main web server
mostly hadn't been overwhelmed by this traffic, because that was the only thing out of
all of our rate limiting changes that our main web server had in
place. Our main web server had no tc limits and we'd turned off
mod_qos several years ago and never revisited that change.
PS: We decided to keep both the Apache mod_qos limits and the
tc based limits, partly for extra insurance. We've decided that
we really don't want this particular web server to run over the
bandwidth limits, so having two mechanisms that limits it means they'd
both have to fail.
(We're not yet worried enough to look into FreeBSD PF's features for bandwidth limits, partly because if we got it wrong on the firewall, we could affect a lot more than this machine.)