美文网首页
nginx只用一个公网端口转发多个内网服务

nginx只用一个公网端口转发多个内网服务

作者: 猫尾草 | 来源:发表于2020-06-07 09:45 被阅读0次

    1. 问题

      一个常见的问题,生产环境的一台有公网ip的服务器,为了安全起见,运维只给开一个端口,于是考虑用nginx根据url的前缀路径来转发到不同服务。例如:

    location /path1 {
     proxy_pass http://ip1:port1;
    }
    location /path2 {
     proxy_pass http://ip2:port2;
    }
    

    以springboot工程为例,我们自己的web服务一般都会通过设置

    server:
      servlet:
        context-path: /xxxxxx
    

    来给该服务的所有url设置一个统一的前缀路径/xxxxxx。这时候nginx就可以将所有带有前缀/xxxxxx的请求转发到该服务。这是一个很简单的事。
      问题是有很多第三方服务,例如kafka manager,他是没有这样的前缀的,假设kafka安装在192.168.0.182机器上,kafka manager的访问地址就是http://192.168.0.182:3000,我们当然可以在首次访问时通过地址http://192.168.0.182:3000/kafka让nginx根据/kafka识别到这是kafka manager服务并转发到http://192.168.0.182:3000,但是我们打开kafka manager页面上的链接时是不会有我们自己添加的/kafka前缀的,上面的方法失效。

    2. 解决方法

      我们都知道http服务是无状态的,就像上面所说即使访问了kafka manager的主页,点击主页上按钮发起的请求也无法被识别为kafka manager请求。但是web服务绝大多是都是需要有状态的,主要有session/cookie、token两种方式来解决这个问题。也可以用来解决上面的问题。
    在nginx中配置:

    // 精确匹配到/kafka,转到kafka manager服务并设置好cookie
    location =/kafka {
      proxy_pass http://10.95.123.66:19900/;
      add_header Set-Cookie key=kafka;
    }
    // 后续的访问,统一进入根匹配,通过cookie判断转发到哪个服务
    location ~ / {
      if ($http_cookie ~* "kafka") {
        proxy_pass http://192.168.0.182:3000;
            break;            
      }
    }
    

      这时候又有一个问题,使用同样的ip:port来访问这些服务,在浏览器看来所有的服务都是一个域的,他们的cookie就会是同一个cookie,这时候nginx没办法根据cookie的不同转发到不同的服务。
      我们想到了给每个服务配置一个域名(没有那么多公网域名可用,就在本地hosts文件配置了),产生跨域的效果,让不同的服务有独立的cookie。
      从来都是解决跨域问题,从没想过有一天要主动跨域

    3. 思考一下

      如果配置了域名,完全可以让nginx根据域名来做识别转发,为什么要用cookie呢?如果你都是配置了公网域名,那确实可以这么干,但是我们是改的hosts文件,保不齐谁的域名就写错了,或者因为只是本地hosts文件的修改根本就没必要统一域名,这时候根据域名做转发就不行了。

    4. 另外一个小问题

      kafka manager的访问是不需要认证的,暴露在公网上、面向所有人是一件可怕的事,我们是设置了VPN和访问白名单。

    相关文章

      网友评论

          本文标题:nginx只用一个公网端口转发多个内网服务

          本文链接:https://www.haomeiwen.com/subject/rdtltktx.html