Hoje eu estava demonstrando pra um colega como o MTLS do Istio funciona. Em poucas palavras, o Istio coloca um contêiner a mais no pod (chamado de sidecar), e esse contêiner funciona como um proxy, e ninguém se comunica com o contêiner da aplicação se não apresentar um certificado. Além disso o Istio cuida de autenticação, rotação de certificados, e mais um monte de outras coisas, mas isso não vem ao caso. Então subimos um serviço no Kubernetes, habilitamos o MTLS com o Istio, e pronto, ao tentarmos chamar aquele pod da rede dá um erro, devido à falta da apresentação do certificado. Mas se chamarmos de um outro pod que tem o certificado tudo funciona.
A maneira mais fácil de demonstrar isso tudo, eu pensei, seria fazer um “kubectl port-forward” para o pod, e ao tentar chamar a url veríamos a falha. FIzemos isso, e deu certo. Não falhou. Fui pesquisar. Algo estava muito estranho. Após um tempo descobri o que acontece, e quero contar pra vocês.
Primeiro você precisa entender como o Istio encaminha o request entre o sidecar a o contêiner da aplicação. Basicamente o que acontece é que o Istio, usando iptables, encaminha a porta da aplicação para o sidecar (iptables é uma funcionalidade do kernel do Linux – ou seja, overhead mínimo). Isso é bem detalhado nesse artigo sobre como criar um sidecar na mão, onde a pessoa explica alguns detalhes interessantes da rede do Kubernetes. É importante ler o artigo porque vou tocar em alguns pontos dele daqui a dois parágrafos.
Em seguida, você precisa entender como funciona o encaminhamento de portas do Kubernetes. Quando você roda “kubectl port-forward” é iniciado um processo com socat (um relay de sockets do Linux) no mesmo namespace do contêiner usando nsenter (namespace do Linux, não do Kubernetes). E então esse socket é encaminhado pra máquina que solicitou o encaminhamento da porta. Dá pra ver isso acontecendo no código do Kubernetes no Github.
Juntando esses dois conhecimentos fica mais fácil entender o que está acontecendo. Como estamos acessando um socket direto no namespace de rede do contêiner, ele pode desviar do iptables (configurado na eth0) se chamar localhost, porque bate na interface de loopback, onde não tem iptables para rotear as portas (isso é explicado no primeiro post que linkei, tem uma imagem que mostra isso). Nesse processo, o sidecar é ignorado, e o request vai direto para a aplicação, e não há checagem de certificados, efetivamente não demandando MTLS.
Isso é um risco de segurança? Claramente não, afinal pra poder rodar um encaminhamento de portas você precisa de credenciais, e para fazer algo parecido você precisaria de acesso ao host do Kubernetes, e ambos são muito bem fechados. Mas interessantíssimo entender como funciona. O que acharam?
Giovanni Bassi
Arquiteto e desenvolvedor, agilista, escalador, provocador. É fundador e CSA da Lambda3. Programa porque gosta. Acredita que pessoas autogerenciadas funcionam melhor e por acreditar que heterarquia é mais eficiente que hierarquia. Foi reconhecido Microsoft MVP há mais de dez anos, dos mais de vinte que atua no mercado. Já palestrou sobre .NET, Rust, microsserviços, JavaScript, TypeScript, Ruby, Node.js, Frontend e Backend, Agile, etc, no Brasil, e no exterior. Liderou grupos de usuários em assuntos como arquitetura de software, Docker, e .NET.