Loading...
Loading...

Como Resolver Problemas de TLS 1.3 em Servidores Windows 2012 R2 Desatualizados Usando Proxy Reverso com NGINX

Em 2023, enquanto prestava consultoria para uma grande empresa de concessão de crédito no Brasil, enfrentei um desafio técnico que pode ajudar quem está lidando com infraestruturas desatualizadas. A empresa possuía um ambiente crítico de servidores Windows 2012 R2 on-premises, espalhados em quatro locais diferentes pelo país. Esses servidores eram a espinha dorsal de um de seus principais produtos, mas a estrutura precisava de cuidados constantes e não oferecia suporte ao protocolo TLS 1.3, essencial para garantir a segurança de algumas comunicações.

O problema surgiu quando um dos fornecedores mais importantes, um órgão governamental, comunicou que, em breve, iria desativar os protocolos TLS 1.0, 1.1 e 1.2 em sua API, mantendo apenas o TLS 1.3. Diante do prazo de 15 dias dado para adaptação, descobrimos que o Windows 2012 R2 não oferecia suporte nativo ao TLS 1.3. A atualização da infraestrutura seria complexa e custosa, demandando migração para Windows 2022 ou para a nuvem – e não tínhamos tempo hábil para isso.

Solução com Proxy Reverso: Usando Node.js para o Primeiro Teste

A solução que propus inicialmente foi implementar um proxy reverso para permitir que as requisições fossem recebidas em TLS 1.2 e, então, encaminhadas ao fornecedor em TLS 1.3. Como prova de conceito, criei um script em Node.js, que usa a biblioteca OpenSSL para fazer o handshake necessário com o protocolo mais recente. Aqui está uma versão simplificada desse código:

const fs = require('fs');
const http = require('http');
const https = require('https');

const server = http.createServer((req, res) => {
    const targetOptions = {
        hostname: 'url-do-fornecedor-tls-1.3',
        port: 443,
        path: req.url,
        method: req.method,
    };
    const protocol = targetOptions.port === 443 ? https : http;
    const proxyReq = protocol.request(targetOptions, (proxyRes) => {
        res.writeHead(proxyRes.statusCode, proxyRes.headers);
        proxyRes.pipe(res, { end: true });
    });
    proxyReq.on('error', (e) => {
        res.writeHead(500);
    });
    req.pipe(proxyReq, { end: true });
});

server.listen(0, () => {
    const port = `${server.address().port}`;
    fs.writeFile(`${port}.PORT`, port, (err) => {
        if (err) {
            return console.log(err);
        }
        console.log(`The port number ${port} has been saved to file ${port}.port`);
    });
});

Embora funcional, essa abordagem em Node.js mostrou-se inadequada para as 100.000 requisições diárias da empresa. Embora não seja uma quantidade de requisições muito alta, uma solução mais robusta e escalável seria necessária.

Solução Final com NGINX: Escalabilidade e Confiabilidade em Proxy Reverso

Para garantir a escalabilidade e a estabilidade da solução, optei por configurar o NGINX como proxy reverso em um servidor Ubuntu. Configurei duas instâncias: uma no mesmo datacenter do servidor on-premises do meu cliente e outra na AWS, ambas com 10 Gbps de rede, 4 GB de RAM e 4 vCPUs, o que atendeu bem ao volume de requisições e saiu em torno de $20 por mês cada máquina. Essa infraestrutura foi configurada para suportar o TLS 1.3, o que permitiu à empresa continuar utilizando o ambiente antigo e resolver a questão de compatibilidade.

Com o NGINX, criei uma configuração de proxy reverso simples que aceitava TLS 1.2 das requisições internas e conversava com a API do fornecedor em TLS 1.3. Abaixo está um exemplo de configuração básica em NGINX para esta situação.


server {
    listen 80;
    listen [::]:80;

    listen 443 ssl;
    listen [::]:443 ssl;

    ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;

    ssl_certificate /path/to/your_certificate.crt;
    ssl_certificate_key /path/to/your_certificate.key;
    server_name reverse-proxy.clientdomain.com;

    location / {
        proxy_pass https://gateway.url-do-fornecedor.com;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

A seguinte linha, garante que o nginx irá rodar com TLSv1.1+

ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;

Porém, ao conectar-se ao cliente, irá utilizar os ciphers de encriptação disponíveis no Ubuntu garantindo assim a comunicação.

Automação com PowerShell para Rápida Expansão da Infraestrutura

Para simplificar a criação de novos servidores, caso fosse necessário replicar a solução, criei um script em PowerShell. Esse script automatiza o provisionamento de um servidor com NGINX e realiza as configurações necessárias para funcionar como proxy TLS 1.3. Veja o código abaixo:

@echo off
set ipAddress=%1

if "%ipAddress%"=="" (
    echo IP address is missing. Please provide an IP address.
    pause
    exit /b
)

ssh root@%ipAddress% "mkdir -p /etc/letsencrypt/live/client-site"
scp -r "F:\certs\client-site\*" root@%ipAddress%:/etc/letsencrypt/live/client-site/
ssh root@%ipAddress% "apt install nginx -y"
scp -r "F:\repos\___config_nginx\nginx-config-th-tls.txt" root@%ipAddress%:/etc/nginx/sites-enabled/default
ssh root@%ipAddress% "systemctl restart nginx"
pause

Essa automação permitiu que a equipe gerenciasse facilmente os servidores proxy e fosse ágil em caso de necessidade de replicação do ambiente.

Considerações Finais: Uma Solução Temporária para Infraestruturas Desatualizadas

Após a implementação, enviei um comunicado ao cliente explicando que essa era uma solução temporária para resolver a questão de compatibilidade com o protocolo TLS 1.3. Para uma abordagem de longo prazo, a recomendação seria a atualização dos servidores para Windows 2022 ou outra infraestrutura moderna, uma vez que o suporte ao Windows 2012 R2 já estava próximo do fim.

Quer Saber Mais Sobre Proxy Reverso com NGINX?

Se você também lida com infraestruturas antigas e precisa implementar soluções de compatibilidade, confira outros artigos aqui no blog sobre como configurar NGINX como proxy reverso, além de outras aplicações possíveis para melhorar a segurança e a escalabilidade de sistemas legados.