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.