Por: @jonasc
Publicado em: 2021-01-29
Inspeção de Pacotes e Controle de Acesso com nDPI Netify
O produto Netify é mantido pela empresa eGloo, que desenvolveu uma versão aprimorada da biblioteca nDPI NTOP. Os dois principais softwares open source (licença LGPLv3) mantidos pela empresa são o NETIFY AGENT - NETIFYD e o NETIFY FIREWALL AGENT - FWA.
O Netifyd é o motor responsável pela análise de rede usando o DPI (deep packet inspection). A função deste agente é fazer capturas de pacotes, analisar os metadados e classificar os tipos de protocolos e serviços que estão passando na rede em tempo real. Para fluxos TCP, ele examina os primeiros 10 pacotes, para outros datagramas, os primeiros 8 pacotes são processados.
O Netify Firewall Agent é um software que se integra ao Netifyd, fazendo a marcação dos pacotes classificados e também o controle de acesso (bloqueio). Futuramente este agente permitirá também a priorização de tráfego (QoS), função ainda em desenvolvimento pela empresa.
Será documentado o uso do FWA para bloquear aplicações específicas, em um cenário que navegação é completamente liberada. Para liberar aplicações em um cenário que o firewall bloqueia tudo não é possível, pois o bloqueio ocorre em camada 4 no primeiro pacote SYN TCP do handshake, logo o netifyd não consegue processar os 10 primeiros pacotes de dados.
Topologia
Topologia de rede padrão com FWFLEX sobre CentOS 8. Requisitos mínimos: 1x LAN e 1x WAN.
NETIFY AGENT - NETIFYD
Instalação
Instalação via repositório RPM:
rpm --import http://download.netify.ai/netify/centos/`rpm --eval '%{centos_ver}'`/stable/RPM-GPG-KEY-netify
curl http://download.netify.ai/netify/centos/`rpm --eval '%{centos_ver}'`/netify.repo -o /etc/yum.repos.d/netify.repo
yum install netifyd
Para validar a instalação e funcionamento básico, salve um arquivo pcap para análise.
tcpdump -nnni ens18 -s0 -w /tmp/teste.pcap
Teste para validar a ferramenta:
[root@localhost ~]# netifyd -d -t -r -I lo,/tmp/teste.pcap
Flow entry size: 8576
void ndSocket::Create(): created
Loading custom protocols from: /etc/netify.d/netify-sink.conf
lo,/tmp/teste.pcap: flows_map, buckets: 1741, max_load: 1,000000
lo: capture file: /tmp/teste.pcap
lo: Loaded 0 flow hash cache entries.
lo,/tmp/teste.pcap: hwaddr: 00:00:00:00:00:00
lo: detection thread created, custom_proto_base: 243.
virtual void* ndSocketThread::Entry(): started
Cumulative Byte Totals:
Wire: 54 KiB
IP: 44.8 KiB IPv4: 44.8 KiB IPv6: 0
Discarded: 5.04 KiB Flows: 11 (+6)
lo: [i4----] DNS.142.netify.whatsapp 172.28.60.13:37477 --> 192.168.47.254:53 H: whatsapp.com
lo: [i4--d-] ICMP.142.netify.whatsapp 157.240.14.52:0 <-- 172.28.60.13:0 H: whatsapp.com
lo: [i4----] DNS.10006.netify.reverse-dns 172.28.60.13:58084 --> 192.168.47.254:53 H: 52.14.240.157.in-addr.arpa
lo: [i4----] DNS 172.28.60.13:51946 --> 192.168.47.254:53 H: ftp.itflex.com.br
lo: end of capture file: /tmp/teste.pcap
lo: capture ended on CPU: 0
Caught signal: [35] Sinal de tempo-real 1: Update
Cumulative Packet Totals [Uptime: 0d 00:01:00]:
Wire: 666 ETH: 666 VLAN: 0
IP: 555 IPv4: 555 IPv6: 0
ICMP/IGMP: 10 UDP: 26 TCP: 519
MPLS: 0 PPPoE: 0
Frags: 0 Discarded: 111 Largest: 1.54 KiB
Cumulative Byte Totals:
Wire: 73 KiB
IP: 60 KiB IPv4: 60 KiB IPv6: 0
Discarded: 6.5 KiB Flows: 15 (+4)
lo: Saved 11 flow hash cache entries.
lo: detection thread destroyed.
netifyd[245419]: Exiting, no remaining detection threads.
Saved 11 of 11 DNS cache entries.
Normal exit.
Configuração
As opções de configuração estão no arquivo /etc/sysconfig/netifyd
. Desative a auto-detecção de redes e especifique as interfaces LAN e WAN. Demais opções podem ficar padrão.
# Auto-detect (when possible) network ineterface roles (yes/no)?
NETIFYD_AUTODETECT="no"
# Define internal network interfaces and if needed, corresponding network
# addresses. Normally network addresses are discovered via Netlink but for
# cases where Netlink is unavailable or when capturing from a mirrored port,
# they should be specified as a comma-delimited list as shown below:
NETIFYD_INTNET="ens20,10.123.55.0/24"
# Define external network interfaces. For PPPoE interfaces, you can optionally
# specify the associated physical ethernet interface to set the MAC address.
NETIFYD_EXTNET="ens19,192.168.10.0/24"
Habilitar e iniciar o serviço:
netifyd --enable-sink
systemctl start netifyd
systemctl enable netifyd
Por último, o guia sugere provisionamento e registro na Netify. Porém esta etapa é opcional.
NETIFY FIREWALL AGENT - FWA
Instalação
Atualmente só há pacotes para o ClearOS, sendo necessário compilar para o CentOS.
Build através do código fonte:
cd /usr/src/
git clone https://gitlab.com/netify.ai/public/netify-fwa.git
cd netify-fwa
./autogen.sh
Gerando RPMs de instalação:
./configure
make dist-gzip
mkdir -p ~/rpmbuild/SOURCES/
cp netify-fwa*.tar.gz ~/rpmbuild/SOURCES/
rpmbuild -ba ./deploy/rpm/netify-fwa.spec
Instalando dependências do RPM:
yum install scl-utils
yum install http://mirror.centos.org/centos/7/sclo/x86_64/rh/Packages/r/rh-python36-runtime-2.0-1.el7.x86_64.rpm
OBS: Requer o pacote python36-runtime, porém não está disponível ainda para CentOS 8, somente no repositório CentOS 7.
Instando o RPM:
yum localinstall ~/rpmbuild/RPMS/noarch/netify-fwa-1.2.5-1.el8.noarch.rpm
Configuração
Opções do serviço
O principal arquivo de configuração é o /etc/netify-fwa/netify-fwa.ini
. As configurações padrão atendem a necessidade, porém é possível alterar opções como timeout dos endereços no ipset, o valor da marcação na tabela mangle, entre outros. Para mais detalhes, consulte o guia disponível na seção de Links Relacionados.
É necessário apenas especificar os devices de interfaces LAN e WAN.
interfaces-external = ens19,ens20
interfaces-internal = ens18
Configuração de regras
A definição das políticas e regras para priorização, marcação e bloqueio de pacotes, é feita através do arquivo /etc/netify-fwa/netify-fwa.json
em formato JSON. A estrutura do JSON inclui:
- versão;
- lista de regras para protocolos e serviços;
- ação para as regras: block ou prioritize*;
- whitelist (exceções).
* As regras do tipo prioritize
serão implementadas no software futuramente. O JSON já possui sintaxe e algumas opções preparadas, mas somente como rascunho. O software não faz absolutamente nada com estas aplicações.
Há dois tipos de ação para as regras: block
para bloquear via iptables quando casar a regra (match-set) e prioritize
para aplicar uma prioridade de QoS ao tráfego. A configuração também permite definir faixa de horários e dias da semana para as regras *. As regras podem ser definidas por ID de protocolo do Netify Agent (ex. 7 - HTTP), por ID de categoria de protocolos (ex. 10 - Instant Messaging), por ID de aplicação (ex. 119 - Facebook) ou por ID de categoria de aplicação (ex. 24 - Social Media).
* Problema: O módulo xt_time, necessário para o netify-fwa, foi removido do RHEL / CentOS 8 de propósito. Segundo resposta da Red Hat no bug aberto, é mais performático deixar regras sempre criadas e usar algum mecanismo como a crontab para add/remover hosts de um ipset atrelado à regra. Porém o netify-fwa usa o xt_time. Solução: Compilar o kernel com o módulo faltante. Mais detalhes nesta lista de discussão.
A whitelist aceita somente IP ou rede no formato com prefixo, exemplo 192.0.0.10/32
.
Estrutura base do arquivo de configuração:
{
"version": "1.0",
"rules": [],
"whitelist": []
}
Exemplo de configuração: Bloquear o Facebook e a categoria de aplicações de file sharing:
{
"version": "1.0",
"rules": [
{
"type": "block",
"application": 119
},
{
"type": "block",
"application_category": 10,
"weekdays": "Mo,Tu,We,Th,Fr",
"time-start": "8:00",
"time-stop": "18:00"
}
],
"whitelist": [
{
"type": "ipv4",
"address": "192.0.0.10\/32"
}
]
}
OBS: Devido a falta do módulo xt_time, o laboratório foi continuado sem as regras de horários.
Habilitando e iniciando o serviço:
systemctl start netify-fwa
systemctl enable netify-fwa
Debugging:
Algumas formas de debug:
# Is the service running?
systemctl status netify-fwa
# look for chains that begin with NFA
iptables -t mangle -L -v -n
# look for sets that begin with NFA
ipset -L
# the service can be run in debug mode which emits extra debug logging
systemctl stop netify-fwa
netify-fwa -d
(CTRL-C to quit)
Testes
Com as aplicações netifyd e netify-fwa em execução, foi realizado algumas simulações para testes e validação da ferramenta.
Configuração inicial, bloqueando a aplicação Facebook e a categoria de aplicações File sharing, adicionando um IP como exceção. Foi também configurando a aplicação Instagram como prioritize, mas o software desconsidera este tipo.
{
"version": "1.0",
"rules": [
{
"type": "block",
"application": 119
},
{
"type": "prioritize",
"application": 201,
"priority": 2
},
{
"type": "block",
"application_category": 10
}
],
"whitelist": [
{
"type": "ipv4",
"address": "192.0.0.10\/32"
}
]
}
Segundo teste realizado no spike #45435, bloqueando Twitter, Netflix, Facebook, Spotify, WhatsApp e TikTok:
{
"version": "1.0",
"rules": [
{
"type": "block",
"application": 120
},
{
"type": "block",
"application": 133
},
{
"type": "block",
"application": 119
},
{
"type": "block",
"application": 156
},
{
"type": "block",
"application": 142
},
{
"type": "block",
"application": 10302
}
],
"whitelist": [
{
"type": "ipv4",
"address": "0.0.0.0/0"
}
]
}
Para detalhes dos protocolos e aplicações, fácil consulta em:
Os IDs das categorias de protocolos e aplicações não aparecem no site. Em /etc/netify-fwa/app-proto-data.json
existe o mapeamento dos IDs, labels e ícones de aplicações e protocolos, além de trazer também os IDs de categorias e labels correspondentes. Em /etc/netify-fwa/netify-categories.json
existe a lista de todos os IDs de protocolos e serviços e a quais categorias eles pertencem.
Para facilitar a leitura:
cat app-proto-data.json | python3 -m json.tool | grep -B1 -A2 Instagram
Resultados
Conforme os usuários tentam acessar as aplicações, o Netify dinamicamente adiciona os endereços a ipsets. Os ipsets são usados para realizar DROP na tabela mangle do iptables.
ipsets criados:
[root@localhost ~]# ipset -L
Name: NFA4_0_0_119_0
Type: hash:ip,port,ip
Revision: 5
Header: family inet hashsize 1024 maxelem 65536 timeout 1200
Size in memory: 512
References: 3
Number of entries: 3
Members:
157.240.226.35,tcp:443,10.123.55.10 timeout 1176
157.240.226.14,tcp:443,10.123.55.10 timeout 1176
157.240.226.13,tcp:443,10.123.55.10 timeout 119
Name: NFA4_0_0_0_10
Type: hash:ip,port,ip
Revision: 5
Header: family inet hashsize 1024 maxelem 65536 timeout 1200
Size in memory: 1024
References: 3
Number of entries: 7
Members:
13.225.218.108,tcp:443,10.123.55.10 timeout 390
162.125.248.18,tcp:443,10.123.55.10 timeout 115
104.16.100.29,tcp:443,10.123.55.10 timeout 1187
162.125.5.18,tcp:443,10.123.55.10 timeout 1187
104.16.99.29,tcp:443,10.123.55.10 timeout 115
13.225.218.17,tcp:443,10.123.55.10 timeout 1187
65.8.205.8,tcp:443,10.123.55.10 timeout 116
Comportamento padrão: Tudo é marcado e bloqueado via tabela mangle:
iptables -t mangle -nvL
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
495 160K NFA_whitelist all -- * * 0.0.0.0/0 0.0.0.0/0
245 125K NFA_ingress all -- ens19 * 0.0.0.0/0 0.0.0.0/0
250 35152 NFA_egress all -- ens20 * 0.0.0.0/0 0.0.0.0/0
0 0 NFA_block all -- * * 0.0.0.0/0 0.0.0.0/0 mark match ! 0x0/0x800
- Para IPs da whitelist (origem ou destino) é realizado ACCEPT;
- Tráfego de entrada da LAN que casar com o ipset é feito mark 0x800;
- Tráfego de saída da WAN que casar com o ipset é feito mark 0x800;
- NFA_block faz DROP de todo tráfego com mark 0x800.
Integração com o FWFLEX
Limitação: Usando somente o Netify, ou bloqueia-se tudo ou nada, permitindo cadastrar apenas algumas exceções.
Possível solução: Configurar Whitelist 0.0.0.0/0
para que o serviço crie os ipsets, mas sem regras de bloqueio no firewall.
As regras de bloqueio podem ser feitas através do iptables, usando o motor do FWFLEX e permitindo mais filtros para as regras. Por exemplo, bloquear somente para a origem 10.123.55.10
:
iptables -A FORWARD -s 10.123.55.10 -m set --match-set NFA4_0_0_0_10 dst,dst,src -j DROP
iptables -A FORWARD -s 10.123.55.10 -m set --match-set NFA4_0_0_119_0 dst,dst,src -j DROP
Evidência de bloqueio no iptables:
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
59 6652 DROP all -- * * 10.123.55.10 0.0.0.0/0 match-set NFA4_0_0_0_10 dst,dst,src
43 2153 DROP all -- * * 10.123.55.10 0.0.0.0/0 match-set NFA4_0_0_119_0 dst,dst,src
Para o usuário, a página fica carregando por alguns segundos, até ocorrer o timeout da requisição. Em apenas um dos testes, o Facebook abriu uma página quebrada, sem formatação, conforme imagem.
Acesso ao Facebook:

Acesso ao Dropbox:

Performance
Ambiente de laboratório não apresentou nenhum tipo de sobrecarga. Necessário avaliar em ambiente com mais regras e mais fluxos.
Resultados
Ferramenta de fácil configuração e implementação. Se mostrou aderente ao produto. Necessário avaliar performance com maior volume de tráfego e regras.
Não se mostrou viável para liberar aplicações em um cenário que o firewall bloqueia tudo. O bloqueio do iptables ocorre em camada 4 no primeiro pacote SYN TCP do handshake, logo o netifyd não consegue processar os 10 primeiros pacotes de dados.