30.3. PF
Anterior | Capítulo 30. Firewalls | Próxima

## 30.3. PF

Revisado e atualizado por John Ferrell.

Desde o FreeBSD 5.3, uma versão portada do firewall PF do OpenBSD foi incluída como uma parte integrada do sistema base. O PF é um firewall completo, cheio de recursos que possui suporte opcional para ALTQ (Alternate Queuing), que fornece Qualidade de Serviço (QoS).

O Projeto OpenBSD mantém a referência definitiva para PF no FAQ do PF. Peter Hansteen mantém um tutorial completo do PF em http://home.nuug.no/~peter/pf/.

### Atenção:

Ao ler o FAQ do PF, tenha em mente que a versão do PF do FreeBSD divergiu substancialmente da versão inicial do OpenBSD ao longo dos anos. Nem todos os recursos funcionam da mesma maneira no FreeBSD como no OpenBSD e vice-versa.

A lista de emails do packet filter do FreeBSD é um bom lugar para perguntar questões relacionadas a configuração e execução do firewall PF. Verifique os arquivos da lista de email antes de perguntar alguma questão, pois ela já pode ter sido respondida.

Esta seção do Handbook foca no PF no que se refere ao FreeBSD. Ele demonstra como ativar o PF e ALTQ. Em seguida, ele fornece vários exemplos para criar conjuntos de regras em um sistema FreeBSD.

### 30.3.1. Ativando o PF

Para usar o PF, seu módulo do kernel deve ser carregado primeiro. Esta seção descreve as entradas que podem ser adicionadas ao `/etc/rc.conf` para habilitar o PF.

Comece adicionando a seguinte linha `pf_enable=yes` ao arquivo `/etc/rc.conf`:

    # sysrc pf_enable=yes

Opções adicionais, descritas em pfctl(8), podem ser passadas para o PF quando ele é iniciado. Adicione esta entrada ao arquivo `/etc/rc.conf` e especifique quaisquer flags necessárias entre duas aspas (`""`):

    pf_flags=""                     # additional flags for pfctl startup

O PF não será iniciado se não puder localizar o arquivo de configuração do conjunto de regras. Por padrão, o FreeBSD não vem com um conjunto de regras e não há um `/etc/pf.conf`. Exemplos de regras podem ser encontrados em `/usr/share/examples/pf/`. Se um conjunto de regras personalizado foi salvo em algum outro lugar, adicione uma linha ao arquivo `/etc/rc.conf` que especifica o caminho completo para o arquivo:

    pf_rules="/path/to/pf.conf"

O suporte de log para o PF é fornecido pelo pflog(4). Para ativar o suporte aos logs, adicione esta linha ao `/etc/rc.conf`:

    # sysrc pflog_enable=yes

As seguintes linhas também podem ser adicionadas para alterar a localização padrão do arquivo de log ou para especificar quaisquer flags adicionais na inicialização do pflog(4):

    pflog_logfile="/var/log/pflog"  # where pflogd should store the logfile
    pflog_flags=""                  # additional flags for pflogd startup

Finalmente, se houver uma LAN atrás do firewall e os pacotes precisarem ser encaminhados para os computadores na LAN, ou se NAT for necessário, adicione a seguinte opção:

    gateway_enable="YES"            # Enable as LAN gateway

Depois de salvar as edições necessárias, o PF pode ser iniciado com o suporte de log, digitando:

    # service pf start
    # service pflog start

Por padrão, o PF lê suas regras de configuração do arquivo `/etc/pf.conf` e modifica, descarta ou libera pacotes de acordo com as regras ou definições especificadas neste arquivo. A instalação do FreeBSD inclui vários arquivos de exemplo localizados em `/usr/share/examples/pf/`. Consulte o FAQ do PF para obter uma cobertura completa dos conjuntos de regras do PF.

Para controlar o PF, use o `pfctl`. Tabela 30.1, “Opções Úteis do `pfctl`” resume algumas opções úteis para este comando. Consulte pfctl(8) para obter uma descrição de todas as opções disponíveis:

Tabela 30.1. Opções Úteis do `pfctl`

Comando | Propósito
--- | ---
`pfctl -e` | Ativa o PF.
`pfctl -d` | Desabilita o PF.
`pfctl -F all -f /etc/pf.conf` | Limpa todas as regras de NAT, filtro, estado e tabela e recarrega o `/etc/pf.conf`.
`pfctl -s [ rules | nat | states ]` | Informa as regras de filtragem, de NAT ou a tabela de estados.
`pfctl -vnf /etc/pf.conf` | Verifica se tem erros no arquivo `/etc/pf.conf`, mas não carrega o conjunto de regras.

### Dica:

security/sudo é útil para executar comandos como `pfctl` que exigem privilégios elevados. Ele pode ser instalado a partir da Coleção de Ports.

Para ficar de olho no tráfego que passa pelo firewall PF, considere instalar o pacote ou port sysutils/pftop. Uma vez instalado, o pftop pode ser executado para exibir um snapshot do estado atual do tráfego em um formato semelhante ao top(1).

### 30.3.2. Conjuntos de Regras do PF

Contribuído por Peter N. M. Hansteen.

Esta seção demonstra como criar um conjunto de regras personalizado. Ele começa com o mais simples dos conjuntos de regras e baseia-se em seus conceitos usando vários exemplos para demonstrar o uso real dos diversos recursos do PF.

O conjunto de regras mais simples possível é para uma única máquina que não executa nenhum serviço e que precisa de acesso a uma rede, que pode ser a Internet. Para criar este conjunto de regras mínimo, edite o arquivo `/etc/pf.conf` para que fique assim:

    block in all
    pass out all keep state

A primeira regra nega todo o tráfego de entrada por padrão. A segunda regra permite que as conexões originadas por este sistema sejam liberadas, mantendo as informações de estado nessas conexões. Essas informações de estado permitem que o tráfego de retorno para essas conexões seja liberado e só deve ser usado em máquinas confiáveis. O conjunto de regras pode ser carregado com:

    # pfctl -e ; pfctl -f /etc/pf.conf

Além de manter estados, o PF fornece listas e macros que podem ser definidas para uso ao criar regras. As macros podem incluir listas e precisam ser definidas antes de serem usadas. Como exemplo, insira essas linhas no topo do conjunto de regras:

    tcp_services = "{ ssh, smtp, domain, www, pop3, auth, pop3s }"
    udp_services = "{ domain }"

O PF entende os nomes das portas, assim como os números das portas, desde que os nomes estejam listados em `/etc/services`. Este exemplo cria duas macros. A primeira é uma lista de sete nomes de portas TCP e a segunda é um nome de porta UDP. Uma vez definidas, as macros podem ser usadas em regras. Neste exemplo, todo o tráfego é bloqueado, exceto pelas conexões originadas por este sistema para os sete serviços TCP especificados e para o serviço UDP especificado:

    tcp_services = "{ ssh, smtp, domain, www, pop3, auth, pop3s }"
    udp_services = "{ domain }"
    block all
    pass out proto tcp to any port $tcp_services keep state
    pass proto udp to any port $udp_services keep state

Embora o UDP seja considerado um protocolo sem estado, o PF é capaz de rastrear algumas informações de estado. Por exemplo, quando uma solicitação UDP é liberada perguntando a um servidor de nomes sobre um nome de domínio, o PF irá procurar pela resposta para libera-la.

Sempre que uma edição é feita em um conjunto de regras, as novas regras devem ser carregadas para que possam ser usadas:

    # pfctl -f /etc/pf.conf

Se não houver erros de sintaxe, o `pfctl` não exibirá nenhuma mensagem durante o carregamento da regra. As regras também podem ser testadas antes de tentar carregá-las:

    # pfctl -nf /etc/pf.conf

A inclusão de `-n` faz com que as regras sejam interpretadas apenas, mas não carregadas. Isso fornece uma oportunidade para corrigir quaisquer erros. Em todos os momentos, o último conjunto de regras válido carregado será imposto até que o PF seja desativado ou um novo conjunto de regras seja carregado.

### Dica:

Adicionando `-v` ao comando `pfctl` no carregamento ou checagem de conjuntos de regras, será exibido as regras exatamente da maneira como elas serão carregadas. Isso é extremamente útil ao depurar regras.

#### 30.3.2.1. Um Gateway Simples com NAT

Esta seção demonstra como configurar um sistema FreeBSD executando PF para atuar como um gateway para pelo menos uma outra máquina. O gateway precisa de pelo menos duas interfaces de rede, cada uma conectada a uma rede separada. Neste exemplo, `xl1` está conectada à Internet e a `xl0` está conectada à rede interna.

Primeiro, ative o gateway para permitir que a máquina encaminhe o tráfego de rede que recebe em uma interface para outra interface. Esta configuração do sysctl encaminhará pacotes IPv4:

    # sysctl net.inet.ip.forwarding=1

Para encaminhar tráfego IPv6, use:

    # sysctl net.inet6.ip6.forwarding=1

Para ativar essas configurações na inicialização do sistema, use o sysrc(8) para adicioná-las ao `/etc/rc.conf`:

    # sysrc gateway_enable=yes
    # sysrc ipv6_gateway_enable=yes

Verifique com o `ifconfig` se ambas as interfaces estão ativadas e em execução.

Em seguida, crie as regras PF para permitir que o gateway transmita tráfego. Embora a regra a seguir permita que o tráfego com informações de estado passe da Internet para os hosts na rede, a palavra-chave `to` não garante a passagem da origem até o destino:

    pass in on xl1 from xl1:network to xl0:network port $ports keep state

Essa regra só permite que o tráfego passe para o gateway na interface interna. Para deixar os pacotes irem mais longe, é necessária uma regra de correspondência:

    pass out on xl0 from xl1:network to xl0:network port $ports keep state

Embora essas duas regras funcionem, regras especificadas dessa forma raramente são necessárias. Para um administrador de rede ocupado, um conjunto de regras legível é um conjunto de regras mais seguro. O restante desta seção demonstra como manter as regras o mais simples possível para facilitar a leitura. Por exemplo, essas duas regras podem ser substituídas por uma regra:

    pass from xl1:network to any port $ports keep state

A notação `interface:network` pode ser substituída por uma macro para tornar o conjunto de regras ainda mais legível. Por exemplo, uma macro `$localnet` pode ser definida como a rede diretamente conectada à interface interna (`$xl1:network`). Alternativamente, a definição de `$localnet` poderia ser alterada para uma notação IP address/netmask para denotar uma rede, como `192.168.100.1/24` para uma sub-rede de endereços privados.

Se necessário, `$localnet` pode ser definido como uma lista de redes. Quaisquer que sejam as necessidades específicas, uma definição sensata de `$localnet` poderia ser usada em uma regra típica de liberação da seguinte maneira:

    pass from $localnet to any port $ports keep state

O conjunto de regras de exemplo a seguir libera todo o tráfego originado por máquinas na rede interna. Primeiro define duas macros para representar as interfaces externas e internas 3COM do gateway.

### Nota:

Para usuários dial-up, a interface externa será `tun0`. Para uma conexão ADSL, especificamente aquelas que usam PPP over Ethernet (PPPoE), a interface externa correta é `tun0`, não a interface física Ethernet.

    ext_if = "xl0"	# macro for external interface - use tun0 for PPPoE
    int_if = "xl1"	# macro for internal interface
    localnet = $int_if:network
    # ext_if IP address could be dynamic, hence ($ext_if)
    nat on $ext_if from $localnet to any -> ($ext_if)
    block all
    pass from { lo0, $localnet } to any keep state

Este conjunto de regras introduz a regra `nat` que é usada para tratar a tradução de endereços de rede dos endereços não roteáveis ​​dentro da rede interna para o endereço IP atribuído à interface externa. Os parênteses em torno da última parte da regra nat `($ext_if)` são incluídos quando o endereço IP da interface externa é atribuído dinamicamente. Ele garante que o tráfego de rede seja executado sem interrupções graves, mesmo se o endereço IP externo for alterado.

Observe que esse conjunto de regras provavelmente permite que mais tráfego seja transmitido para fora da rede do que o necessário. Uma configuração razoável poderia criar essa macro:

    client_out = "{ ftp-data, ftp, ssh, domain, pop3, auth, nntp, http, \
        https, cvspserver, 2628, 5999, 8000, 8080 }"

para usar na regra principal de liberação:

    pass inet proto tcp from $localnet to any port $client_out \
        flags S/SA keep state

Algumas outras regras de aprovação podem ser necessárias. Esta permite ativar o SSH na interface externa:

    pass in inet proto tcp to $ext_if port ssh

Esta definição de macro e regra permite DNS e NTP para clientes internos:

    udp_services = "{ domain, ntp }"
    pass quick inet proto { tcp, udp } to any port $udp_services keep state

Observe a palavra-chave `quick` nesta regra. Como o conjunto de regras consiste em várias regras, é importante entender as relações entre as regras em um conjunto de regras. As regras são avaliadas de cima para baixo, na sequência em que são escritas. Para cada pacote ou conexão avaliado pelo PF, a última regra correspondente no conjunto de regras é aquela que é aplicada. No entanto, quando um pacote corresponde a uma regra que contém a palavra-chave `quick`, o processamento da regra é interrompido e o pacote é tratado de acordo com essa regra. Isso é muito útil quando é necessária uma exceção às regras gerais.

#### 30.3.2.2. Criando um Proxy FTP

Configurar regras funcionais de FTP pode ser problemático devido à natureza do protocolo FTP. O FTP pré-data os firewalls por várias décadas e é inseguro em seu design. Os pontos mais comuns contra o uso do FTP incluem:

- As senhas são transferidas em texto puro.

- O protocolo exige o uso de pelo menos duas conexões TCP (controle e dados) em portas separadas.

- Quando uma sessão é estabelecida, os dados são transmitidos usando portas selecionadas aleatoriamente.

Todos esses pontos apresentam desafios de segurança, mesmo antes de considerar possíveis pontos fracos de segurança no software cliente ou servidor. Há alternativas mais seguras para a transferência de arquivos, como sftp(1) ou scp(1), que apresentam autenticação e transferência de dados através de conexões criptografadas.

Para as situações em que o FTP é necessário, o PF fornece o redirecionamento do tráfego FTP para um pequeno programa proxy chamado ftp-proxy(8), que está incluído no sistema base do FreeBSD. O papel do proxy é inserir dinamicamente e excluir regras no conjunto de regras, usando um conjunto de âncoras, para lidar corretamente com o tráfego de FTP.

Para habilitar o proxy FTP, adicione esta linha ao `/etc/rc.conf`:

    ftpproxy_enable="YES"

Em seguida, inicie o proxy executando `service ftp-proxy start`.

Para uma configuração básica, três elementos precisam ser adicionados ao arquivo `/etc/pf.conf`. Primeiro, as âncoras que o proxy usará para inserir as regras que ele gera para as sessões de FTP:

    nat-anchor "ftp-proxy/*"
    rdr-anchor "ftp-proxy/*"

Em segundo, é necessária uma regra de liberação para permitir o tráfego de FTP para o proxy.

Terceiro, as regras de redirecionamento e NAT precisam ser definidas antes das regras de filtragem. Insira esta regra `rdr` imediatamente após a regra `nat`:

    rdr pass on $int_if proto tcp from any to any port ftp -> 127.0.0.1 port 8021

Finalmente, permita que o tráfego redirecionado passe:

    pass out proto tcp from $proxy to any port ftp

onde `$proxy` se expande para o endereço ao qual o daemon proxy está vinculado.

Salve o arquivo `/etc/pf.conf`, carregue as novas regras e verifique a partir de um cliente se as conexões FTP estão funcionando:

    # pfctl -f /etc/pf.conf

Este exemplo cobre uma configuração básica em que os clientes na rede local precisam entrar em contato com servidores FTP em outro lugar. Essa configuração básica deve funcionar bem com a maioria das combinações de clientes e servidores FTP. Como mostrado em ftp-proxy(8), o comportamento do proxy pode ser alterado de várias maneiras adicionando opções na linha `ftpproxy_flags=`. Alguns clientes ou servidores podem ter peculiaridades específicas que devem ser compensadas na configuração ou pode ser necessário integrar o proxy de maneiras específicas, como atribuir tráfego FTP a uma fila específica.

Para formas de executar um servidor FTP protegido por PF e ftp-proxy(8), configure um `ftp-proxy` separado em modo reverso, usando `-R`, em uma porta separada com sua própria regra de redirecionamento de passagem.

#### 30.3.2.3. Gerenciando ICMP

Muitas das ferramentas usadas para depurar ou solucionar problemas de uma rede TCP/IP dependem do Internet Control Message Protocol (ICMP), o qual foi projetado especificamente para depuração.

O protocolo ICMP envia e recebe mensagens de controle entre hosts e gateways, principalmente para fornecer feedback a um remetente sobre quaisquer condições incomuns ou difíceis na rota para o host de destino. Os roteadores usam ICMP para negociar tamanhos de pacote e outros parâmetros de transmissão em um processo geralmente chamado de descoberta de path MTU.

Do ponto de vista do firewall, algumas mensagens de controle ICMP são vulneráveis ​​a vetores de ataque conhecidos. Além disso, deixar todo o tráfego de diagnóstico passar incondicionalmente torna a depuração mais fácil, mas também torna mais fácil para os outros extraírem informações sobre a rede. Por esses motivos, a regra a seguir pode não ser a ideal:

    pass inet proto icmp from any to any

Uma solução é permitir todo o tráfego de ICMP originado na rede local e bloquear as chamadas provenientes de fora da rede:

    pass inet proto icmp from $localnet to any keep state
    pass inet proto icmp from any to $ext_if keep state

Opções adicionais estão disponíveis, o que demonstra algumas das flexibilidades do PF. Por exemplo, em vez de liberar todas as mensagens ICMP, pode-se especificar as mensagens usadas pelo ping(8) e traceroute(8). Comece definindo uma macro para esse tipo de mensagem:

    icmp_types = "echoreq"

e uma regra que usa a macro:

    pass inet proto icmp all icmp-type $icmp_types keep state

Se outros tipos de pacotes ICMP forem necessários, expanda `icmp_types` para uma lista desses tipos de pacotes. Digite `more /usr/src/sbin/pfctl/pfctl_parser.c` para ver a lista de tipos de mensagem ICMP suportados pelo PF. Consulte http://www.iana.org/assignments/icmp-parameters/icmp-parameters.xhtml para uma explicação de cada tipo de mensagem.

Como o Unix `traceroute` usa UDP por padrão, outra regra é necessária para permitir o comando `traceroute` do Unix:

    # allow out the default range for traceroute(8):
    pass out on $ext_if inet proto udp from any to any port 33433 >< 33626 keep state

Como o `TRACERT.EXE` em sistemas Microsoft Windows usa ICMP echo request messages, somente a primeira regra é necessária para permitir rastreamentos de rede desses sistemas. O Unix `traceroute` também pode ser instruído a usar outros protocolos e usará ICMP echo request messages se `-I` for usado. Verifique a página de manual traceroute(8) para detalhes.

##### 30.3.2.3.1. Descoberta de Path MTU

Os protocolos de Internet são projetados para serem independentes do dispositivo, e uma consequência da independência do dispositivo é que o tamanho ideal do pacote para uma determinada conexão nem sempre pode ser previsto com segurança. A principal restrição no tamanho do pacote é a Maximum Transmission Unit (MTU), que define o limite superior do tamanho do pacote para uma interface. Digite `ifconfig` para exibir os MTUs para as interfaces de rede do sistema.

O TCP/IP usa um processo conhecido como descoberta de path MTU para determinar o tamanho correto do pacote para uma conexão. Este processo envia pacotes de tamanhos variados com o conjunto de flag “Não fragmentar”, esperando um pacote de retorno ICMP de “tipo 3, código 4” quando o limite for alcançado. O tipo 3 significa “destino inacessível”, e o código 4 é uma abreviação para “fragmentação necessária, mas a flag para não fragmentar está definida”. Para permitir que a descoberta de path MTU suporte conexões com outros MTUs, adicione o tipo `destination unreachable` à macro `icmp_types`:

    icmp_types = "{ echoreq, unreach }"

Como a regra de liberação já usa essa macro, ela não precisa ser modificada para suportar o novo tipo de ICMP:

    pass inet proto icmp all icmp-type $icmp_types keep state

O PF permite filtrar todas as variações dos tipos e códigos de ICMP. A lista de tipos e códigos possíveis está documentada em icmp(4) and icmp6(4).

#### 30.3.2.4. Usando Tabelas

Alguns tipos de dados são relevantes para filtragem e redirecionamento em um determinado momento, mas sua definição é muito longa para ser incluída no arquivo do conjunto de regras. O PF suporta o uso de tabelas, que são listas definidas que podem ser manipuladas sem a necessidade de recarregar todo o conjunto de regras e que podem fornecer pesquisas rápidas. Nomes de tabelas são sempre colocados dentro de `< >`, assim:

    table <clients> { 192.168.2.0/24, !192.168.2.5 }

Neste exemplo, a rede `192.168.2.0/24` faz parte da tabela, exceto pelo endereço `192.168.2.5`, que é excluído pelo operador `!`. Também é possível carregar tabelas de arquivos onde cada entrada está em uma linha separada. como neste exemplo `/etc/clients`:

    192.168.2.0/24
    !192.168.2.5

Para se referir ao arquivo, defina a tabela da seguinte forma:

    table <clients> persist file "/etc/clients"

Depois que a tabela é definida, ela pode ser referenciada por uma regra:

    pass inet proto tcp from <clients> to any port $client_out flags S/SA keep state

O conteúdo de uma tabela pode ser manipulado ao vivo, usando `pfctl`. Este exemplo adiciona outra rede a tabela:

    # pfctl -t clients -T add 192.168.1.0/16

Observe que quaisquer alterações feitas dessa maneira terão efeito imediato, tornando-as ideais para testes, mas não sobreviverão a uma falha de energia ou reinicialização. Para tornar as alterações permanentes, modifique a definição da tabela no conjunto de regras ou edite o arquivo a que a tabela se refere. É possível manter a cópia em disco da tabela usando uma tarefa cron(8) que copia o conteúdo da tabela para o disco em intervalos de tempo, usando um comando como `pfctl -t clients -T show >/etc/clients`. Alternativamente, o `/etc/clients` pode ser atualizado com o conteúdo da tabela na memória:

    # pfctl -t clients -T replace -f /etc/clients

#### 30.3.2.5. Usando Tabelas de Sobrecarga para Proteger o SSH

Aqueles que executam o SSH em uma interface externa provavelmente já viram algo assim nos logs de autenticação:

    Sep 26 03:12:34 skapet sshd[25771]: Failed password for root from 200.72.41.31 port 40992 ssh2
    Sep 26 03:12:34 skapet sshd[5279]: Failed password for root from 200.72.41.31 port 40992 ssh2
    Sep 26 03:12:35 skapet sshd[5279]: Received disconnect from 200.72.41.31: 11: Bye Bye
    Sep 26 03:12:44 skapet sshd[29635]: Invalid user admin from 200.72.41.31
    Sep 26 03:12:44 skapet sshd[24703]: input_userauth_request: invalid user admin
    Sep 26 03:12:44 skapet sshd[24703]: Failed password for invalid user admin from 200.72.41.31 port 41484 ssh2

Isso indica um ataque de força bruta em que alguém ou algum programa está tentando descobrir o nome de usuário e senha que os permitirá entrar no sistema.

Se o acesso externo ao SSH for necessário para usuários legítimos, a alteração da porta padrão usada pelo SSH pode oferecer alguma proteção. No entanto, o PF fornece uma solução mais elegante. As regras de liberação podem conter limites sobre o que os hosts de conexão podem fazer e os violadores podem ser banidos para uma tabela de endereços aos quais é negado algum ou todo o acesso. É até possível descartar todas as conexões existentes de máquinas que excedem os limites.

Para configurar isso, crie esta tabela na seção de tabelas do conjunto de regras:

    table <bruteforce> persist

Então, em algum lugar no início do conjunto de regras, adicione regras para bloquear o acesso bruto, permitindo acesso legítimo:

    block quick from <bruteforce>
    pass inet proto tcp from any to $localnet port $tcp_services \
        flags S/SA keep state \
        (max-src-conn 100, max-src-conn-rate 15/5, \
        overload <bruteforce> flush global)

A parte entre parênteses define os limites e os valores devem ser alterados para atender aos requisitos locais. Isso pode ser lido da \seguinte forma:

`max-src-conn` é o número de conexões simultâneas permitidas de um host.

`max-src-conn-rate` é a taxa de novas conexões permitidas de qualquer host único (`15`) por número de segundos (`5`).

`overload <bruteforce>` significa que qualquer host que excede esses limites obtém seu endereço adicionado à tabela `bruteforce`. O conjunto de regras bloqueia todo o tráfego de endereços na tabela `bruteforce`.

Finalmente, `flush global` diz que quando um host atinge o limite, todo (`global`) das conexões desse host será finalizado (`flush`).

### Nota:

Estas regras não irão bloquear bruteforcers lentos, como descrito em http://home.nuug.no/~peter/hailmary2013/.

Este conjunto de regras de exemplo é projetado principalmente como uma ilustração. Por exemplo, se um número grande de conexões em geral é desejado, mas o desejo é ser mais restritivo quando se trata de ssh, complemente a regra acima com algo como o abaixo, no início do conjunto de regras:

    pass quick proto { tcp, udp } from any to any port ssh \
        flags S/SA keep state \
        (max-src-conn 15, max-src-conn-rate 5/3, \
        overload <bruteforce> flush global)

### Pode Não ser Necessário Bloquear Todos os Overloaders:

É importante notar que o mecanismo de sobrecarga é uma técnica geral que não se aplica exclusivamente ao SSH, e nem sempre é ideal bloquear totalmente todo o tráfego dos infratores.

Por exemplo, uma regra de sobrecarga pode ser usada para proteger um serviço de email ou um serviço Web e a tabela de sobrecarga pode ser usada em uma regra para atribuir infratores a uma fila com uma alocação de largura de banda mínima ou redirecionar para uma página Web específica.

Com o tempo, as tabelas serão preenchidas por regras de sobrecarga e seu tamanho crescerá incrementalmente, ocupando mais memória. Às vezes, um endereço de IP que é bloqueado é atribuído dinamicamente, que já foi atribuído a um host que tem um motivo legítimo para se comunicar com hosts na rede local.

Para situações como essas, o pfctl fornece a capacidade de expirar as entradas da tabela. Por exemplo, este comando removerá entradas de tabela `<bruteforce>` que não foram referenciadas por `86400` segundos:

    # pfctl -t bruteforce -T expire 86400

Funcionalidade semelhante é fornecida por security/expiretable, que remove entradas de tabela que não foram acessadas por um período de tempo especificado.

Uma vez instalado, o expiretable pode ser executado para remover entradas de tabela `<bruteforce>` mais antigas que uma tempo especifico. Este exemplo remove todas as entradas com mais de 24 horas:

    /usr/local/sbin/expiretable -v -d -t 24h bruteforce

#### 30.3.2.6. Protegendo Contra SPAM

Não deve ser confundido com o daemon spamd que vem junto com spamassassin, mail/spamd pode ser configurado com o PF para fornecer uma defesa externa contra SPAM. Esse spamd conecta-se à configuração do PF usando um conjunto de redirecionamentos.

Os spammers tendem a enviar um grande número de mensagens, e o SPAM é enviado principalmente de algumas redes amigáveis ​​de spammers e um grande número de máquinas sequestradas, sendo que ambas são reportadas a blacklists bem rápido.

Quando uma conexão SMTP de um endereço que está em uma blacklist é recebido, o spamd apresenta seu banner e imediatamente muda para um modo em que ele responde o trágefo SMTP um byte de cada vez. Esta técnica, que pretende desperdiçar tanto tempo quanto possível do spammer, é chamada de tarpitting. A implementação específica que usa respostas de um byte SMTP é muitas vezes referenciada como stuttering.

Este exemplo demonstra o procedimento básico para configurar o spamd com blacklists atualizadas automaticamente. Consulte as páginas de manual que são instaladas com o mail/spamd para mais informações.

Procedimento 30.1. Configurando o spamd

1. Instale o pacote ou port mail/spamd. Para usar os recursos de greylist do spamd, fdescfs(5) deve ser montado em `/dev/fd`. Adicione a seguinte linha ao arquivo `/etc/fstab`:

        fdescfs /dev/fd fdescfs rw 0 0

   Em seguida, monte o sistema de arquivos:

       # mount fdescfs

2. Em seguida, edite o conjunto de regras do PF para incluir:

       table <spamd> persist
       table <spamd-white> persist
       rdr pass on $ext_if inet proto tcp from <spamd> to \
           { $ext_if, $localnet } port smtp -> 127.0.0.1 port 8025
       rdr pass on $ext_if inet proto tcp from !<spamd-white> to \
           { $ext_if, $localnet } port smtp -> 127.0.0.1 port 8025

   As duas tabelas `<spamd>` e `<spamd-white>` são essenciais. O trafego SMTP de um endereço listado em `<spamd>` mas não em `<spamd-white>` é redirecionado para o daemon spamd ouvindo a porta 8025.

3. O próximo passo é configurar o spamd no arquivo `/usr/local/etc/spamd.conf` e adicionar alguns parâmetros no arquivo `rc.conf`.

   A instalação do mail/spamd inclui um arquivo de configuração de exemplo (`/usr/local/etc/spamd.conf.sample`) e uma página de manual para o `spamd.conf`. Refira-se a estes para opções adicionais de configuração além daquelas mostradas neste exemplo.

   Uma das primeiras linhas no arquivo de configuração que não começa com um sinal de comentário `#` contém o bloco que define a lista `all`, que especifica as listas a serem usadas:

       all:\
           :traplist:whitelist:

   Esta entrada adiciona as blacklists desejadas, separadas por dois pontos (`:`). Para usar uma whitelist para subtrair endereços de uma blacklist, adicione o nome da whitelist imediatamente após o nome dessa blacklist. Por exemplo: `:blacklist:whitelist:`.

   Isto é seguido pela definição da blacklist especificada:

       traplist:\
           :black:\
           :msg="SPAM. Your address %A has sent spam within the last 24 hours":\
           :method=http:\
           :file=www.openbsd.org/spamd/traplist.gz

   onde a primeira linha é o nome da blacklist e a segunda linha especifica o tipo da lista. O campo `msg` contém a mensagem a ser exibida aos remetentes da blacklist durante a comunicação SMTP. O campo `method` especifica como o spamd-setup busca os dados da lista; os métodos suportados são `http`, `ftp`, de um `arquivo` em um sistema de arquivos montado e via `exec` de um programa externo. Finalmente, o campo `file` especifica o nome do arquivo que o spamd espera receber.

   A definição da whitelist especificada é semelhante, mas omite o campo `msg` porque uma mensagem não é necessária:

       whitelist:\
           :white:\
           :method=file:\
           :file=/var/mail/whitelist.txt

   ### Escolha Fontes de Dados com Cuidado:

   Usar todas as blacklists do arquivo de exemplo `spamd.conf` irá colocar na blacklist grandes blocos da Internet. Os administradores precisam editar o arquivo para criar uma configuração ideal que use fontes de dados aplicáveis ​​e, quando necessário, use listas personalizadas.

   Em seguida, adicione esta entrada ao arquivo `/etc/rc.conf`. Flags adicionais são descritas na página de manual especificada pelo comentário:

       spamd_flags="-v" # use "" and see spamd-setup(8) for flags

   Quando terminar, recarregue o conjunto de regras, inicio o spamd digitando `service obspamd start`, e complete a configuração usando `spamd-setup`. Finalemente, crie uma tarefa cron(8) que chame `spamd-setup` para atualizar as tabelas razoáveis.

Em um gateway típico na frente de um servidor de email, os hosts logo começam a ficar presos dentro de segundos ou alguns minutos.

PF também suporta greylist, que rejeita temporariamente mensagens de hosts desconhecidos com códigos `45n`. Conexões de hosts que estão na greylist e que tentam novamente dentro de um tempo razoável de tempo são liberados. O tráfego de remetentes que estão configurados para se comportarem dentro dos limites estabelecidos pela RFC 1123 e pela RFC 2821 é imediatamente permitido.

Mais informações sobre técnicas de greylist podem ser encontradas no site greylisting.org. A coisa mais surpreendente sobre greylist, além de sua simplicidade, é que ainda funciona. Os spammers e os criadores de malware têm sido muito lentos para se adaptar, a fim de contornar essa técnica.

O procedimento básico para configurar o greylist é o seguinte:

Procedimento 30.2. Configurando Greylist

1. Certifique-se de que fdescfs(5) esteja montado conforme descrito na Etapa 1 do Procedimento anterior.

2. Para executar spamd no modo greylist, adicione esta linha ao `/etc/rc.conf`:

       spamd_grey="YES"  # use spamd greylisting if YES

   Consulte a página de manual do spamd para obter descrições de parâmetros relacionados adicionais.

3. Para concluir a configuração da greylist:

       # service obspamd restart
       # service obspamlogd start

Nos bastidores, a ferramenta de banco de dados spamdb e o atualizador de whitelist spamlogd executam funções essenciais para o recurso de greylist. O spamdb é a interface principal do administrador para gerenciar as greylists, blacklists e whitelists por meio do conteúdo do banco de dados `/var/db/spamdb`.

#### 30.3.2.7. Higiene de Rede

Esta seção descreve como o `block-policy`, `scrub`, e `antispoof` pode ser usado para fazer o conjunto de regras se comportar corretamente.

O `block-policy` é uma opção que pode ser definida na parte de `opções` do conjunto de regras, que precede as regras de redirecionamento e filtragem. Essa opção determina qual feedback, se houver, que o PF envia para hosts que são bloqueados por uma regra. A opção tem dois valores possíveis: `drop` descarta pacotes bloqueados sem feedback, e `return` retorna um código de status como `Connection refused`.

Se não definido, a política padrão é `drop`. Para alterar o `block-policy`, especifique o valor desejado:

    set block-policy return

No PF, `scrub` é uma palavra-chave que permite a normalização do pacote de rede. Esse processo remonta pacotes fragmentados e descarta pacotes TCP que possuem combinações de sinalizadores inválidos. Ativar `scrub` fornece uma medida de proteção contra certos tipos de ataques com base no manuseio incorreto de fragmentos de pacotes. Várias opções estão disponíveis, mas a forma mais simples é adequada para a maioria das configurações:

    scrub in all

Alguns serviços, como o NFS, exigem opções específicas de manipulação de fragmentos. Consulte https://home.nuug.no/~peter/pf/en/scrub.html para mais informações.

Este exemplo remonta fragmentos, limpa o bit “não fragmentar” e define o tamanho máximo do segmento para 1440 bytes:

    scrub in all fragment reassemble no-df max-mss 1440

O mecanismo `antispoof` protege contra a atividade de endereços IP falsos ou forjados, principalmente bloqueando pacotes que aparecem em interfaces e em direções que logicamente não são possíveis.

Essas regras eliminam tráfego falsificado do resto do mundo, bem como qualquer pacote falsificado originado na rede local:

    antispoof for $ext_if
    antispoof for $int_if

#### 30.3.2.8. Manipulando Endereços Não-Roteados

Mesmo com um gateway configurado adequadamente para lidar com a tradução de endereços de rede, pode ser necessário compensar as configurações incorretas de outras pessoas. Uma configuração incorreta comum é permitir o tráfego com endereços não roteáveis ​​para a Internet. Como o tráfego de endereços não roteados pode desempenhar um papel em várias técnicas de ataque de DoS, considere bloquear explicitamente o tráfego de endereços não roteáveis de entrar na rede por meio da interface externa.

Neste exemplo, uma macro contendo endereços não roteáveis ​​é definida e usada em regras de bloqueio. O tráfego de origem e destino para esses endereços é silenciosamente descartado na interface externa do gateway.

    martians = "{ 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, \
    	      10.0.0.0/8, 169.254.0.0/16, 192.0.2.0/24, \
    	      0.0.0.0/8, 240.0.0.0/4 }"

    block drop in quick on $ext_if from $martians to any
    block drop out quick on $ext_if from any to $martians

### 30.3.3. Ativando o ALTQ

No FreeBSD, o ALTQ pode ser usado com PF para fornecer Qualidade de Serviço (QOS). Depois que o ALTQ é ativado, as filas podem ser definidas no conjunto de regras que determina a prioridade de processamento dos pacotes de saída.

Antes de ativar o ALTQ, consulte altq(4) para determinar se os drivers das placas de rede instaladas no sistema suportam isto.

ALTQ não está disponível como um módulo de kernel carregável. Se as interfaces do sistema suportarem ALTQ, crie um kernel personalizado usando as instruções em Capítulo 8, Configurando o kernel do FreeBSD. As seguintes opções do kernel estão disponíveis. O primeira é necessária para ativar o ALTQ. Pelo menos uma das outras opções é necessária para especificar o algoritmo do scheduler de enfileiramento:

    options         ALTQ
    options         ALTQ_CBQ        # Class Based Queuing (CBQ)
    options         ALTQ_RED        # Random Early Detection (RED)
    options         ALTQ_RIO        # RED In/Out
    options         ALTQ_HFSC       # Hierarchical Packet Scheduler (HFSC)
    options         ALTQ_PRIQ       # Priority Queuing (PRIQ)

Os seguintes algoritmos de agendamento estão disponíveis:

CBQ

  Class Based Queuing (CBQ) é usado para dividir a largura de banda de uma conexão em diferentes classes ou filas para priorizar o tráfego com base nas regras de filtragem.

RED

  Random Early Detection (RED) é usado para evitar o congestionamento da rede, medindo o comprimento da fila e comparando-a com os limites mínimo e máximo da fila. Quando a fila está acima do máximo, todos os novos pacotes são descartados aleatoriamente.

RIO

  No modo Random Early Detection In and Out (RIO), RED mantém vários comprimentos médios de fila e vários valores limite, um para cada nível QOS.

HFSC

  Hierarchical Fair Service Curve Packet Scheduler (HFSC) é descrito em `http://www-2.cs.cmu.edu/~hzhang/HFSC/main.html`.

PRIQ

  Priority Queuing (PRIQ) sempre passa primeiro o tráfego que está em uma fila mais alta.

Maiores informações sobre os algoritmos de agendamento e os conjuntos de regras de exemplo estão disponíveis no `arquivo web do OpenBSD`.

Anterior | Acima | Próxima
30.2. Conceitos de Firewall | Principal | 30.4. IPFW

All FreeBSD documents are available for download at https://download.freebsd.org/ftp/doc/

Questions that are not answered by the documentation may be sent to <freebsd-questions@FreeBSD.org>.
Send questions about this document to <freebsd-doc@FreeBSD.org>.