V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
NGINX
NGINX Trac
3rd Party Modules
Security Advisories
CHANGES
OpenResty
ngx_lua
Tengine
在线学习资源
NGINX 开发从入门到精通
NGINX Modules
ngx_echo
ddd270700
V2EX  ›  NGINX

用 nginx 反代用友软件报 404 错误,有偿求助

  •  
  •   ddd270700 · 342 天前 via Android · 4102 次点击
    这是一个创建于 342 天前的主题,其中的信息可能已经有所发展或是发生改变。
    62 条回复    2022-01-02 19:19:14 +08:00
    ddd270700
        1
    ddd270700  
    OP
       342 天前 via Android
    用 nginx 作反向代理报 404 错,有偿求答

    ##背景
    在公司内网上,一台服务器上作了反向代理远端的用友 U9 平台,用的是最简单的配置全部如下:
    events {
    works_connections 1024;
    }

    http {
    include mime.types;
    default_tpye application/octet-stream;

    server {
    listen 80;
    server_name localhost;

    location / {
    proxy_pass http://10.108.11.149/U9/;
    root html
    index index.html index.htm
    }
    }
    }

    ##出错
    被代理远端用友软件,在服务器上是可以正常访问的;
    服务器是 windows 系统,配置好后,启动 nginx ,在地址栏目输入 127.0.0.1 ,得到 404 错误。
    将地址后面的斜杠〔“/”〕去掉再尝试,也是 404 错误。

    ## 其他的侧面尝试
    报错后,在上面同样的配置文件上,仅仅修改了 proxy_pass 一行去测试其他的服务,服务器地址栏输入 127.0.0.1 访问,都没有问题,大致如下:
    proxy_pass http://10.247.1.44; 成功;
    proxy_pass http://10.161.64.77:9001; 成功;
    ddd270700
        2
    ddd270700  
    OP
       342 天前 via Android
    希望大佬指点迷津。
    50 元起步酬谢,802 分信用极好。
    liuxu
        3
    liuxu  
       342 天前 via Android
    location /U9/ {
    proxy_pass http://10.108.11.149;



    location /U9/ {
    proxy_pass http://10.108.11.149/U9/;

    试试
    liuxu
        4
    liuxu  
       342 天前 via Android
    @liuxu
    第二个打错了,是

    location /U9/ {
    proxy_pass http://10.108.11.149/;
    ddd270700
        5
    ddd270700  
    OP
       342 天前 via Android
    大致结构:
    服务器( windows 安装 nginx )===远端的用友软件(地址是 10.108.11.149 )
    ddd270700
        6
    ddd270700  
    OP
       342 天前 via Android
    @liuxu 我马上去试
    twinsdestiny
        7
    twinsdestiny  
       342 天前
    看 nginx 日志,实际访问的地址是什么
    redial39
        8
    redial39  
       342 天前
    首先确定远端服务是不是监听在 10.108.11.149 这个 ip 上了...如果监听在 127.0.0.1 上..你怎么调都是 404
    ysc3839
        9
    ysc3839  
       342 天前   ❤️ 1
    @redial39 如果只监听了 localhost ,那外部连接应该会被拒绝,nginx 应该会返回 5xx 错误而不是 404 。
    redial39
        10
    redial39  
       342 天前
    location /U9 {
    proxy_pass http://10.108.11.149/U9;
    }
    redial39
        11
    redial39  
       342 天前
    @redial39 不对
    location /U9 {
    proxy_pass http://10.108.11.149;
    }
    ddd270700
        12
    ddd270700  
    OP
       342 天前 via Android
    @liuxu
    两个都尝试了,还是弹出 404 错误。
    值得注意的是,这次的 404 是 nginx 报的。而此前的 404 是用友报的(从报错的画面看出来的)
    ddd270700
        13
    ddd270700  
    OP
       342 天前 via Android
    @redial39 我马上去试
    redial39
        14
    redial39  
       342 天前
    @ddd270700 说到底...你还是需要提供一下 NG 的 URL 转向的后台期望 URL..按照你提供的信息是不够的
    redial39
        15
    redial39  
       342 天前
    如果代理后端需要 U9 上下文就用 10 楼的,如果后端没有上下文,就用 11 楼的
    hymzhek
        16
    hymzhek  
       342 天前
    不要加路径
    location /
    {
    proxy_pass http://10.108.11.149;

    }
    dier
        17
    dier  
       342 天前
    先确认一下 http://10.108.11.149/U9/ 这个链接能正常访问到吗?/U9/是你加上去用于区分还是本身就有的。
    如果本身就有,应该是

    location /U9/ {
    proxy_pass http://10.108.11.149/U9/;
    }

    如果是你用来区分,就不能在 proxy 地址后面加 /U9

    location /U9/ {
    proxy_pass http://10.108.11.149/;
    }
    Ptu2sha
        18
    Ptu2sha  
       342 天前
    试试加上 proxy_set_header Host "你的真实服务的域名";
    dier
        19
    dier  
       342 天前
    另外,如果 location /U9/不是必需要配置的话,建议用# 16 楼的方式
    fantastM
        20
    fantastM  
       342 天前
    error_log 调到 debug 级别,然后看看日志

    http://nginx.org/en/docs/debugging_log.html
    ddd270700
        21
    ddd270700  
    OP
       342 天前 via Android
    @redial39
    您的方案也尝试了,还是报 404 ( nginx 报的)。
    liuxu
        22
    liuxu  
       342 天前
    你先在你的 nginx 服务器上访问 http://10.108.11.149/U9/,看看能不能访问吧,path 应该是有问题的
    darkengine
        23
    darkengine  
       342 天前
    server_name localhost;

    我觉得是这里的问题,你从其他机器访问内网服务器,还能命中这个 server 吗
    cpstar
        24
    cpstar  
       342 天前
    如果是 location /那直接 upstream 三层代理
    ddd270700
        25
    ddd270700  
    OP
       342 天前 via Android
    @hymzhek
    @dier
    回答:
    http://10.108.11.149/U9 是必须的,很奇怪,用友就是装到了目录下,不这样不行。
    在装 nginx 的服务器上,这个地址是完全可以正常访问的。
    lindas
        26
    lindas  
       342 天前
    装个 tcpdump 抓包看一下 nginx 发给 web 服务器的请求就知道怎么回事了
    ddd270700
        27
    ddd270700  
    OP
       342 天前 via Android
    @redial39
    刚才太着急,10 楼的方案午饭后去试。
    hymzhek
        28
    hymzhek  
       342 天前
    @ddd270700 #25 用我那样的配置 访问 用 http://127.0.0.1/U9 就行了 我本地有用友环境 刚才试了下
    dongpengfei1
        30
    dongpengfei1  
       342 天前
    location / {
    proxy_pass http://10.108.11.149/U9/;
    proxy_set_header Host $host;
    proxy_set_header WL-Proxy-SSL true;
    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 Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Origin "";
    }
    那这个换上去试试,基本可用覆盖所有场景了
    先用 curl 或者 wget http://10.108.11.149/U9/ 看看返回什么,是正常界面还是 404
    dongpengfei1
        31
    dongpengfei1  
       342 天前
    server {
    listen 443 ssl http2;
    server_name ___;
    ssl_certificate ___;
    ssl_certificate_key ___;

    # Specify SSL config if using a shared one.
    #include conf.d/ssl/ssl.conf;

    # Allow large attachments
    #client_max_body_size 128M;

    location / {
    proxy_pass http://10.108.11.149/U9/;
    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-Server $host;
    client_max_body_size 64M;
    proxy_read_timeout 300s;
    }
    error_log ___;
    }
    还是给你贴全了吧
    gtchan13579
        32
    gtchan13579  
       342 天前
    server {
    listen 80;
    server_name _;

    location ^~ /U9 {
    proxy_pass http://10.108.11.149/U9/;
    proxy_set_header Host $proxy_host;
    }
    }
    }
    0o0O0o0O0o
        33
    0o0O0o0O0o  
       342 天前 via iPhone
    看日志吧,还有虽然多半和这个无关,不过 proxy 还要考虑一下 underscores_in_headers
    bfdh
        34
    bfdh  
       342 天前
    如果对报文没有处理需求的话,何不直接用 tcp 代理?

    stream {
    upstream http-proxy {
    server 10.108.11.149:80;
    }

    server {
    listen 80;
    proxy_pass http-proxy;
    }
    }
    ddd270700
        35
    ddd270700  
    OP
       342 天前 via Android
    首先非常感谢各位大佬百忙中的回答。我刚才试了一下,@hymzhek 的办法是成功访问了用友环境了的。
    因此 50 元红包奉上〔后面联系〕。

    但是还没有达到我的预期目的,根据大佬的发问,我再重新描述下我的诉求。

    我在一个公司的内网中,里面有 OA ,有邮件,有报销,也有一个用友环境,都分部在不同的地址上。所有这些在我的计算机上〔也就是上文中的所谓服务器〕都能访问。
    现在我的诉求是在我的计算机上〔也就是上文的服务器〕做一个反代,通过访问我的 ip 地址〔也可以加上端口号〕就能访问以上这些业务。为什么这么做,因为要解决 029 的居家办公问题,说多了眼泪成河。
    别的服务,oa ,内部邮件,财务报销都解决了,唯独这个用友环境解决不了。值得注意的是,它的访问地址后面带了一个目录,也就是必须 http://10.108.11.149/U9 。
    也就是,要通过访问我的 ip 〔也可以加上端口号〕来访问用友环境〔在 http://10.108.11.149/U9 〕是我的难处和要求。而现在做到了通过访问 127.0.0.1/u9,还不行。我要的是通过访问 127.0.0.1 ,或者 127.0.0.1:8080 之类来访问用友环境。

    其他的代码见最上面,我就不贴了。
    有偿求助继续有效,感谢大家对 yi 区的帮助。有些啰嗦,希望我说明白了。
    jasonyang9
        36
    jasonyang9  
       342 天前
    @ddd270700 #35 你这个需求用端口映射也就是 DNAT 应该也可以解决
    hymzhek
        37
    hymzhek  
       342 天前
    wangxkww
        38
    wangxkww  
       342 天前
    你第二个需求做下 url rewrite 就可以吧

    location /
    {
    rewrite ^(/.*)$ /U9/$1 break; // 类似这样
    proxy_pass http://10.108.11.149;

    }
    leehaoze
        39
    leehaoze  
       342 天前
    赞同这个 @bfdh 老哥 如果没有额外的处理 直接四层代理转走
    webfrogs
        40
    webfrogs  
       342 天前
    试试这个:

    location /
    {
    proxy_pass http://10.108.11.149/U9$request_uri;
    }
    redial39
        41
    redial39  
       342 天前
    你想用端口区分业务.可以在 ng 里启多个 server,listen 不通的端口,当然还有更简单的 frp,只要后端应用不是写的绝对地址引用,都可以用
    waler
        42
    waler  
       342 天前
    location ~* /U9 {
    proxy_pass http://10.108.11.149:80;
    proxy_set_header X-Real-ip $remote_addr;
    proxy_set_header Host $host:$server_port;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Port $server_port;
    }

    试一下这样,看着跟金蝶的问题差不多,u9 其实不是目录程序的服务会对这个路径进行处理的
    hymzhek
        43
    hymzhek  
       342 天前
    @ddd270700 #35 端口转发 的方法还是不能隐藏 U9,不过为何一定要隐藏路径,iis 根目录加个 html 跳转下不就行了

    邮件地址 Y29sbGVnZS5sZW5zZXMtMGJAaWNsb3VkLmNvbQ== 邮件地址留下了,红包给不给随便,iCloud 隐藏地址 过段时间会失效
    gesse
        44
    gesse  
       342 天前
    你是不是用的 windows 下的 nginx ??? 🐶🐶🐶
    ddd270700
        45
    ddd270700  
    OP
       342 天前 via Android
    @gesse 是的,我用的是 windows 的 nginx 。
    ddd270700
        46
    ddd270700  
    OP
       342 天前 via Android
    @leehaoze 但是这样直接转走,能解决我的核心要求吗,也就是将对我的计算机(也就是上文的服务器)的 IP 地址(可以加端口)的访问,指向用友环境( http://10.108.11.149/u9 )的访问吗
    ddd270700
        47
    ddd270700  
    OP
       342 天前 via Android
    @waler 我马上去试你的方案
    oott123
        48
    oott123  
       342 天前 via Android
    建议你不要再试了,改写 URL 很难的,软件设计得不合理的话可能软件工作过程中就挂了。
    stach
        49
    stach  
       342 天前
    你的问题应该是代理后的路径写法不合法吧,试试下面这个写法

    location / {
    proxy_pass http://10.108.11.149/U9$request_uri;
    proxy_redirect off;
    }
    stach
        50
    stach  
       342 天前
    把访问 127.0.0.1/$request_uri 代理到 http://10.108.11.149/U9$request_uri
    stach
        51
    stach  
       342 天前
    建议你对比一下自己模拟成功的 http request ,和 nginx 代理后发出 http request ,对比一下具体有啥区别。

    可以写个简单的 http server 来模拟用友,看看修改 nginx 配置后的具体效果快速调整。
    gesse
        52
    gesse  
       341 天前
    @ddd270700
    那就破案了,windows url 不区分大小写
    wangxin13g
        53
    wangxin13g  
       341 天前
    @ddd270700 你这个需求 openvpn 不就行了 内网部署一个 openvpn 服务 把这个 openvpn 暴露出去 签发 key 还好管理 而且数据不会泄露到公网
    ysq
        54
    ysq  
       341 天前
    location /u9 {
    proxy_pass http://10.108.11.149;
    }
    amrom
        55
    amrom  
       341 天前
    关键词 selinux 我遇到过,这个设置问题
    ddd270700
        56
    ddd270700  
    OP
       341 天前 via Android
    @wangxkww
    我试过了,返回 404 。
    ddd270700
        57
    ddd270700  
    OP
       341 天前 via Android
    @wangxkww
    测试过了,返回 404 。
    ddd270700
        58
    ddd270700  
    OP
       341 天前 via Android
    @webfrogs
    测试过了,返回 404
    ddd270700
        59
    ddd270700  
    OP
       341 天前 via Android
    @waler
    试过了,也是返回 404
    ddd270700
        60
    ddd270700  
    OP
       341 天前 via Android
    @stach 您的方案试过了,返回 404
    ddd270700
        61
    ddd270700  
    OP
       341 天前 via Android   ❤️ 1
    再次感谢各位热心的大佬热心回应。

    最后 @hymzhek 的方案解决了我的问题〔已如约酬谢,不成敬意〕,使我方便的实现了远程办公。
    下面我把我的方案总结一下,给有需要的参考。


    ##居家办公的需要
    #方便
    总体上是基于 frp 的,这样的好处是在家办公的人通过公网地址就能直接访问内网的服务了〔内部邮件、OA 、U9 等等〕,和在办公室一样,速度完全可以接受。
    没有用 vpn 是因为那样的化客户端也要装软件,麻烦;
    #不惊扰
    所有的部署都在我的个人计算机上进行,不用接近、更改隔山隔水的邮件、OA 、U9 等服务器
    #简单
    整个方案几乎不要什么代码,frp 服务端,客户端所有的代码加起来不超过 50 行〔即使考虑到后来的 nginx 配置〕。
    #无痕
    疫情结束后,把我的个人计算机从网线上拔下来,抱走就好了。

    ##遇到的问题
    一切进行的都很顺利,直到发现 U9 的访问地址并不是一个单纯的 ip 地址,是带了字母的,也就是“http://10.108.11.149/U9”,以我所有的经验和能力,frp 是不能处理这个情形的〔如果有大佬能解决还请告诉我〕,所以我的核心诉求就变成了在公司内网内将一个单纯的 ip 地址指向它。所以才有了前面的发问。

    ## nginx 的两个解决方案
    nginx 实现了一个反向代理功能,将对它的 ip 地址的访问,指向了 http://10.108.11.149/U9 。

    方案一,修改了 html 目录下的 index.html 文件,这样通过 html 实现 http 层的跳转;
    方案二,是在 server_name 这一行的下面加了一句 rewrite ^/$ /U9 permanent; ,这样就解决了问题。

    两个方案都可行,第二个要快一些。

    以上方案已经验证过。
    高手莫笑,再次感谢。
    ddd270700
        62
    ddd270700  
    OP
       338 天前 via Android
    如果谁有缘看到了这里,且想按照这个方案做,请注意:如果采用方案二,frp 服务端要映射 80 端口。这个很奇怪,我试了很久才发现的。方案一没有这个必要,映射哪个端口都行。
    希望帮助到有需要的人。
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   1910 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 57ms · UTC 17:14 · PVG 01:14 · LAX 09:14 · JFK 12:14
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.