Вопрос: Сделать nginx для передачи имени хоста вверх по потоку при обратном преобразовании


Я запускаю несколько контейнеров докеров с именами хостов:

web1.local web2.local web3.local

Маршрутизация выполняется на основе имени хоста nginx. У меня есть прокси перед этой настройкой (на другой машине, подключенной к Интернету), где я определяю восходящий поток как:

    upstream main {
      server web1.local:80;
      server web2.local:80;
      server web3.local:80;
    }

И фактическое описание виртуального хоста:

    server {
      listen 80;
      server_name example.com;
      location / {
        proxy_pass http://main;
      }
    }

Теперь, поскольку контейнеры получают имя хоста «main» вместо «web1.local», они не отвечают должным образом на запрос.

Вопрос: как я могу сказать nginx передать имя восходящего сервера вместо имени восходящей группы серверов в заголовке Host: при запросе проксирования?


71
2018-05-23 20:46


Источник


Я не думаю, что ты можешь. Почему бы вам не настроить серверные серверы для ответа на главный или example.com? Это не значит, что бэкэнд не знает, кто Это является. Реверс легко возможен: proxy_set_header Host $ host; заменит любую переменную хоста, возвращающуюся из восходящего потока с именем хоста из исходного запроса. - Andrew Domaszek
Правильное дело - исправить приложение. - Michael Hampton♦


Ответы:


На самом деле вы можете сделать это через proxy_set_header.

Для более подробной информации смотрите здесь: http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_set_header или см. пример использования: https://stackoverflow.com/questions/12847771/configure-nginx-with-proxy-pass

Я включил динамический подход в вашу выше размещенную конфигурацию:

server {
  listen 80;
  server_name example.com;
  location / {
    proxy_pass       http://main;
    proxy_set_header Host            $host;
    proxy_set_header X-Forwarded-For $remote_addr;
  }
}

Вот пример со статическим именем хоста:

server {
  listen 80;
  server_name example.com;
  location / {
    proxy_pass       http://main;
    proxy_set_header Host            www.example.com;
    proxy_set_header X-Forwarded-For $remote_addr;
  }
}

85
2018-05-24 08:10



proxy_set_header X-Forwarded-For $ proxy_add_x_forwarded_for; кажется лучше - sivann
@pavel: понял. На самом деле я также провел некоторые исследования и некоторые тесты. Кажется, что нет прямого подхода к выполнению вашего требования. Таким образом, даже «подчёркнутое» решение является решением. Я не люблю спрашивать, почему вы хотели бы это сделать. Я уверен, что у вас есть причины. :-) - Jens Bradler
@JensBradler. Вы выглядите более экспертом, чем я, не могли бы вы рассказать мне, что вы думаете о моем решении? Я хочу сделать то же самое, потому что я запускаю две копии своего веб-сайта из двух учетных записей моего провайдера: site1.myisp.com а также site2.myisp.com и они отвечают только на свое имя. Теперь я владею своим доменным именем, и я бы хотел использовать свой веб-сайт ISP для загрузки баланса моих серверов. Разве это не веская причина? Большое спасибо ;) - ncenerar
@ncenerar Вы можете это сделать, но это приведет вас к одной точке отказа: балансировщик нагрузки. Если это относится к балансировке нагрузки (а не к избыточности), вы также можете использовать балансировку нагрузки на основе DNS в сочетании с отказоустойчивостью DNS. - Jens Bradler
Этот ответ отражает совет официального блога, - Bernard Rosset


У меня была та же проблема, и я, наконец, решил ее, используя два уровня прокси. Вот как вы могли бы сделать для своей ситуации (я думаю):

server {
  listen      8001 default_server;
  server_name web1.example.com;
  location / {
    proxy_pass       http://web1.local:80;
    proxy_set_header Host web1.local:80;
  }
}

server {
  listen      8002 default_server;
  server_name web2.example.com;
  location / {
    proxy_pass       http://web2.local:80;
    proxy_set_header Host web2.local:80;
  }
}

server {
  listen      8003 default_server;
  server_name web3.example.com;
  location / {
    proxy_pass       http://web3.local:80;
    proxy_set_header Host web3.local:80;
  }
}

upstream main {
  server 127.0.0.1:8001;
  server 127.0.0.1:8002;
  server 127.0.0.1:8003;
}

server {
  listen      80;
  server_name example.com;
  location / {
    proxy_pass http://main;
  }
}

Как вы можете видеть, трюк заключается в создании локального сервера, отвечающего на определенный порт, который проксирует сервер, переписывая правильный хост для каждого сервера. Затем вы можете использовать эти локальные серверы в своем потоке вверх и, наконец, использовать этот поток вверх в реальном прокси.


20
2017-08-20 15:20



Первоначально я использовал подход Lua, но теперь полностью переключился на HAProxy, который позволяет делать именно то, что я хотел со стандартной конфигурацией. - pavel_karoukin


Поэтому, прочитав всю документацию для nginx (я не смог разобрать код для upstream module = (), я придумал это бастардированное решение. К сожалению, это решение не отслеживает неудавшиеся хосты, а просто выбирает случайный и перенаправляет запрос на него. Поэтому мне нужно настроить какой-то мониторинг, чтобы убедиться, что все серверы запущены.

server {
        listen 80;
        server_name example.com;
        resolver 127.0.0.1;

        location / {
                set $upstream "";
                rewrite_by_lua '
                        local upstreams = {
                                "http://web1.dokku.localdomain",
                                "http://web2.dokku.localdomain",
                                "http://web3.dokku.localdomain",
                                "http://web4.dokku.localdomain"
                        }
                        ngx.var.upstream = upstreams[ math.random( #upstreams ) ] 
                ';
                proxy_pass $upstream;
        }
}

2
2018-05-24 13:39





Мы передаем вверху addr в виде отдельного заголовка, подобного этому

server {
  listen 80;
  server_name example.com;
  location / {
    proxy_pass       http://main;
    proxy_set_header Host            $host;
    proxy_set_header X-Forwarded-For $remote_addr;
    add_header       X-Upstream      $upstream_addr;
  }
}

Что, если вы попробуете?

server {
  listen 80;
  server_name example.com;
  location / {
    proxy_pass       http://main;
    proxy_set_header Host            $upstream_addr;
    proxy_set_header X-Forwarded-For $remote_addr;
    add_header       X-Host          $host;
  }
}

2
2018-04-26 17:49





Хотя цель кажется логичной, nginx не собирается менять заголовок Host:, чтобы соответствовать восходящему потоку, Вместо этого он обращается upstream доменные имена, такие как CNAME в DNS - как способ доступа к IP-адресу.

Заголовки запроса (и корпус) фиксируются до того, как выбран канал вверх. Восходящий поток может изменить средний запрос, если обнаружено, что определенный восходящий поток не реагирует, но запрос не изменяется.


1
2018-06-23 01:06