Proxy Websockets e HTTP através da mesma localização no Nginx

1

Neste momento, há um aplicativo que permite que as pessoas se conectem a um aplicativo da área de trabalho pela Web, expondo um servidor da Web AngularJS com tecnologia Atmosphere . O aplicativo Desktop expõe o endereço IP da pessoa atual para que qualquer pessoa com o endereço possa se conectar.

Estou tentando mascarar esse IP fazendo proxy por meio do meu servidor (example.com). Atualmente, meu servidor hospeda uma série de aplicativos (Ruby on Rails + Pesquisa Elástica, Logstash, Kibana - ELK) e são intermediados por proxy por um cliente Nginx.

Eu trabalhei para mascarar com êxito os endereços IP através do Node HTTP Proxy (localmente), e agora estou tentando fazê-lo funcionar enquanto estiver usando o Nginx. O aplicativo AngularJS usa Websockets, então eu preciso fazer proxy tanto na solicitação HTTP quanto na WS.

Veja este diagrama:

Estoumuitopertodedescobrirtudo.EutesteilocalmentesemNginxeosendereçosIPestãosendomascaradoscorretamente.EstoutendoumdesafioparafazeroNginxredirecionaroHTTPeoWebsocketspelomesmolocal(vejaocódigo).

Detodosostutoriaisepostagensdefalhadoservidor,viqueosWebsocketsgeralmenteapontamparaumlocaldiferente,eoNginxatualizaaconexãonormalmente.

Estoutendoumdesafioagora,queestoutentandofazerproxyatravésdomesmolocalHTTP/2eprotocolosWebsockets.EurecorriahacksmalvadoscomousarIFdentrodosblocoslocation(maselesnãofuncionaram).

Idealmente,gostariaqueosWebsocketsapontassemparaumlocaldiferentedoHTTP,eissoresolveriaoproblema.Meuproblemaatualéqueeunãotenhoocódigo-fonteparaoaplicativoAngularJSparaqueeupossafazerisso.

OservidorAtmosphereparecedetectaraconexãocomWebsocketspormeiodeparâmetrosdeconsulta(essaéaURLàqualeleseconecta):

ws://the-user-ip/?X-Atmosphere-tracking-id=0&X-Atmosphere-Framework=2.3.2-javascript&X-Atmosphere-Transport=websocket&Content-Type=application/json&X-atmo-protocol=true.

AquiestápartedaminhaconfiguraçãoatualdoNginx:

upstreamipmask_docker_app{serveripmask:5050;}server{server_name"~^\d+\.example\.co$";

  # listen 80;
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  # HTTPS config omitted due to conciseness. 

 location / {
    # https://www.digitalocean.com/community/questions/error-too-many-redirect-on-nginx
        # proxy_ignore_headers X-Accel-Expires Expires Cache-Control;
        # proxy_ignore_headers Set-Cookie;
        # proxy_hide_header Set-Cookie;
        # proxy_hide_header X-powered-by;
        # 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 https;
        proxy_set_header Host $http_host;
        proxy_pass http://ipmask_docker_app;

        proxy_http_version 1.1;

    # Enables Websockets
    # https://www.nginx.com/blog/websocket-nginx/
    # https://stackoverflow.com/a/46675414/1057052
    # Have the http_version 1.1 disabled. I want to know if it works

      # THIS IS EVIL:
      set $ws_header_upgrade  '';
      set $ws_value_upgrade  '';
      set $ws_header_connection ''; 

      proxy_set_header 'Debug Header' $query_string;

      if ($args ~* "X-Atmosphere-tracking-id") {
        set  $ws_header_upgrade Upgrade;
        set  $ws_value_upgrade $http_upgrade;
        set $ws_header_connection "Upgrade";
      }

      proxy_set_header $ws_header_upgrade  $ws_value_upgrade;
      proxy_set_header Connection $ws_header_connection;

    # limit_req zone=one;
    access_log /var/www/cprint/log/nginx.access.log;
    error_log /var/www/cprint/log/nginx.error.log;
  }
}

No código acima, parece que não tenho proxy_set_header Host $http_host; e proxy_set_header Upgrade $http_upgrade no mesmo bloco location . É por isso que tentei corresponder sem sucesso a query_string de X-Atmosphere-tracking-id e configurar os cabeçalhos para atualizá-lo, caso ele corresponda a ele.

Caso contrário, se eu fizer o upgrade da conexão, não consigo ver a Página da Web carregada, pois ela não parece ser o proxy do protocolo HTTP, mas do WS.

A única maneira de atualizar o Websockets é apontar para um diferente location ? Ou existe uma maneira de atualizar ambos (HTTP e WS) apontando-os para o mesmo local?

Obrigado!

    
por Jose A 04.05.2018 / 22:46

1 resposta

2

A maneira mais fácil que encontrei foi saltar para locais diferentes com base no cabeçalho "Upgrade":

map $http_upgrade $type {
  default "web";
  websocket "ws";
}

server {
  # ...

  location / {
    try_files /nonexistent @$type;
  }

  location @ws {
    # websocket related stuff
  }

  location @web {
    # web related stuff
  }
}
    
por 24.07.2018 / 11:18