CGNAT na pratica

De Wiki BPF
Ir para navegação Ir para pesquisar

Objetivo:

Com o esgotamento do IPv4 mundialmente, precisamos tomar algumas providências para que a Internet não pare. As que vejo de imediatas são: IPv6 e CGNAT (Carrier Grade NAT). O IPv6 é a real solução para os problemas de esgotamento e o CGNAT seria a "gambiarra" necessária para continuar com o IPv4 até que a Internet esteja 100% em IPv6. Nesse artigo será explicado como montar uma caixa CGNAT funcional para atender as necessidades básicas. O que será colocado abaixo, funciona muito bem aqui no nosso AS e nos permite avançar com o IPv6. No nosso exemplo as caixas PPPoE (B-RAS - Broadband Remote Access Server) não fazem NAT, pois o recurso de controlar estados de conexões e controles de NAT, consomem muito processamento e podem atrapalhar a performance da caixa PPPoE.

Diagrama de exemplo:

Diagrama exemplo do CGNAT.png

No B-RAS é configurado um PBR (Policy Based Routing) onde apenas IPs do bloco 100.64.0.0/10 são roteados diretamente para a caixa CGNAT. Qualquer IPv4 público ou IPv6, são roteados diretamente para o Router/Firewall. Isso evita processamento e tráfego desnecessário na caixa de CGNAT. Através dessa manobra evitamos qualquer uso de stateful e NAT no B-RAS, aumentando a performance do mesmo. No diagrama ao lado a linha vermelha simboliza o tráfego do bloco 100.64.0.0/10 indo para o CGNAT. A linha amarela seria o tráfego já nateado e sendo roteado para o Router/Firewall. A linha verde é o tráfego mais limpo, sem "gambiarras" e o real objetivo que devemos seguir para uma Internet melhor.

O Router/Firewall é um equipamento onde podemos inserir algumas regras de Firewall stateless para filtrar alguns pacotes indesejados como alguns tipos de spoofing, alguns pacotes UDP de certas portas usadas para ataques de amplificação, etc. Nunca! Jamais faça uso de regras stateful nesse nível de Firewall, pois determinados ataques podem estourar suas tabelas de controle de estados de conexões e derrubar todo o tráfego.

O Router de Borda dispensa comentários não é mesmo? Vamos voltar para o conteúdo que realmente interessa.

O objetivo deste artigo é exemplificar algumas configurações básicas e deixar para o leitor criar suas próprias ferramentas para facilitar a criação das regras que na maioria das vezes são em grande quantidade e inviável de se fazer manualmente.

Algumas ferramentas de uso público serão comentadas e passadas as devidas referências.

Dados técnicos do equipamento usado no exemplo:

  • Intel Dual Xeon E5-2630 v2 @ 3.1GHz.
  • 16Gb de RAM.
  • 2 interfaces Intel X520-SR2 (2 portas ópticas de 10GbE).
  • 1 SSD 120Gb.

Dados técnicos do Sistema usado:

  • Debian 9 (stretch) 64 bits.
  • kernel 4.19 (backports do Debian).
  • Netfilter/IPTables.

Gráficos CGNAT em produção:

Zabbix cgnat.png
Bmon.png
Htop.png

Descrição:

Como todo bom sistema não basta apenas instalar os programas e por um passe de mágica tudo funcionar como deveria. Estamos falando aqui de um sistema que se mal configurado, a caixa apresentará problemas de performance e você não conseguirá alcançar seu objetivo que é montar uma caixa CGNAT BBB (Bom Bonito e Barato). Para isso você vai precisar instalar um sistema Debian 9 64 bits e remover todos os serviços desnecessários. Faça uma instalação bem clean, Mantenha o serviço sshd rodando para que possa acessar remotamente e continuar configurando o equipamento. Lembre-se: serviços desnecessários rodando, poderão ser uma vulnerabilidade no futuro. O sistema aqui em produção gerencia um tráfego de CGNAT, em horário de pico, de 3Gbps e com bastante folga de recursos. Abaixo continuaremos com as configurações do sistema.

CPU Affinity:

Balancear o tráfego das interfaces de rede em seus devidos cores é importantíssimo para o melhor aproveitamento do hardware. Essa configuração é um pouco mais complexa quando estamos trabalhando com arquitetura NUMA. Usando NUMA é importante verificar se a mother board possui gerencia de slots por CPU. Dessa forma você pode colocar uma interface de 10GbE em um slot gerenciado pela CPU0 e uma outra interface de 10GbE em outro slot gerenciado pela CPU1. Isso você pode procurar no manual técnico da mother board. Para checar qual CPU é responsável pela sua interface de rede, use o comando abaixo substituindo <interface> pela interface desejada. Obs.: se o valor retornado for -1 sua mother board não é boa pra CPU affinity. Os valores retornados para um equipamento com 2 CPUs deveriam ser 0 ou 1. Onde 0 seria CPU0 e 1, CPU1.

# cat /sys/class/net/<interface>/device/numa_node

Para saber os cores relacionados à CPU podemos usar os seguintes comandos abaixo:

# cat /sys/devices/system/node/node0/cpulist

0-5

# cat /sys/devices/system/node/node1/cpulist

6-11

Um conjunto de ferramentas que costumo usar é o netutils-linux que pode ser encontrado aqui. Nele encontrará ferramentas para setar o cpu affinity, maximizar a frequência das CPUs e aumentar o buffer de rx das interfaces de rede.

Variáveis /proc:

Vamos fazer alguns ajustes nas variáveis do /proc porque como o sistema vai utilizar o recurso de conntracks, precisamos mexer em alguns timeouts tcp/udp e outras variáveis. Isso faz parte do tuning para que o sistema fique mais leve e performático. Caso não façamos essas alterações, corremos o risco de estourar a tabela de conntracks e interromper os acessos.

echo 5 > /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_syn_sent

echo 5 > /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_syn_recv

echo 300 > /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_established

echo 10 > /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_fin_wait

echo 10 > /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_close_wait

echo 10 > /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_last_ack

echo 10 > /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_time_wait

echo 10 > /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_close

echo 3 > /proc/sys/net/netfilter/nf_conntrack_tcp_max_retrans

echo 300 > /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_unacknowledged

echo 10 > /proc/sys/net/netfilter/nf_conntrack_udp_timeout

echo 180 > /proc/sys/net/netfilter/nf_conntrack_udp_timeout_stream

echo 10 > /proc/sys/net/netfilter/nf_conntrack_icmp_timeout

echo 600 > /proc/sys/net/netfilter/nf_conntrack_generic_timeout

Variáveis sysctl:

Agora temos umas poucas variáveis de sysctl para justar em /etc/sysctl.conf:

net.core.default_qdisc=fq

net.ipv4.tcp_congestion_control=bbr

net.core.rmem_max = 2147483647

net.core.wmem_max = 2147483647

net.ipv4.tcp_rmem = 4096 87380 2147483647

net.ipv4.tcp_wmem = 4096 65536 2147483647

net.ipv4.conf.all.forwarding=1

net.ipv6.conf.all.forwarding=1

Ativando o BBR (TCP Congestion Control do Google):

O Google desenvolveu um TCP Congestion Control que já no kernel da distro Debian e pode ser facilmente habilitado. A finalidade é ter um melhor controle do congestionamento dos fluxos de TCP. Seria um substituto para o CUBIC e New Reno. Nas variáveis sysctl acima especificamos o BBR mas precisamo carregar o módulo do kernel antes de usá-lo. Basta adicionarmos o tcp_bbr em /etc/modules que o mesmo será carregado após o boot do sistema. Também adicionei o dummy que não tem nenhum relacionamento com o BBR, mas que será usado para criarmos as interfaces virtuais com os IPs públicos que serão usados no NAT.

tcp_bbr

dummy

Arquivos de configuração do Sistema:

Os arquivos de configurações do Sistema, são aqueles que usaremos para fazer algumas optimizações, levantar as interfaces de rede e carregar as regras de CGNAT propriamente ditas. Esses arquivos foram alterados para o nosso exemplo e são mais para dar uma ideia de como podem ser feitos. Cabe ao leitor decidir a melhor forma de implementar o que será colocado à seguir. O objetivo é fazer com que o sysadmin melhore e crie novas maneiras de se fazer o proposto nesse artigo.

/etc/network/interfaces:

Interfaces.png

O /usr/local/bin/rx-buffers-increase é uma das ferramentas do netutils-linux, citado mais acima. A interface ens5f0 é a interface externa do CGNAT que fala com o Router/Firewall e a ens5f1, a interface interna do CGNAT que fala com o B-RAS.

/etc/rc.local:

Rc local.png