[Anterior: Tabelas] [Conteúdo] [Próximo: Tradução do Endereço de Rede (NAT)]
Regras de filtragem especificam o critério em que o pacote deve se enquadrar e a ação resultante, que pode ser bloqueio ou liberação, tomada quando o pacote casa com a regra. As regras de filtragem são avaliadas em sequência da primeira a última. A não ser que o pacote encontre um regra contendo a palavra-chave quick, o mesmo será avaliado contra todas as regras de filtragem antes da ação final ser tomada. A última regra a casar é a "vencedora" e dita qual ação tomar. Existe um pass all implícito no início das regras de filtragem, que significa que caso o pacote não case com nenhuma regra a ação resultante será pass.
ação [direção] [log] [quick] [on interface] [af] [proto protocolo] \
[from src_addr [port src_port]] [to dst_addr [port dst_port]] \
[flags tcp_flags] [state]
Para criar uma política de filtragem negar por padrão, as primeiras duas regras de filtragem devem ser:
block in all
block out all
Isto irá bloquear todo o tráfego em todas interfaces em qualquer direção, de qualquer lugar para qualquer lugar.
Alguns exemplos:
# Autoriza passagem de tráfego chegando em dc0 vindo da rede local 192.168.0.0/24,
# e indo para a máquina OpenBSD com endereço IP 192.168.0.1. Também permite
# tráfego de retorno saindo via dc0.
pass in on dc0 from 192.168.0.0/24 to 192.168.0.1
pass out on dc0 from 192.168.0.1 to 192.168.0.0/24
# Permite tráfego TCP chegando em fxp0 e indo para o servidor web
# rodando na máquina OpenBSD. O nome da interface, fxp0, é usado como
# endereço de destino, para que apenas pacotes destinados à
# máquina OpenBSD casem com a regra.
pass in on fxp0 proto tcp from any to fxp0 port www
Errado:
block in on fxp0 proto tcp from any to any port ssh
pass in all
Neste caso, a linha block será avaliada, mas jamais terá efeito algum, pois é seguida de uma linha que permite a passagem de tudo.
Melhor:
block in quick on fxp0 proto tcp from any to any port ssh
pass in all
Essas regras são avaliadas de maneira ligeiramente diferente. Caso a linha block case com a regra, devido o uso da opção quick, o pacote será bloqueado, e o restante das regras serão ignoradas.
Manter informações de estado das conexões traz muitas vantagens incluindo simplicidade na configuração das regras e melhor performance na filtragem de pacotes. O PF pode criar entradas na tabela de estado para pacotes indo em qualquer direção, o que significa que regras de filtragem que autorizam o tráfego de retorno não precisam ser escritas. E, como pacotes que possuem entradas na tabela de estado não são avaliados pelas regras, o tempo que o PF gasta no processamento destes pode ser drasticamente reduzido.
Quando uma regra cria estados, o primeiro pacote que casa com a regra cria um "estado" entre transmissor e receptor. Agora, não somente os pacotes do transmissor para o receptor combinam com a entrada na tabela e passam direto pelas regras, como também as respostas do receptor.
A partir do OpenBSD 4.1, todas as regras de filtragem automaticamente criam um estado quando um pacote combinar com a regra. Nas versões anteriores do OpenBSD a regra de filtragem precisava explicitamente usar a opção keep state.
Exemplo usando OpenBSD 4.1 e posteriores:
pass out on fxp0 proto tcp from any to any
Exemplo ussando OpenBSD 4.0 e anteriores:
pass out on fxp0 proto tcp from any to any keep state
Estas regrais permitem qualquer tráfego TCP saindo pela interface fxp0, bem como o tráfego retornando em resposta ao firewall. Além do recurso de manutenção de estado ser uma excelente característica, seu uso ainda melhora a performance do firewall, pois pesquisas na tabela de estado são muito mais rápidas do que comparar o pacote contra todas as regras de filtragem.
A opção modulate state funciona como a keep state exceto que ela se aplica apenas a pacotes TCP. Com modulate state, o Número de Sequência Inicial (ISN) de conexões saindo do firewall é aleatório. Isso é útil para proteger conexões iniciadas por certos sistemas operacionais que não fazem um bom trabalho ao escolher ISNs. Desde o OpenBSD 3.5, a opção modulate state pode ser usada também em regras que especifiquem protocolos diferentes do TCP.
Mantendo estado em pacotes TCP, UDP e ICMP e modulanto ISNs TCP:
pass out on fxp0 proto { tcp, udp, icmp } from any \
to any modulate state
Outra vantagem de manter o estado é que o tráfego ICMP correspondente também passa pelo firewall. Por exemplo, se uma conexão TCP passando pelo firewall for rastreada como stateful e chegar uma mensagem ICMP source-quench referenciando esta conexão, ela será identificada como pertencendo a uma entrada válida na tabela de estado e passará direto pelo firewall.
O escopo de uma entrada na tabela de estado é controlado globalmente pela opção state-policy em tempo de execução, e com base nas regras de estado pelas palavras-chave if-bound, group-bound e floating. Essas palavras-chave usadas nas regras tem o mesmo efeito de quando são usadas na opção state-policy. Exemplo:
pass out on fxp0 proto { tcp, udp, icmp } from any \
to any modulate state (if-bound)
Essa regra define que para um pacote casar com a entrada na tabela de estado, ele deve estar transitando na interface fxp0.
Perceba que para regras nat, binat e rdr é implícita a criação de estados para conexões válidas desde que os pacotes passem pelas regras de filtragem.
Opções são especificadas dentro de parênteses e imediatemente depois de uma das palavras-chave (keep state, modulate state ou synproxy state). Múltiplas opções são separadas por virgulas. No OpenBSD 4.1 e posterior, a opcão keep state se tornou padrão para todas as regras de filtragem. Apesar disso, quanto estiver especificando opções stateful, uma das palavras-chave ainda deve ser usada na frente das opções
Uma regra de exemplo:
pass in on $ext_if proto tcp to $web_server \
port www keep state \
(max 200, source-track rule, max-src-nodes 100, max-src-states 3)
A regra acima define o seguinte comportamento:
Um conjunto separado de restrições pode ser colodado em conexões TCP stateful que completaram o 3-way handshake.
Ambas as opções invocam automaticamente a opção source-track rule e são incompatíveis com source-track global.
Uma vez que estes limites são colocados em conexões TCP que completaram o 3-way handshake, ações mais agressivas podem ser tomadas em endereços IP ofensivos.
Um exemplo:
table <abusive_hosts> persist
block in quick from <abusive_hosts>
pass in on $ext_if proto tcp to $web_server \
port www flags S/SA keep state \
(max-src-conn 100, max-src-conn-rate 15/5, overload <abusive_hosts> flush)
Isto faz o seguinte:
Para que o PF inspecione os flags TCP durante a avaliação de uma regra, a palavra-chave flags é usada com a seguinte sintaxe:
flags check/mask
flags any
A parte mask diz ao PF para verificar apenas os flags indicados e a parte check informa qual(is) flag(s) devem estar "setados" no cabeçalho para que o pacote case com a regra. Usando a palavra-chave any permite que qualquer combinação de flags seja configurada no cabeçlho.
pass in on fxp0 proto tcp from any to any port ssh flags S/SA
A regra acima autoriza tráfego TCP com a flag SYN setada, mas verifica somente os flags SYN e ACK. Um pacote com os flags SYN e ECE combinam com a regra acima, enquanto um pacote com SYN e ACK ou somente ACK não combina.
No OpenBSD 4.1 e posterior, a flag padrão aplicada em regras TCP é flags S/SA. Cobinado com o padrão de regras de filtragem keep state do OpenBSD 4.1, estas duas regras são equivalentes:
pass out on fxp0 proto tcp all flags S/SA keep state
pass out on fxp0 proto tcp all
Cada regra irá combinar com pacotes TCP com a flag SYN configurada e a flag ACK limpa e criará uma entrada na tabela de estados. A flag padrão pode ser substituída usado a opção flags como descrito acima.
No OpenBSD 4.0 e anteriores, não existia uma flag padrão aplicada em todas as regras de filtragem. Cada regra tinha que especificar qual(ais) flag(s) e também tinham que usar explicitamente a opção keep state.
pass out on fxp0 proto tcp all flags S/SA keep state
Deve-se tomar cuidado ao usar flags -- entenda o que você está fazendo e o
porquê, e tenha cuidado com conselhos dados pelos outros, pois grande
parte deles é incorreto. Algumas pessoas sugerem a criação de estado
"somente se o flag SYN estiver setado e nenhum outro". Esta regra deve
ficar asssim:
. . . flags S/FSRPAUEW má idéia!!
A teoria é, crie estado apenas no início da sessão TCP, e a sessão deve ser iniciada somente com um flag SYN, nada mais. O problema é que alguns sites estão começando a usar o flag ECN e qualquer um que use ECN e tente se conectar ao seu servidor terá os pacotes rejeitados por esta regra. Uma abordagem muito melhor seria não especificar uma flag e deixar que o PF aplique a flag padrão para suas regras. Se você realmente precisa especificar flags então esta combinação deve ser segura:
. . . flags S/SAFR
Além de ser prático e seguro, também não é necessário verificar os flags FIN e RST caso o tráfego passe antes por regras scrub. No processo de normalização o PF descartará quaisquer pacotes que cheguem com combinações de flags TCP inválidas (como SYN e RST) e normalizará combinaçãoes ambiguas em potencial (como SYN e FIN).
Normalmente quando um cliente inicia uma conexão TCP com o servidor, o PF transfere os pacotes do handshake da forma como eles vieram. O PF, porém possui a habilidade de fazer proxy no handshake. Com o uso de proxy no handshake, o próprio PF completará o handshake com o cliente, iniciará um handshake com o servidor, e então transferirá pacotes entre os dois. O benefício deste procedimento é que nenhum pacote é enviado ao servidor antes do cliente completar o handshake. Isso evita que ataques TCP SYN flood spoofados atinjam o servidor porque uma conexão spoofada não conseguirá completar o handshake.
O TCP SYN proxy é habilitado usando as palavras-chave synproxy state em regras de filtragem. Exemplo:
pass in on $ext_if proto tcp from any to $web_server port www \
flags S/SA synproxy state
Aqui, as conexões para o servidor web passarão pelo proxy do PF.
Pela forma como o synproxy state funciona, ele também inclui as mesmas funcionalidades de keep state e modulate state.
O SYN proxy não funcionará caso o PF esteja atuando numa bridge(4).
O PF oferece alguma proteção contra spoofing através do uso da palavra-chave antispoof:
antispoof [log] [quick] for interface [af]
Exemplo:
antispoof for fxp0 inet
Quando as regras são carregadas, quaisquer ocorrências da palavra antispoof são expandidas em duas regras de filtragem. Assumindo que a interface fxp0 possui endereço IP 10.0.0.1 e máscara de rede 255.255.255.0 (ex. /24), a regra antispoof acima será expandida para:
block in on ! fxp0 inet from 10.0.0.0/24 to any
block in inet from 10.0.0.1 to any
Estas regras fazem duas coisas:
NOTA: As regras de filtragem antispoof expandidas também irão bloquear pacotes enviados pela interface de loopback para o endereço local. Recomenda-se evitar qualquer tipo de filtragem na interface de loopback, mas isto se torna uma necessidade quando usamos regras antispoof:
set skip on lo0
antispoof for fxp0 inet
O uso de antispoof deve ser restrito a interfaces que possuam endereço IP. Usar antispoof numa interface sem um endereço IP resultará em regras como:
block drop in on ! fxp0 inet all
block drop in inet all
Nestas regras existe o risco de se bloquear todo tráfego entrante em todas as interfaces.
A partir do OpenBSD 4.0, PF oferece Encaminhamento Unicast Reverso (uRPF). Quanto um pacote é verificado pelo uRPF, o endereço IP de origem do pacote é procurado na tabela de roteamento. Se a interface de saída encontrada na tabela de roteamento é a mesma da interface que o pacote entrou, então a verificação uRPF passa. Se a interface não combinar, então é possível que o pacote tenha seu endereço de origem falsificado (spoofed).
A verificação uRPF pode ser aplicada aos pacotes usando a palavra-chave urpf-failed nas regras de filtragem:
block in quick from urpf-failed label uRPF
Note que a verificação uRPF só faz sentido em um ambiente onde o roteamento seja simétrico.
uRPF oferece a mesma funcionalidade que as regras antispoof.
Passive OS Fingerprinting (OSFP) é um método para identificar de maneira passiva o sistema operacional de um host remoto com base em certas características dos pacotes TCP SYN gerados pelo host. Esta informação pode então ser usada como critério em regras de filtragem.
O PF determina o sistema operacional remoto comparando as características do pacote TCP SYN contra um arquivo de impressões digitais, que por padrão é /etc/pf.os. Quando o PF está habilitado, a lista atual de impressões digitais pode ser vista com o comando:
# pfctl -s osfp
Numa regra de filtragem, a impressão digital pode ser especificada pela classe do SO, versão ou subtipo/revisão. Cada um dos itens é listado como saída do comando pfctl mostrado acima. Para especificar uma impressão digital numa regra de filtragem, a palavra-chave os deve ser usada.
pass in on $ext_if from any os OpenBSD keep state
block in on $ext_if from any os "Windows 2000"
block in on $ext_if from any os "Linux 2.4 ts"
block in on $ext_if from any os unknown
A classe de sistema operacional unknown permite o enquadramento de pacotes quanto a impressão digital do SO não é conhecida.
TOME NOTA:
pass in quick on fxp0 all allow-opts
ext_if = "fxp0"
int_if = "dc0"
lan_net = "192.168.0.0/24"
# tabela contendo todos endereços IP atribuídos ao firewall
table <firewall> const { self }
# não filtra na interface loopback
set skip on lo0
# faz scrub em pacotes que chegam
scrub in all
# define o política padrão
block all
# ativa proteção contra spoof para todas as interfaces
block in quick from urpf-failed
# permite conexões ssh vindas apenas da rede interna, e se for
# de um computador confiável, 192.168.0.15. usa "block return" de
# forma que um TCP RST é enviado para derrubar conexões bloqueadas.
# usa "quick" para que esta regra não seja invalidada por alguma
# regra "pass" abaixo.
block return in quick on $int_if proto tcp from ! 192.168.0.15 \
to $int_if port ssh
# aceita tráfego indo e vindo para a rede interna.
# estas regras criarão estados devido a opção
# padrão "keep state" que será automaticamente aplicada.
pass in on $int_if from $lan_net to any
pass out on $int_if from any to $lan_net
# aceita tcp, udp, e icmp saindo pela interface externa (Internet).
# conexões tcp configuradas com modulate, udp/icmp serão
# rastredos de forma stateful.
pass out on $ext_if proto { tcp udp icmp } all modulate state
# permite conexões ssh na interface externa contanto que NÃO sejam
# destinadas ao firewall (ex., conexões destinadas a máquinas na rede
# local). loga os pacotes iniciais para que mais tarde possamos saber
# quem tentou se conectar. usa tcp syn proxy nas conexões.
# A flag padrão "S/SA" será automaticamente aplicada na regra
# pelo PF.
pass in log on $ext_if proto tcp from any to ! <firewall> \
port ssh synproxy state
|
[Anterior: Tabelas] [Conteúdo] [Próximo: Tradução do Endereço de Rede (NAT)]