在haproxy+nginx+php-fpm环境下访问网站URL被自动加上了nginx服务的私网端口号的故障分析

近日,针对公司生产环境的PHP网站服务应用主机进行了单点安全隐患的技术改造,将单一主机上的nginx+php-fpm应用迁移至了一套haproxy/keepalived+nginx+php-fpm的双机负载均衡系统中去。

haproxy监听HTTP和HTTPS端口,对公网提供服务。
nginx+php-fpm分别在两个应用主机上部署,处理haproxy分发来的访问请求。nginx监听8080提供HTTP服务,监听8081端口提供HTTPS服务。

1、
在实际测试中,使用浏览器通过域名访问集群上的网站服务,如http://abc.example.com/ 。浏览器打开网页超时,且地址栏返回的URL变成了:http://abc.example.com:8080/xxx/index.php 。
在使用HTTPS协议访问时,也同样超时,且URL中出现了8081的端口。

考虑到我们是使用两个主机部署的全套haproxy/keepalived+nginx+php-fpm的应用,且haproxy的工作网段与nginx处在相同网段。而nginx又使用了自定义的服务端口。所以才会产生了这种问题,即haproxy把访问请求分发给了nginx,但nginx在返回响应时却在URL中携带了自已的服务端口。恰恰haproxy和nginx使用的端口是不同的,因此产生了以上故障。

关于以上分析,可以使用firefox的firebug插件进行网络跟踪,比较容易看到nginx返回的响应头带上了自己的8080或8081的端口号。

带着这个疑问在网上搜索了下相关资料,于是看到了nginx的port_in_redirect选项。这是一个使用在nginx.conf的http段落中的配置项。功能是决定nginx在响应访问请求时,时否在响应头中加上自己的服务端口号,默认开启。

于是调整为 port_in_redirect off;

重启服务后,除phpmyadmin之外的全部项目都可以正常访问了。

2、
在使用http或https访问phpmyadmin服务时,仍然会超时,仍然在拿到的HTTP响应中URL地址被添加了nginx的服务端口。

使用Wireshark在本机抓包,分析访问phpmyadmin时的本机收发数据包,不有任何发现。

登录nginx应用主机,使用tcpdump对服务器端的haproxy和nginx服务地址、端口进行抓包,分析数据通信流向,仍然没有任何发现。

虽然其它我们公司自行研发上线的php项目都已经可以正常浏览和使用了,但phpmyadmin继续固执得在返回HTTP响应时带上了NGINX的服务端口。

于是,转而怀疑是phpmyadmin源码存在问题。忽然想起之前在网上查阅这方面资料时,偶然看到有人提到过php在使用一个环境变量SERVER_PORT时的注意事项。因此,我猜想phpmyadmin在使用该环境变量时,是不是存在问题。

进入到phpmyadmin的应用目录,执行:
$find . -name "*.php" | xargs grep SERVER_PORT
找到了这个文件:
./libraries/Config.class.php
if (empty($url['port']) && PMA_getenv('SERVER_PORT')) {
     $url['port'] = PMA_getenv('SERVER_PORT');
}

从字面意思上,就能理解为,这个判断条件是phpmyadmin对url地址进行了判断,如果url中没有明确使用端口且本地HTTP Server中定义了服务端口,那么就把url中的端口号设置为本地Http Server服务的端口中号!

终于找到了为什么phpmyadmin固执得返回nginx的8080和8081服务端口的原因了。

果断把上面的判断逻辑修改为:
if (empty($url['port']) && PMA_getenv('SERVER_PORT')) {
    // $url['port'] = PMA_getenv('SERVER_PORT');
    if ( PMA_getenv('SERVER_PORT') == 8080 ) {
         $url['port'] = 80;
    } elseif ( PMA_getenv('SERVER_PORT') == 8081 ) {
         $url['port'] = 443;
    }
}

实测,一切问题都烟消云散。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值