Как настроить nginx X-Forwarded-Port как исходный порт запроса

Я использую nginx в стандартном сценарии обратного прокси, чтобы передавать все запросы /auth на другой хост, однако я пытаюсь использовать нестандартные порты.

Моя конечная цель - установить заголовок X-Forwarded-Port на порт, на который поступает запрос.

Вот мой блок местоположения в nginx.conf:

location /auth/ {
    proxy_pass       http://otherhost:8090;
    proxy_set_header Host $host;
    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 $scheme;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Port <VAR>;
}

Этот nginx работает в контейнере докеров, который настроен для пересылки запросов с 8085 на 80 в контейнере, так что процесс nginx прослушивает 80:

0.0.0.0:8085->80/tcp

Когда я нажимаю URL:

http://localhost:8085/auth/

Я правильно перенаправлен на http://otherhost:8090, но заголовок X-Forwarded-Port отсутствует или неправильный.

Если в исходном блоке у меня <VAR>, я пробовал следующее:

  • $server_port - это порт, который прослушивает nginx (80), а не порт запроса.

  • $pass_port - Кажется, что в моей настройке значение null, поэтому nginx отбрасывает заголовок.

  • $http_port - это случайный порт для каждого запроса.

  • $remote_port - это случайный порт для каждого запроса.

Я могу изменить свою конфигурацию во время развертывания, чтобы жестко указать известный порт входящих запросов, но в идеале я мог бы изменить передний порт без каких-либо изменений в конфигурации nginx.

Я просмотрел список переменных nginx, но не нашел ничего похожего на $request_port. Есть ли у меня какой-нибудь способ реализовать свои намерения?


person Andrew Stubbs    schedule 10.03.2020    source источник
comment
Вы пробовали $remote_port? Кроме того, мне трудно понять, чем порт, который слушает nginx ($server_port), будет отличаться от порта запроса.   -  person Mehdi    schedule 10.03.2020
comment
@Mehdi - $ remote_port также кажется случайным для каждого запроса. Запросы попадают на хост докера на порт 8085, который пересылается в контейнер на порт 80, поэтому nginx прослушивает 80, но порт в URL-адресе - 8085.   -  person Andrew Stubbs    schedule 10.03.2020


Ответы (5)


Это грубая идея для написания Nginx conf, но я уверен, что это поможет вам в перенаправлении.

server {    
    listen 80;  
    server_name host.docker.internal;   

    # By default land on localhost:80 to root so in root we copied UI build to the ngnix html dir.
    # have a look to docker-compose uiapp service.
    location / {    
            root   /usr/share/nginx/html;   
            index  index.html index.htm;    
    }   

   # after location add filter, from which every endpoint starts with or comes in endpoint 
   # so that ngnix can capture the URL and reroute it.
   # like /backend/getUserInfo/<UserId> 
   # In above example /backend is that filter which will be captured by Ngnix and reroute the flow.
    location /backend { 
        proxy_set_header X-Forwarded-Host $host;    
        proxy_set_header X-Forwarded-Server $host;  
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        #proxy_pass http://<ContainerName>:<PortNumber>; 
        # In our case Container name is as we setup in docker-compose `beservice` and port 8080
        proxy_pass http://beservice:8080;   
    }   
}

Для более подробной информации вы можете посмотреть этот проект.

https://github.com/dupinder/NgnixDockerizedDevEnv

person Dupinder Singh    schedule 18.08.2020

Единственный обходной путь, который я нашел, - это использовать правило map для получения порта из переменной http_host, например.

    map $http_host $port {
      default 80;
      "~^[^\:]+:(?<p>\d+)$" $p;
    }
person pditommaso    schedule 11.08.2020

Странно, что на это еще не ответили, но ответ таков:

proxy_set_header X-Forwarded-Port $server_port;
person Sander Steffann    schedule 07.06.2020
comment
Спасибо за ответ, но я не думаю, что это так. $ server_port - это порт, который прослушивает процесс nginx, не обязательно порт, на который был сделан запрос - person Andrew Stubbs; 08.06.2020
comment
Документация для server_port, похоже, указывает, что это порт, на котором был сделан запрос. http://nginx.org/en/docs/http/ngx_http_core_module.html $ server_port порт сервера, который принял запрос - person Nicholi; 28.08.2020
comment
Если перед nginx есть балансировщик нагрузки, который получает запрос от клиента на порт 8000 и перенаправляет его на 8100, а nginx слушает на 8100, то $ server_port равен 8100. Но автору нужен порт из оригинала. запрос (8000) - person user1383029; 09.09.2020

Внутри контейнера вы не можете получить доступ к внешнему конфигу. И nginx не поддерживает использование переменных среды внутри большинства блоков конфигурации.

Но если вы используете poco, вы можете определить свои порты, пути и т. Д. В простом файле env. Это определение также используется конфигурацией docker-compose или переменной env. Например

yourconfig.env

PROJECT_HOME=..
MAGIC_DOCKER_PORT=8085

файл poco.yml (основная конфигурация вашего проекта, определение планов)

version: '3.0'
maintainer: "[email protected]"

environment:
  include: docker/conf/yourconfig.env

plan:
  live:
    description: "your plan to run live"
    docker-compose-file:
      - docker/dc-proxy.yml
      - docker/dc-other-service.yml
# you can define other plans to run local/dev env

и в файле docker / dc-proxy.yml (соответствующая часть):

version: '3'
services:
  proxy:
    image: nginx:alpine
    env_file: conf/yourconfig.env
    ports:
      - ${MAGIC_DOCKER_PORT}:80
    command: /bin/sh -c "envsubst < /etc/nginx/conf.d/mysite.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'" 

и, наконец, соответствующая часть вашего шаблона конфигурации из /etc/nginx/conf.d/mysite.template

listen ${MAGIC_DOCKER_PORT};
...
  location /auth/ {
    ...
    proxy_set_header X-Forwarded-Port ${MAGIC_DOCKER_PORT};
    ...
  }

Для организации файлов я использую следующую структуру папок. Это не является обязательным, но для меня легко использовать, потому что структура всех моих проектов одинакова.

/
  docker                <- all of docker related files here
    conf                <- env files, service configs, etc
    scripts             <- shell scripts which used by containers
    dc-*.yml            <- separate all services into single compose files
  poco.yml              <- main config, "start here" point
  project-related-files <- separated by each service

Объяснение

Определите пару "ключ-значение" в файле .env. Это используется poco для создания файлов docker-compose, а также для создания переменной среды в контейнере nginx. После этого используйте envsubst для заполнения шаблона конфигурации nginx и, наконец, запускает службу nginx.

person sarkiroka    schedule 12.08.2020

Я использовал это:

map $http_x_forwarded_port $my_forwarded_port {
    default $remote_port;
    "~^(.*)$" $1;
}

Все заголовки устанавливаются в переменных в nginx с префиксом http. То есть, если в заголовке указано origin = domain.com, вы можете использовать $ http_origin для получения domain.com. Итак, мой код устанавливает $my_forwarded_port на перенаправленный порт, если он установлен, в противном случае - на $ remote_port

person user1383029    schedule 09.09.2020