terça-feira, 14 de julho de 2020

Comandos uteis do PF, um firewall para FreeBSD


Atualmente tenho feito bastante manutenção em servidores que rodam FreeBSD, dessa forma acabei gerando um compilado referente ao firewall PF, criação de VLAN's em terminal e criação de tabelas no PF para uso diversos. Segue diversos comandos e macetes que de alguma forma podem auxiliar o administrador de servidores FreeBSD no dia a dia:




########## Comandos uteis de gerenciamento do PF

# Executa as regras no arquivo destinado ao pf
pfctl -f arquivodopf

#Carrega as regras na memória, mas sem ativar de fato
pfctl -nf arquivodopf

#Lê somente as regras de nat que estiverem no arquivo do pf
pfctl -Nf arquivodopf

#Lê somente as regras do filtro de pacote, descartando as regras de NAT
pfctl -Rf arquivodopf

#Mostra as regras para tratamento de NAT
pfctl -sn

#Mostra as regras atuais
pfctl -sr

#Mostra a tabela de estados de conexões do kernel
pfctl -ss

#Mostra as estatisticas sobre o filtro de pacotes e contadores
pfctl -si

#Mostra tudo agrupado
pfctl -as

#Mostra as regras por ordem na memória
pftcl -vvs rules

#Limpa regras
pfctl -d 


#Exemplo de regras com agrupamento de variáveis em listas( coisas entre chaves {})

#Bloqueia saída via fxp0 com origem nos IP's que estão entre as chaves, isso faz duas regras em uma linha apenas
block out on fxp0 from {192.168.0.1, 10.5.32.6} to any

#Bloqueio de protocolos com origem nos IP's que estão entre as chaves para qualquer lugar que tenha um serviço de ssh ou telnet
block out on fxp0 proto { tcp udp } from { 192.168.0.1, 10.5.32.6 } to any port { ssh telnet }

A regra acima contem 8 regras em apenas uma linha.


#Exemplo de regras com macros, que nada mais são que as variáveis.

Interface_Externa="fxp0"
Redes_Amigas = "{192.168.1.0/24,10.0.0.0/8,192.168.10.0/24}"

Outras formas de agrupamento

HOST1="192.168.1.1"
HOST2="192.168.1.2"

Todos_Hosts = "{" $HOST1 $HOST2 "}"


#Exemplo de regras com tabelas de regras

const - componentes da tabela, mutáveis

persist - dados criados na tabela que ficaram na memória, até que sejam removidos do sistema. 

Exemplo:

table <amigos> {192.168.1.2/24}

table <rfc1918> const { 192.168.1.0/16, 172.16.1.0/12, 10.1.1.0/8 }

table <spammers> persist { 192.168.1.1/32, 192.168.1.4/32}

#regra, bloqueia entrada pela fxp0 com IP's originados da interface 
block in on fxp0 from { <rfc1918>,<spammers> } to any 


#Libera tabela amigos para qualquer lugar.
pass in on fxp0 from <amigos> to any


Atributo de negação também é válido
table <amigos> {192.168.1.0/24,!192.168.1.10}
Serão considerados os amigos, a rede 192.168.1.0/24, estando de fora o 192.168.1.10.


#também é possível criar lista de IP's para bloqueio
table <sites_com_virus> persist file "/root/virus.txt"

#Para adicionar mais IP's na tabela, podemos usar o comando, se não existir a tabela ele vai criar uma
pfctl -t sites_com_virus -T add 192.168.40.0/16

#Exibição do conteudo de um tabela, use o comando
pfctl -t sites_com_virus -T show

#Para remoção de dados de uma tabela que está rodando em memória, use o parâmetro delete:
pfctl -t sites_com_virus -T delete 192.168.40.0/16


########## Filtro de pacotes no PF

Lógica: ação direção [log] [quick] on interface [af] [proto protocolo] from src_addr/netmask [port src_port] to dst_addr/netmask [port dst_port]

ação: infroma se é bloqueio ou liberação. pass ou block

direção: in ou out, ou seja, entrando e saindo do firewall

log: informa se a atividade estará sendo logada no sistema de logs

quick: Indica se o pacote se enquadra com a regra proposta na linha do quick, a regra é considerada a última a ser examinada e a ação é instantanea

af: Família de endereços que pertence a interface(IPv4 ou IPV6), o padrão é IPv4

protocolo: referenciar o protocolo usado(TCP,UDP,ICMP,ICMP6) ver todos em /etc/protocols 

src_addr: endereço de origem, com sua mascara de rede

dst_addr: endereço de destino, com sua mascara de rede

src_port/dst_port: Portas de origem e destino, podem ser especificadas diretamente ou com o uso de limitação de ranges:

!= Diferente
< Menor que
> Maior que
<= Menor ou igual
>= Maior ou igual
>< range
<> range inverso

tcp_flags: Flags que devem ser definidas no header TCP, usado pelo protocolo tcp. Exemplo, regras de SYN ou ACK
S(SYN): Synchronize: Indica a requisição para o início da sessão
R(RST): Reset: encerra a conexão
P(PUSH): Push: pacote é enviado imediatamente
A(ACK): Acknowledgement
U(URG): Urgente
E(ECE): Notifica congestionamento explicitamente
W(WCR): Janela de congestionamento é reduzida

state: Estado da informação no pacote

keep state: Mantem o estado anterior(protocolos TCP,UDP e ICMP).

modulate state: Funciona somente para pacotes TCP. São feitas sequências fortes para os pacotes para elevar a segurança da conexão.

synproxy state: Elabora um proxy de pacotes que chegam para conexões TCP visando proteger servidores de ataques do tipo spoof TCP SYN. 

#Existem dois tipos de bloqueio:
#
#Tudo é bloqueado até que seja explicitamente necessário ou tudo é permitido até que se prove o contrário

#Bloqueia tudo na entrada e na saída
block in all
block out all

#Para haver resposta de bloqueio para a tentativa, necessário usar return
block return in all
block return out all

#Caso queira logar tudo 
block in log all
block out log all

####### Exemplos

# Permite que o tráfego de entrada e saída pela interface fxp0 da rede 
# Do endereço 10.10.10.0/24 para o endereço 10.10.10.1
pass in on fxp0 from 10.10.10.0/24 to 10.10.10.1
pass out on fxp0 from 10.10.10.0/24 to 10.10.10.1

#Permite trafego de entrada pela interface fxp0 com o protocolo
#tcp de qualquer lugar para o endereço IP 10.10.10.1 na porta 10.10.10.1 na porta www(80)
pass in on fxp0 proto tcp from any to 10.10.10.1 port www



###### Antispoof


Lógica: antispoof [log] [quick] for interface [af]

log: Especifica se o pacote será logado no sistema de logs.

quick: Se o pacote coincidir com uma regra, ele será removido da pilha de pacotes

interface: a interface de rede que deve ser verificada

#Exemplo
antispoof for fxp0 inet 
#No exemplo, a interface fxp0 tem o endereço IP 10.1.10.1 e a mascara de /24, assim a regra exibida pode ser interpretada pelo sistema como:

block in on !fxp0 inet from 10.1.10.0/24 to any
block in inet from 10.1.10.1 to any

#Isso faz com que:
#Todo o tráfego vindo da rede 10.1.10.0/24, que não passou pela interaface fxp0, seja bloqueado
#Como o sistema não envia pacotes para si mesmo pela interface externa, qualquer pacote externo que passe pela interface de entrada será bloqueado.

#####IMPORTANTE LOOPBACK SEMPRE LIBERADO
pass quick on lo0 all

antispoof for fxp0 inet

########################### Exemplo de FW #######################################

#Variáveis macro
EXT_IF="fxp3"
INT_IF="fxp2"
rede_interna: "177.254.200.0/24"

#Bloqueando pacotes de combinações ilegais de sinalizações SYN,FIN ou RST
scrub in all

#Definindo regras globais pro router
block in all
block out all

#Permite o tráfego de loopback em qualquer direção no router
pass quick on lo0 all

#Ativa a proteção de ataque spoof na interface interna
antispoof quick for $INT_IF inet
antispoof quick fro $INT_IF inet6

#Permite o uso de ssh somente das máquinas internas para servidores confiáveis
block return in quick on $INT_IF proto tcp from !10.40.1.45 to $INT_IF port ssh

#Permite o tráfego da rede interna
pass in on $INT_IF from $rede_interna to any
pass out on $INT_IF from any to $rede_interna

#Permite o tráfego dos protocolos tcp,udp e icmp na interface externa, mas elabora keep state para conexões que usem o protocolo
pass out on $EXT_IF proto tcp all modulate state flags S/SA 
pass out on $EXT_IF proto { udp,icmp } all keep state





########## Funcionamento do NAT no PF

Lógica: nat [pass] on interface [af] from origem [port porta_origem] to destino [port porta_destino] -> endereço_externo[pool_type] [static-port]

pass: Faz com que as instruções do NAT não usem as regras de filtros 

interface: Variável ou nome da interface usada

af: Família de endereços: inet(IPv4) ou inet6(IPV6)

origem/destino: Endereço que sofrerá influência do NAT podendo ser, um único endereço IP ou uma sub-rede ou bloco de IPs, um FQDN ou nome de uma interface de rede
seguido por uma máscara, ou uma tabela ou lista 

porta_origem/porta_destino: Portas podem ser especificadas ou com delimitação de ranges
!= Diferente
< Menor que
> Maior que
<= Menor ou igual
>= Maior ou igual
>< Intervalo
<> Intervalo inverso

endereço_externo: Endereço da placa de rede externa que fará o NAT, tornando-se o que chamamos de NAT gateway. Poder ser, uma lista de endereços, um bloco de rede,
um único endereço IP, um FQDN

pool_type: Grupo de endereços que será usado no momento da tradução ou no momento do mapeamento NAT. Isso referencia a quantidade de endereços externos que serão 
usados. Podemos mapear para um único endereço externo ou para vários endereços externos

static-port: Informa o sistema NAT para não efetuar a tradução das portas da máquina-fonte(cliente) para pacotes TCP ou UDP.

####Exemplos de NAT

nat on rl0 from fxp0/24 to any -> rl0
#Essa configuração é prática, pois não se prende a endereços IP. Assim, podemos mudar o endereço das interfaces envolvidas sem influenciar o mapeamento elaborado.


##Também é possível fazer NAT com exceções
no nat on tl0 from 192.168.25.90 to any
nat on tl0 from 192.168.25.0/24 to any -> 10.10.10.1
# A rede 192.168.25.0/24 terá seus pacotes nateados com o endereço externo 10.10.10.1, exceto para o computador 192.168.25.90


########## Redirecionamento de pacotes

Lógica: rdr on Interface proto protocolo from origem to destino port -> IP port 

##Exemplo de redirecionamento
#O primeiro exemplo redireciona todo o tráfego TCP e UDP da interface interna de qualquer host destinato à porta 80 ao endereço IP contido na macro Firewall na porta 81.

Interface_Interna:"xl0"
Firewall:"10.10.11.1/32"
rdr on $Interface_Interna proto { tcp,udp } from any to any port 80 -> $Firewall port 81

#O exemplo abaixo usa o comando rdr para redirecionar todo o tráfego TCP destinado à porta 80 para um dos três servidores web definidos, ocasionando um balanceamento de carga
#Esses servidores web devem estar dentro da sub-rede da interface interna(xl0)

servidores_web="{10.10.11.10,10.10.11.11,10.10.11.12,}"
rdr on $ext_if proto tcp from any to port 80 -> $servidores_web


########### Visualização de logs do pflog

# O PFlog lança os logs no arquivo em tcpdump em formato binário, então vamos ter que usar o tcpdump pra visualizar o log
#Exemplo de visualização da porta 80 no log 
tcpdump -n -e -ttt -r /var/log/pflog port 80

#-ttt significa que é no formato extendido

#Mais infos
# https://www.openbsd.org/faq/pf/logging.html


########## Bloqueio de bruteforce

#Primeiro criar a tabela para armazenar os IP's bloqueiados
table < bruteforce > persist

#Depois cria a regra de drop
block quick from < bruteforce >

#Regra de liberação com rate
pass proto tcp to $rede_interna port ssh keep state ( max-src-conn 100, max-src-conn-rate 15/5, overload < bruteforce > flush global)

Onde:
max-src-conn : máximo de conexões simultaneas por host
max-src-conn-rate: máximo de novas conexões de um único host. No exemplo acima, são 15 novas conexões em 5 segundos
overload < bruteforce >: qualquer host que exceder os limites, são adicionados a tabela bruteforce, como já tem a regra de bloqueio antes, vai dropar
flush global: quando o host atingir os limites configurados, todos os estados de conexão são terminados

########## Visualização de tabelas no PF

# visualizar tabelas
pfctl -s Tables

# Inserir manualmente nas tabelas
pfctl -t bruteforce -T add 1.1.1.1

#Remover das tabelas
pfctl -t bruteforce -T delete 1.1.1.1

# Visualizar conteudo de uma tabela
sudo pfctl -t ospf -T show





Have a nice day =D

Nenhum comentário:

Postar um comentário