Skrypt powłoki, aby zablokować adres IP

8

Niektóre adresy IP otwierają tysiące połączeń mojego serwera. Mam serwer Ubuntu 14. Sprawdzam wszystkie połączenia za pomocą następującego polecenia:

netstat -an | grep tcp | awk '{print 5 $}' | cut -f 1 -d: | sortuj | uniq -c | sortuj -n

Następnie używam następującej reguły iptables, aby zablokować winowajcę.

iptables -I WEJŚCIE 1 -s xxxx -j DROP

Działa dobrze i blokuje adres IP. Nie mogę jednak pozostać online 24/7, aby monitorować serwer. Zastanawiałem się, czy jest jakiś skrypt Shell, którego mogę użyć, aby zrobić to automatycznie? Na przykład, jeśli adres IP otwiera w dowolnym momencie więcej niż X połączeń, powinien zostać automatycznie zbanowany zgodnie z powyższą regułą iptables.

użytkownik3404047
źródło
6
Czy sprawdziłeś, czy fail2ban spełnia twoje potrzeby?
John1024,
Przepraszam za moją ograniczoną wiedzę. Czy nie jest fail2ban dla uwierzytelnienia ssh? Nie jestem pewien, czy użyję go na porcie 80. Ponadto mój serwer jest serwerem czatu, więc użytkownik może próbować połączyć się / pingować wiele razy. W takim przypadku fail2ban wygeneruje wiele fałszywie dodatnich alarmów i zablokuje legalny ruch. Jakiekolwiek myśli?
user3404047,

Odpowiedzi:

10

Przede wszystkim nie wymyślaj koła na nowo. Właśnie po to denyhostsjest:

   DenyHosts  is a python program that automatically blocks ssh attacks by
   adding entries to /etc/hosts.deny.  DenyHosts will  also  inform  Linux
   administrators  about  offending  hosts,  attacked users and suspicious
   logins.

O ile mi wiadomo, denyhostsdotyczy tylko sshpołączeń, ale jest też coś, fail2banco dotyczy praktycznie wszystkiego:

   Fail2Ban consists of a client, server and configuration files to  limit
   brute force authentication attempts.

   The  server  program  fail2ban-server is responsible for monitoring log
   files and issuing ban/unban commands.  It  gets  configured  through  a
   simple  protocol  by fail2ban-client, which can also read configuration
   files and issue corresponding configuration commands to the server.

Oba są dostępne w repozytoriach:

sudo apt-get install denyhosts fail2ban

Możesz to również napisać, jeśli chcesz. Coś jak:

#!/usr/bin/env sh
netstat -an | 
    awk -vmax=100 '/tcp/{split($5,a,":"); if(a[1] > 0 && a[1]!="0.0.0.0"){c[a[1]]++}}
    END{for(ip in c){if(c[ip]>max){print ip}}}' |
        while read ip; do iptables -I INPUT 1 -s "$ip" -j DROP; done

awkBędzie wyodrębnić IP i policzyć je i wydrukować tylko te, które pojawiają się więcej niż maxrazy (tu -vmax=100, zmień je odpowiednio). Adresy IP są następnie podawane do pętli while, która uruchamia odpowiednią iptablesregułę.

Aby uruchomić to 24/7, zrobiłbym cronjob, który uruchamia polecenie powyżej co minutę. Dodaj tę linię do/etc/crontab

* * * * * root /path/to/script.sh
terdon
źródło
Dzięki terdon za dokładną odpowiedź. AFAIK, fail2ban służy do uwierzytelniania ssh. Wszystkie połączenia są otwierane na porcie 80. Zbadam, czy mogę użyć fail2ban na porcie 80. W przypadku skryptu niestandardowego, jak mogę uruchomić go 24/7 w tle? polecenie ekranowe? Lub zainstalować crona? BTW. Używam serwera jako serwera czatu, więc osoba może pingować wiele razy (lub otwierać wiele połączeń), więc mogę wybrać niestandardowy skrypt, który podałeś.
user3404047,
2
@ user3404047 możesz uruchomić jako cronjob, tak. Zobacz zaktualizowaną odpowiedź. Nie dotyczy fail2banto jednak tylko ssh. Działa również dobrze dla portu 80. Zobacz, na przykład tutaj , tutaj i tutaj .
terdon
1

Możliwą alternatywną opcją jest identyfikacja i rozwiązywanie problemów z adresami IP w ramach zestawu reguł iptables przy użyciu recentmodułu. Wyzwaniem dla tej metody jest domyślny limit liczby trafień wynoszący 20, więc trzeba albo odstąpić od wartości domyślnych, albo utworzyć liczniki przenoszenia na wyższym poziomie, aby osiągnąć wyższy punkt aktywacji liczby trafień.

Poniższy przykład pochodzi z mojego zestawu reguł iptables i zablokuje adres IP na nieco ponad 1 dzień, jeśli nawiąże 80 nowych połączeń TCP na porcie 80 w mniej niż 12 minut. Gdy znajdziesz się na liście złych facetów, każda próba połączenia spowoduje zresetowanie licznika 1-dniowego na 0. Ta metoda może osiągnąć maksymalnie 400 trafień, zanim będzie wymagane rozszerzenie do innego przenoszenia (i przetestowałem inny łańcuch przenoszenia). Pamiętaj, że opublikowany kod ma infrastrukturę, której można używać do blokowania przez długi czas tylko przy wielu wyzwalaczach o krótszym czasie. Obecnie mam ustawiony długi czas po pierwszym uruchomieniu.

#######################################################################
# USER DEFINED CHAIN SUBROUTINES:
#
# http-new-in4
#
# A NEW Connection on port 80 part 4.
#
# multiple hits on the banned list means you get a one day ban.
# (I re-load the firewall rule set often, so going longer makes
# little sense.)
#
# Custom tables must exist before being referenced, hence the order
# of these sub-toutines.
#
# Place holder routine, but tested. Logs if a day ban would have
# been activated.
#
$IPTABLES -N http-new-in4
#$IPTABLES -A http-new-in4 -m recent --set --name HTTP_BAN_DAY

$IPTABLES -A http-new-in4 -j LOG --log-prefix "DAY80:" --log-level info
$IPTABLES -A http-new-in4 -j DROP

#######################################################################
# USER DEFINED CHAIN SUBROUTINES:
#
# http-new-in3
#
# A NEW Connection on port 80 part 3.
#
# carry forward to the actual banned list:
# Increment this count. Leave the previous count.
#
# Custom tables must exist before being referenced, hence the order
# of these sub-toutines.
#
$IPTABLES -N http-new-in3
$IPTABLES -A http-new-in3 -m recent --remove --name HTTP_02
$IPTABLES -A http-new-in3 -m recent --update --hitcount 1 --seconds 86400 --name HTTP_BAN -j http-new-in4
$IPTABLES -A http-new-in3 -m recent --set --name HTTP_BAN

$IPTABLES -A http-new-in3 -j LOG --log-prefix "BAN80:" --log-level info
$IPTABLES -A http-new-in3 -j DROP

#######################################################################
# USER DEFINED CHAIN SUBROUTINES:
#
# http-new-in2
#
# A NEW Connection on port 80 part 2.
#
# carry forward from previous max new connections per unit time:
# Increment this count and clear the lesser significant count.
#
$IPTABLES -N http-new-in2
$IPTABLES -A http-new-in2 -m recent --remove --name HTTP_01
$IPTABLES -A http-new-in2 -m recent --update --hitcount 3 --seconds 720 --name HTTP_02 -j http-new-in3
$IPTABLES -A http-new-in2 -m recent --set --name HTTP_02

$IPTABLES -A http-new-in2 -j LOG --log-prefix "CARRY80:" --log-level info
$IPTABLES -A http-new-in2 -j ACCEPT

#######################################################################
# USER DEFINED CHAIN SUBROUTINES:
#
# http-new-in
#
# A NEW Connection on port 80:
#
$IPTABLES -N http-new-in

echo Allowing EXTERNAL access to the WWW server

# . check the static blacklist.
#
# http related
$IPTABLES -A http-new-in -i $EXTIF -s 5.248.83.0/24 -j DROP
... delete a bunch on entries ...
$IPTABLES -A http-new-in -i $EXTIF -s 195.211.152.0/22 -j DROP
$IPTABLES -A http-new-in -i $EXTIF -s 198.27.126.38 -j DROP

# . check the dynamic banned list
#
# The 1 Hour banned list (bumped to more than a day):
$IPTABLES -A http-new-in -m recent --update --seconds 90000 --name HTTP_BAN --rsource -j LOG --log-prefix "LIM80:" --log-level info
$IPTABLES -A http-new-in -m recent --update --seconds 90000 --name HTTP_BAN --rsource -j DROP

# A generic log entry. Usually only during degugging
#
#$IPTABLES -A http-new-in -j LOG --log-prefix "NEW80ALL:" --log-level info

# Dynamic Badguy List. Least significant hit counter.  Detect and DROP Bad IPs that do excessive connections to port 80.
#
$IPTABLES -A http-new-in -m recent --update --hitcount 20 --seconds 240 --name HTTP_01 -j http-new-in2
$IPTABLES -A http-new-in -m recent --set --name HTTP_01

$IPTABLES -A http-new-in -j LOG --log-prefix "NEW80:" --log-level info
$IPTABLES -A http-new-in -j ACCEPT

... a bunch of stuff not included here

# Allow any related traffic coming back to the server in.
#
#
$IPTABLES -A INPUT -i $EXTIF -s $UNIVERSE -d $EXTIP -m state --state ESTABLISHED,RELATED -j ACCEPT

... the above is needed before the below ...

# If required, go to NEW HTTP connection sub-routine
#
$IPTABLES -A INPUT -i $EXTIF -m state --state NEW -p tcp -s $UNIVERSE -d $EXTIP --dport 80 -j http-new-in
Doug Smythies
źródło