Faça com que seu script PHP grave os endereços IP incorretos em um arquivo de log. Em seguida, instale o Fail2Ban e configure-o para ler o seu arquivo de log.
Um dos nossos servidores está sendo atingido diariamente por um grande número de spam bots. Eles não são capazes de postar nenhum spam, mas ainda assim tentam e acabam retardando o servidor para usuários reais.
Para combater isso, eu tenho um script PHP em execução no site que detecta seus endereços IP. No entanto, quero que esse script adicione automaticamente esses endereços IP ao firewall (em vez de eu ter que fazer isso manualmente). Executando algo assim:
iptables -I INPUT -j DROP -s 123.123.123.123
No entanto, parece que os comandos iptables
só podem ser executados como root. Qualquer maneira de contornar isso?
Eu acho que eu poderia ter os comandos adicionados a um arquivo que root
é executado via cron, mas realmente não quero nenhum atraso entre o script php tomando a decisão de banir um IP e a proibição sendo adicionada.
Faça com que seu script PHP grave os endereços IP incorretos em um arquivo de log. Em seguida, instale o Fail2Ban e configure-o para ler o seu arquivo de log.
A maneira mais fácil seria, como você sugere, ter seu script gravando os IPs incorretos em um arquivo de log. Você pode então ter outro script em execução (como root) em um loop que lê o arquivo e envia o comando iptables
. Algo como:
#!/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
Você pode então executar este script como root ao iniciar, seja como um serviço ou criando este crontab para o root:
@reboot /path/to/banips.sh logfile.txt
Eu assumo que o atraso com o qual você está preocupado é o mínimo de um minuto do cron. Como o script será executado em um loop infinito, você não precisa executá-lo a cada minuto usando o cron e o atraso depende de você. Tal como está, o script irá ler o arquivo de log a cada segundo.
Como uma alternativa às respostas existentes e adicionando sshguard
(não tão bem conhecido por seu escopo, de longe, excede o que o nome sugere) para o mencionado Fail2Ban eu gostaria de sugerir a você sudo
.
O arquivo /etc/sudoers
pode ser configurado para controlar com segurança quem pode executar o que como quem e de qual máquina. Portanto, você pode escrever um pequeno wrapper como em a resposta de terdon e, em seguida, chown root:
e garantir que suas permissões sejam definidas . Jogue-o em uma pasta como /usr/sbin
e permita que ele seja executado como root
de qualquer conta de usuário em que seu script PHP seja executado. Certifique-se de que, se o seu script for executado no contexto do servidor da web e for chrooted, o script estará dentro do chroot. Tenha em mente que isso poderia ser usado para comprometer o chroot "jail" se o seu script estiver mal escrito. Uma linha de exemplo em /etc/sudoers
poderia ser:
www-data ALL= (root) NOPASSWD: /usr/sbin/yourscript.sh
que permite ao usuário www-data
executar /usr/sbin/yourscript.sh
como root
sem fornecer uma senha em todas as máquinas ( sudoers
pode ser central para todas as máquinas em uma rede, é por isso ...).
sudo
é considerado mais seguro do que definir o suid
em seu script, mas suponho que haja boas razões para usar essa alternativa, por exemplo, quando não há sudo
disponível.
Você também pode verificar esta resposta eu dei na irmã SE site askubuntu.com.
Um método muito simples ...
Eu escrevi um script php que escreve o ip indesejado em um arquivo de texto em cada linha (insira sempre que necessário)
$banlist = file_get_contents( '/var/www/banlist.txt' );
$remoteip = $_SERVER['REMOTE_ADDR'];
if( strpos( $banlist, $remoteip ) === false ){
file_put_contents( '/var/www/banlist.txt', $remoteip."\n", FILE_APPEND );
}
Então eu criei uma cadeia iptables personalizada e a chamei de " banlist " (chame como quiser) usando o comando ...
sudo iptables --new-chain banlist
Também instalando o iptables-persistent usando ...
sudo apt-get install iptables-persistent
Por fim, usando o comando ...
sudo crontab -e
Eu adicionei esta linha ao cronjob da raiz da seguinte forma para executar a cada 5 minutos (alterar o tempo que você gosta) que lê cada ip, adiciona-os à cadeia de iptables que criei com um destino DROP e limpa o arquivo de texto. ..
*/5 * * * * while read in; do sudo iptables -A banlist -s "$in" -j DROP; done < /var/www/banlist.txt && > /var/www/banlist.txt
Também adicionei esta linha para garantir que as regras sejam salvas a cada 5 minutos ...
*/5 * * * * iptables-save > /etc/iptables/rules.v4 && ip6tables-save > /etc/iptables/rules.v6
É isso! Doce e simples, teste-o adicionando um ip aleatório (ou ip's cada em uma nova linha) ao arquivo de texto e esperando que seu cronjob seja executado no intervalo escolhido ... Cuidado para não se proibir testando o script php da sua própria rede ...
Nota: Para limpar todos os ip's na iptables Chain você pode usar " sudo iptables -F banlist "