iptables - add rules not as root
Solution 1
Have your PHP script write the offending IP addresses to a log file. Next, install Fail2Ban and configure it to read your log file.
Solution 2
The easiest way would be, as you suggest, having your script write the offending IPs in a log file. You can then have another script running (as root) in a loop that reads the file and sends the iptables
command. Something like:
#!/bin/bash
while true
do
while read IP
do
## Check if this IP is already banned
if ! iptables -L INPUT -v -n | grep $IP >/dev/null
then
## If it is not banned, ban it
iptables -I INPUT -j DROP -s $IP
fi
done < $1
## Sleeping to avoid spamming, if even a one second
## delay is too slow for you(!) adjust as needed.
sleep 1
done
You can then have this script run as root on start up, either as a service or by creating this crontab for root:
@reboot /path/to/banips.sh logfile.txt
I assume the delay you are worried about is cron's one minute interval minimum. Since the script will run in an infinite loop, you don't need to run it every minute using cron and the delay is up to you. As it stands, the script will read the logfile every second.
Solution 3
As an alternative to the existing answers and adding sshguard
(not so well-named for its scope by far exceeds what the name suggests) to the mentioned Fail2Ban I would like to suggest to you sudo
.
The file /etc/sudoers
can be configured to control tightly who can run what as who and from which machine. Therefore you can write a little wrapper much like in terdon's answer and then chown root:
it and make sure its permissions are set tight. Throw it into a folder such as /usr/sbin
and allow it to be run as root
from whatever user account your PHP script runs as. Make sure that if your script runs in the context of the web server and it's chrooted that the script is inside the chroot. Keep in mind that this could be used to compromise the chroot "jail" if your script is badly written. An example line in /etc/sudoers
could be:
www-data ALL= (root) NOPASSWD: /usr/sbin/yourscript.sh
which allows user www-data
to run /usr/sbin/yourscript.sh
as root
without giving a password on all machines (sudoers
can be a central one for all machines in a network, that's why ...).
sudo
is considered safer than setting the suid
bit on your script, but I suppose there are good reasons for using this alternative, e.g. when no sudo
is available.
You can also check out this answer I gave over at the sister SE site askubuntu.com.
Related videos on Youtube
Ross McLellan
Updated on September 18, 2022Comments
-
Ross McLellan almost 2 years
One of our servers is being hit daily by a large number of spam bots. They're not able to post any spam, but they still try and end up slowing down the server for real users.
To counter this, I have a PHP script running on the site which detects their IP addresses. However, I want this script to automatically add these IP addresses to the firewall (rather than me having to do that manually). Running something like this:
iptables -I INPUT -j DROP -s 123.123.123.123
However, it looks like
iptables
commands can only be run as root. Any way around this? I guess I could have the commands added to a file whichroot
runs via cron, but don't really want any delay between the php script making the decision to ban an IP and the ban being added.-
terdon over 11 yearsWhy don't you run the php script as root?
-
Ross McLellan over 11 yearsThe script is being run at the end of page load, by the web server. It does various logic to work out if the page load was by a spam bot or not.
-
user over 11 yearsMake a suid root shell script which calls out to iptables? Just make sure to sanitize your inputs very carefully. Something like
s/[^0-9.:]//
on the IP address and not accepting anything else as input. I'd tighten it down even further in such a scenario.
-
-
0xC0000022L over 11 yearsThere are canned and proven solutions for the problem at hand, why reinvent the wheel?
-
terdon over 11 years@0xC0000022L because in this case the wheel is simple to invent, because software recommendations are considered off topic and this is a solution that requires no third party software and because personally I prefer having small scripts doing things since I can control their behavior perfectly.
-
0xC0000022L over 11 yearsfair enough, even mentioned your script in my own answer. Suppose you have a point :)
-
Ross McLellan over 11 yearsThanks. Am giving this method a try for now. I do prefer to not rely on 3rd party scripts when a simple custom script will do the job, but fail2ban seems to have quite a lot of useful capabilities, like unbanning after a certain period of time. Was bit of a pain to get setup and seems to lack documentation for some bits, but seems to be running as desired now. Will just see how it copes the next time an attack hits.
-
Ross McLellan over 11 yearsThank you @terdon, I hadn't realised a cron job could run like that in a while loop. I'm trying fail2ban at the moment, but will probably try this method out at some point too, even if just to see how it works.
-
Ross McLellan over 11 yearsThanks. I was slightly reluctant to let my web server user run all iptables commands, I knew sudoers could limit the commands you can run, but didn't realise I would be able to limit it to a specific .sh file (one which runs the specific iptables command).