最近单位里面调整应用端口和防火墙配置,原先起在 80 端口上的服务,须要调整到 8180 端口上进行部署。为了对公网的影响度最小,公网端口依旧采用的 80 端口暴露服务,由网络的同事在 WAF 侧作了一个 80 到 8180 端口的映射。造成了一个这样的网络拓扑(脱敏简化)图。html
造成这样的网络拓扑以后,按理公网上访问 http://test.snowheart.cn/ 时便可正常访问到后台的应用服务。But,后端有一些地方用到了 sendRedirect(url) 方法,这就致使了在进行 302 网络跳转的时候,Response 的 Location Header 上面带了内部的端口,即造成了下述形式的 Location Header。java
HTTP/1.1 302 Moved Temporarily Date: Mon, 11 May 2020 15:45:29 GMT Location: http://test.snowheart.cn:8180/app/login.jsp Content-Type: text/html;charset=utf-8 Connection: close Transfer-Encoding: chunked
浏览器在进行跳转时,使用了前面一个请求的 Location,在公网上请求了 8180 端口,由于防火墙的缘故,没法访问,报错。nginx
在 HTTP 的 Code 响应码中,301 表示永久重定向,302 表示临时重定向。git
// DemoServlet1 // 经过设置 Header 和 Status,来进行重定向操做,其余什么都不作 response.setHeader("Location", request.getContextPath() + "/hello.html"); response.setStatus(302);
上述例子中的 Servlet URL,在浏览器中访问以后,你会发现浏览器被重定向到了项目中的 /hello.html,其代码在实现结果上,等价于下面的代码:github
// DemoServlet2 // 经过 sendRedirect(url) 来进行重定向操做,其余什么都不作 response.sendRedirect(request.getContextPath() + "/hello.html");
若是 WAF 上是同端口透明出去了,公网和内网前置机的 Port 一致;shell
链路上除前置机应用端口为 8180 外,其他地方端口均与此无关;后端
只是依赖 Apache 或 Nginx 的反向代理,是不会出现后端 Port 暴露的事情;浏览器
看来是在 WAF 作了端口转换以后,内网前置机的 Apache 并不知道公网上的端口已是 80 了,故在 Location 上增长了 8180 端口的信息;服务器
亦可经过在各环节打印日志的形式,来检测 8180 端口是哪一个环节增长的...
故:咱们断定,在从前置机 Apache 返回时,Location 上就已经有了前面的域名 + 端口,如今须要作的事情就是在返回以前,将 Location 上的端口给抹掉,亦或者是将 Location 上的域名 + 端口给抹掉,仅剩余从 / 开始的 URI 地址。网络
最早时候,想经过本身最熟悉的 Nginx 来进行 HTTP Response Header 的重写
Windows 下的 Nginx 程序包没法进行再次编译,没有办法来加载其余 Nginx 模块;故须要使用 Linux 下的 Nginx 服务,以最大限度地与服务器保持一致。
# 下载最新的 ngx_headers_more 模块包 wget https://github.com/openresty/headers-more-nginx-module/archive/v0.33.tar.gz tar -xzvf v0.33.tar.gz # 跳转到 Nginx 目录 # 查看 Nginx 编译参数 ./nginx -V # 跳转至 Nginx 源码目录,增长 ngx_headers_more 配置并编译 # 每一个人的目录都不相同,仅供参考 ./configure --prefix=/usr/local/nginx/server --with-http_stub_status_module --with-http_ssl_module --with-pcre=/tool/pcre-8.44 --with-http_realip_module --with-http_sub_module --with-http_gzip_static_module --add-module=/tool/echo-nginx-module-0.62rc1 --add-module=/tool/headers-more-nginx-module-0.33 make # 切记,不要 make install,不然会覆盖掉以前Nginx的配置文件这些。 cp /usr/local/nginx/server/sbin/nginx /usr/local/nginx/server/sbin/nginx.origin cp objs/nginx /usr/local/nginx/server/sbin/nginx
map $upstream_http_Location $location{ # 这种方案是把全部到 8180 端口的重定向都改为 80 端口,有必定的风险,容易误伤 # ~http://(?<domains>.*):8180/(?<param>.*) http://$domains/$param; # 这种方案是针对特定域名 8180 端口的重定向,范围可控,写法冗长 ~http://test.snowheart.cn:8180/(?<param>.*) http://test.snowheart.cn/$param; # 默认状况,保持原状 default $upstream_http_Location; } server { location /app { proxy_pass http://192.168.36.72:7001/app; proxy_set_header Host $host:$server_port; proxy_set_header X-Real-IP $remote_addr; proxy_set_header REMOTE-HOST $remote_addr; proxy_redirect off; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; more_set_headers -s '301 302' 'Location $location'; } }
$ curl http://test.snowheart.cn/app/RedirectServlet --dump - HTTP/1.1 302 Server: nginx/1.14.2 Date: Mon, 11 May 2020 16:41:23 GMT Content-Length: 0 Location: http://test.snowheart.cn/app/hello.html Connection: keep-alive
大坑
Nginx 须要安装新的 module,这又涉及到从新编译和 root 安装等操做,在企业里面,作这些是须要必定的流程和规范性评估的,故通过考虑后,放弃此方案。上述笔记仅做为 POC 阶段使用。
Nginx 方案受阻后,使用当前测试环境在用的 Apache 来实现 Location 的重写
# httpd.conf # 打开 Rewrite 功能 RewriteEngine On # 对 Location 进行重写 Header edit Location "(^http[s]?://test.snowheart.cn:8180/)" "/" Header edit Location "(^http[s]?://123.234.123.234:8180/)" "/"
$ curl http://test.snowheart.cn/app/RedirectServlet --dump - HTTP/1.1 302 Server: nginx/1.14.2 Date: Mon, 11 May 2020 16:41:23 GMT Content-Length: 0 Location: http://test.snowheart.cn/app/hello.html Connection: keep-alive
简单的三行配置,即达成了咱们的目的。
本文由博客一文多发平台 OpenWrite 发布!