O IPFW é um firewall stateful para o FreeBSD, que suporta tanto o IPv4 como o IPv6. Ele é composto de vários componentes: o processador de regras de filtro de firewall do kernel e seu recurso integrado de contabilidade de pacotes, o recurso de registro em log, NAT, o dummynet(4) traffic shaper, um recurso de forward, um recurso de bridge e uma habilidade ipstealth.
O FreeBSD fornece um conjunto de regras de exemplo em /etc/rc.firewall
que define vários tipos de firewall para cenários comuns para ajudar usuários iniciantes a gerar um conjunto de regras apropriado. O IPFW fornece uma poderosa sintaxe que os usuários avançados podem usar para criar conjuntos de regras personalizados que atendam aos requisitos de segurança de um determinado ambiente.
Esta seção descreve como ativar o IPFW, fornece uma visão geral de sua sintaxe de regra e demonstra vários conjuntos de regras para cenários comuns de configuração.
O IPFW está incluído na instalação base do FreeBSD como um módulo carregável do kernel, o que significa que um kernel customizado não é necessário para ativar o IPFW.
Para aqueles usuários que desejam compilar estaticamente o suporte ao IPFW em um kernel personalizado, veja Seção 30.4.6, “Opções do Kerne para o IPFW”.
Para configurar o sistema para ativar o IPFW no momento da inicialização, adicione firewall_enable="YES"
ao /etc/rc.conf
:
#
sysrc firewall_enable="YES"
Para usar um dos tipos de firewall padrão fornecidos pelo FreeBSD, adicione outra linha que especifique o tipo:
#
sysrc firewall_type="open"
Os tipos disponíveis são:
open
: passa todo o tráfego.
client
: protege apenas esta máquina.
simple
: protege toda a rede.
closed
: desativa completamente o tráfego IP, exceto na interface de loopback.
workstation
: protege apenas esta máquina usando regras stateful.
UNKNOWN
: desativa o carregamento de regras de firewall.
: caminho completo do arquivo que contém o conjunto de regras do firewall.filename
Se firewall_type
estiver definido como client
ou simple
, modifique as regras padrão encontradas em /etc/rc.firewall
para se adequar a configuração do sistema.
Observe que o tipo filename
é usado para carregar um conjunto de regras customizado.
Uma maneira alternativa de carregar um conjunto de regras personalizado é definir a variável firewall_script
para o caminho absoluto de um script executável que inclui comandos IPFW. Os exemplos usados nesta seção assumem que o firewall_script
está definido como /etc/ipfw.rules
:
#
sysrc firewall_script="/etc/ipfw.rules"
Para habilitar o registro em log por meio do syslogd(8), inclua esta linha:
#
sysrc firewall_logging="YES"
Somente regras de firewall com opção de log
vão ser registradas. As regras padrão não contém essa opção e deve ser adicionada manualmente. Por isso é avisado que o conjunto de regras padrão é editado para logar. Em adição a isso, rotacionamento de log é desejado se os logs estiverem em um arquivo separado.
Não existe uma variável em /etc/rc.conf
para definir os limites de log. Para limitar o número de vezes que uma regra é registrada por tentativa de conexão, especifique o número usando esta linha no /etc/sysctl.conf
:
#
echo "net.inet.ip.fw.verbose_limit=
5
" >> /etc/sysctl.conf
Para habilitar o registro através de uma interface dedicada chamada ipfw0
, adicione esta linha ao /etc/rc.conf
em vez disso:
#
sysrc firewall_logif="YES"
Em seguida, use o tcpdump para ver o que está sendo registrado:
#
tcpdump -t -n -i ipfw0
Não há sobrecarga devido ao log, a menos que o tcpdump esteja anexado.
Depois de salvar as edições necessárias, inicie o firewall. Para ativar os limites de log agora, defina também o valor sysctl
especificado acima:
#
service ipfw start
#
sysctl net.inet.ip.fw.verbose_limit=
5
Quando um pacote entra no firewall IPFW, ele é comparado com a primeira regra no conjunto de regras e avança uma regra por vez, movendo-se de cima para baixo em sequência. Quando o pacote corresponde aos parâmetros de seleção de uma regra, a ação da regra é executada e a pesquisa do conjunto de regras termina para esse pacote. Isto é conhecido como “primeira combinação vence”. Se o pacote não corresponder a nenhuma das regras, ele será pego pela regra padrão obrigatória IPFW de número 65535, que bloqueia todos os pacotes e os descarta silenciosamente. No entanto, se o pacote corresponder a uma regra que contenha as palavras-chave count
, skipto
ou tee
, a pesquisa continuará. Consulte ipfw(8) para obter detalhes sobre como essas palavras-chave afetam o processamento de regras.
Ao criar uma regra IPFW, as palavras-chave devem ser escritas na seguinte ordem. Algumas palavras-chave são obrigatórias, enquanto outras são opcionais. As palavras mostradas em maiúsculas representam uma variável e as palavras mostradas em minúsculas devem preceder a variável que a segue. O símbolo #
é usado para marcar o início de um comentário e pode aparecer no final de uma regra ou em sua própria linha. Linhas em branco são ignoradas.
CMD RULE_NUMBER set SET_NUMBER ACTION log LOG_AMOUNT PROTO from SRC SRC_PORT to DST DST_PORT OPTIONS
Esta seção fornece uma visão geral dessas palavras-chave e suas opções. Não é uma lista exaustiva de todas as opções possíveis. Consulte ipfw(8) para obter uma descrição completa da sintaxe de regra que pode ser usada ao criar regras IPFW.
Toda regra deve começar com ipfw add
.
Cada regra é associada a um número de 1
até 65534
. O número é usado para indicar a ordem do processamento da regra. Várias regras podem ter o mesmo número e, nesse caso, elas são aplicadas de acordo com a ordem em que foram adicionadas.
Cada regra é associada a um número definido de 0
até 31
. Os conjuntos podem ser desativados ou ativados individualmente, possibilitando adicionar ou excluir rapidamente um conjunto de regras. Se um SET_NUMBER não for especificado, a regra será adicionada no conjunto 0
.
Uma regra pode ser associada a uma das ações a seguir. A ação especificada será executada quando o pacote corresponder ao critério de seleção da regra.
allow | accept | pass | permit
: essas palavras-chave são equivalentes e permitem pacotes que correspondem à regra.
check-state
: verifica o pacote em relação à tabela de estados dinâmicos. Se uma correspondência for encontrada, execute a ação associada à regra que gerou essa regra dinâmica, caso contrário, vá para a próxima regra. Uma regra check-state
não possui critério de seleção. Se nenhuma regra check-state
estiver presente no conjunto de regras, a tabela de regras dinâmicas será verificada na primeira regra keep-state
ou limit
.
count
: atualiza os contadores de todos os pacotes que correspondem à regra. A pesquisa continua com a próxima regra.
deny | drop
: qualquer das duas palavras descarta silenciosamente os pacotes que correspondem a essa regra.
Ações adicionais estão disponíveis. Consulte ipfw(8) para detalhes.
Quando um pacote corresponde a uma regra com a palavra-chave log
, uma mensagem será registrada no syslogd(8) com nome SECURITY
. O registro somente ocorre se o número de pacotes registrados para essa regra específica não exceder um LOG_AMOUNT especificado. Se nenhum LOG_AMOUNT for especificado, o limite será retirado do valor de net.inet.ip.fw.verbose_limit
. Um valor de zero remove o limite de registro. Quando o limite for atingido, o registro em log poderá ser reativado, limpando o contador de registro ou o contador de pacotes para essa regra, usando ipfw resetlog
.
O registro é feito depois que todas as outras condições de correspondência de pacote foram atendidas e antes de executar a ação final no pacote. O administrador decide quais regras habilitar o log.
Este valor opcional pode ser usado para especificar qualquer nome ou número de protocolo encontrado no arquivo /etc/protocols
.
A palavra-chave from
deve ser seguida pelo endereço de origem ou por uma palavra-chave que represente o endereço de origem. Um endereço pode ser representado por any
, me
(qualquer endereço configurado em uma interface neste sistema), me6
, (qualquer endereço IPv6 configurado em uma interface neste sistema), ou table
seguido pelo número de uma tabela de consulta que contém uma lista de endereços. Ao especificar um endereço IP, ele pode ser seguido opcionalmente pela máscara ou pela máscara de sub-rede do CIDR. Por exemplo, 1.2.3.4/25
ou 1.2.3.4:255.255.255.128
.
Uma porta de origem opcional pode ser especificada usando o número da porta ou um nome de /etc/services
.
A palavra-chave to
deve ser seguida pelo endereço de destino ou por uma palavra-chave que represente o endereço de destino. As mesmas palavras-chave e endereços descritos na seção SRC podem ser usados para descrever o destino.
Uma porta de destino opcional pode ser especificada usando o número da porta ou um nome de /etc/services
.
Várias palavras-chave podem seguir a origem e o destino. Como o nome sugere, OPTIONS são opcionais. As opções comumente usadas incluem in
ou out
, que especificam a direção do fluxo de pacotes, icmptypes
seguido pelo tipo de mensagem ICMP e keep-state
.
Quando uma regra keep-state
é correspondida, o firewall criará uma regra dinâmica que corresponda ao tráfego bidirecional entre os endereços e portas de origem e destino usando o mesmo protocolo.
O recurso de regras dinâmicas é vulnerável ao esgotamento de recursos de um ataque SYN-flood, o que abriria um grande número de regras dinâmicas. Para combater esse tipo de ataque com IPFW, use limit
. Esta opção limita o número de sessões simultâneas verificando as regras dinâmicas abertas, contando o número de vezes que esta regra e a combinação de endereços IP ocorreram. Se essa contagem for maior que o valor especificado por limit
, o pacote será descartado.
Dezenas de OPTIONS estão disponíveis. Consulte ipfw(8) para obter uma descrição de cada opção disponível.
Esta seção demonstra como criar um exemplo de script de conjunto de regras de firewall stateful chamado /etc/ipfw.rules
. Neste exemplo, todas as regras de conexão usam in
ou out
para esclarecer a direção. Eles também usam via
nome-da-interface
para especificar a interface que o pacote está percorrendo.
Ao criar ou testar um conjunto de regras de firewall, considere esta configuração temporária:
net.inet.ip.fw.default_to_accept="1"
Isso define a política padrão do ipfw(8) para ser mais permissiva do que o padrão deny ip from any to any
, tornando um pouco mais difícil ficar bloqueado fora do sistema logo após a reinicialização.
O script de firewall começa indicando que é um script Bourne shell e limpa quaisquer regras existentes. Em seguida, ele cria a variável cmd
para que ipfw add
não precise ser digitado no início de cada regra. Ele também define a variável pif
que representa o nome da interface que está conectada à Internet.
#!/bin/sh # Flush out the list before we begin. ipfw -q -f flush # Set rules command prefix cmd="ipfw -q add" pif="dc0" # interface name of NIC attached to Internet
As duas primeiras regras permitem todo o tráfego na interface interna e na interface de loopback:
# Change xl0 to LAN NIC interface name $cmd 00005 allow all from any to any via xl0 # No restrictions on Loopback Interface $cmd 00010 allow all from any to any via lo0
A próxima regra permite que o pacote passe se corresponder a uma entrada existente na tabela de regras dinâmicas:
$cmd 00101 check-state
O próximo conjunto de regras define quais conexões stateful os sistemas internos podem criar para hosts na Internet:
# Allow access to public DNS # Replace x.x.x.x with the IP address of a public DNS server # and repeat for each DNS server in /etc/resolv.conf $cmd 00110 allow tcp from any to x.x.x.x 53 out via $pif setup keep-state $cmd 00111 allow udp from any to x.x.x.x 53 out via $pif keep-state # Allow access to ISP's DHCP server for cable/DSL configurations. # Use the first rule and check log for IP address. # Then, uncomment the second rule, input the IP address, and delete the first rule $cmd 00120 allow log udp from any to any 67 out via $pif keep-state #$cmd 00120 allow udp from any to x.x.x.x 67 out via $pif keep-state # Allow outbound HTTP and HTTPS connections $cmd 00200 allow tcp from any to any 80 out via $pif setup keep-state $cmd 00220 allow tcp from any to any 443 out via $pif setup keep-state # Allow outbound email connections $cmd 00230 allow tcp from any to any 25 out via $pif setup keep-state $cmd 00231 allow tcp from any to any 110 out via $pif setup keep-state # Allow outbound ping $cmd 00250 allow icmp from any to any out via $pif keep-state # Allow outbound NTP $cmd 00260 allow udp from any to any 123 out via $pif keep-state # Allow outbound SSH $cmd 00280 allow tcp from any to any 22 out via $pif setup keep-state # deny and log all other outbound connections $cmd 00299 deny log all from any to any out via $pif
O próximo conjunto de regras controla conexões de hosts da Internet para a rede interna. Ele começa negando pacotes tipicamente associados a ataques e, em seguida, permite explicitamente tipos específicos de conexões. Todos os serviços autorizados originados da Internet usam limit
para evitar ataques de flood.
# Deny all inbound traffic from non-routable reserved address spaces $cmd 00300 deny all from 192.168.0.0/16 to any in via $pif #RFC 1918 private IP $cmd 00301 deny all from 172.16.0.0/12 to any in via $pif #RFC 1918 private IP $cmd 00302 deny all from 10.0.0.0/8 to any in via $pif #RFC 1918 private IP $cmd 00303 deny all from 127.0.0.0/8 to any in via $pif #loopback $cmd 00304 deny all from 0.0.0.0/8 to any in via $pif #loopback $cmd 00305 deny all from 169.254.0.0/16 to any in via $pif #DHCP auto-config $cmd 00306 deny all from 192.0.2.0/24 to any in via $pif #reserved for docs $cmd 00307 deny all from 204.152.64.0/23 to any in via $pif #Sun cluster interconnect $cmd 00308 deny all from 224.0.0.0/3 to any in via $pif #Class D & E multicast # Deny public pings $cmd 00310 deny icmp from any to any in via $pif # Deny ident $cmd 00315 deny tcp from any to any 113 in via $pif # Deny all Netbios services. $cmd 00320 deny tcp from any to any 137 in via $pif $cmd 00321 deny tcp from any to any 138 in via $pif $cmd 00322 deny tcp from any to any 139 in via $pif $cmd 00323 deny tcp from any to any 81 in via $pif # Deny fragments $cmd 00330 deny all from any to any frag in via $pif # Deny ACK packets that did not match the dynamic rule table $cmd 00332 deny tcp from any to any established in via $pif # Allow traffic from ISP's DHCP server. # Replace x.x.x.x with the same IP address used in rule 00120. #$cmd 00360 allow udp from any to x.x.x.x 67 in via $pif keep-state # Allow HTTP connections to internal web server $cmd 00400 allow tcp from any to me 80 in via $pif setup limit src-addr 2 # Allow inbound SSH connections $cmd 00410 allow tcp from any to me 22 in via $pif setup limit src-addr 2 # Reject and log all other incoming connections $cmd 00499 deny log all from any to any in via $pif
A última regra registra todos os pacotes que não correspondem a nenhuma das regras do conjunto de regras:
# Everything else is denied and logged $cmd 00999 deny log all from any to any
O firewall IPFW do FreeBSD possui duas implementações de NAT: a implementação do sistema base natd(8) e a implementação de NAT interno do IPFW. Ambos trabalham em conjunto com o IPFW para fornecer tradução de endereço de rede. Isso pode ser usado para fornecer uma solução de compartilhamento de conexão com a Internet, para que vários computadores internos possam se conectar à Internet usando um único endereço IP público.
Para isso, a maquina FreeBSD conectada na internet deve atuar como um gateway. Esse sistema deve ter duas NICs, onde uma é conectada a internet e a outra conectada a LAN interna. Cada maquina conectada com a LAN deve estar associada a um endereço IP no espaço de rede privado, como definido pela RFC 1918.
Algumas configuração adicionais são necessárias para ativar a funcionalidade in-kernel NAT do IPFW. Para ativar o suporte ao in-kernel NAT no momento da inicialização do sistema, o seguinte deve ser definido em /etc/rc.conf
:
gateway_enable="YES" firewall_enable="YES" firewall_nat_enable="YES"
Quando firewall_nat_enable
estiver definido, mas firewall_enable
não estiver, ele não terá efeito e não fará nada. Isso ocorre porque a implementação do in-kernel NAT é compatível apenas com o IPFW.
Quando o conjunto de regras contém regras stateful, o posicionamento da regra NAT é crítico e a ação skipto
é usada. A ação skipto
requer um número de regra para que ele saiba para qual regra saltar. O exemplo abaixo se baseia no conjunto de regras do firewall mostrado na seção anterior. Ele adiciona algumas entradas adicionais e modifica algumas regras existentes para configurar o firewall com in-kernel NAT. Ele começa adicionando algumas variáveis adicionais que representam o número da regra para pular para, a opção keep-state
e uma lista de portas TCP que serão usadas para reduzir o número de regras.
#!/bin/sh ipfw -q -f flush cmd="ipfw -q add" skip="skipto 1000" pif=dc0 ks="keep-state" good_tcpo="22,25,37,53,80,443,110"
Com o in-kernel NAT é necessário desativar o descarregamento da segmentação TCP (TSO) devido à arquitetura do libalias(3), uma biblioteca implementada como um módulo do kernel para fornecer o in-kernel NAT do IPFW. O TSO pode ser desativado em uma interface de rede usando ifconfig(8) ou em todo o sistema usando sysctl(8). Para desativar o TSO em todo o sistema, deve-se definir o seguinte em /etc/sysctl.conf
:
net.inet.tcp.tso="0"
Uma instância NAT também será configurada. É possível ter várias instâncias de NAT, cada uma com sua própria configuração. Para este exemplo, apenas uma instância NAT é necessária; Instância NAT número 1. A configuração pode receber algumas opções, como: if
, que indica a interface pública, same_ports
, que cuida para que as portas mapeadas e o números das portas locais sejam mapeados da mesma maneira, unreg_only
resultará em apenas espaços de endereço não registrados (privados) a serem processados pela instância NAT e reset
, que ajudará a manter uma instância NAT em funcionamento, mesmo quando o endereço de IP público da máquina IPFW for alterado. Para todas as opções possíveis que podem ser passadas para uma única configuração de instância NAT, consulte ipfw(8). Ao configurar um firewall NAT stateful, é necessário permitir que pacotes traduzidos sejam reinjetados no firewall para processamento subsequente. Isso pode ser obtido desativando o comportamento one_pass
no início do script do firewall.
ipfw disable one_pass ipfw -q nat 1 config if $pif same_ports unreg_only reset
A regra NAT de entrada é inserida após as duas regras que permitem todo o tráfego nas interfaces interna e de loopback e após a regra de remontagem, mas antes da regra check-state
. É importante que o número da regra selecionada para esta regra NAT, neste exemplo 100
, seja maior que as três primeiras regras e menor que a regra check-state
. Além disso, devido ao comportamento do in-kernel NAT, é recomendável colocar uma regra de remontagem pouco antes da primeira regra NAT e depois das regras que permitem tráfego nas interfaces. Normalmente, a fragmentação IP não deve ocorrer, mas ao lidar com o tráfego de tunelamento com IPSEC/ESP/GRE, isso pode ocorrer e a recomposição de fragmentos é necessária antes de entregar o pacote completo para o mecanismo de in-kernel NAT.
A regra de remontagem não era necessária com o natd(8) do sistema base porque o recurso interno de divert
no IPFW já cuida disso, remontando os pacotes antes da entrega no socket, também informado em ipfw(8).
A instância NAT e o número da regra usados neste exemplo não coincidem com a instância NAT e o número da regra padrão criados por rc.firewall
. rc.firewall
é um script que configura as regras de firewall padrão presentes no FreeBSD.
$cmd 005 allow all from any to any via xl0 # exclude LAN traffic $cmd 010 allow all from any to any via lo0 # exclude loopback traffic $cmd 099 reass all from any to any in # reassemble inbound packets $cmd 100 nat 1 ip from any to any in via $pif # NAT any inbound packets # Allow the packet through if it has an existing entry in the dynamic rules table $cmd 101 check-state
As regras de saída são modificadas para substituir a ação allow
com a variável $skip
, indicando que o processamento da regra continuará na regra 1000
. As sete regras tcp
foram substituídas pela regra 125
porque a variável $good_tcpo
contém as sete portas de saída permitidas.
Lembre-se de que o desempenho do IPFW é amplamente determinado pelo número de regras presentes no conjunto de regras.
# Authorized outbound packets $cmd 120 $skip udp from any to x.x.x.x 53 out via $pif $ks $cmd 121 $skip udp from any to x.x.x.x 67 out via $pif $ks $cmd 125 $skip tcp from any to any $good_tcpo out via $pif setup $ks $cmd 130 $skip icmp from any to any out via $pif $ks
As regras de entrada permanecem as mesmas, exceto a ultima regra que remove via $pif
com intenção de casar com ambas regras de entrada e saida. A regra de NAT deve seguir essa ultima regra de saida, deve ter um numero maior que a ultima regra, e o numero da regra deve referenciar a ação skipto
. Nesse conjunto de regras, o numero de regra 1000
lida com a passagem de todos os pacotes para nossa instância configurada para processamento NAT. A próxima regra permite que qualquer pacote submetido ao processamento NAT seja liberado.
$cmd 999 deny log all from any to any $cmd 1000 nat 1 ip from any to any out via $pif # skipto location for outbound stateful rules $cmd 1001 allow ip from any to any
Neste exemplo, as regras 100
, 101
, 125
, 1000
e 1001
controlam a tradução de endereços dos pacotes de saída e de entrada para que as entradas na tabela de estado dinâmico sempre registrem o endereço de IP privado da LAN .
Considere um navegador Web interno que inicialize uma nova sessão HTTP pela porta 80. Quando o primeiro pacote de saída entra no firewall, ele não corresponde à regra 100
porque ele está saindo e não entrando. Ele pula a regra 101
porque este é o primeiro pacote e ainda não foi inserido na tabela de estados dinâmicos. O pacote finalmente corresponde à regra 125
pois é uma conexão de saída em uma porta permitida e tem um endereço IP de origem da LAN interna. Ao combinar essa regra, duas ações ocorrem. Primeiro, a ação keep-state
adiciona uma entrada à tabela de estados dinâmicos e a ação especificada, skipto rule 1000
, é executada. Em seguida, o pacote passa pelo NAT e é enviado para a Internet. Este pacote faz o seu caminho para o servidor web de destino, onde um pacote de resposta é gerado e enviado de volta. Este novo pacote entra no topo do conjunto de regras. Ele corresponde à regra 100
e tem seu endereço de destino IP mapeado de volta para o endereço interno original. Em seguida, ele é processado pela regra check-state
, é encontrado na tabela como uma sessão existente e é liberado para a LAN.
No lado da entrada, o conjunto de regras deve negar pacotes inválidos e permitir apenas serviços autorizados. Um pacote que corresponde a uma regra de entrada é postado na tabela de estados dinâmicos e o pacote é liberado para a LAN. O pacote gerado como resposta é reconhecido pela regra check-state
como pertencente a uma sessão existente. Em seguida, ele é enviado para a regra 1000
para passar pelo NAT antes de ser liberado para a interface de saída.
A transição do natd(8) do sistema base para o in-kernel NAT pode parecer fácil no início, mas há algumas particularidades. Ao usar o kernel GENERIC, o IPFW carregará o módulo libalias.ko
do kernel, quando o firewall_nat_enable
estiver ativado no rc.conf
. O módulo do kernel libalias.ko
fornece apenas a funcionalidade básica de NAT, enquanto a implementação do natd(8) do sistema base possui todas as funcionalidades de NAT disponível na userland sem nenhuma configuração extra. Toda funcionalidade refere-se aos seguintes módulos do kernel que podem ser carregados adicionalmente quando necessário, além do módulo do kernel padrão libalias.ko
: alias_cuseeme.ko
, alias_ftp.ko
, alias_bbt.ko
, skinny.ko
, irc.ko
, alias_pptp.ko
and alias_smedia.ko
usando a diretiva kld_list
em rc.conf
. Se um kernel personalizado for usado, a funcionalidade completa do sistema base poderá ser compilada no kernel, usando a opção options LIBALIAS
.
A desvantagem com NAT em geral é que os clientes da LAN não estão acessíveis na Internet. Os clientes na LAN podem fazer conexões de saída para o mundo, mas não podem receber conexões diretas. Isso é um problema ao tentar executar serviços de Internet em uma das máquinas clientes da LAN. Uma forma simples de contornar isso é redirecionar as portas selecionadas da Internet na máquina NAT para um cliente da LAN.
Por exemplo, um servidor IRC é executado no cliente A
e um servidor Web é executado no cliente B
. Para que isso funcione corretamente, as conexões recebidas nas portas 6667 (IRC) e 80 (HTTP) devem ser redirecionadas para as respectivas máquinas.
Com o in-kernel NAT, toda a configuração é feita na configuração da instância NAT. Para obter uma lista completa de opções que uma instância in-kernel NAT pode usar, consulte ipfw(8). A sintaxe IPFW segue a sintaxe do natd. A sintaxe para redirect_port
é a seguinte:
redirect_port proto targetIP:targetPORT[-targetPORT] [aliasIP:]aliasPORT[-aliasPORT] [remoteIP[:remotePORT[-remotePORT]]]
Para configurar o exemplo de instalação acima, os argumentos devem ser:
redirect_port tcp 192.168.0.2:6667 6667 redirect_port tcp 192.168.0.3:80 80
Depois de adicionar esses argumentos à configuração da instância 1 de NAT no conjunto de regras acima, as portas TCP serão encaminhadas para as máquinas clientes da LAN que rodam os serviços IRC e HTTP.
ipfw -q nat 1 config if $pif same_ports unreg_only reset \ redirect_port tcp 192.168.0.2:6667 6667 \ redirect_port tcp 192.168.0.3:80 80
Intervalos de portas podem ser indicados com redirect_port
. Por exemplo, tcp 192.168.0.2:2000-3000 2000-3000
redirecionaria todas as conexões recebidas entre as portas 2000 e 3000 para as portas 2000 a 3000 no cliente A
.
Redirecionamento de endereços é útil se mais de um endereço IP estiver disponível. Cada cliente da LAN pode receber seu próprio endereço IP externo pelo ipfw(8), que reescreverá os pacotes de saída dos clientes da LAN com o endereço IP externo apropriado e redirecionará todo o tráfego recebido naquele endereço IP específico de volta para o cliente da LAN específico. Isso também é conhecido como NAT estático. Por exemplo, se o endereço IP 128.1.1.1
, 128.1.1.2
, e 128.1.1.3
estiverem disponíveis, 128.1.1.1
pode ser usado pelo ipfw(8) como o endereço IP de saída externa, enquanto 128.1.1.2
e 128.1.1.3
são encaminhados de volta para os clientes da LAN A
e B
.
A sintaxe redirect_address
é a seguinte, onde localIP
é o endereço IP interno do cliente da LAN e publicIP
é o endereço IP externo que corresponde ao cliente da LAN .
redirect_address localIP publicIP
No exemplo, os argumentos seriam:
redirect_address 192.168.0.2 128.1.1.2 redirect_address 192.168.0.3 128.1.1.3
Como o redirect_port
, esses argumentos são inseridos na configuração da instância NAT. Com o redirecionamento de endereço, não há necessidade de redirecionamento de porta, pois todos os dados recebidos em um determinado endereço IP são redirecionados.
Os endereços IP externos na máquina ipfw(8) devem estar ativos e com alias na interface externa. Consulte rc.conf(5) para mais informações.
Vamos começar com uma declaração: a implementação de NAT do sistema base: natd(8), tem mais sobrecarga do que no in-kernel NAT. Para que o natd(8) traduza pacotes, os pacotes precisam ser copiados do kernel para o espaço do usuário e vice-versa, o que gera uma sobrecarga extra que não está presente com o in-kernel NAT.
Para ativar o daemon de NAT do sistema base , natd(8), no momento da inicialização do sistema, é necessário a seguinte configuração mínima em /etc/rc.conf
. Onde natd_interface
é definido com o nome da interface NIC conectada à Internet. O script rc(8) do natd(8) verifica automaticamente se um endereço IP dinâmico é usado e configura-se para lidar com isso.
gateway_enable="YES" natd_enable="YES" natd_interface="rl0"
Em geral, o conjunto de regras acima, conforme explicado para o in-kernel NAT, também pode ser usado junto com natd(8). As exceções são a configuração da instância in-kernel NAT (ipfw -q nat 1 config ...)
que não é necessária junto com a regra de remontagem 99 porque sua funcionalidade é incluída na ação divert
. As regras número 100 e 1000 terão que mudar ligeiramente, como mostrado abaixo.
$cmd 100 divert natd ip from any to any in via $pif $cmd 1000 divert natd ip from any to any out via $pif
Para configurar o redirecionamento de porta ou endereço, é usada uma sintaxe semelhante à do in-kernel NAT. Embora agora, em vez de especificar a configuração em nosso script de conjunto de regras, como no in-kernel NAT, a configuração do natd(8) é melhor realizada em um arquivo de configuração. Para fazer isso, uma flag extra deve ser passado através do /etc/rc.conf
, que especifica o caminho do arquivo de configuração.
natd_flags="-f /etc/natd.conf"
O arquivo especificado deve conter uma lista de opções de configuração, uma por linha. Para obter mais informações sobre esse arquivo de configuração e possíveis variáveis, consulte natd(8). Abaixo estão dois exemplos de valores, um por linha:
redirect_port tcp 192.168.0.2:6667 6667 redirect_address 192.168.0.3 128.1.1.3
O ipfw
pode ser usado para adicionar ou excluir regras únicas e manuais ao firewall ativo enquanto ele estiver em execução. O problema com o uso desse método é que todas as alterações são perdidas quando o sistema é reinicializado. Recomenda-se, em vez disso, gravar todas as regras em um arquivo e usar esse arquivo para carregar as regras no momento da inicialização e substituir as regras de firewall em execução no momento em que o arquivo for alterado.
O ipfw
é uma maneira útil para se exibir as regras de firewall em execução na tela do console. O recurso de contabilidade IPFW cria dinamicamente um contador para cada regra que case com cada pacote que corresponde à regra. Durante o processo de teste de uma regra, listar a regra com seu contador é uma maneira de determinar se a regra está funcionando conforme o esperado.
Para listar todas as regras em execução em sequência:
#
ipfw list
Para listar todas as regras em execução com um registro de data e hora de quando a última vez em que a regra foi utilizada:
#
ipfw -t list
O próximo exemplo lista as informações contábeis e a contagem de pacotes das regras correspondentes, junto com as próprias regras. A primeira coluna é o número da regra, seguido pelo número de pacotes e bytes correspondidos, seguidos pela própria regra.
#
ipfw -a list
Para listar regras dinâmicas além das regras estáticas:
#
ipfw -d list
Para mostrar também as regras dinâmicas expiradas:
#
ipfw -d -e list
Para zerar os contadores:
#
ipfw zero
Para zerar os contadores apenas para a regra com o número NUM
:
#
ipfw zero
NUM
Mesmo com o recurso de geração de log ativado, o IPFW não irá gerar nenhum log de regras por conta própria. O administrador do firewall decide quais regras no conjunto de regras serão logadas e adiciona a palavra-chave log
a essas regras. Normalmente, apenas as regras de bloqueio são logadas. É costume duplicar a regra “ipfw default deny everything” com a palavra-chave log
incluída como a última regra no conjunto de regras. Dessa forma, é possível ver todos os pacotes que não correspondem a nenhuma das regras do conjunto de regras.
O log é uma espada de dois gumes. Se não houver cuidado, uma abundância de dados de log ou um ataque DoS pode encher o disco com arquivos de log. As mensagens de log não são gravadas apenas no syslogd, mas também são exibidas na tela do console do root e logo se tornam irritantes.
A opção do kernel IPFIREWALL_VERBOSE_LIMIT=5
limita o número de mensagens consecutivas enviadas para o syslogd(8), referente à correspondência de pacotes de uma regra dada. Quando esta opção está ativada no kernel, o número de mensagens consecutivas relativas a uma regra específica é limitado ao número especificado. Não há nada a ganhar com 200 mensagens de log idênticas. Com essa opção definida como cinco, cinco mensagens consecutivas referentes a uma regra específica seriam registradas no syslogd e as mensagens consecutivas idênticas restantes seriam contadas e postadas no syslogd com uma frase assim:
last message repeated 45 times
Todas os pacotes logados são escritos por padrão no arquivo /var/log/security
, que é definido no /etc/syslog.conf
.
Os usuários mais experientes do IPFW criam um arquivo contendo as regras e as codificam de maneira compatível com sua execução como um script. A principal vantagem de fazer isso é que as regras de firewall podem ser atualizadas em massa sem a necessidade de reinicializar o sistema para ativá-las. Este método é conveniente para testar novas regras, pois o procedimento pode ser executado quantas vezes forem necessárias. Sendo um script, a substituição simbólica pode ser usada para valores usados frequentemente para serem substituídos em várias regras.
Este script de exemplo tem a sintaxe compatível com shells sh(1), csh(1), e tcsh(1). Campos de substituição simbólicos são prefixados com um sinal de dólar ($). Campos simbólicos não possuem o prefixo $. O valor para preencher o campo simbólico deve ser colocado entre aspas duplas ("").
Inicie o arquivo de regras assim:
############### start of example ipfw rules script ############# # ipfw -q -f flush # Delete all rules # Set defaults oif="tun0" # out interface odns="192.0.2.11" # ISP's DNS server IP address cmd="ipfw -q add " # build rule prefix ks="keep-state" # just too lazy to key this each time $cmd 00500 check-state $cmd 00502 deny all from any to any frag $cmd 00501 deny tcp from any to any established $cmd 00600 allow tcp from any to any 80 out via $oif setup $ks $cmd 00610 allow tcp from any to $odns 53 out via $oif setup $ks $cmd 00611 allow udp from any to $odns 53 out via $oif $ks ################### End of example ipfw rules script ############
As regras não são importantes, pois o foco deste exemplo é como os campos de substituição simbólica são preenchidos.
Se o exemplo acima estiver no arquivo /etc/ipfw.rules
, as regras podem ser recarregadas pelo seguinte comando:
#
sh /etc/ipfw.rules
/etc/ipfw.rules
pode estar localizado em qualquer lugar e o arquivo pode ter qualquer nome.
A mesma coisa pode ser realizada executando esses comandos manualmente:
#
ipfw -q -f flush
#
ipfw -q add check-state
#
ipfw -q add deny all from any to any frag
#
ipfw -q add deny tcp from any to any established
#
ipfw -q add allow tcp from any to any 80 out via tun0 setup keep-state
#
ipfw -q add allow tcp from any to 192.0.2.11 53 out via tun0 setup keep-state
#
ipfw -q add 00611 allow udp from any to 192.0.2.11 53 out via tun0 keep-state
Para compilar estaticamente o suporte ao IPFW em um kernel personalizado, consulte as instruções em Capítulo 8, Configurando o kernel do FreeBSD. As seguintes opções estão disponíveis para o arquivo de configuração do kernel personalizado:
options IPFIREWALL # enables IPFW options IPFIREWALL_VERBOSE # enables logging for rules with log keyword to syslogd(8) options IPFIREWALL_VERBOSE_LIMIT=5 # limits number of logged packets per-entry options IPFIREWALL_DEFAULT_TO_ACCEPT # sets default policy to pass what is not explicitly denied options IPFIREWALL_NAT # enables basic in-kernel NAT support options LIBALIAS # enables full in-kernel NAT support options IPFIREWALL_NAT64 # enables in-kernel NAT64 support options IPFIREWALL_NPTV6 # enables in-kernel IPv6 NPT support options IPFIREWALL_PMOD # enables protocols modification module support options IPDIVERT # enables NAT through natd(8)
O IPFW pode ser carregado como um módulo do kernel: as opções acima são compiladas por padrão como módulos ou podem ser configuradas em tempo de execução usando parâmetros configuráveis.
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>.