Назад | Перейти на главную страницу

Прокси-серверы и HTTP через одно и то же место в Nginx

Прямо сейчас есть приложение, которое позволяет людям подключаться к настольному приложению через Интернет, открывая веб-сервер AngularJS на базе Атмосфера. Настольное приложение предоставляет IP-адрес текущего человека, чтобы любой, у кого есть этот адрес, мог подключиться.

Я пытаюсь замаскировать этот IP-адрес, проксируя его через свой сервер (example.com). В настоящее время на моем сервере размещается ряд приложений (Ruby on Rails + Elastic Search, Logstash, Kibana - ELK) и проксируются клиентом Nginx.

Я работал над тем, чтобы успешно замаскировать IP-адреса через прокси-сервер Node HTTP (локально), и теперь я пытаюсь заставить его работать при использовании Nginx. Приложение AngularJS использует веб-сокеты, поэтому мне нужно проксировать как HTTP, так и WS-запрос.

См. Эту схему:

Я очень близок к тому, чтобы во всем разобраться. Я тестировал локально без Nginx, и IP-адреса маскируются правильно. У меня возникла проблема с тем, чтобы Nginx перенаправлял HTTP и веб-сокеты через одно и то же место (см. Код).

Из всех руководств и сообщений о сбоях сервера я видел, что веб-узлы обычно указывают на другое место, а Nginx аккуратно обновляет соединение.

Прямо сейчас у меня возникла проблема: я пытаюсь использовать прокси-сервер через протоколы HTTP / 2 и Websockets в одном месте. Я прибегал к злобным хитростям, таким как использование IF внутри location блоки (но они не работали).

В идеале я бы хотел, чтобы веб-сокеты указывали на другое место, чем HTTP, и это решило бы проблему. Моя текущая проблема в том, что у меня нет исходного кода приложения AngularJS, чтобы я мог это сделать.

Кажется, что сервер Atmosphere обнаруживает соединение Websockets через параметры запроса (это URL-адрес, к которому он подключается):

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.

Вот часть моей текущей конфигурации от Nginx:

upstream ipmask_docker_app {
  server ipmask: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;
  }
}

В приведенном выше коде кажется, что у меня нет proxy_set_header Host $http_host; и proxy_set_header Upgrade $http_upgrade В то же самое location блок. Вот почему я попробовал сопоставить безуспешно query_string из X-Atmosphere-tracking-idи настройте заголовки для обновления в случае совпадения.

В противном случае, если я обновлю соединение, я не смогу увидеть загруженную веб-страницу, поскольку она, похоже, проксирует не протокол HTTP, а протокол WS.

Единственный способ обновить веб-сокеты - указать на другой location? Или есть способ обновить оба (HTTP и WS), указав их в одном месте?

Спасибо!

Самый простой способ, который я нашел, - это перейти в разные места на основе заголовка «Обновление»:

server {
  # ...

  location / {
    try_files /nonexistent @$http_upgrade;
  }

  location @websocket {
    # websocket related stuff
  }

  location @ {
    # web related stuff
  }
}