Nos meus arquivos de log do Apache, eu encontro muitas entradas que contêm "GET /w00tw00t.at.ISC.SANS.DFind:) HTTP/1.1" 400
ou lixo similar. Eles vêm de conexões não-RFC2616 (HTTP / 1.1 sem nome de host).
Não quero que meus arquivos de log sejam spamados com essas mensagens. Então eu quero rejeitar essas conexões usando o iptables. Portanto, eu quero procurar pela string "HTTP / 1.1" seguida por dois CR / LFs subsequentes (CR / LF / CR / LF) (o que dá no total a string hexagonal 485454502f312e310d0a0d0a
) na carga útil dos pacotes.
Mas é estúpido desperdiçar ciclos de CPU procurando por essa string em todos os pacotes TPC quando eu sei que está no primeiro pacote. Ele até estaria errado porque "HTTP / 1.1" seguido por dois CR / LFs subseqüentes pode ser uma parte legal da transmissão dentro da carga útil de solicitações http.
Aqui, o link é uma solução para esse problema, mas não entendo a parte que identifica o primeiro pacote de uma conexão tcp estabelecida.
O que não entendo é por que todos os 3 pacotes do TCP-Handshake inicial (SYN, ACK + SYN, ACK) podem ser vistos na cadeia INPUT ou em uma cadeia que só pode ser alcançada a partir do INPUT. Até onde entendi o iptables e suas cadeias, o segundo pacote (ACK + SYN) nunca passa por INPUT. Eu acho que passa OUTPUT porque é eu (ou seja, o servidor) que está enviando.
Este é o script do spamcleaner.org, eu mudei apenas alguns comentários na primeira parte do script, mas deixei todos os comandos inalterados:
#!/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
E há uma segunda coisa que não entendo:
A última regra está procurando pela cadeia hexagonal em um pacote que possui seus conjuntos de sinalizadores PSH e ACK. Mas como posso ter certeza de que o PSH está definido para o meu pacote? Não tenho certeza, mas acho que é possível e legal enviar pacotes TCP que tenham sua bandeira PSH desativada.
EDITAR:
Há uma terceira pergunta: o que acontece se o servidor receber dois usuários usavam mais solicitações HTTP sobre TCP dos mesmos endereços IP ao mesmo tempo (cada solicitação com seu próprio número de porta)?