Nginx代理出现403问题分析

2023-08-19 09:45:47 浏览数 (2)

背景

最近在处理一个业务场景问题: 项目需要调用某个系统的接口,但是那个系统因为比较历史了,对接口调用来源ip有严格限制,需要将来源ip添加为白名单,但是我们项目的这个工具是使用的serverless平台,无法知道具体的机器 ip,scf是即时性资源,因此来源ip肯定是变化的,因此决定通过一个代理来转发。

nginx配置

通过nginx来进行接口转发(nginx采用statefulset的固定ip部署),配置如下

代码语言:javascript复制
user root;
worker_processes  auto;

error_log  /var/log/nginx/error.log;

pid        /var/log/nginx/nginx.pid;

events {
    worker_connections  1024;
}

http {
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    access_log  /var/log/nginx/access.log  main;
    keepalive_timeout  65;


    upstream cmdb_server {
        server xxxx;
    }

    upstream xingyun_server {
        server xxxx;
    }

    server {
        listen 80;
        server_name xxxx;
        client_max_body_size 100M;
        proxy_read_timeout 120;

        location /cmdb {
            rewrite /cmdb/(.*)$ /$1 break;
            proxy_pass          http://cmdb_server;
        }

        location /xingyun {
            rewrite /xingyun/(.*)$ /$1 break;
            proxy_pass          http://xingyun_server;
        }
    }
}

问题描述

代码语言:javascript复制
root@cmdb-proxy-0:/# curl -vvv http://9.139.61.234/xingyun/api/prm/prm_env_proxy/
*   Trying 9.139.61.234:80...
* Connected to 9.139.61.234 (9.139.61.234) port 80 (#0)
> GET /xingyun/api/prm/prm_env_proxy/ HTTP/1.1
> Host: 9.139.61.234
> User-Agent: curl/7.74.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 403 Forbidden
< Server: nginx/1.23.3
< Date: Fri, 03 Feb 2023 02:55:52 GMT
< Content-Type: text/html; charset=utf-8
< Content-Length: 146
< Connection: keep-alive
< 
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx</center>
</body>
</html>
* Connection #0 to host 9.139.61.234 left intact

测试发现访问该接口一直报403,

解决方法

经过了解,原来对端系统会校验请求header中的host(如果带了的话) 但是我这个访问明显没有带host啊,经过查阅资料,发现nginx会自动带上host字段,value为代理机器的ip,也就是访问url中的ip。

那就指定host试试:

代码语言:javascript复制
root@cmdb-proxy-0:/# curl -vvv -H "Host:api.xingyun.tencentyun.com" http://9.139.61.234/xingyun/api/prm/prm_env_proxy/
*   Trying 9.139.61.234:80...
* Connected to 9.139.61.234 (9.139.61.234) port 80 (#0)
> GET /xingyun/api/prm/prm_env_proxy/ HTTP/1.1
> Host: api.xingyun.tencentyun.com
> User-Agent: curl/7.74.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 403 Forbidden
< Server: nginx/1.23.3
< Date: Fri, 03 Feb 2023 02:55:52 GMT
< Content-Type: text/html; charset=utf-8
< Content-Length: 146
< Connection: keep-alive
< 
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx</center>
</body>
</html>
* Connection #0 to host 9.139.61.234 left intact

结果还是报403,检查nginx配置才发现,没有设置host转发配置

更新配置如下:

代码语言:javascript复制
location /xingyun {
    rewrite /xingyun/(.*)$ /$1 break;
    proxy_pass          http://xingyun_server;
    proxy_set_header Host $host;
}

加上proxy_set_header Host $host;这个

再次测试:

代码语言:javascript复制
root@cmdb-proxy-0:/# curl -vvv -H "Host:api.xingyun.tencentyun.com" http://9.139.61.234/xingyun/api/prm/prm_env_proxy/
*   Trying 9.139.61.234:80...
* Connected to 9.139.61.234 (9.139.61.234) port 80 (#0)
> GET /xingyun/api/prm/prm_env_proxy/ HTTP/1.1
> Host:api.xingyun.tencentyun.com
> User-Agent: curl/7.74.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.23.3
< Date: Fri, 03 Feb 2023 02:55:25 GMT
< Content-Type: application/json
< Content-Length: 132
< Connection: keep-alive
< 
* Connection #0 to host 9.139.61.234 left intact
{"code": 6000, "message": "prm_env_proxy() missing 3 required positional arguments: 'interface', 'params', and 'env'", "data": null}root@cmdb-proxy-0:/# 
root@cmdb-proxy-0:/#

现在OK了。

知识点

变量

是否显示端口

值是否存在

host

"Host:value"显示值为a:b的时候,只显示a

http_host

"Host:value",value存在就显示

proxy_host

默认80不显示其他端口显示

"Host:value"显示

0 人点赞