Network Policies no Kubernetes: Segmentando o Tráfego do Cluster
Saiba como as network policies do Kubernetes segmentam o tráfego do cluster com default-deny, podSelector e egress para proteger a comunicação pod a pod.
Suba um cluster Kubernetes novo, faça o deploy de alguns serviços e algo surpreendente já é verdade: todo pod consegue conversar com qualquer outro pod. Seu serviço de pagamentos alcança o sidecar de logging, um pod de marketing comprometido pode abrir uma conexão com o seu banco de dados, e o tráfego cruza fronteiras de namespace sem pedir permissão. Esse é o padrão plano e permissivo das network policies do Kubernetes e da rede do cluster, e é uma das lacunas mais comuns que vemos quando as equipes começam a mover workloads para produção. Este mergulho profundo faz parte do nosso guia de segurança do Kubernetes e foca em uma única alavanca: usar network policies para segmentar o tráfego do cluster de modo que os pods só alcancem aquilo de que realmente precisam.
O problema: a rede do Kubernetes é plana e permite tudo por padrão
O modelo de rede do Kubernetes é deliberadamente simples. Cada pod recebe seu próprio endereço IP, e cada pod alcança diretamente o IP de qualquer outro pod, sem NAT no meio do caminho. Essa simplicidade é ótima para a velocidade do desenvolvimento e para a descoberta de serviços, mas significa que a rede, por si só, não oferece isolamento. Não há firewall implícito entre namespaces, nenhuma barreira entre a camada de frontend e a camada de dados, e nada que impeça um workload de fazer conexões de saída para onde quiser.
A consequência de segurança aparece durante os incidentes. Se um atacante consegue execução de código em um único pod, essa rede plana se torna o playground dele. Movimentação lateral, alcance a endpoints administrativos internos e exfiltração de dados para um host externo estão todos trivialmente disponíveis, porque a rede nunca diz não. O princípio do menor privilégio, que aplicamos com cuidado às identidades por meio do RBAC do Kubernetes e aos workloads por meio da pod security, precisa de um equivalente na camada de rede. Esse equivalente é a NetworkPolicy.
O que é uma NetworkPolicy (e por que ela precisa de uma CNI que a aplique)
Uma NetworkPolicy é um recurso do Kubernetes com escopo de namespace que descreve quais conexões são permitidas de e para um conjunto de pods. Você a escreve de forma declarativa, do mesmo jeito que escreve um Deployment ou um Service, e ela vive ao lado dos workloads que protege.
Há uma ressalva crucial. O servidor de API do Kubernetes aceitará e armazenará de bom grado uma NetworkPolicy, mas o servidor de API não a aplica. A aplicação é tarefa do seu plugin de Container Network Interface (CNI). Se a CNI instalada no seu cluster não implementa network policy, suas regras cuidadosamente escritas ficam inertes: elas existem como objetos, mas não mudam nada no tráfego real. Várias CNIs amplamente usadas aplicam políticas e várias não, então, antes de confiar na segmentação, confirme que a camada de rede do seu cluster realmente aplica os recursos de NetworkPolicy. Uma forma rápida de ganhar confiança é aplicar uma regra de negação e verificar se o tráfego bloqueado realmente para.
Os blocos de construção: podSelector, ingress, egress e peers
Toda NetworkPolicy tem uma anatomia pequena e consistente.
podSelector escolhe a quais pods do namespace a política se aplica, com base nos seus labels. Um podSelector: {} vazio seleciona todos os pods do namespace, que é exatamente o que você quer para uma base que abrange todo o namespace.
policyTypes declara se a política governa Ingress (conexões de entrada), Egress (conexões de saída) ou ambos. Isso importa: uma política que lista Ingress mas nenhuma regra de ingress nega todo o tráfego de entrada para os pods selecionados, deixando o egress intocado.
Peers descrevem a outra ponta de uma conexão permitida. Você tem três maneiras de nomear um peer:
podSelectorcorresponde a pods por label dentro do mesmo namespace.namespaceSelectorcorresponde a namespaces inteiros pelos seus labels, que é como você permite fluxos entre namespaces.ipBlockcorresponde a faixas CIDR, útil para nós no cluster ou sistemas externos, com uma listaexceptopcional para recortar faixas.
ports restringem um fluxo permitido a portas e protocolos específicos (TCP, UDP, SCTP), para que você possa permitir conexões à porta 5432 sem abrir todo o resto.
Um detalhe sutil, mas importante: dentro de uma única regra, múltiplas entradas de peer são combinadas com OR, mas um namespaceSelector e um podSelector escritos dentro da mesma entrada de peer são combinados com AND, significando "pods com este label, mas somente em namespaces com aquele label". Acertar essa distinção é a diferença entre uma regra restrita e uma acidentalmente aberta.
O padrão default-deny
O hábito mais valioso com network policies é começar pela negação e abrir de forma deliberada, em vez de começar aberto e tentar fechar as brechas. Esse é o padrão default-deny, e ele é a fundação da microssegmentação prática.
Você começa negando todo o tráfego em um namespace e depois sobrepõe políticas explícitas de permissão. Como as network policies são aditivas, uma regra de permissão em qualquer lugar do namespace concede aquele fluxo; não existe uma regra de "negação" que sobreponha uma permissão. Esse modelo aditivo é o motivo pelo qual a negação de base é expressa como uma política sem regras de permissão, em vez de um bloqueio explícito.
Aqui está uma política que nega todo o ingress e todo o egress para cada pod de um namespace:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: payments
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
Com isso no lugar, nada entra ou sai de nenhum pod do namespace payments até que você diga o contrário. Isso parece agressivo, e é, mas transforma cada fluxo permitido em uma decisão consciente que você pode revisar.
Exemplos práticos
Permitir ingress apenas de um app específico. Suponha que um pod api deva aceitar conexões somente dos pods frontend, e apenas na porta 8080. Uma vez que o default-deny esteja no lugar, você adiciona:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-api
namespace: payments
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
Agora os pods api aceitam tráfego do frontend na 8080 e de mais nada, enquanto o default-deny continua bloqueando qualquer outra origem.
Restringir o egress, incluindo o DNS. O controle de egress é onde as equipes mais tropeçam, porque quase todo pod precisa de DNS para resolver nomes de serviço, e o DNS roda no namespace kube-system. Se você aplicar uma negação de egress sem permitir o DNS, seus pods quebram de maneiras confusas. Esta política permite que os pods api resolvam DNS e alcancem um banco de dados na porta 5432, e nada mais:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-egress
namespace: payments
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432
A regra de DNS é a linha nada glamorosa que impede que as políticas de egress virem uma queda de serviço.
Isolamento de namespace e multitenancy
Namespaces são uma fronteira organizacional no Kubernetes, mas, por padrão, não são uma fronteira de rede. Se você hospeda várias equipes, ambientes ou tenants em um cluster, as network policies são como você faz os namespaces se comportarem como segmentos isolados.
Um padrão comum é dar a cada namespace de tenant uma base default-deny e, então, permitir ingress apenas de pods dentro do mesmo namespace usando um podSelector vazio dentro do from do ingress. O tráfego entre tenants passa então a ser impossível, a menos que uma política específica, apoiada em um namespaceSelector, o permita explicitamente. Rotular os namespaces de forma consistente (muitos clusters expõem o label embutido kubernetes.io/metadata.name) torna essas regras entre namespaces legíveis e auditáveis. O resultado é microssegmentação de verdade: cada tenant vive em sua própria ilha de rede, com as pontes entre ilhas registradas como política explícita e revisável.
Limitações a ter em mente
As network policies são poderosas, mas não são uma história completa de segurança de rede, e ajuda ser honesto quanto aos limites.
- Apenas L3/L4. As network policies padrão correspondem a endereços IP e portas. Elas não conseguem, por si só, permitir "GET /health mas não POST /admin", corresponder a hostnames ou SNI, nem inspecionar cabeçalhos HTTP. A filtragem na camada 7 exige ferramentas adicionais, como um service mesh ou uma CNI que ofereça extensões cientes de L7.
- Escopo de namespace. Uma NetworkPolicy só seleciona pods do seu próprio namespace. Não existe um objeto de política de abrangência de cluster embutido no Kubernetes central, então proteger um cluster grande significa gerenciar políticas em muitos namespaces, o que é um forte argumento a favor de templates e automação.
- Dependente da CNI. Como visto acima, a aplicação vive na CNI. O comportamento em casos de borda e quaisquer recursos de L7 ou de abrangência de cluster podem variar entre plugins, então valide contra a CNI que você de fato executa.
Nenhum desses é motivo para pular as network policies. São motivos para tratar a segmentação como uma camada em uma abordagem de defesa em profundidade que também inclui RBAC, pod security e a varredura de imagens e manifests.
Testando e validando suas políticas
Uma network policy que você não testou é uma hipótese, não um controle. Como o efeito de uma política é "tráfego que costumava funcionar agora falha", a única forma de ter certeza é exercitar os caminhos.
Comece confirmando o caso negativo: a partir de um pod que deveria estar bloqueado, tente alcançar o serviço protegido e verifique se a conexão dá timeout ou é recusada. Um pod de debug leve rodando curl, wget ou nc contra o alvo costuma ser suficiente. Depois, confirme o caso positivo: a partir de um pod que deveria ser permitido, verifique se a conexão tem sucesso. Faça isso tanto para ingress quanto para egress, e lembre-se de testar explicitamente a resolução de DNS, já que uma regra de egress de DNS quebrada é a falha silenciosa mais comum.
Além das verificações manuais, mantenha uma pequena biblioteca de testes de conectividade que você possa rodar após qualquer mudança de política, e trate um sucesso inesperado (tráfego que deveria ser negado mas não é) com a mesma seriedade de uma falha inesperada. Como as políticas são aditivas, uma única regra de permissão excessivamente ampla em outro ponto do namespace pode desfazer silenciosamente um isolamento que você achava que tinha.
Shift left: revise as network policies como código
As network policies são YAML que vive nos seus repositórios, o que significa que podem ser revisadas, testadas e barradas antes mesmo de tocarem um cluster. É aqui que a segmentação deixa de ser um combate a incêndio do "dia dois" e passa a fazer parte de como você constrói.
Trate cada mudança de política como qualquer outra mudança de código. Exija revisão em pull requests que modifiquem ou adicionem manifests de NetworkPolicy, e fique especialmente atento a mudanças que ampliem um selector, adicionem um ipBlock com um CIDR amplo ou removam um default-deny. No CI, faça a varredura dos seus manifests do Kubernetes e da infraestrutura como código, de modo que um namespace enviado sem um default-deny, ou uma política que abra egress para o mundo, seja sinalizado automaticamente em vez de descoberto durante um incidente. Pegar uma política ausente ou permissiva demais em um pull request é dramaticamente mais barato do que pegá-la em produção, e mantém a conversa de segurança perto dos desenvolvedores que são donos do workload.
Como a Rainforest ajuda
A Rainforest traz a revisão de network policies para o mesmo fluxo shift-left que sua equipe já usa para código. Nossa varredura de infraestrutura como código e manifests analisa os manifests do Kubernetes e a IaC nos seus pipelines, de modo que bases default-deny ausentes, selectors amplos demais e regras de egress arriscadas surjam como achados no pull request, com o contexto de que os desenvolvedores precisam para corrigi-los. Como parte da plataforma mais ampla de testes de segurança de aplicações, ela conecta essas verificações de configuração do cluster ao restante do seu programa de AppSec, dando a você um único lugar para ver e priorizar o risco em código e infraestrutura.
Se você quiser ver como a revisão de policy-as-code se encaixa no seu fluxo de segurança do Kubernetes, agende uma demonstração e a percorreremos com os seus próprios manifests.
Perguntas frequentes
O que é uma network policy do Kubernetes?
Uma network policy do Kubernetes é um recurso com escopo de namespace que define quais conexões de rede são permitidas de e para um grupo de pods, selecionados pelos seus labels. Ela controla o tráfego no nível de IP e porta (L3/L4) e é aplicada pelo plugin de CNI do seu cluster, e não pelo próprio servidor de API do Kubernetes.
O Kubernetes nega tráfego por padrão?
Não. Por padrão, a rede do Kubernetes é plana e permite tudo: todo pod pode se comunicar com qualquer outro pod, inclusive entre namespaces, sem restrições. Você só obtém o comportamento de negação depois de aplicar network policies que selecionem esses pods.
O que é uma network policy default-deny?
Uma network policy default-deny seleciona todos os pods de um namespace (usando um podSelector vazio) e declara os tipos de política de ingress e/ou egress sem nenhuma regra de permissão, o que bloqueia todo o tráfego correspondente. Você então adiciona políticas explícitas de permissão por cima para os fluxos específicos de que cada workload precisa, já que as políticas são aditivas.
As network policies precisam de uma CNI especial?
Sim. O servidor de API do Kubernetes armazena os objetos de NetworkPolicy, mas não os aplica. A aplicação é tratada pelo plugin de CNI, e nem toda CNI implementa network policy. Confirme que sua CNI suporta e aplica as políticas, idealmente aplicando uma regra de negação e verificando se o tráfego realmente para.
As network policies conseguem filtrar por hostname ou L7?
Não por si só. As network policies padrão do Kubernetes operam em L3/L4, correspondendo a endereços IP, faixas CIDR e portas. Elas não conseguem corresponder a hostnames, SNI, métodos HTTP ou caminhos. A filtragem na camada 7 exige ferramentas adicionais, como um service mesh ou uma CNI com extensões cientes de L7.

Escrito por
Bruno Baldo
CMO
Um pouco de marketing e um pouco de curiosidade e temos a receita pra criar um apaixonado por cyber!

Segurança no Kubernetes: o guia completo
Guia completo de segurança no Kubernetes: o modelo dos 4C's, superfície de ataque, RBAC, pods, network policies, secrets, cadeia de suprimentos e shift-left.

Kubernetes Pod Security: Standards, Admission e securityContext
Um guia prático de Kubernetes Pod Security: os Pod Security Standards, o Pod Security Admission e as configurações de securityContext que mantêm os pods protegidos.

RBAC no Kubernetes: o controle de acesso baseado em funções explicado
RBAC no Kubernetes explicado: como funcionam Roles, bindings e ServiceAccounts, como o acesso é avaliado e boas práticas de menor privilégio.
