В моих файлах журнала Apache я нахожу много записей, содержащих "GET /w00tw00t.at.ISC.SANS.DFind:) HTTP/1.1" 400
или подобная хрень. Они поступают из не-RFC2616-соединений (HTTP / 1.1 без имени хоста).
Я не хочу, чтобы мои файлы журналов засыпались этими сообщениями. Поэтому я хочу отклонить эти подключения с помощью iptables. Поэтому я хочу найти строку «HTTP / 1.1», за которой следуют два последующих CR / LF (CR / LF / CR / LF) (что в сумме дает шестнадцатеричную строку 485454502f312e310d0a0d0a
) в полезной нагрузке пакетов.
Но глупо тратить циклы процессора на поиск этой строки во всех TPC-пакетах, когда я знаю, что она находится в самом первом пакете. Это было бы даже неправильно, потому что «HTTP / 1.1», за которым следуют два последующих CR / LF, может быть законной частью передачи внутри полезной нагрузки http-запросов.
Вот http://spamcleaner.org/en/misc/w00tw00t.html является решением этой проблемы, но я не понимаю, какая часть идентифицирует первый пакет установленного tcp-соединения.
Я не понимаю, почему все 3 пакета первоначального TCP-рукопожатия (SYN, ACK + SYN, ACK) можно увидеть в INPUT-Chain или в цепочке, доступной только из INPUT. Насколько я понял iptables и его цепочки, второй пакет (ACK + SYN) никогда не проходит через INPUT. Я думаю, что он проходит OUTPUT, потому что это я (то есть сервер), который его отправляет.
Это форма скрипта spamcleaner.org, я изменил только некоторые комментарии в первой части скрипта, но все команды оставил без изменений:
#!/bin/bash
# allow loopback
iptables -A INPUT -i lo -j ACCEPT
# DROP any IP that is in the blacklist "w00tlist" and set the
# blacklist-timeout to 6 hour
iptables -A INPUT -p tcp -m recent --name w00tlist --update --seconds 21600 -j DROP
# create the chain "w00tchain"
iptables -N w00tchain
# this chain will add the IP to the blacklist "w00tlist"
# and will reset the connection:
iptables -A w00tchain -m recent --set --name w00tlist -p tcp \
-j REJECT --reject-with tcp-reset
# create another chain named "w00t". It's purpose is to identify the first packet
# of an newly established tcp-connection and to search for a string in it:
iptables -N w00t
# redirect all incoming (no outgoing!) TCP packets to the chain "w00t":
iptables -A INPUT -p tcp -j w00t
# all remaining rules are part of the chain "w00t"
#---------------------------------------------------------------
# all following comments in lowercase are unchanged from spamcleaner.org
# COMMENTS IN UPPERCASE ARE FROM ME
#---------------------------------------------------------------
# look for the SYN packet and create the list :
iptables -A w00t -m recent -p tcp --syn --dport 80 --set
# look for the SYN,ACK packet and update the list :
iptables -A w00t -m recent -p tcp --tcp-flags PSH,SYN,ACK SYN,ACK --sport 80 --update
#---------------------------------------------------------------------------------
# THIS IS WHAT I DON'T UNDERSTAND:
# THE CHAIN w00t CAN ONLY BE REACHED FROM THE CHAIN INPUT. SO WE ARE DEALING HERE
# WITH PACKETS THAT THE CLIENT IS SENDING AND THAT THE SERVER IS RECEIVING. BUT IN
# STEP 2 OF TCP-HANDSHAKE ITS THE SERVER WHO IS SENDING AND THE CLIENT WHO IS
# RECEIVING. SO THE PACKET WITH SYN AND ACK SET AND WITH sport 80 GOES THROUGH THE
# CHAIN "OUTPUT", NOT "INPUT". SO HOW CAN IT BE DETECTED IN CHAIN w00t?
#---------------------------------------------------------------------------------
# look for the ACK packet and update the list :
iptables -A w00t -m recent -p tcp --tcp-flags PSH,SYN,ACK ACK --dport 80 --update
# look for the hexadecimal string in the first PSH+ACK.
# If found, redirect to w00tchain in order to blacklist the IP and
# to close the connection.
# Delete our list, we do not want to filter any further packet from that connection :
iptables -A w00t -m recent -p tcp --tcp-flags PSH,ACK PSH,ACK --dport 80 --remove \
-m string --to 80 --algo bm --hex-string '|485454502f312e310d0a0d0a|' -j w00tchain
И есть вторая вещь, которую я не понимаю:
Последнее правило ищет шестнадцатеричную строку в пакете, для которого установлены флаги PSH и ACK. Но как я могу быть уверен, что для моего пакета установлен PSH? Я не уверен, но думаю, что можно и законно отправлять TCP-пакеты, у которых не установлен PSH-флаг.
РЕДАКТИРОВАТЬ: есть третий вопрос: что, если сервер получает два дополнительных HTTP-запроса по TCP с одних и тех же IP-адресов одновременно (каждый запрос с собственным номером порта)?
Забудьте о IPTables. Вы можете просто использовать mod_security с действием nolog. Примерно так (непроверено):
SecRule REQUEST_URI "^/w00tw00t\.at\.ISC\.SANS\.DFind" phase:1,nolog,deny,id:1000
Или вы можете создать фиктивный виртуальный хост с отдельными журналами, который просто отклоняет все запросы и настраивает его как первый. Клиенты, которые не предоставляют имя хоста или предоставляют неизвестное имя хоста, всегда заканчиваются на этом.