如何将nginx X-Forwarded-Port配置为原始请求端口

qzwqbdag  于 2023-11-17  发布在  Nginx
关注(0)|答案(6)|浏览(323)

我在一个标准的反向代理场景中使用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运行在一个docker容器中,它被配置为将来自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删除了header。
  • $http_port-这是每个请求的随机端口。
  • $remote_port-这是每个请求的随机端口。

我可以在部署时修改我的配置,以硬编码到传入请求的已知端口,但理想情况下,我可以在不更改nginx配置的情况下更改前端端口。
我已经搜索了the nginx variable list,但找不到任何类似$request_port的东西。有什么方法可以让我实现我的意图吗?

p5cysglq

p5cysglq1#

我发现的唯一解决方法是使用map规则从http_host变量中获取端口,例如。

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

字符串

k7fdbhmy

k7fdbhmy2#

这是一个写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

eqoofvh9

eqoofvh93#

从容器内部你不能访问外部配置。并且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 compose文件中(相关部分):

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服务

pepwfjgg

pepwfjgg4#

这里是一个工作的解决方案,当你的nginx可以在反向代理后面(如果你不在反向代理后面,或者反向代理不添加X-Forwarded-* 头文件,也可以工作):

# Check if a X-Forwarded-Proto header (set by reverse-proxy) is already present. If not take the scheme used to call our nginx server.
map $http_x_forwarded_proto $x_forwarded_proto {
    default $http_x_forwarded_proto;
    ""      $scheme; # Note that if the reverse-proxy does not add a X-Forwarded-Proto header, it may be incorrect if the protocol used by the reverse proxy is not the same as the one on which your nginx server is listening. In this case you have no solution than harcode the correct value.
}

# Check if a X-Forwarded-Host header (set by reverse-proxy) is already present. If not take the value of the 'Host' header.
map $http_x_forwarded_host $x_forwarded_host {
    default $http_x_forwarded_host;
    ""      $http_host;
}

# Set the default port of each scheme/protocol (80 for http, 443 for https)
map $x_forwarded_proto $default_http_port {
    default 80;
    "https" 443;
}

# Extract the real port of the client request url (unfortunatly nginx has no variable to get this info)
map $http_host $request_port {
    default                 $default_http_port; # If port not explicitely defined in url take the default one associated to the calling scheme/protocol (80 for http, 443 for https)
    "~^[^\:]+:(?<p>\d+)$"   $p;
}

# Check if a X-Forwarded-Port header (set by reverse-proxy) is already present. If not take the port from the client request url
map $http_x_forwarded_port $x_forwarded_port {
    default $http_x_forwarded_port;
    ""      $request_port;
}

...

proxy_set_header X-Forwarded-Proto $x_forwarded_proto;
proxy_set_header X-Forwarded-Host $x_forwarded_host;
proxy_set_header X-Forwarded-Port $x_forwarded_port;

字符串

vmdwslir

vmdwslir5#

我用这个:

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

字符串
所有的头部都是在nginx的变量中设置的,以http. I.e为前缀,如果你在头部中有origin = domain.com,你可以使用$http_origin来获得“domain.com”。所以我的代码将$my_forwarded_port设置为转发端口,如果它被设置,否则为$remote_port

sy5wg1nm

sy5wg1nm6#

奇怪的是,这个问题还没有答案,但答案是

proxy_set_header X-Forwarded-Port $server_port;

字符串

相关问题