V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
nangdiea
V2EX  ›  问与答

请求时好像是候绕过 Nginx 中间件导致参数缺失 - 如何排查并解决请求未经过 Nginx 的问题?

  •  1
     
  •   nangdiea · 2023-08-25 15:36:34 +08:00 · 695 次点击
    这是一个创建于 440 天前的主题,其中的信息可能已经有所发展或是发生改变。

    背景

    • 解析:百度服务器 + (腾讯云域名 + 自带免费解析)
    • 服务器端:linux + 用宝塔搭建(最新) + nginx + nestjs
    • 客户端:微信小程序 + uni-app

    描述问题

    我遇到了一个问题,有时候(虽然非常罕见,我无法复现),在向服务器发送请求时,收到的消息“request.data”是空的,并且响应中的请求头不包含 Nginx 的信息,但是状态码仍然是 200 。正常情况下,响应中会包含 Nginx 的参数,并且由于我使用的是 nestjs ,无论处理结果如何,都会统一格式化返回的数据,所以数据不可能为空 response.json({总是一个对象})

    以下是出现问题时的错误截图

    • 图片中显示 [4|200](其中 200 是状态码)( 4 表示重试了 4 次但仍然出错,当收到空数据时我会进行重试)。
    • 图片中的 xxx/user/token?t=${index} 表示 0-4 次请求(我怀疑这是缓存问题)。
    • 图片中的 "h":"xxx" 是响应请求头数据:h: result.headers 。
    • 图片中的 "s": request:ok 是响应的 msg:result.statusText 。

    test

    • 经常会收到这个,导致无法正常使用,因为拿不到 token test

    问题判断标准

    • 状态码是 200
    • 返回的 result.data 是空的(不可能空)
    • 响应请求头不包含 nginx 信息,只留下不知道哪里设置的信息 “x-request-xxx”

    尝试过的办法

    • 尝试打开 Nginx 日志进行查询,查看是否包含某个请求 t=x (t=x 前面讲了重试时会出现 0-4 ,确认请求没有经过 Nginx 处理)
    • 尝试在服务器文件中查找是否包含某个内容"x-requestproxy"(已排除 sys 和 proc 文件夹,但没有找到)
    • 腾讯域名解析已升级至企业版,仍然出现问题(这是我作为新手领取的免费版本)。
    • 问了 GPT 没解决,被气到了
    • 向腾讯云咨询了域名解析问题,也询问了服务器是否存在问题,但没有发现任何异常。

    为了查明问题的原因,我使用了以下命令来查找文件中是否存在包含"requestproxy"的内容:

    查找哪个文件有这个字段名(无收获)
    find . \( -path ./sys -o -path ./proc \) -prune -o -type f -exec grep -q "requestproxy-ip" {} \; -print 2>/dev/null
    
    查找高频率 ip (无收获)
    find . \( -path ./sys -o -path ./proc \) -prune -o -type f -exec grep -q "9.141.233.128" {} \; -print 2>/dev/null
    

    错误与正常的规律

    正常情况

    无论请求是否报错,正常响应中的请求头都应该包含以下内容:

    server: nginx
    x-powered-by: Express
    

    正常情况下,返回的数据( data )永远不会为空,因为 nestjs 都会格式化返回的数据。

    request.data.xxx // 不可能为空
    

    异常情况(非正常返回):

    返回 http 状态码为 200 和 request:'ok' 并且请求响应头中会包含以下信息(注意:server 和 x-powered-by 等信息不会包含在响应头中):

    x-requestproxy-internal-501:1
    x-requestproxy-ip:[ip,ip] // 总会出 2 个美国 IP
    x-requestproxy-ssl-peer-failed-verifiaction:-1
    
    另外,x-requestproxy-ip 中的某些 IP 出现频率较高,如:
    9.141.233.128 // 这个出现频率好像挺高
    9.141.177.175
    9.141.140.10
    9.141.140.228
    9.141.142.146
    9.141.176.16
    9.141.176.2
    11.151.86.163
    

    异常情况下,data 为空,即 request.data='',没有任何内容返回。

    8 条回复    2023-08-30 23:02:04 +08:00
    nangdiea
        1
    nangdiea  
    OP
       2023-08-25 20:21:22 +08:00
    没有懂得老哥么,help me
    julyclyde
        2
    julyclyde  
       2023-08-27 19:18:55 +08:00
    你的描述太混乱了,包含了大量无用的内容,而且也不严谨
    这个截图“连接失败”是哪个软件产生的?它在整个事件里是什么角色?你的域名真的指向那个服务器嘛?中间是否还有其他转发节点?

    要区分:
    客户端到 nginx 、nginx 到你的服务器软件,这两段,分别描述
    首先控制好从客户端发给 nginx 的请求,curl -v 看细节
    然后核实一下 nginx 转发给后面服务器软件的请求啥样子,后面服务器返回给 nginx 的响应啥样子,别依赖你的 nestjs ,而是直接抓包看或者用更简单的 dummy server 来看
    nangdiea
        3
    nangdiea  
    OP
       2023-08-29 17:04:19 +08:00
    @julyclyde
    微信小程序请求域名 => (域名直连解析到 IP ) => (宝塔提供的,直接填写自动生成) Nginx => nodejs 端口

    这个截图“连接失败”是哪个软件产生的?
    答:使用小程序返回时,发现错误,我会弹出这个错误提示,打印信息:请求成功后返回的响应头数据

    你的域名真的指向那个服务器嘛?
    答:仅有一个服务器+一个域名,我是域名直接解析到服务器 IP = 记录 A : 服务器 IP

    我的服务器很简单,就单纯的一个服务器+一个域名,另外服务器没有自己配置任何东西,一切配置修改均来自 “宝塔” 生成、启动、依赖安装

    这个是相同请求正常返回的响应头数据(显然和图片的不一致):
    access-control-allow-origin: *
    content-length: 2629
    content-type: application/json; charset=utf-8
    date: Tue, 29 Aug 2023 09:02:52 GMT
    etag: W/"a45-LbgYYOlIgtMqVzvuaHXDpyYu94M"
    for-weapp-devtools: {"server":["nginx"],"date":["Tue, 29 Aug 2023 09:02:52 GMT"],"content-type":["application/json; charset=utf-8"],"content-length":["2629"],"x-powered-by":["Express"],"access-control-allow-origin":["*"],"etag":["W/\"a45-LbgYYOlIgtMqVzvuaHXDpyYu94M\""],"x-custom-header":["Custom Value"]}
    server: nginx (这里会有 nginx )
    x-custom-header: Custom Value
    x-powered-by: Express
    nangdiea
        4
    nangdiea  
    OP
       2023-08-29 17:14:55 +08:00
    ![avatar]( https://img1.imgtp.com/2023/08/29/AfdzwJ4V.png)

    我的客户端代码:
    ```javascript
    const data = result.data?.data;
    if (!data) throw new Error(`[${index}|${result.status}]code: ${JSON.stringify({
    h: result.headers,
    s: result.statusText
    })}`);
    ```
    nangdiea
        5
    nangdiea  
    OP
       2023-08-29 17:18:16 +08:00
    server
    {
    listen 80;
    listen 443 ssl http2;
    server_name xxx.xx.com;

    index index.html index.htm default.htm default.html;
    #root /www/wwwroot/self-sy/service;
    # 添加自定义标头在这里
    add_header X-Custom-Header "Custom 2Value" always;

    #SSL-START SSL 相关配置
    #error_page 404/404.html;
    ssl_certificate /www/server/panel/vhost/cert/sy/fullchain.pem;
    ssl_certificate_key /www/server/panel/vhost/cert/sy/privkey.pem;
    ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    add_header Strict-Transport-Security "max-age=31536000";
    error_page 497 https://$host$request_uri;
    #SSL-END

    #ERROR-PAGE-START 错误页相关配置
    #error_page 404 /404.html;
    #error_page 502 /502.html;
    #ERROR-PAGE-END


    #REWRITE-START 伪静态相关配置
    include /www/server/panel/vhost/rewrite/node_sy.conf;
    #REWRITE-END

    #禁止访问的文件或目录
    location ~ ^/(\.user.ini|\.htaccess|\.git|\.svn|\.project|LICENSE|README.md|package.json|package-lock.json|\.env) {
    return 404;
    }

    #一键申请 SSL 证书验证目录相关设置
    location /.well-known/ {
    root /www/wwwroot/self-sy/service;
    }

    #禁止在证书验证目录放入敏感文件
    if ( $uri ~ "^/\.well-known/.*\.(php|jsp|py|js|css|lua|ts|go|zip|tar\.gz|rar|7z|sql|bak)$" ) {
    return 403;
    }


    # HTTP 反向代理相关配置开始 >>>
    location ~ /purge(/.*) {
    proxy_cache_purge cache_one $host$request_uri$is_args$args;
    }

    location / {
    proxy_pass http://127.0.0.1:3010;
    # 添加自定义标头在这里
    add_header X-Custom-Header "Custom Value" always;
    proxy_set_header Host $host:$server_port;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header REMOTE-HOST $remote_addr;
    add_header X-Cache $upstream_cache_status;
    proxy_set_header X-Host $host:$server_port;
    proxy_set_header X-Scheme $scheme;
    proxy_connect_timeout 30s;
    proxy_read_timeout 86400s;
    proxy_send_timeout 30s;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    }
    # HTTP 反向代理相关配置结束 <<<

    access_log /www/wwwlogs/sy.log;
    error_log /www/wwwlogs/sy.error.log;
    }
    julyclyde
        6
    julyclyde  
       2023-08-30 16:06:10 +08:00
    我是有点怀疑微信小程序是直接访问服务器的还是经过腾讯再去访问的……没了解过,但微信打开网页明显是经过腾讯服务器的。

    你的 server header 是 response 里边的啊,这也是符合规定的。但你提问的时候说的是 request header 啊

    另外,总会出两个美国 IP 是不是你翻墙了?
    nangdiea
        7
    nangdiea  
    OP
       2023-08-30 22:56:49 +08:00
    @julyclyde
    关于 header:
    我发出来都是 response 服务器响应返回的 header ,没有打印请求头,都是响应头 (非发送时 header );

    关于美国 IP:
    这个参数的 x-requestproxy-ip 这个是放在响应头里面的,里面都会带上 IP ,应该是经过转发,我的机器是国内百度云的,不支持翻墙。
    另外我说 IP 属于是美国,是我在百度搜索 IP 地址出来的,不知道准确不。
    nangdiea
        8
    nangdiea  
    OP
       2023-08-30 23:02:04 +08:00
    域名解析应该没问题,就很奇怪,因为有时候可以,有时候不行,真是太过于奇怪了。
    我想尝试搜索 requestproxy 整个服务器是否有关于这个字段的文件,似乎没有;( 查询姿势不对?)
    我傻了,虽然不影响使用,但是如果是小概率出现,还是会对个别用户有影响。(该不会百度云有问题吧,中毒咯?)
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   997 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 21:38 · PVG 05:38 · LAX 13:38 · JFK 16:38
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.