Ajuste fino e tuning no kernel Linux

Saudações. Nesse artigo vou expor alguns problemas graves do comportamento padrão do Kernel Linux e como você pode tirar proveito do seu hardware com ajustes finos pontuais.

Artigo vivo, sofrerá adições constantes.

Visualize: você recebeu um carregamento de 5 mil tijolos e contratou uma pessoa para recolhe-los ao seu depósito nos fundos do imóvel. A pessoa pega o carrinho de mão, coloca um único tijolo e faz a viagem de 30 metros, gastando 1 minuto.

Obviamente, a pessoa poderia colocar no mínimo 16 tijolos no carrinho!

O tamanho do carrinho importa, a quantidade de tijolos importa, tudo isso precisa ser definido para que o trabalho seja executado de maneira eficiente importa.

Assim, dizer que “a configuração de 1 tijolo por viagem” é uma configuração padrão que satisfaz todos os tamanhos de carrinho que existem. É exatamente assim que o kernel Linux se comporta.

O kernel Linux possui parâmetros (valores iniciais de operação) para trabalhar em hardwares medíocres e fracos pois são maioria.

Entendido isso, quando você vai rodar em um servidor cujo hardware é centenas de vezes mais poderoso que um PC ou notebook, o kernel não fará uso de todo esse poder e velocidade.

No exemplo do tijolo, seu kernel usando apenas 1 megabyte de memória por vez para transmitir um arquivo de 500 GB é um exemplo, esse valor poderia ser 128 megabytes se você tem 32 GB de RAM que não fará diferença para a RAM, mas fará total diferença performance da transferência.

Ao rodar o Linux em servidores de alta-performance ele continuará a trabalhar de maneira limitada, evitando alocar grandes volumes de memória, acionando SWAP, usando pequenos segmentos repetitivamente, sobrecarregando um único núcleo enquanto os demais ficam ociosos. Tudo com o objetivo de favorecer pequenos hardwares e ambientes tímidos em desfavor de servidores ou computadores mais fortes.

O mundo do software livre tem uma pequena armadilha:

Se o software é gratuito a única forma de pegar seu dinheiro é com suporte técnico e versões "premium". Todas as configurações iniciais do sistema serão pensadas em causar problemas no médio e longo prazo visando impedir o escalonamento. 

Ao subir em ambientes para volumes lucrativos você irá se deparar com problemas sem fim até que sua única saída seja adquirir uma versão especial do software ou pagar pela consultoria de “ajustes finos”.

Você deve sempre presumir que todos os ajustes iniciais são SABOTAGENS para te prejudicar.

Vou compartilhar com você todos os ajustes finos do kernel Linux e como eles afetam a performance. Vamos começar pelos conceitos de procfs, sysfs e sysctl.

PROCFS e SYSFS

O parâmetros iniciais do kernel são definidos no código fonte e compilados, não podem ser alterados depois disso e o Linux que você instalou está assim. Ao ser carregado na memória pela primeira vez o kernel se porta com timidez.

Uma vez “acordado”, o kernel então pode ser orientado a assumir parâmetros mais realistas somente e tão somente se você ordenar. Existem 3 canais de instrução de parâmetros o kernel:

  • Via arquivos virtuais em /sys
  • Via arquivos virtuais em /proc/sys
  • Via SYSCALL (mensagens para a API do kernel);

Todos os parâmetro informados o kernel são armazenados na memória RAM e serão perdidos em caso de reboot.

O kernel tem uma forma simples de permitir que programas obtenham informações de sua estrutura interna por meio de arquivos virtuais. Dois pontos de montagem coordenam esses acessos:

  • /proc: montado (procfs) durante o boot inicial (initrd), essa pasta permite que você “enxergue” o conteúdo do kernel em formato de arquivos. Todos os arquivos e diretórios dentro de /proc são virtuais, eles só existem na memória RAM. Alguns são “somente leitura” e servem como relatórios informativos. Outros (/proc/sys) são para permitir que você manipule o comportamento do kernel.
  • /sys: semelhante ao /proc, mas de tipo diferente (sysfs) e propósito diferente, o /sys é mais orientado ao hardware periférico, seus componentes e subsistemas (recursos, circuitos, drivers, buffers).

Um módulo do kernel que trata uma tecnologia padronizada deverá ser manifesto em /proc, já opções de um periférico específico (placa de rede, placa de vídeo) deverão ser declarados em /sys.

Como o kernel se comporta, quantidade de RAM que o kernel irá usar, NAT, roteamento: /proc/

Bash
# /proc/, consultando:
cat  /proc/cmdline
cat  /proc/meminfo

# /proc/, alterando:
echo 128 > /proc/sys/net/ipv4/ip_default_ttl

Como usar um núcleo de CPU, desativar threads, controle de energia e frequência de clock, MTU ou MAC de uma interface de rede, sensor de temperatura : /sys

Bash
# /sys/, consultando:
cat  /sys/class/net/eth0/address   # MAC da eth0

# /sys/, alterando para 9000:
echo 9000 > /sys/class/net/eth0/mtu

# /sys/, alterando para 1500 (default, manter esse valor por padrao):
echo 1500 > /sys/class/net/eth0/mtu

Navegue pelas pastas /proc e /sys para se familiarizar melhor!

Kernel e seus parâmetros iniciais

Observe esse comando:

Bash
# Ajustar o kernel para reiniciar apos 5 segundos em caso de Kernel PANIC:
echo 5 > /proc/sys/kernel/panic

Ele grava o número 5 no arquivo virtual “/proc/sys/kernel/panic”.

Aplicação: quando o kernel encontrar algum problema impossível de ser resolvido ele entrará em pânico (tipo a tela azul do windows) e fará a leitura desse valor, se o valor for 0 (zero) ele ficará com a tela travada até que você vá lá no servidor/computador e reinicie-o manualmente. Se o valor for 1 ou maior, ele aguardará esse valor em segundos antes de reiniciar automaticamente.

Você prefere de deslocar até o servidor para reiniciá-lo ou apenas ser avisado que ele reiniciou e que a vida voltou ao normal? Infelizmente o valor inicial é 0 (zero)!

SYSCTL – Sistema de controle de ajustes

Um programa foi criado para facilitar essas configurações, ele se chama sysctl

Ele serve para consultar ou alterar os parâmetros do kernel (apenas /proc).

Sua principal função é tornar possível criar arquivos de configurações que serão aplicados durante o carregamento do kernel Linux (boot).

Durante o boot, os seguintes comandos são executados:

Bash
# Aplica todas as configurações persistentes:
# - Lendo somente diretorios ".d"
sysctl --system

# - Lendo somente arquivo raiz /etc/sysctl.conf
sysctl -p

O comando “sysctl –system” realiza a leitura de arquivos .conf nos seguintes diretórios:

  • /etc/sysctl.d/
  • /run/sysctl.d/
  • /usr/local/lib/sysctl.d/
  • /usr/lib/sysctl.d/
  • /lib/sysctl.d/

Recomendo que você utilize somente o diretório /etc/sysctl.d/ pois ele é o padrão de todas as distribuições Linux. Os demais diretórios podem ser usados por pacotes que colocam neles configurações muito específicas.

Sempre investigue os diretórios acima para saber como seu sistema está sendo manipulado.

O comando “sysctl -p” realiza a leitura exclusiva de um único arquivo: /etc/sysctl.conf

Exemplos (guia rápido) de uso do sysctl:

Bash
# Visualizar um parâmetro especifico:
sysctl kernel.panic

# Visualizar o valor de um parâmetro específico (bom para scripts):
sysctl -n kernel.panic

# Visualizar todos os valores de uma sessão:
sysctl vm
sysctl net.ipv4
sysctl net.ipv4

# Visualizar todos os valores (os 4 comandos baixo são apelidos entre si):
sysctl  -a
sysctl  -A
sysctl  --all
sysctl  -X

# Visualizar todos os parâmetros que possuem "tcp" no nome:
sysctl  -a -r tcp

# Alterar um parâmetro manualmente (sem espaços):
sysctl -w kernel.panic=5
# ou (com espaços mas entre aspas)
sysctl -w "kernel.panic = 5"

# Altera um parâmetro silenciosamente (sem exibir nada, -q = quiet):
sysctl -q -w kernel.panic=5

# Alterar parâmetro com varios valores manualmente:
sysctl -w "net.ipv4.tcp_allowed_congestion_control = reno cubic htcp"

SYSCTL – Configuração persistentes

Agora que você ja aprendeu o conceito e o funcionamento do sysctl vamos criar arquivos com parâmetros personalizados:

Bash
# TTL padrão durante a criação de pacotes IPv4
sysctl net.ipv4.ip_default_ttl
       net.ipv4.ip_default_ttl = 64

# Vamos gravar um arquivo com um parâmetro adequado para servidor: 128
echo "net.ipv4.ip_default_ttl = 128" > /etc/sysctl.d/062-default-ttl-ipv4.conf

# Vamos aplicar todas as configurações (semelhante ao momento do boot):
sysctl -q --system
sysctl -q -p

# Conferindo novo valor
sysctl net.ipv4.ip_default_ttl
       net.ipv4.ip_default_ttl = 128

SYSFS – Configurações periféricas

Infelizmente os parâmetros controlados pelo /sys (SYSFS) não podem ser simplificados pela ferramenta sysctl e requerem outros métodos de personalização.

Para cada módulo, driver ou periférico que se instala em /sys há uma ferramenta específica de manipulação, exemplo:

Bash
# Pacote de controle de opções de rede (interfaces, rotas, tuneis, ...)
apt-get -y install  iproute2

# Alterar MTU da interface eth0 via "ip" do pacote iproute2
ip  link  set  mtu 9000 dev eth0

# Alterar o MTU usando /sys (SYSFS):
echo 1500 > /sys/class/net/eth0/mtu

Meu primeiro conselho é que você estude o parâmetro que deseja alterar e descubra qual ferramenta exata faz essa função pontualmente, e então crie um script e registre-o durante o boot para realizar tal tarefa. Todavia…

O “systemd-tmpfiles” é um subsistema do systemd criado para gerenciar arquivos temporários e tarefas que envolvam arquivos temporários.

Usando a declaração “w” do tmpfiles, podemos ordenar o preenchimento de conteúdo nos arquivos de parâmetros do /sys.

Exemplo de criação de manifesto tmpfile e aplicação imediata:

Bash
# Criar manifesto de preenchimento de arquivo:
echo 'w /sys/class/net/eth0/mtu - - - - 1500' > /etc/tmpfiles.d/eth0-mtu.conf

# Aplicando manifestos do tmpfiles imediatamente:
systemd-tmpfiles --create

Simples assim, o arquivo “/sys/class/net/eth0/mtu” terá seu conteúdo preenchido com o valor “1500” durante o boot.

Já abordamos “o que, pra que, como e onde”, agora vamos aos principais ajustes que faço em meus servidores.

Algumas “maldades” do kernel

O caso SWAP

Um exemplo de parâmetro padrão perigoso é o “vm.swappiness“.

Quando o Linux foi criado, os computadores raramente tinham mais de 64MB de RAM (isso mesmo, muito pouco). Discos IDE/ATA possuíam entre 512M e 2GB.

Como a memória é crítica para execução do kernel, de drivers e programas – Arquitetura de von Neumann – o kernel optou por resolver a falta de memória com um truque chamado SWAP – Memória virtual.

SWAP é um recurso onde parte do disco é usado como “falsa memória RAM”. Quando um programa solicita ao kernel 32MB de RAM, o kernel responde “tudo bem, está aqui o endereço do espaço que você pediu”, e envia ao programa um endereço virtual que está mapeado na partição SWAP do disco. O programa executará muito lento, mas executará!

Memória virtual é todo o montante da memória física (RAM) e memória SWAP.
Programas críticos precisam de acesso direto a memória (MMAP, DMA), os demais programas podem ser mapeados na memória virtual (o programa não sabe se está na RAM ou na SWAP).

Rodar na SWAP é melhor que não rodar!

Criou-se então uma regra antiga, mas defasada, que ao instalar o Linux, devemos reservar no disco rígido para a partição de SWAP o dobro da quantidade de RAM.

Essa regra não faz nenhum sentido nos dias atuais. Um PC com 64GB de RAM é muito comum, sacrificar, baseado nessa regra, 128GB de espaço em SSD/NVME/SATA para SWAP é totalmente sem sentido!

Vamos voltar no tempo em que se tinha 64MB a 128MB de RAM então. O kernel decretava que quando houvesse menos que 60% de RAM livre (40% de uso ou mais) os novos pedidos de espaço em RAM deveriam ser redirecionados para a SWAP.

Em um sistema com 128MB de RAM, ao alocar 51MB (40% de uso) já era possível ver o disco gritando (discos faziam muito barulho antigamente).

Isso é o que vm.swappiness=60 significa.

Essa valor era ideal em 1998, mas é injustificável em 2025.
Um notebook moderno com 8G de RAM iniciará um stress desnecessário do SSD/NVME toda vez que você abrir o navegador, pois o kernel e a interface gráfica/X facilmente alocarão 40% de RAM (3.2GB de uso).

Soluções recomendadas:

  • Na raiz do problema: Não criar partição de SWAP na instalação, ou
  • Pontual: comando “swapoff -a” para desativar o uso de SWAP, e comente o registro da montagem SWAP em /etc/fstab, a partição pode ser utilizada para outros fins ou ficar de prontidão para uso em swap caso necessário,
  • Simples: Definir vm.swappiness em 0 (zero) para que a SWAP só seja acionada com o fim da RAM, ou
  • Elegante: separar uma unidade PCIe 5.0 NVME somente para SWAP, assim ela poderá aumentar absurdamente o volume da memória virtual e prover altíssimas velocidades. Se essa unidade for torrada até a morte com swap isso não irá carregar o sistema inteiro para a morte.

O caso Hugepages

Sistemas operacionais gerenciam o uso de memória de uma forma bem parecida como um livro:

  • As últimas páginas são reservadas ao próprio kernel e seu gerenciamento interno;
  • Todas as páginas do inicio do livro até o kernel são “livres para emprestar”, cada página tem 4KB de espaço.

Sempre que um programa é aberto e solicita 40MB de memória ao kernel, por baixo dos panos o kernel alocou 10 mil páginas de 4KB. É um número muito grande de páginas, e o cache dessas páginas são aceleradas no processador por um recurso chamado TLB, que tem um tamanho muito limitado, assim, o processador não consegue acelerar nada pois vários programas rodando ao mesmo tempo não permite que páginas sejam frequentemente repetidas em sequência.

O recurso hugepages permite que o kernel reserve “páginas do livro memória” para terem 2MB ou 1GB de tamanho. Assim, um programa que solicitar 40MB de RAM vai receber 20 páginas de 2MB e rodar extremamente rápido, tanto na gerência do kernel quanto no TLB do processador. Em processadores de datacenter com 64MB a 512MB de cache interno, essa velocidade é assustadora.

É OBVIO que esse recurso não é ativado por padrão!

Em ambientes com mais de 4GB de RAM, você pode reservar 25% ou mais de RAM para hugepages, dessa forma aplicações como banco de dados, linguagens modernas e gordas como Javascript/Typescript/Node/DENO poderão abusar do uso de RAM sem abusar do processador/TLB/paginação.

Exemplo para um sistema com 64GB de RAM:

Bash
# Conferir quantidade de RAM
free -g
               total      used      free    shared  buff/cache   available
    Mem:          62         1        61         0           0          61
    Swap:          0         0         0

# Conferir status atual das hugepages:
grep '^Huge'  /proc/meminfo
    HugePages_Total:       0         < RUIM, não  nenhuma hugepage
    HugePages_Free:        0
    HugePages_Rsvd:        0
    HugePages_Surp:        0
    Hugepagesize:       2048 kB      < Tamanho padrão de 2048 kB (2MB)
    Hugetlb:               0 kB

# Vamos colocar 25% da RAM em hugepages, 16GB / 2MB = 8 mil hugepages
# - Escolha qual formato de comando você mais gosta!
echo 8192 > /proc/sys/vm/nr_hugepages
sysctl -w 'vm.nr_hugepages=8192'

# Conferindo novamente:
grep '^Huge'  /proc/meminfo
    HugePages_Total:    8192         < 8 mil páginas disponiveis
    HugePages_Free:     8192         < 8 mil p. livres, ninguem pediu ainda
    HugePages_Rsvd:        0
    HugePages_Surp:        0
    Hugepagesize:       2048 kB      < Tamanho padrão de 2048 kB (2MB)
    Hugetlb:        16777216 kB

Caso você queira usar hugepages de 1G você precisará subir a definição do tamanho da HP durante o carregamento do kernel pois esse valor não pode ser alterado em execução, você precisará inserir os seguintes argumentos no boot do kernel – escolha um dos exemplos:

Bash
# - Para HUGEPAGE de 2MB
  # Exemplo de páginas de 2MB, 512 páginas (1 GB em HP)
  default_hugepagesz=2M hugepagesz=2M hugepages=512

  # Exemplo de páginas de 2MB, 1024 páginas (2 GB em HP)
  default_hugepagesz=2M hugepagesz=2M hugepages=1024

  # Exemplo de páginas de 2MB, 2048 páginas (4 GB em HP)
  default_hugepagesz=2M hugepagesz=2M hugepages=2048

  # Exemplo de páginas de 2MB, 4096 páginas (8 GB em HP)
  default_hugepagesz=2M hugepagesz=2M hugepages=4096

  # Exemplo de páginas de 2MB, 8192 páginas (16 GB em HP)
  default_hugepagesz=2M hugepagesz=2M hugepages=8192

# - Para HUGEPAGE de 1G
  # Exemplo de páginas de 1G, 2 páginas (2 GB em HP)
  default_hugepagesz=1G hugepagesz=1G hugepages=2

  # Exemplo de páginas de 1G, 4 páginas (4 GB em HP)
  default_hugepagesz=1G hugepagesz=1G hugepages=4

  # Exemplo de páginas de 1G, 8 páginas (8 GB em HP)
  default_hugepagesz=1G hugepagesz=1G hugepages=8

# Escolha o valor para adicionar na variável GRUB_CMDLINE_LINUX em /etc/default/grub
# e execute em seguida: grub-mkconfig -o /boot/grub/grub.cfg
# Requer reboot.

Exemplos de tuning do Kernel Linux

Bash
# Salvar parâmetros atuais como referência de valores alterados:
sysctl -a  2>/dev/null >  /etc/backup-sysctl.conf

# HugePages - deixei comentado pois depende do
# - volume de RAM
# - tamanho padrao da hugepage
# - espaço total a ser reservado
#(
#    echo  "vm.nr_hugepages=8192"
#)  >  /etc/sysctl.d/040-hugepages.conf

# Liberar mais RAM para aceleração de rede
(
    echo  "net.core.rmem_default=31457280"
    echo  "net.core.wmem_default=31457280"
    echo  "net.core.rmem_max=134217728"
    echo  "net.core.wmem_max=134217728"
    echo  "net.core.netdev_max_backlog=250000"
    echo  "net.core.optmem_max=33554432"
    echo  "net.core.default_qdisc=fq"
    echo  "net.core.somaxconn=4096"
)  >  /etc/sysctl.d/051-net-core.conf

# Aumentar capacidades de rede do protocolo TCP
(
    echo "net.ipv4.tcp_sack = 1"
    echo "net.ipv4.tcp_timestamps = 1"
    echo "net.ipv4.tcp_low_latency = 1"
    echo "net.ipv4.tcp_max_syn_backlog = 8192"
    echo "net.ipv4.tcp_rmem = 4096 87380 67108864"
    echo "net.ipv4.tcp_wmem = 4096 65536 67108864"
    echo "net.ipv4.tcp_mem = 6672016 6682016 7185248"
    echo "net.ipv4.tcp_congestion_control=htcp"
    echo "net.ipv4.tcp_mtu_probing=1"
    echo "net.ipv4.tcp_moderate_rcvbuf =1"
    echo "net.ipv4.tcp_no_metrics_save = 1"
)  >  /etc/sysctl.d/052-net-tcp-ipv4.conf

# Aumentando a faixa de portas de origem (usar toda faixa de portas altas)
(
    echo "net.ipv4.ip_local_port_range=1024 65535"
) >  /etc/sysctl.d/056-port-range-ipv4.conf

# TTL padrão dos pacotes IPv4
(
    echo "net.ipv4.ip_default_ttl=128"
) >  /etc/sysctl.d/062-default-ttl-ipv4.conf


# Ajustes de ARP e fragmentacao (maior capacidade) - IPv4
(
    echo "net.ipv4.neigh.default.gc_interval = 30"
    echo "net.ipv4.neigh.default.gc_stale_time = 60"
    echo "net.ipv4.neigh.default.gc_thresh1 = 4096"
    echo "net.ipv4.neigh.default.gc_thresh2 = 8192"
    echo "net.ipv4.neigh.default.gc_thresh3 = 12288"
    echo
    echo "net.ipv4.ipfrag_high_thresh=4194304"
    echo "net.ipv4.ipfrag_low_thresh=3145728"
    echo "net.ipv4.ipfrag_max_dist=64"
    echo "net.ipv4.ipfrag_secret_interval=0"
    echo "net.ipv4.ipfrag_time=30"
)  >  /etc/sysctl.d/063-neigh-ipv4.conf

# Ajustes de ARP e fragmentacao (maior capacidade) - IPv6
(
    echo "net.ipv6.neigh.default.gc_interval = 30"
    echo "net.ipv6.neigh.default.gc_stale_time = 60"
    echo "net.ipv6.neigh.default.gc_thresh1 = 4096"
    echo "net.ipv6.neigh.default.gc_thresh2 = 8192"
    echo "net.ipv6.neigh.default.gc_thresh3 = 12288"
    echo
    echo "net.ipv6.ip6frag_high_thresh=4194304"
    echo "net.ipv6.ip6frag_low_thresh=3145728"
    echo "net.ipv6.ip6frag_secret_interval=0"
    echo "net.ipv6.ip6frag_time=60"
)  >  /etc/sysctl.d/064-neigh-ipv6.conf

# Ativar roteamento de pacotes IPv4
(
    echo  "net.ipv4.conf.default.forwarding=1"
)  >  /etc/sysctl.d/065-default-foward-ipv4.conf

# Ativar roteamento de pacotes IPv6
(
    echo  "net.ipv6.conf.default.forwarding=1"
) >  /etc/sysctl.d/066-default-foward-ipv6.conf

# Ativar roteamento em todas as interfaces de rede
echo  "net.ipv4.conf.all.forwarding=1"   >  /etc/sysctl.d/067-all-foward-ipv4.conf
echo  "net.ipv6.conf.all.forwarding=1"   >  /etc/sysctl.d/068-all-foward-ipv6.conf
echo  "net.ipv4.ip_forward=1"            >  /etc/sysctl.d/069-ipv4-forward.conf

# Aumentar capacidades de arquivos abertos
(
    echo "fs.file-max=26110208"
    echo "fs.aio-max-nr=3263776"
    echo "fs.mount-max=1048576"
    echo "fs.mqueue.msg_max=128"
    echo "fs.mqueue.msgsize_max=131072"
    echo "fs.mqueue.queues_max=4096"
    echo "fs.pipe-max-size=8388608"
)  >  /etc/sysctl.d/072-fs-options.conf

# Nao usar SWAP enquanto houver memoria RAM livre
echo  "vm.swappiness=0"            >  /etc/sysctl.d/073-swappiness.conf

# Usar mais RAM para priorizar metadados de sistema de arquivos
echo  "vm.vfs_cache_pressure=50"   >  /etc/sysctl.d/074-vfs-cache-pressure.conf

# Reiniciar o kernel apos 3 segundos em caso de pane geral
echo  "kernel.panic=3"             >  /etc/sysctl.d/081-kernel-panic.conf

# Aumentar limite de threads por processo (vital para NODE.js e accel-ppp)
echo  "kernel.threads-max=1031306" >  /etc/sysctl.d/082-kernel-threads.conf

# Aumentar limite de processos rodando paralelamente
echo  "kernel.pid_max=262144"      >  /etc/sysctl.d/083-kernel-pid.conf

# Tamanho de buffer de mensagens de sistema (SYSCALL)
echo  "kernel.msgmax=327680"       >  /etc/sysctl.d/084-kernel-msgmax.conf
echo  "kernel.msgmnb=655360"       >  /etc/sysctl.d/085-kernel-msgmnb.conf
echo  "kernel.msgmni=32768"        >  /etc/sysctl.d/086-kernel-msgmni.conf

# CRITICO: 
# - Quantidade de RAM reservada pelo kernel para operacoes criticas
# - Requer tabela de acordo com quantidade de RAM:
#   Ex.:
#     abaixo de 4GB......:  32 MB
#     entre 8 GB e 32 GB.: 128 MB
#     32GB ou mais.......: 512 MB
#
# echo  "vm.min_free_kbytes = 32768" >  /etc/sysctl.d/087-kernel-free-min-kb.conf


# Conntrack
#----------------------------------------------------------

# Permitir ate 8 milhoes de registros de NAT/Redirecionamento/CGNAT
(
    echo "net.nf_conntrack_max=8000000"  # 262144
) >  /etc/sysctl.d/090-netfilter-max.conf

# Aumentar tabela de controle da conntrack
(
    echo "net.netfilter.nf_conntrack_buckets=262144"
    echo "net.netfilter.nf_conntrack_checksum=1"
    echo "net.netfilter.nf_conntrack_events = 1"
    echo "net.netfilter.nf_conntrack_expect_max = 1024"
    echo "net.netfilter.nf_conntrack_timestamp = 0"
) >  /etc/sysctl.d/091-netfilter-generic.conf

# Ativar helpers (ALG de NAT/CGNAT)
(
    echo "net.netfilter.nf_conntrack_helper=1"
) > /etc/sysctl.d/092-netfilter-helper.conf

# Esquecer registros ICMP apos 30 segundos sem atividade
(
    echo "net.netfilter.nf_conntrack_icmp_timeout=30"
    echo "net.netfilter.nf_conntrack_icmpv6_timeout=30"
) >  /etc/sysctl.d/093-netfilter-icmp.conf

# Esquecer registros TCP apos um tempo minimamente toleravel sem atividade
(
    echo "net.netfilter.nf_conntrack_tcp_be_liberal=0"
    echo "net.netfilter.nf_conntrack_tcp_loose=1"
    echo "net.netfilter.nf_conntrack_tcp_max_retrans=3"
    echo "net.netfilter.nf_conntrack_tcp_timeout_close=10"
    echo "net.netfilter.nf_conntrack_tcp_timeout_close_wait=10" #60
    echo "net.netfilter.nf_conntrack_tcp_timeout_established=600" #432000
    echo "net.netfilter.nf_conntrack_tcp_timeout_fin_wait=10" #120
    echo "net.netfilter.nf_conntrack_tcp_timeout_last_ack=10" #30
    echo "net.netfilter.nf_conntrack_tcp_timeout_max_retrans=60" #300
    echo "net.netfilter.nf_conntrack_tcp_timeout_syn_recv=5" #60
    echo "net.netfilter.nf_conntrack_tcp_timeout_syn_sent=5" #60
    echo "net.netfilter.nf_conntrack_tcp_timeout_time_wait=30" #120
    echo "net.netfilter.nf_conntrack_tcp_timeout_unacknowledged=300"
)  >  /etc/sysctl.d/094-netfilter-tcp.conf

# Esquecer registros UDP apos 30 segundos sem atividade, 180s para stream
(
    echo "net.netfilter.nf_conntrack_udp_timeout=30"
    echo "net.netfilter.nf_conntrack_udp_timeout_stream=180"
)  >  /etc/sysctl.d/095-netfilter-udp.conf

# Opcoes de SCTP (pouco usado, opcional)
(
    echo "net.netfilter.nf_conntrack_sctp_timeout_closed=10"
    echo "net.netfilter.nf_conntrack_sctp_timeout_cookie_echoed=3"
    echo "net.netfilter.nf_conntrack_sctp_timeout_cookie_wait=3"
    echo "net.netfilter.nf_conntrack_sctp_timeout_established=432000"
    echo "net.netfilter.nf_conntrack_sctp_timeout_heartbeat_acked=210"
    echo "net.netfilter.nf_conntrack_sctp_timeout_heartbeat_sent=30"
    echo "net.netfilter.nf_conntrack_sctp_timeout_shutdown_ack_sent=3"
    echo "net.netfilter.nf_conntrack_sctp_timeout_shutdown_recd=0"
    echo "net.netfilter.nf_conntrack_sctp_timeout_shutdown_sent=0"
)  >  /etc/sysctl.d/096-netfilter-sctp.conf

# Opcoes de DCCP (pouco usado, opcional)
(
    echo "net.netfilter.nf_conntrack_dccp_loose=1"
    echo "net.netfilter.nf_conntrack_dccp_timeout_closereq=64"
    echo "net.netfilter.nf_conntrack_dccp_timeout_closing=64"
    echo "net.netfilter.nf_conntrack_dccp_timeout_open=43200"
    echo "net.netfilter.nf_conntrack_dccp_timeout_partopen=480"
    echo "net.netfilter.nf_conntrack_dccp_timeout_request=240"
    echo "net.netfilter.nf_conntrack_dccp_timeout_respond=480"
    echo "net.netfilter.nf_conntrack_dccp_timeout_timewait=240"
)  >  /etc/sysctl.d/097-netfilter-dccp.conf

# Controle de fragmentacao de pacotes IPv6 (sim, existe!)
(
    echo "net.netfilter.nf_conntrack_frag6_high_thresh=4194304"
    echo "net.netfilter.nf_conntrack_frag6_low_thresh=3145728"
    echo "net.netfilter.nf_conntrack_frag6_timeout=60"
)  >  /etc/sysctl.d/099-netfilter-ipv6.conf


# Aplicar imediatamente:
sysctl -q --system  2>/dev/null
sysctl -q -p        2>/dev/null

Esses são meus ajustes favoritos, se você tem ajustes diferentes e fez descobertas, compartilhe comigo!

Patrick Brandão, patrickbrandao@gmail.com