[FUG-BR] RES: Filtro L7
Patrick Tracanelli
eksffa em freebsdbrasil.com.br
Segunda Novembro 26 12:33:59 BRST 2007
Vou tentar resumir o ambiente que eu uso pra filtrar L7, aja que a
thread esta bem grande.
Instale via ports o snort_inline, e entao configure o snort_inline.conf
com algo proximo a isso (pode comecar com isso e depois customizar):
### Network variables
var HOME_NET [192.168.0.0/16,10.0.0.0/8,200.X.Y.0/22]
#var HOME_NET any
var HONEYNET any
var EXTERNAL_NET any
var SMTP_SERVERS any
var TELNET_SERVERS any
var HTTP_SERVERS any
var SQL_SERVERS any
var HTTP_PORTS 80
var SHELLCODE_PORTS !80
var ORACLE_PORTS 1521
var DNS_SERVERS any
var SSH_PORTS 22 2222 2022
#config checksum_mode: all
config ipfw_reinject_rule: 65500
var RULE_PATH /usr/local/share/snort_inline/rules
preprocessor flow: stats_interval 0 hash 2
output alert_fast: inline_fast
include /usr/local/share/snort_inline/classification.config
include /usr/local/share/snort_inline/reference.config
#include /usr/local/share/snort_inline/rules/classification.config
include $RULE_PATH/FBSDBR/patrick.rules
include $RULE_PATH/FBSDBR/patrick-p2p-drop.rules
include $RULE_PATH/p2p.rules
include $RULE_PATH/bleeding-p2p.rules
Na regra 65500 u tenho um "add count tag 30 all from any to any keep-state"
E logo abaixo faco queue (Wf2Q+) de tudo "tagged 30". Um pipe obviamente
também serve.
No comeco de tudo, faca um "skipto 65500 all from any to any tagged 30".
As dicas são:
- resuma seu firewall a regras antes da 65500, de forma que nada que nao
for desviado/reinjetado para 65500 jamais chegue nela (ou seja: "add
65499 deny all from any to any" pra ter a politica antes desse pool
final de regras. Desvie para a 65500 apenas pelo snort_inline - o .conf
acima ja esta configurado pra isso);
- desvie para o snort_inline o trafego desejado, NO MOMENTO que voce
jugar necessario: comece com "divert 8000 all from any to any" pra
testes, depois seja seletivo: "divert 8000 all from $minharede to any
out", "divert 8000 all from any to $minharede in"
- lembre-se que apos o desvio 2 coisas acontecem: se o snort_inline nao
classificar o pacote com as regras carregadas, o pacote volta pra
proxima regra do firewall, se bater com as regras, o pacote sera
reinjetado para a ipfw_reinject_rule configurada;
- porque usar "tag" e "count" e "keep-state"? porque voce nao quer
permitir, nem negar, nem ja jogar pro controle de banda, apenas aquele
pacote; voce quer com base no pacote conhecer a sessao toda
(keep-state), e taggear *todos* os pacotes da sessao, e depois manipula-los
Por ultimo, eleve o net.inet.ip.fw.dyn_udp_lifetime, eu uso-o em 300 sem
dó (sim, 5 minutos).
Agora algumas considerações:
- SANS Security recomenda que toda analise de payload nao seja feita
pelo firewall, e preferencialmente seja feita por aplicacoes de
userlevel pois se comprometidas nao desestabiliza o sistema (ao
contrario de analise me kernel);
- O custo de desviar pra uma aplicacao de userland com divert em relacao
ao processamento que seria feito se fosse em kernel, é de 2 syscall para
os pacotes nao classificados (praticamente todos) e 3 syscall para os
classificados; isso realmente gera impacto no seu ambiente?
- O custo de processamento do snort_inline, que atua de forma pró-ativa
(veja bem: snort convencional: passivo, snort com flexresp: responsivo,
snort com snortsam ou OSSEC evocando rotinas externas: resposta ativa,
snort_inline = pró-ativo pois se o snort não reinjetar, não volta pro
firewall e consequentemente não volta pra pilha IP) é no máximo 5%
superior ao snort atuando em modo passivo. Você não tem CPU suficiente
para o snort com meia duzia de rules seletivas?
Por último, algumas considerações adicionais:
- Impacto negativo: você está desviando um dado fluxo para o
snort_inline, isso quer dizer que se não tive nada ouvindo na porta 8000
protocolo div4, aquele fluxo vai pra /dev/null (ou seja, tudo para);
mas o snort_inline nunca morre sozinho; se mesmo assim você tem medo:
daemontools pra que te quero.
- Você pode anular o ponto negativo anterior trocando "divert" por "tee"
na regra de firewall. Nesse caso uma cópia vai para o snort_inline e
outra, do pacote, fica no firewall. Portanto voce vai querer repensar
seu firewall pra copia q fica nao cair num "allow" antes de cair no seu
controle de banda. Dica: skipto vai resolver.
- Funciona 100%? Não! Digamos, uns 70%. Porque? Porque tem alguns P2P
que detectamos via TCP mas o tráfego vai por UDP. Nesse caso precisaria
de um tipo de "keep-state" no firewall que mantesse a sessão apenas por
IP, sem se ligar em porta ou protocolo. Ai sim funcionaria
perfeitamente. Tai algo q mereceria ser investigado e feito no ipfw.
- Eu amenizei todas as situações onde os "30%" q nao funcionava era um
problema analisando com tcpdump os trafegos e criando minhas proprias
regras. Ai que mora outra vantagem: regras snort, nada mais facil de fazer.
Finalmente, consideracoes de experiencia propria:
- Nessa mauqina:
# dmesg | grep "CPU:\|memory"
CPU: Intel(R) Core(TM)2 CPU T7200 @ 2.00GHz (2010.15-MHz
686-class CPU)
real memory = 1072103424 (1022 MB)
avail memory = 1031237632 (983 MB)
Eu filtro 34Mbit/s, load avg dela nesse momento:
load averages: 0,98 1,23 1,22
Latencia maxima percebida com divert pro snort_inline, comparado com sem
o divert, foi de 83ms. Não é pouco. Mas para internet não é
significativo. Essa é a máxima, a latencia média é inferior a 20ms.
Ultima consideração: H323 não funciona!! Não descobri o porque, o pacote
é reinjetado numa boa, mas não passa nada H323 depois do divert. Ta
certo que H323 é um lixo, mas as vezes esse lixo na sua rede não pode
ser substituído por RTP. Foi o meu caso. A solução foi permitir o
tráfego H.323 pro meu gatekeeper antes do divert.
Bom, essa é a melhor abordagem que eu conheço, funcional, e a que eu uso
- portanto a que eu recomendo. Espero que lhes seja útil.
--
Patrick Tracanelli
FreeBSD Brasil LTDA.
Tel.: (31) 3516-0800
316601 em sip.freebsdbrasil.com.br
http://www.freebsdbrasil.com.br
"Long live Hanin Elias, Kim Deal!"
Mais detalhes sobre a lista de discussão freebsd