What is the most efficient way to block access to 8-10k IP addresses?
My server runs EngineX on Debian.
If possible, I would like to show all of the addresses an Internal Server Error (500).
The IP's are scattered and not under any particular subsets.
if the addresses are grouped in one or few continuous subnets [ eg few /24s ] - i would create simple prerouting rule that would DNAT all traffic on port 80 from them to something listening on port 81 [ eg vhost from nginx ] that would just serve error page:
if this is 8-10k unique ips scattered 'all around'... it'll be interesting ;-] - i would still go with above scenario but for matching i would use ipset. something like this:
Might take a look at: http://www.hipac.org/ It handles large numbers of rules quite well. If there is a pattern to the IPs you are trying to block, you could use the MATCH rule. pQd's prerouting rule would work well with nf-hipac which uses a hash table to store the rules and is considerably quicker than the default iptables lookups.
You could write the ruleset into deny lines in your location block. To make it simple, you could include a file that included your deny blocks and reload the config on an hourly basis. Since it would be within the nginx config file, it shouldn't impact performance too much.
If you have a list of these addresses in a file, you can try the following in Nginx config:
1 Define an IP group using geo directive (inside http block):
It means that variable $block will be set to 0 by default.
2 Prepare a blacklist file to look like this:
That is, set variable $block to 1 for these addresses.
3 Inside the `location' block, check this variable and report 500 error if it's 1:
PS: The efficiency of this solution is arguable, since the connections from banned IPs are accept()ed and passed to the web server. However, if this tiny overhead is not critical for your host, I would rather do it with Nginx, not with iptables.