美文网首页WEB前端程序开发程序员
基于nginx实现全局停服页面

基于nginx实现全局停服页面

作者: usun | 来源:发表于2019-09-27 15:30 被阅读0次

    问题描述

    现在的企业服务,往往不是单体的,同时可能涉及中间件的访问如dubbo、solr、mq等。对于中间件的监控页面访问,如果直接暴露在公网,肯定这安全。需发对中间件访问进行安全加固,方法主要有:
    (1)限制使用IP白名单访问。
    (2)安全密码访问,不使用简单密码,对于没有密码的,可以使用basic认证,强密码访问。
    (3)屏蔽端口,通过nginx代理,减少端暴露。

    本文要讲的是(3)使用nginx代理,中间可能遇到的问题。

    nginx反向代理,可以配置location代理不同的服务,这里就涉及到context-path。如果代理服务本来就不是通过“http://ip:端口/”访问的,而是通过“http://ip:端口/contextpath”访问的,就不会有问题。如果服务不支持“http://ip:端口/contextpath”访问,就涉及“/”路径的问题。

    location /activemq/ {
         proxy_pass http://192.168.17.19:8161/;
    }
    

    如上代码,location activemq经反向代理后,访问的实际是8161端口下面的activemq路径,而8161端口"/activemq"下没有内容,就会返回404。当然如果只是代理一个服务是没有问题的(可以用“/”location做反向代理),代理多个服务就需要多个location,必然出现问题。

    解决方案

    经研究和网上查询,nginx反向代理的contextpath问题(contextPath是java servlet的说法,一般就是指http://example.com/aaa/bbb/ccc.html里/aaa这个字段。)主要解决思路如下:
    首先,研究服务能不能通过context-path提供。如jetty服务是否支持配置contextpath,如是war考虑部署到tomcat的contextpath访问。
    如果实在不能提供contextpath部署访问,解决方案主要有:

    sub_filter方案

    使用nginx在jenkins返回的所有资源链接前面都加上/jenkins字段,这样用户接下来产生的GET请求都可以map到location /jenkins区块。要实现这个功能需要用到nginx的ngx_http_sub_module。参考Example,可以写出类似配置:

    location /jenkins {
        sub_filter '<a href="/'  '<a href="/jenkins/';
        sub_filter '<img src="/' '<img src="/jenkins/';
        # ...其他替换规则...
        sub_filter_once off;  # 查找并替换多次
        proxy_pass http://localhost:8002;
    }
    

    案例因特殊情况,使用了这种配置(公供参考):

            #mq
            location /activemq/ {
               sub_filter '<a href="/'  '<a href="/activemq/';
               sub_filter '<a title="Manage ActiveMQ broker" href="/admin/'  '<a href="/activemq/admin/';
               sub_filter '<a title="See some Web demos" href="/demo/'  '<a href="/activemq/demo/';
               sub_filter '<img src="/' '<img src="/activemq/';
               sub_filter '<script src="/' '<script src="/activemq/';
               sub_filter "type='text/javascript' src='/" "type='text/javascript' src='/activemq/";
               sub_filter '<link href="/' '<link href="/activemq/';
               sub_filter 'url(/' 'url(/activemq/';
               sub_filter "@import url('/" "@import url('/activemq/";
               sub_filter_once off;  # 查找并替换多次
               proxy_pass http://192.168.7.19:8161/;
               allow 219.143.147.82;#访问控制
               allow 220.160.125.218;#访问控制
               allow 36.110.62.178;
               # allow for sslvpn access
               allow 36.110.218.132;
               allow 112.48.19.106;
               deny all;
    
            }
    
            #solr
            location /solr/ {
               proxy_pass http://192.168.17.18:8983/solr/;
               allow 219.143.147.82;#访问控制
               allow 220.160.125.218;#访问控制
               allow 36.110.62.178;
               # allow for sslvpn access
               allow 36.110.218.132;
               allow 112.48.19.106;
               deny all;
    
            }
            #dubbo-admin
            location /dubbo-admin/ {
               proxy_pass http://192.168.17.20:8090/dubbo-admin/;
               allow 219.143.147.82;#访问控制
               allow 220.160.125.218;#访问控制
               allow 36.110.62.178;
               # allow for sslvpn access
               allow 36.110.218.132;
               allow 112.48.19.106;
               deny all;
    
            }
            #dubbo-monitor
            location /dubbo-monitor/ {
               sub_filter '<a href="/'  '<a href="/dubbo-monitor/';
               sub_filter '<img src="/' '<img src="/dubbo-monitor/';
               #sub_filter_once off;  # 查找并替换多次
               proxy_pass http://192.168.17.21:8081/;
               allow 219.143.147.82;#访问控制
               allow 220.160.125.218;#访问控制
               allow 36.110.62.178;
               # allow for sslvpn access
               allow 36.110.218.132;
               allow 112.48.19.106;
               deny all;
    
            }
    

    但是这样做效率很低、且filter遗漏和出错可能性大(比如=>其他2)。

    使用重定向

    location /activemq/ {
        return 302 http://www.domain.com:8161/; 
    }
    

    这样做的前提是开通8002的端口映射,还是涉及端口暴露问题。

    单独域名访问

    如果条件允许的话,应该是分配一个子域名(子域名都是单独的公网IP),比如activemq.domain.com会更合理和方便。nginx同一80端口,支持多域名监听配置。

    配置参考

    server {
            listen       443;
            server_name  activemq.domain.com;
            add_header X-Frame-Options SAMEORIGIN;
            #rewrite ^(.*)$ http://${server_name}$1 permanent;
                    ssl on;
                    ssl_certificate /etc/nginx/sslkey/_.XXX.com_bundle.crt;
                    ssl_certificate_key /etc/nginx/sslkey/XXX.com.key;
                    ssl_session_timeout 5m;
                    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
                    ssl_ciphers AESGCM:ALL:!DH:!EXPORT:!RC4:+HIGH:!MEDIUM:!LOW:!aNULL:!eNULL;
                    ssl_prefer_server_ciphers on;
            add_header X-Via nginx;
            #static path
           location / {
             proxy_pass http://192.168.17.19:8161/;
           }
        }
    
    

    臭味相投的朋友们,我在这里:
    猿in小站:http://www.yuanin.net
    csdn博客:https://blog.csdn.net/jiabeis
    简书:https://www.jianshu.com/u/4cb7d664ec4b
    微信免费订阅号“猿in”

    猿in

    参考:https://blog.csdn.net/silvita/article/details/72781266

    相关文章

      网友评论

        本文标题:基于nginx实现全局停服页面

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