Однажды отсортировав лог веб-сервера увидел over 1k запросов вида:

642 187.45.214.10 "GET /w00tw00t.at.ISC.SANS.DFind:) HTTP/1.1" 400 349 "-" "-"
342 189.126.109.215 "GET /w00tw00t.at.ISC.SANS.DFind:) HTTP/1.1" 400 349 "-" "-"
80 187.45.224.218 "GET /w00tw00t.at.ISC.SANS.DFind:) HTTP/1.1" 400 349 "-" "-"

в гугле говорят что это веб-сканер уязвимостей, который сканирует все сервера с открытым 80 портом, хотя, едва ли это поделие можно назвать сканером, он то и делает только один и тот же GET запрос к серверу.
Но в логи веб-сервера всё же флудит, поэтому я подумал, что лучше всего будет дропать его с помощью iptables.

I. дропаем GET запросы w00tw00t.at.ISC.SANS.DFind:)
Для этого надо добавить следующее правило:

iptables -I INPUT -d 178.63.227.44 -p tcp --dport 80 -m string --to 70 --algo bm --string 'GET /w00tw00t.at.ISC.SANS.' -j DROP

* где 178.63.227.44 — ip вашего сервера

Теперь эти запросы будут блокироваться и в логах веб-сервера не будет флуда.

Это можно легко проверить, попробовав зайти на один из ваших хостов в браузере с таким запросом:

http://ваш.домен/w00tw00t.at.ISC.SANS.DFind:)

Вроде бы всё.. ааа нет (=

II. логирование в iptables

Захотелось логировать ip таких запросов в iptables, для статистики или just for fun.

чтобы логировать нужно добавить следущее правило:

iptables -I INPUT -d 178.63.227.44 -p tcp --dport 80 -m string --to 70 --algo bm --string 'GET /w00tw00t.at.ISC.SANS.' -j LOG --log-level debug --log-prefix "#w00tw00t**"

Правило логирования должно стоять выше/первее правила блокировки запросов «w00tw00t.at.ISC.SANS», иначе в лог ничего не упадёт.

Теперь история таких запросов будет складываться в /var/log/debug ..хм, а также в /var/log/syslog & /var/log/messages & /var/log/kern.log

Как-то не камильфо, да?

Чтобы iptables скидывался в отдельный лог нужно настроить syslog и изменить правило логирования в iptables.

1. меняем правило логирования в iptables

iptables -I INPUT -d 178.63.227.44 -p tcp --dport 80 -m string --to 70 --algo bm --string 'GET /w00tw00t.at.ISC.SANS.' -j LOG --log-level 4 --log-prefix "#w00tw00t "

* где 178.63.227.44 — ip вашего сервера
* —log-level 4 — уровень важности сообщений warning в syslog

2. нужно добавить следущую строку в /etc/syslog.conf

kern.warning /var/log/iptables.log

перезапускаем syslog от рута:

root@ilab:~$ /etc/init.d/sysklogd restart
 * Restarting system log daemon...                             [ OK ]

теперь лог iptables будет скидываться в /var/log/iptables.log

Dec 22 16:34:32 ilab kernel: #w00tw00t IN=eth0 OUT= MAC=00:16:3e:c2:cd:a5:0a:c4:93:62:b6:09:08:00 SRC=62.141.46.80 DST=178.63.227.44 LEN=86 TOS=0x00 PREC=0x00 TTL=122 ID=27853 DF PROTO=TCP SPT=65180 DPT=80 WINDOW=64240 RES=0x00 ACK PSH URGP=0
Dec 22 16:34:37 ilab kernel: #w00tw00t IN=eth0 OUT= MAC=00:16:3e:c2:cd:a5:0a:c4:93:62:b6:09:08:00 SRC=62.141.46.80 DST=178.63.227.44 LEN=86 TOS=0x00 PREC=0x00 TTL=122 ID=32669 DF PROTO=TCP SPT=65180 DPT=80 WINDOW=64240 RES=0x00 ACK PSH FIN URGP=0
Dec 22 18:11:38 ilab kernel: #w00tw00t IN=eth0 OUT= MAC=00:16:3e:c2:cd:a5:0a:c4:93:62:b6:09:08:00 SRC=69.59.188.212 DST=178.63.227.44 LEN=86 TOS=0x00 PREC=0x00 TTL=110 ID=23760 DF PROTO=TCP SPT=1107 DPT=80 WINDOW=65535 RES=0x00 ACK PSH URGP=0
Dec 22 18:11:47 ilab kernel: #w00tw00t IN=eth0 OUT= MAC=00:16:3e:c2:cd:a5:0a:c4:93:62:b6:09:08:00 SRC=69.59.188.212 DST=178.63.227.44 LEN=86 TOS=0x00 PREC=0x00 TTL=110 ID=31969 DF PROTO=TCP SPT=1107 DPT=80 WINDOW=65535 RES=0x00 ACK PSH FIN URGP=0

3. Не смотря на то, что kern.warning вывели в отдельный лог, в /var/log/syslog & /var/log/messages & /var/log/kern.log всё равно будет параллельно логироваться iptables.

Это я исправил следующим образом в /etc/syslog.conf, строки:

*.*;auth,authpriv.none      -/var/log/syslog

kern.*              -/var/log/kern.log

*.=info;*.=notice;*.=warning;
auth,authpriv.none;
cron,daemon.none;
mail,news.none      -/var/log/messages

изменил на:

*.*;kern.!=warning;auth,authpriv.none       -/var/log/syslog

kern.*;kern.!=warning;              -/var/log/kern.log

*.=info;*.=notice;*.=warning;kern.!=warning;
auth,authpriv.none;
cron,daemon.none;
mail,news.none      -/var/log/messages

опять перезапускаем syslog от рута:

/etc/init.d/sysklogd restart

Всё, теперь лог с нашего правила в iptables будет скидываться только в /var/log/iptables.log

Фактически мы все сообщения от ядра уровня warning перенаправили в /var/log/iptables.log
Но при нормальном ходе дел кроме iptables туда ничего попадать не будет.
При необходимости можно повысить/изменить уровень важности с warning на другой, более удобный вам.

Если вдруг пакеты с запросами w00tw00t.at.ISC.SAN дропаются, но логирования нет, то следует проверить порядок правил в iptables:

root@ilab:~$ iptables -L -n --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination
1    LOG        tcp  --  0.0.0.0/0            178.63.227.44       tcp dpt:80 STRING match "GET /w00tw00t.at.ISC.SANS." ALGO name bm TO 70 LOG flags 0 level 4 prefix `#w00tw00t '
2    DROP       tcp  --  0.0.0.0/0            178.63.227.44       tcp dpt:80 STRING match "GET /w00tw00t.at.ISC.SANS." ALGO name bm TO 70
3    ACCEPT     all  --  127.0.0.1            0.0.0.0/0
...

мы видим, что правило логирования идёт первее правила блокировки, как и должно быть.

III. ограничение и сортировка лога iptables

Также наверно будет актуально выставить лимит логирования, особенно если на сервере сильно ограничено дисковое пространство, это можно сделать так:

iptables -I INPUT -d 178.63.227.44 -p tcp --dport 80 -m string --to 70 --algo bm --string 'GET /w00tw00t.at.ISC.SANS.' -m limit --limit 5/m --limit-burst 7 -j LOG --log-level 4 --log-prefix "#w00tw00t "

где:

-m limit --limit 5/m

Максимальная средняя частота совпадений/пакетов в минуту, которые запишутся в лог.

--limit-burst 7

Максимальное число совпадений/пакетов, при котором условие ещё считается выполненным.
Это число увеличивается на единицу каждый раз когда условие выполняется.
По истечению интервала —limit 5/m значение —limit-burst уменьшается на единицу.

IV. отлючаем ротацию syslog’ом файла /var/log/iptables.log

По умолчанию syslog будет ротировать наш iptables.log раз в неделю, возможно вас это не устроит, как и меня.
За ротацию отвечают несколько скриптов: /etc/cron.daily/sysklogd и /etc/cron.weekly/sysklogd
Открываем /etc/cron.weekly/sysklogd и находим строки:

logs=$(syslogd-listfiles --weekly)

ага, вот и список файлов, которые будут ротироваться:

root@ilab:~$ syslogd-listfiles --weekly
/var/log/mail.warn
/var/log/user.log
/var/log/daemon.log
/var/log/messages
/var/log/debug
/var/log/auth.log
/var/log/mail.err
/var/log/iptables.log
/var/log/mail.log
/var/log/kern.log
/var/log/lpr.log
/var/log/mail.info

ну что, традиционно grep?

syslogd-listfiles --weekly | grep -v -i 'iptables'

хотя.. постойте:

root@ilab:~$ syslogd-listfiles -h
Usage: syslogd-listfiles <options>
Options: -f file        specifies another syslog.conf file
         -a | --all     list all files (including news)
         --auth         list all files containing auth.<some prio>
         --ignore-size  don't rotate files which got too large
         --large nnn    define what is large in bytes (default: 1MB)
         --news         include news logfiles, too
         -w | --weekly  use weekly pattern instead of daily
         -s pattern     skip files matching pattern

ага, как видем есть специальынй ключ «-s», поэтому будет правильнее воспользоваться именно им:

root@ilab:~$ syslogd-listfiles --weekly -s "iptables"
/var/log/mail.warn
/var/log/user.log
/var/log/daemon.log
/var/log/messages
/var/log/debug
/var/log/auth.log
/var/log/mail.err
/var/log/mail.log
/var/log/kern.log
/var/log/lpr.log
/var/log/mail.info

Итак, заменяем в /etc/cron.weekly/sysklogd

logs=$(syslogd-listfiles --weekly)

на

logs=$(syslogd-listfiles --weekly -s "iptables")

сохраняем файл, всё, теперь sysklogd не будет ротировать наш iptables.log

Как видим ежедневный /etc/cron.daily/sysklogd я не изменял, так как он не трогал мой iptables.log, но если что мысль думаю ясна.

—-
Ну и напоследок, смотрим результаты в /var/log/iptables.log:

# смотрим последнюю запись в логе
root@ilab:~$ tail -1 /var/log/iptables.log
Dec 22 21:27:31 ilab kernel: #w00tw00t IN=eth0 OUT= MAC=00:16:3e:c2:cd:a5:0a:c4:93:62:b6:09:08:00 SRC=69.162.104.136 DST=178.63.227.44 LEN=86 TOS=0x00 PREC=0x00 TTL=108 ID=1024 DF PROTO=TCP SPT=1316 DPT=80 WINDOW=65535 RES=0x00 ACK PSH FIN URGP=0
#
# выводим список всех ip w00tw00t и сортируем по кол-ву совпадений
root@ilab:~$ grep "#w00tw00t" /var/log/iptables.log | sed 's/  / //g' | cut -f 10 -d " " | sort | uniq -c| sort -r -n | sed -e s/SRC=//g
     18 67.212.82.3
     14 69.162.104.136
     12 62.141.46.80
      9 94.136.45.55

# или так с использованием awk
root@ilab:~$ grep "#w00tw00t" /var/log/iptables.log |awk '{print $10}' | sort | uniq -c| sort -r -n | sed -e s/SRC=//g
     18 67.212.82.3
     14 69.162.104.136
     12 62.141.46.80
      9 94.136.45.55

#тестировалось на Ubuntu 9.04 Jaunty