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

原创 2015年11月18日 09:38:53
近日,针对公司生产环境的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;
    }
}

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

nginx添加301跳转到HTTPS并保留部分80端口的URL

为什么有这个需求,因为Let’s Encrypt的证书有一个URL必须在80端口认证,很多配置都是全跳到https这就有问题了 参考文章:http://www.tuicool.com/articles...

强制https访问,在浏览器中输入http的访问地址自动转换为https,端口问题

参考: http://hengstart.iteye.com/blog/840265 强制https访问   在tomcat\conf\web.xml中的后面加上这样一段: Java...

Ubuntu16.10下php7.0-fpm与Nginx配置

Ubuntu16.10配LEMP(Linux-Nginx-MySQL-PHP),Nginx报错Bad Gateway(无效网管),因为Ubuntu16默认安装php7,php7默认是使用socket的...

【转】如何对PHP程序中的常见漏洞进行攻击(上)

如何对PHP程序中的常见漏洞进行攻击(上)from:http://blog.csdn.net/abaowu/archive/2005/07/20/429833.aspx 创建时间:2001-07-...

PHP 如何实现多进程 and mysql查询效率

首先我来说说这个我的需求吧。 需求: 有极少的用户来访问我的网页,但是一旦有用户...
  • cogbee
  • cogbee
  • 2014年06月26日 20:20
  • 6609

添加服务到开机自动启动(centos7开机自启动nginx,php-fpm)

说明 参考网络上其他人文章。将他人技术文章亲自测试并总结补充。 开机自启动nginx,php-fpm(其他服务类似) centos 7以上是用Systemd进行系统初始化的,Systemd 是 Lin...
  • ijijni
  • ijijni
  • 2017年11月12日 18:21
  • 76

Nginx学习篇一:将访问路径中的端口号去掉

mac安装nginx 先安装Homebrew,终端输入brew install nginx,即可安装成功。我安装后的路径是/usr/local/etc/nginx。此时nginx已经运行。输入ng...

Nginx配置相同端口号访问多个工程

Nginx配置相同端口号访问多个工程,多个工程在不同的tomcat,而且访问路径不同,特此记录一下配置过程。 有A,B两个项目,访问localhost即访问A工程,访问localhost/b即访问B...

lnmp之php-fpm+nginx+ulimit的综合设置之故障排除

相信其它的地方大家都懂,这里重点说下面红色粗体部分 参数设置必须与系统的 ulimit -Sn 参数一致,并且 php-fpm.conf,nginx,conf中的设置要一致,否则会出现诸多历史遗留问题...
  • zqtsx
  • zqtsx
  • 2014年04月27日 18:52
  • 4815

同wifi环境下android设备自动获取socket服务端的ip地址和端口号的方法-UDP广播

一、最近做项目,需要使用socket做一个常连接,实现实时通信,但是需求是在同一个wifi环境下,ip地址是动态获取的,这样就造成了服务端地址的不确定性。解决这个问题的关键就是如何拿到服务端的Ip。我...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:在haproxy+nginx+php-fpm环境下访问网站URL被自动加上了nginx服务的私网端口号的故障分析
举报原因:
原因补充:

(最多只允许输入30个字)