04 - Subsistema de Rede (pilha TCP-IP, netfilter)
video: https://youtu.be/... no frontmatter da nota.1. Arquitetura da Pilha de Protocolos no Kernel
O subsistema de rede do Linux é uma das implementações de pilha TCP/IP mais robustas e performáticas da computação. Diferente de implementações de espaço de usuário, a pilha do kernel integra-se profundamente com o gerenciamento de interrupções da CPU, o sistema de buffer de memória (sk_buff) e a camada de drivers de hardware. Arquiteturalmente, ela segue o modelo de camadas OSI, embora sua implementação interna seja otimizada para o fluxo de dados em Ring 0.
O Buffer de Rede: sk_buff
A estrutura central de todo o subsistema é o struct sk_buff (Socket Buffer). Este não é apenas um contêiner de bytes; é um gerenciador de metadados complexo. Quando um pacote viaja pela pilha (seja subindo da placa de rede para a aplicação ou descendo do socket para o fio), o sk_buff permanece o mesmo, mas o kernel manipula os ponteiros internos para adicionar ou remover cabeçalhos de protocolo (Ethernet, IP, TCP) sem a necessidade de copiar o payload do pacote entre as camadas, garantindo eficiência de memória (Zero-Copy).
2. O Fluxo de Dados: netif_receive_skb ao Socket
O tráfego de entrada inicia quando a NIC (Network Interface Card) recebe um frame físico. O driver da placa, operando no modo de interrupção ou NAPI (New API - para evitar livelock sob carga alta), aloca um sk_buff, copia os dados via DMA para a RAM e chama netif_receive_skb.
-
Camada de Enlace (L2): O kernel verifica o endereço MAC. Se for endereçado à máquina ou um broadcast/multicast aceitável, o protocolo de rede (ex:
eth_type_trans) identifica que é um pacote IPv4 ou IPv6 e o entrega à camada superior. -
Camada de Rede (L3 - IP): Aqui ocorre o roteamento. O subsistema verifica a
fib_table(Forwarding Information Base). Se o destino for local, o pacote é desempacotado; se não, ele é encaminhado para outra interface (IP Forwarding). -
Camada de Transporte (L4 - TCP/UDP): O kernel identifica o socket de destino baseado na quádrupla (IP origem, porta origem, IP destino, porta destino). Os dados são copiados do buffer da pilha de rede para o buffer de recepção do socket, e o processo (PID) que está aguardando no wait queue do socket é despertado pelo escalonador.
3. Netfilter: O Framework de Filtragem de Pacotes
O Netfilter é o coração da segurança e do roteamento avançado no Linux. Ele não é o iptables ou nftables; estes são apenas utilitários de espaço de usuário para configurar o Netfilter. O Netfilter consiste em "Hooks" (ganchos) inseridos estrategicamente no código da pilha TCP/IP dentro do kernel.
Os Cinco Hooks de Conexão
Os pacotes, ao atravessarem o kernel, são forçados a passar por estes pontos de inspeção:
-
PREROUTING: Pacotes recém-chegados, antes de qualquer decisão de roteamento. Ideal para DNAT (Destination NAT).
-
INPUT: Pacotes cujo destino final é a própria máquina local.
-
FORWARD: Pacotes destinados a outros hosts, sendo roteados pela máquina.
-
OUTPUT: Pacotes gerados internamente pela própria máquina.
-
POSTROUTING: Pacotes que já foram roteados e estão prestes a sair pela interface física. Ideal para SNAT (Source NAT ou Masquerading).
4. Concorrência e Performance: SoftIRQs e NAPI
O gerenciamento de rede precisa ser extremamente resiliente à latência. O uso de SoftIRQs (Software Interrupts) é fundamental aqui. Quando uma placa de rede gera uma interrupção de hardware, o kernel não processa o pacote no contexto daquela interrupção (o que bloquearia outros processamentos de hardware). Em vez disso, o driver apenas agenda uma NET_RX_SOFTIRQ. Em um momento assíncrono posterior, o escalonador de SoftIRQs processa os pacotes pendentes em um contexto que permite a preempção e o uso de travas de kernel, garantindo que o sistema não trave sob rajadas de tráfego.
O NAPI (procedimento de polling integrado) é o mecanismo que protege o kernel contra tempestades de interrupções. Sob tráfego intenso, o driver desativa a interrupção de hardware e muda para o modo de polling, onde o kernel consulta a NIC em ciclos de tempo fixos, convertendo o processamento orientado a interrupção em processamento orientado a lotes (batching), reduzindo drasticamente a carga da CPU.
5. Roteamento e Tabela FIB
O subsistema de roteamento do Linux é gerenciado pela FIB (Forwarding Information Base). A FIB é uma estrutura de árvore (Trie otimizado) que permite a busca do caminho de roteamento mais longo (Longest Prefix Match) em tempo constante ou quase constante, independente do tamanho da tabela.
As rotas não são apenas estáticas; o kernel permite a existência de múltiplas tabelas de roteamento (identificadas por IDs). Isso possibilita o Policy Based Routing (PBR), onde a decisão de roteamento depende não apenas do destino, mas da porta de origem, do protocolo ou da marcação de pacotes (fwmark) realizada pelo Netfilter. O comando ip rule é a interface de usuário para configurar essas políticas que alteram a tabela de roteamento consultada pelo kernel no momento da tomada de decisão de encaminhamento.
6. Otimizações Modernas: XDP e BPF
Para cenários de performance extrema (ex: roteadores de 100Gbps+), o caminho tradicional da pilha TCP/IP (com alocação de sk_buff e cópias entre camadas) pode ser lento. O XDP (eXpress Data Path) permite executar programas BPF (Berkeley Packet Filter) diretamente no driver da placa de rede, antes da alocação de qualquer estrutura de sk_buff. Isso permite que o kernel descarte pacotes de ataque DDoS, ou encaminhe pacotes diretamente de uma interface para outra, na velocidade da placa de rede, contornando toda a pilha de protocolos e alcançando eficiência próxima ao hardware puro (wire-speed).