
Ao criar uma aplicação segura, normalmente você nega a ela permissão para se conectar fora da Virtual Private Cloud (VPC). Mas, às vezes, é preciso abrir uma brecha — por exemplo, quando a aplicação precisa acessar uma API de terceiros.

Gateway to Domain, ao estilo Lovecraft. Crédito: StableDiffusion
O caminho mais comum é liberar a saída apenas para os endereços IP relevantes, configurados no Firewall do Google Cloud Platform ou nas Network ACLs da AWS. Só que endereços IP podem mudar com o tempo, enquanto o Fully Qualified Domain Name (FQDN), por exemplo api.example.com, oferece um endpoint estável e de conhecimento público. A maioria das aplicações é configurada para acessar um FQDN, e não um endereço IP.

Neste artigo, vou apresentar formas de permitir a saída apenas para um FQDN específico, com as vantagens e desvantagens de cada abordagem.
A ideia é encontrar opções baratas, fáceis de manter, robustas e simples.
Também vou falar de opções com o diferencial de reconhecer o Kubernetes: por exemplo, se a aplicação roda em Kubernetes, você pode querer liberar a saída de um namespace específico do Kubernetes e não dos demais.
Outro ponto é a granularidade no nível do domínio, já que um único endereço IP pode atender a vários domínios. A maioria das soluções aqui não faz essa distinção — se você libera o acesso a um domínio com determinado endereço IP, elas liberam a saída para todos os domínios atrás daquele endereço. Em geral, isso não é problema de segurança, porque normalmente todos os domínios em um mesmo IP são controlados pela mesma entidade. Mas o virtual hosting baseado em nome permite esse cenário, então também vamos apresentar soluções que dão conta dele.
As opções analisadas aqui são:
- Squid, como exemplo de proxy autogerenciado
- AWS Network Gateway, com inspeção profunda de pacotes, que permite controle no nível do domínio, inclusive em virtual hosting.
- Um novo recurso no Google Firewall, que oferece controle de FQDN com a praticidade de um serviço serverless
- O novo Google Secure Web Gateway, que adiciona controle granular até no nível do domínio e até mesmo da URL.
- Soluções com reconhecimento de Kubernetes: Cilium e Istio.
(Uma observação sobre as camadas OSI: como nomes de domínio e DNS ficam na "camada de aplicação" do modelo OSI, a Camada 7, o FQDN Egress Control às vezes é chamado de "Layer 7 Egress Control". Já a Camada 3 é onde os endereços IP são definidos e onde atuam os firewalls tradicionais e as Network ACLs.)
Implementando por conta própria
Primeiro, vamos pensar em como faríamos isso por conta própria. Não que eu recomende, mas ajuda a entender o que essas soluções fazem nos bastidores.
Mesmo que a aplicação esteja configurada com o FQDN da API de terceiros, sua solução precisa bloquear pacotes no nível do endereço IP, já que é isso que todo o tráfego de rede usa. Os nomes de domínio só entram em cena antes da tentativa de conexão, quando o cliente faz a resolução do IP a partir do nome.
Vale lembrar também que um único FQDN pode corresponder a vários endereços IP. Isso não é problema, pois uma consulta DNS comum retorna todos eles, e você pode liberar o acesso para a lista de IPs.
Você tem um Firewall ou uma Network ACL que bloqueia todo o tráfego, exceto para os endereços IP relevantes.
Você escreve e implanta uma aplicação que checa o DNS periodicamente para descobrir o IP atual do FQDN da API, api.example.com. (Uma boa pedida para rodar isso a baixo custo é o GCP Cloud Functions ou o AWS Lambda em um trigger periódico.) Nos raros casos em que o IP mudou, sua aplicação atualiza o Firewall ou a Network ACL.
Reverse web proxies autogerenciados
Uma solução "clássica" para o FQDN Egress Control é o reverse web proxy, sendo o Squid a alternativa open-source mais conhecida. Você usa o serviço de roteamento da sua nuvem para direcionar todo o tráfego de saída por uma VM que executa o proxy Squid; ele então confere se o IP corresponde ao nome do domínio — conforme definido em uma whitelist de ACL — e encaminha o tráfego se houver correspondência.
O Squid está disponível no AWS Marketplace; veja esta discussão de arquitetura. Também está disponível no GCP Marketplace; veja esta configuração de rede. Confira também esta discussão sobre FQDN egress control no Squid e em outros proxies, como o DiscrimiNAT e o Aviatrix.
Proxies como o Squid rodando em uma VM trazem custo de manutenção — atualizar o sistema operacional da VM, lidar com travamentos, etc. Como todo o tráfego de rede passa por uma única VM (a menos que você tenha o trabalho extra de configurar uma implantação com balanceamento de carga), a carga pode ficar pesada, comprometendo a robustez e exigindo uma VM maior rodando 24x7, mesmo quando ela não é totalmente necessária.
AWS Network Firewall
O AWS Network Firewall faz inspeção profunda de pacotes e, com isso, ganha mais poder de filtragem. Por isso, ele não é diretamente comparável ao Google Firewall, que se aproxima mais das Network ACLs da AWS.
O AWS Network Firewall oferece suporte a FQDN Egress Control via stateful domain list rule groups. Usando o Server Name Indicator (SNI) enviado durante a negociação de uma conexão TCP para tráfego HTTPS, ele consegue distinguir domínios em cenários de virtual hosting.
O Network Firewall pode ser integrado ao Route 53 DNS Firewall, que bloqueia tentativas de resolução DNS — assim, por exemplo, uma consulta DNS para api.example.com vinda de uma aplicação dentro da VPC não é resolvida em um IP. Mas o DNS Firewall, sozinho, não bloqueia o acesso a esse IP; quem faz isso é o Network Firewall.
O Network Firewall é uma boa escolha, mas pode sair caro: ele foi pensado para ambientes corporativos complexos, com várias redes. ( Veja meu artigo no blog da DoiT comparando os casos de uso dos diversos serviços do tipo Firewall na AWS.)
Google Firewall e Web Gateway
É mais fácil usar uma solução totalmente gerenciada pelo provedor de nuvem do que cuidar da VM por conta própria. E o Google está justamente lançando algumas soluções nesse sentido. Em um próximo post, vou detalhar como usá-las, mas, por enquanto, ficam aqui os destaques.
O Google Firewall tem um novo recurso, o FQDN Objects, hoje em Preview limitado. Ele usa o Cloud DNS a cada 30 segundos para consultar o IP atual do serviço externo.
Outro serviço em Preview limitado, o Secure Web Gateway, também permite controle no nível do domínio. Para isso, você concede a ele acesso aos seus certificados SSL no GCP Certificate Manager, para que ele possa descriptografar/criptografar seu tráfego HTTPS. Esse acesso profundo lhe dá poder de controlar a saída no nível do domínio, mesmo em cenários de virtual hosting. Como ele enxerga a requisição HTTP inteira, permite até controle no nível da URL.
Cilium
As soluções acima atuam no nível da VPC. Mas, se a aplicação roda em Kubernetes, você pode querer que o controle de saída funcione com conceitos do próprio Kubernetes. Para isso, você pode usar a CiliumNetworkPolicy. Trata-se de uma Custom Resource Definition (CRD) que resolve nomes de domínio em endereços IP e, depois, bloqueia ou libera o tráfego na camada de rede do Cilium baseada em eBPF. (Veja dois posts no blog da DoiT.) A CRD reconhece o Kubernetes, então dá para distinguir pods por namespace: alguns com acesso liberado à API externa, outros não. Outra CRD, a CiliumClusterwideNetworkPolicy, faz o mesmo, mas sua configuração vale para todo o cluster, atravessando os namespaces.
Essa solução adiciona alguma complexidade ao cluster, por conta da camada de rede extra do Cilium. Em breve, conforme indicado na documentação do Cilium, "toda a funcionalidade será incorporada ao formato de recurso padrão e essa CRD não será mais necessária". Ainda não há uma especificação padrão disponível, mas o Kubernetes Networking Special Interest Group já está trabalhando nisso.
Istio
A solução mais completa em recursos é o service mesh Istio. O Istio controla todo o tráfego, permitindo bloquear toda a saída, exceto onde definido em um ServiceEntry. Ao especificar resolution: DNS, você diz ao Istio para não confiar no IP ao qual o cliente (um pod) está se conectando, e sim resolver periodicamente o nome do domínio via DNS. O Istio-service pode ser exposto apenas aos namespaces que você escolher. O Istio oferece o maior nível de controle, mas traz mais complexidade que o Cilium, com toda a potência e funcionalidade de uma camada de service mesh.
E aí, qual escolher?
Você tem várias opções: o consagrado Squid (ou outro reverse web proxy); os novos serviços gerenciados, Google Firewall FQDN Objects e AWS Network Firewall; o Secure Web Gateway, com proxy HTTP; e, ainda, o Cilium e o Istio, que reconhecem Kubernetes.
Se você quer uma solução estável e gerenciada, a recomendação é apostar no novo Google Firewall (depois que ele amadurecer) e no AWS Network Firewall (se o preço couber no orçamento). Se precisa de controle no nível dos namespaces do Kubernetes, o caminho mais simples é uma CRD do Cilium; quando o padrão nativo do Kubernetes for lançado, vá nele.