WEB应用

分享一个Nginx反向代理的另类应用案例

Jager · 5月2日 · 2019年 · · · 1874次已读

博客前面分享了一篇《分享一个Nginx正向代理的另类应用案例》,时隔不久,身为救火队员、万金油的博主又再一次接到了一个另「W」类「T」需「F」求:

场景和上次有些类似,也是部门引进的第三方应用,部署在各个网络区域,从OA办公区域无法直接访问。目前,运营人员都需要登陆Windows跳板机,才能打开这些应用的WEB控制台。既不方便,而且还有一定Windows服务器的维护工作量,于是找到我们团队,希望通过运维手段来解决。

分享一个Nginx反向代理的另类应用案例

拿到这个需求后,我先问了下各个应用的基本情况,得知每个应用的框架基本是一样的,都是通过IP+端口直接访问,页面path也基本一样,没有唯一性。然后拿到了一个应用WEB控制台地址看了下,发现html引用的地址都是相对路径。

乍一想,这用Nginx代理不好弄吧?页面path一样,没法根据 location 来反代到不同的后端,只能通过不同Nginx端口来区分,那就太麻烦了!每次他们新上一个应用,我们就得多加一个新端口来映射,这种的尾大不掉、绵绵不绝事情坚决不干,Say pass。

再一想,我就想到了上次那个正向代理另类应用方案,感觉可以拿过来改改做动态代理。原理也简单:先和用户约定一个访问形式,比如:

Nginx代理地址为myproxy.oa.com,需要代理到IP为 192.168.2.100:8080 的控制器,用户需要访问http://myproxy.oa.com/192.168.2.100:8080/path。

动态代理的原理及实现:

1、Nginx从$request_uri变量中,通过斜杠提取第一段作为要反向代理的对象,即proxy_pass,提取后面的作为需要反代的路径;

2、对于Html、JS、CSS等资源引用则需要通过Nginx的替换模块,将路径替换为上述约定形式,比如:Html里面的href=”/js/jquery.min.js”,需要替换为href=”http://myproxy.oa.com/192.168.2.100:8080/js/juqery.min.js”,即所有资源地址都保证符合代理约定的形式,才能够正确走代理获取。

3、通过代理去访问,查看浏览器开发者工具中的Network和console,找到无法访问的地址,并分析引用的位置,写规则替换掉即可。

4、实际测试发现,他们的应用可能还会有https协议(…),而且是伪证书模式,只是开了https协议访问。上述设计模式下,https页面是无法打开的,这里需要兼容https后端才行,因此最后的约定形式简单修改为:如果是 http://myproxy.oa.com/https-192.168.2.101:8080/path,即:如果是https协议,需要在第一段path的IP前面加上https-来区分,而http协议则可加可不加。

基本通过上述几步,就完全搞定了,最终Nginx规则如下:

server {
        listen 80;
        server_name myproxy.oa.com;
        #resolver 223.5.5.5; # 如果被代理的地址存在域名,需要加一个dns配置,否则会502,报错信息为:no resolver defined to resolve xxx.com
        index index.html;
        root /html;
        # 初始化变量
        set $node "";      # 后端主机地址
        set $proxy_url ""; # 后端页面地址
        set $proxy_scheme http; # 后端协议,默认http
        set $proxy_scheme_url ""; # 改造后的代理path,这里会带上协议约定,如 https-
        # 通过正则提取约定协议、后端节点和后端节点url
        if ( $request_uri ~* "^/(https-|)([^/]+)/(.*)$" ) {
            set $proxy_scheme_url "$1";
            set $node "$2";
            set $proxy_url "$3";
        }
        # 当协议变量值是https-的时候,设置代理后端协议为https,此规则就兼容了后端https的情况
        if ( $proxy_scheme_url = "https-" ) {
            set $proxy_scheme https;
        }
        # 不带后端地址直接访问代理IP的时候,定向到/html路径,里面可以放index.html导航页面,方便用户点击访问
        location ~ ^/($|static|favicon.ico) {
            break;
        }
        # 当访问的路径没有命中上述规则,且存在字符串的时候,将会进入到这个location开始反向代理
        location ~ ^/(.+)/ {
            # 使用 subs_filter 模块进行替换(不了解的话,请自行百度这个关键词)
            # ======================== replace Url begin ========================
            # 替换支持所有类型
            subs_filter_types *;
            # 替换html里面的静态资源引用,即 src=、href=等引用形式,另外还考虑到可能存在 / 打头的相对路径或“http://节点”的绝对路径引用形式。
            subs_filter "(href|src)(\s*)=(\s*)('|\")($proxy_scheme://$node|)/" '$1="http://$host/$proxy_scheme_url$node/' igr;
# 替换js里面的一些ajax请求地址:
            subs_filter "url:(\s*)('|\")/([^'\"]*)('|\")" "url: 'http://$host/$proxy_scheme_url$node/$3'" igr;

            # 这里替换实际访问发现还有问题的路径(这里主要是用了xmlhttprequest导致上述正则没命中)
            subs_filter "/workerProxy\?ip=" "http://$host/$proxy_scheme_url$node/workerProxy?ip=" igr;
            # you can write replace rule with subs_filter if found more.
            # ======================== replace Url end ===========================
            # 代理到动态后端
            proxy_pass $proxy_scheme://$node/$proxy_url;
            # 关闭gzip,以防替换不了内容(不能解决后端强制了gip压缩的情况...)
            proxy_set_header Accept-Encoding "";
            # 其他proxy参数略.
        }
}

Tips:实际调试过程中,可以给Nginx集成一个echo模块,可以将变量打印出来,方便调试。

最后,在Nginx服务器的/html目录放一个index.html导航页面,用户只需要访问代理地址http://myproxy.oa.com/,就能看到全部的后端节点,点击访问即可,真的不要太爽哦!

不得不再一次感慨,Nginx真是一个好东西,完美~

35 条回应
  1. 本质游戏 2019-5-5 · 10:20

    大哥,你是给我带来好运的人。
    刚打开您的博客评论了一下,就收到百度联盟的授权邮件了。3年了都没有通过。。。
    刚开始做网站的时候就知道您了,3年后又到了您这儿,还给了我一个小惊喜~~

    • Jager 2019-5-5 · 23:39

      :mrgreen: 恭喜你了。

  2. 本质游戏 2019-5-5 · 10:21

    您是我遇到为数不多或者说是仅有折腾wordpress还不卡的人~

    • Jager 2019-5-5 · 23:40

      现在略卡,服务器在国外,用的国外CDN。比之前差很多。

  3. 章郎虫 2019-5-9 · 9:50

    博客确实慢了很多,为了换域名代价有点大啊。

  4. Rares 2019-5-9 · 10:30

    有段时间没有来了,不明觉厉,万金油

  5. 吴昊博客 2019-5-13 · 16:14

    这个nginx写的真骚气 👿 👿 👿

  6. 创业博客 2019-5-14 · 21:49

    虽然看不太懂,但是文章很精致的

  7. 动平衡仪 2019-5-16 · 14:20

    你的博客就是一本万能书

  8. 楚狂人 2019-5-17 · 22:30

    解释的很详细,学习了

  9. 奶爸de笔记 2019-5-19 · 16:21

    好多搞反代的大神。

  10. 跨境电商 2019-5-22 · 22:14

    今日看点Jager兄换域名了,有品位,不过短时间内不利于收录和排名哦。

  11. 安全时代 2019-5-30 · 16:39

    哇,张哥,新主题很好看啊!!!

  12. 月宅 2019-6-1 · 10:27

    张戈换了个主题,感觉资源不好找了呢..还是挺喜欢以前的CMS布局

  13. repostone 2019-6-1 · 16:08

    不是一般理解的代理。

  14. aunsen 2019-6-1 · 21:53

    新主题超赞!
    请教个问题,后台数据库被疯狂写入恶意数据,全是什么远程手机短信拦截木马设备之类的,手动删掉了还会来,大概是哪里挂马?或者是vps被爆破了?

    • Jager 2019-6-2 · 10:06

      1、查看本地连接并检查数据库绑定的不是0.0.0.0,是否有外网IP连接了本地数据库;
      2、如果1否定,则说明恶意数据由其他程序写入,可能是web被注入也可能是本地跑了木马;
      3、如果是WEB注入,可以查看web日志,看看是否有可疑请求,实在找不到,先把WEB停了看看数据库是否还在写入;
      4、若排除了WEB注入,则说明书本地又什么恶意进程,这个可以用 ps 和 top命令去看是否有高占用CPU的进程,或者可疑的进程。

      • aunsen 2019-6-2 · 16:28

        数据库地址localhost
        web.log里大量的”114.103.47.213 – – [28/May/2019:17:24:21 +0800] “GET /qa-ask-question.html HTTP/1.1” 499 0 “-” “Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36″”数据。看提示呢我就把DW Question & Answer插件升级了,明天再看看log有什么变化没,谢谢张戈

  15. cchu 2019-6-14 · 15:36

    试试反代百度地图

  16. 明月登楼的博客 2019-6-19 · 23:07

    我不得不说,博主换的这个主题很炫酷,但是速度真心不敢恭维,当然也可能是新主题配置优化上需要时间适应和熟悉!

    • Jager 2019-6-19 · 23:19

      博主这话说的有些外行了吧?当网站纯静态化之后,前台加载的速度和主题其实关系不大了,除非是主题JS、CSS不合理,或者有BUG导致浏览器渲染慢。
      我后面的文章也说了,当前这个域名没法备案,主机在国外,然后用的CF CDN,部分地区访问绕道美西,你说能不卡吗?

      • 明月登楼的博客 2019-6-19 · 23:32

        哈哈,抱歉,才看到你是迁移到国外了,为啥不用香港服务器呢?用AWS+CF这个方案看似高大上其实性价比很低的!你要是有国内备案域名的话但是可以借助“动静分离”来变相优化一下!需要不?我手里有可以给你个二级域名!

        • Jager 2019-6-19 · 23:38

          大兄弟,你先看下我静态资源域名吧,博客动静分离貌似还是我先分享出来的吧。。。https://zhang.ge/5130.html
          再说,我现在博客放在家里的NAS上,用CDN套一层,省得别人说我没备案,也就是说我博客现在基本不花钱。

          • 明月登楼的博客 2019-6-19 · 23:40

            这不睡不着,手机访问的!不方便!那就没办法了!为了个域名这损失有点儿大呀?

            • Jager 2019-6-19 · 23:42

              没办法,同样睡不着只能当夜猫了。没办法,就是喜欢这个个性域名,其他的都不重要。

  17. 明月登楼的博客 2019-6-19 · 23:42

    其实我是来体验你的这个新主题的,我也有点儿心动了!还指着你有点儿评测啥的!

    • Jager 2019-6-19 · 23:44

      还在折腾改造呢,说个自私的话,我个人很不希望这主题和begin那样,过于流行,最终烂大街~~~

      • 明月登楼的博客 2019-6-19 · 23:55

        其实吧,玩内容的博客,主题是不是烂大街没关系的!就是个心理作用而已了!

        • Jager 2019-6-19 · 23:57

          你说的是有道理,但是begin烂大街的事实没法否认~太流行了, 三教九流啥都用,已经毫无个性可言,就算我DIY了各种功能,依然没法扭转这个形势。而且Begin用了好些年了,换个口味也是不错的。

          • 明月登楼的博客 2019-6-20 · 0:00

            好多人说我的博客首页“丑”,都被我无视了,我对这个一直不是太注重!你说的很对换个口味还是很不错的!毕竟“生命不止,折腾不息”嘛!嘎嘎!最近比较看好的主题除了你用的这个还有个“柒比贰”商用主题也很不错的,朋友给了一个授权体验很好!

            • Jager 2019-6-20 · 0:02

              好的,我去了解下。

  18. 武陵红苗 2019-7-10 · 13:56

    学习学习

  19. 子虚 2019-7-17 · 8:21

    最近正好遇到如此的场景,但测试发现这个nginx检测一直无法通过,提示变量问题nginx: [emerg] match part cannot contain variable during regex mode in

    subs_filter “(href|src)(\s*)=(\s*)(‘|\”)($proxy_scheme://$node|)/” ‘$1=”http://$host/$proxy_scheme_url$node/’ igr;

    ,无法进行静态资源的引用;望博主支撑

  20. Erin 2019-9-9 · 17:16

    发现这玩意只能代理后端是IP的url ,若是域名URL则行不通

  21. 广州办公室装修 2019-9-29 · 9:50

    你好博主!辛苦了