Proxy reverso de passagem TLS seletivo Nginx baseado em SNI

Proxy reverso de passagem TLS seletivo Nginx baseado em SNI

Tenho um sistema de dispositivos IoT atrás de um NAT, portanto eles não são acessíveis pela Internet pública (embora seja desejado). Para superar isso, amarrei-os a uma VPN, com um membro exposto à Internet pública para atuar como gateway. A VPN possui um domínio interno configurado, e cada membro da rede possui um subdomínio baseado em um ID exclusivo (vamos usar o endereço MAC), assim:12a4f81ead4e.vpn.example.com

Desejo criar um proxy reverso nas Gatwaysolicitações de proxy, executando o nginx.

O plano é criar um registro DNS para o gateway, *.gateway.come rotear (ahem, proxy) o tráfego que vai de/ 12a4f81ead4e.gateway.compara 12a4f81ead4e.vpn.example.com. E assim o usuário final precisaria apenas digitar 12a4f81ead4e.gateway.comno navegador para acessar o dispositivo. Eu gostaria de usar o nginx, pois o gateway já está executando o nginx para outros fins.

Espero que as solicitações HTTP sejam fáceis e possam ser feitas com uma proxy_passdiretiva nginx cuidadosamente elaborada.

Mas e as solicitações HTTPS? Pelo que entendi, a passagem TLS baseada em SNI agora é implementada pelo nginx, mas todos os exemplos que vi até agora criam um mapa estático para ... mapear bem o SNI de entrada para um upstream de destino:

stream {
  map $ssl_preread_server_name $selected_upstream {
    example.org upstream_1;
    example.net upstream_2;
    example.com upstream_3;
    default upstream_4;
  }
  upstream upstream_1 { server 10.0.0.1:443; }
  upstream upstream_2 { server 10.0.0.2:443; }
  upstream upstream_3 { server 10.0.0.3:443; }
  upstream upstream_4 { server 10.0.0.4:443; }
  server {
    listen 10.0.0.5:443;
    proxy_pass $selected_upstream;
    ssl_preread on;
  }
}

O problema é que os dispositivos são adicionados/removidos dinamicamente da VPN e não quero reescrever os arquivos de configuração do nginx o tempo todo. Se for possível ler o mapa de um arquivo, é um passo na direção certa, embora eu ache que o nginx precisaria ser recarregado toda vez que mudasse, o que levanta problemas de permissão, que poderiam ser contornados com regras do sudo, é claro, mas não o melhor solução.

Além disso, só quero fazer proxy de solicitações que chegam *.gateway.come servir outras solicitações https normalmente para os vhosts existentes. Se possível, gostaria de evitar o encerramento da conexão SSL. Não é realmente um requisito difícil, mas gostaria de implementá-lo dessa forma, se for tecnicamente viável. Também apenas para diversão.

Estou bem ouvindo internamente em uma porta alternativa para os outros vhosts, fiz algo semelhante para HTTP quando quis definir um local "global" e movi todos os vhosts HTTP para a porta 81 e implementei um vhost abrangente na porta 80 que atendia a localização "global" e fazia proxy de todo o resto para a porta 81. :)

Então... O que eu precisaria seria algo assim (obviamente não está funcionando):

stream {
  map $ssl_preread_server_name $selected_upstream {
    (.*).gateway.com $1.vpn.example.com;
    default normal_serve;
  }

  upstream normal_serve { server 127.0.0.1:8443; }

  server {
    listen 0.0.0.0:443;
    proxy_pass $selected_upstream;
    ssl_preread on;
  }

  server {
    listen 127.0.0.1:8443;
    server_name other.website.com;

    (...)
  }
}

Responder1

Isso resolve o problema:

stream {
  resolver 8.8.8.8;

  map $ssl_preread_server_name $selected_upstream {
    ~(.*).gateway.example.com $1.vpn.example.com:443;
    default 127.0.0.1:8443;
  }

  server {
    listen 0.0.0.0;
    proxy_pass $selected_upstream;
    ssl_preread on;
  }
}

http {
  resolver 8.8.8.8;
  server {
    listen 127.0.0.1:8443 ssl;
    (...)
  }
}

informação relacionada