I'm trying to protect my applications from some bots that are either malfunctioning or trying to take my sites down (lots of requests from the same IPs in the logs).
Every time someone requests an expensive or security-related action, I save the name of that action, the IP, and the date. Then I check for some limits, eg: the action login.fail has a limit of 10 attempts every 10 minutes, and 20 per hour. If the limit is exceeded, I save the ban and allow no more actions from that IP (I simplified the description a bit).
This works well, but this could leave legitimate users out. For example, if lots of users are coming from the same VPN and share the same IP (even if the bots are not coming from that IP). And I don't want to create sites that hinder privacy (by banning VPNs) just to be safe from bots.
I can't check for headers like the User-Agent because those can be faked.
So what can I do? Is there a way around this? Anything else I can check other than the IP?