Permitir uma conexão TLS passthrough no contexto stream do NGINX
O NGINX pode recusar um relay TCP TLS sem terminar o TLS. Coloque a regra de admissão em stream, não num location HTTP, e verifique qual endereço de par chega.
Encaminhar bytes cifrados sem nunca deter o certificado é o que um relay TLS passthrough faz, e o arranjo é prático e um pouco confuso ao mesmo tempo. Como nada é decifrado, não existe nada em forma de HTTP para filtrar, então o bloco location habitual e as suas regras de acesso não servem aqui. A decisão de que o NGINX dispõe diz respeito à própria conexão: qual par da rede bateu e se esse par deve ser encaminhado.
A decisão pertence ao stream, não ao HTTP
No contexto stream o NGINX trabalha com sessões TCP. Vê o endereço de par da conexão e pode aplicar-lhe regras allow e deny ordenadas antes de qualquer byte chegar ao backend. É uma decisão de admissão completa e não exige chave privada, certificado nem análise HTTP.
| Mechanism | What it decides | Where it lives |
|---|---|---|
| stream allow/deny | Whether this TCP peer is relayed | stream server block |
| ssl_preread map | Which backend a named connection goes to | stream, with the preread module |
| HTTP location rule | Whether an HTTP request is served | http server block |
Essas três linhas nunca se substituem. Copiar uma diretiva de acesso HTTP para o ficheiro que menciona a porta 443 não muda nada, porque o servidor stream nunca lê o contexto http.
Admite a conexão antes de a encaminhar
Suponha uma instalação existente com os módulos stream e stream-access disponíveis, clientes VPN que mantêm endereços de origem em 10.90.0.0/24, e um backend em 192.168.50.20:443 que já serve a identidade HTTPS pretendida.
stream {
server {
listen 443;
allow 10.90.0.0/24;
deny all;
proxy_pass 192.168.50.20:443;
}
}
Leia isto como um fragmento de um novo listener, não como uma substituição direta de uma configuração em funcionamento. Reveja primeiro os listeners e includes existentes, porque um segundo listener numa porta já ocupada falha no reload, não no momento do pedido.
Repare no que falta: não há listen ... ssl, não há diretiva de certificado. O NGINX encaminha o fluxo cifrado, e o backend termina o TLS e apresenta o certificado que o cliente valida. Um cliente que falhe a allowlist recebe a sessão TCP rejeitada, não uma página HTTP 403, e qualquer ferramenta que espere um código de estado reportará algo inútil.
O que a allowlist cobre e o que não cobre
Se o relay já escolhe backends pelo nome do servidor, ssl_preread e um map podem continuar a fazer esse trabalho, desde que o módulo esteja disponível. O nome continua a ser fornecido pelo cliente, e nada em apresentar um nome prova que o cliente aderiu à VPN.
A regra de exemplo cobre todo o listener stream. Isso torna-a inadequada para um único ponto de entrada que serve uma mistura de sítios públicos e sítios apenas para VPN, onde seria necessária uma exceção por nome; listeners separados são geralmente mais claros do que uma política dependente do nome que ninguém consegue ler.
Vale a pena nomear mais duas lacunas. Uma correspondência de prefixo não diz nada sobre por que interface o pacote chegou, e uma regra HTTP noutro lugar não pode restringir este listener. Ambas são razões para manter a política de entrada ao nível do host no quadro em vez de tratar uma linha allow como toda a fronteira. Escreva a fronteira como dois controlos que têm de concordar, para que qualquer alteração num deles seja revista.
Que endereço o NGINX vê realmente?
Um balanceador de carga, outro proxy ou um source NAT podem colocar um intermediário à frente do NGINX, pelo que o par observado não é o endereço interno do cliente VPN. Inspecione o caminho real antes de escolher um prefixo, porque uma allowlist escrita para o endereço errado ou admite todos os que estão atrás do tradutor ou ninguém.
O protocolo PROXY e o tratamento de IP real são respostas legítimas, e só devem ser configuradas para remetentes compatíveis e explicitamente fidedignos. Ambos os mecanismos acreditam no que o remetente diz, e é precisamente por isso que a lista de remetentes tem de ser curta. Confiar num cabeçalho de identidade de qualquer cliente de internet não torna a informação de origem fiável outra vez; converte uma recusa correta numa aceitação falsificada.
Teste os dois resultados antes do reload
Valide a configuração, faça reload e depois teste duas vezes: uma nova sessão permitida que tem de funcionar e uma recusada que não deve. Mantenha a verificação normal do certificado do backend no teste permitido, porque um relay que liga mas não consegue validar o backend resolveu um problema e criou outro.
nginx -t
ss -tnp | grep ':443'
Verifique também a rota até ao backend e a resposta em separado. Passar a allowlist prova apenas que o NGINX aceitou a sessão; não consegue fazer um backend inalcançável responder, nem reparar um caminho de retorno que faltava antes de começar.