貌似现在只要我更新博客就说明又在没事瞎折腾了… =.=
很久以前就遇到过这个问题,或者不如说实际上就是因为无法正确获取客户端IP才让我一直用的 Apache + nginx
的构架。今天折腾一下午 + 一晚上总算是把这个问题(还算)圆满地解决掉了。
首先是参考这篇文章配置好整个服务器构架,后端使用 Apache httpd
来处理 PHP, 中间用 Varnish
做缓存,前端使用 Tengine
作为 web 服务器,所以来自客户端的请求的处理流程是:
Client -> Tengine:80 -> Varnish:8090 ->(Miss)-> httpd:81
然后问题就来了,处在最后面的 httpd
拿不到正确的客户端IP地址,总是显示为127.0.0.1
. 这个问题有趣在于,一直以来我都是使用了 mod_rpaf
来获取 X-Forwarded-For
中的客户端IP的,而如果我去掉中间那一层 Varnish
直接让 Tengine/nginx
反向代理给 httpd
的话,IP地址是能够正确获取的,更进一步实验表明,在只有一次代理的情况下一切都是正常的,当代理变成了两层,无论两层代理的顺序如何,都会出现这个问题。
中间各种股沟各种查文档就[此处省略6小时]了…
基本上有两个比较主要的原因。
1. X-Forwarded-For
在经过了多个代理服务器后会变成一个IP列表,形如:X-Forwarded-For: client, proxy1, proxy2
;
2. mod_rpaf
只会从 X-Forwarded-For
列表的最右侧取出IP地址,所以代理超过一层的时候就无法取到客户端IP而是把上一层代理的IP当成客户端了。
解决办法也很简单,从 2.3 版开始,Apache 官方提供了一个 mod_remoteip
模块,而且在 2.4 版本中已经默认集成并开启。而对于 2.2 版本,也有第三方自制的兼容版本。
参照说明编译安装好模块:
1 |
apxs -i -c -n mod_remoteip.so mod_remoteip.c |
完成过后,在 httpd.conf
中加上:
1 2 3 |
LoadModule remoteip_module modules/mod_remoteip.so RemoteIPHeader X-Forwarded-For RemoteIPInternalProxy 127.0.0.1 |
别忘了把 mod_rpaf
的给去掉避免冲突。
如果你和我一样是拿 ArchLinux 做生产环境的倒霉孩子(呵呵),也可以直接用我打的AUR包: https://aur.archlinux.org/packages/mod_remoteip/
最后重启 httpd 使模块载入即可。
你的博客的URL真有趣……
因为纯数字不好玩…
感谢楼主,两行代码就帮我解决了问题,网上很多方法都过时了,修改这修改那的,其实apache现在很强大了,大部分还在用老版本。
主要是 apache 2.2 到 2.4 改动太大了,配置文件很多地方不兼容,好多动态内容的调用方式也有变化,所以各大发行版都很谨慎,连一向激进的 ArchLinux 都没有直接跟进到官方仓库,而是在 AUR 里面放了一个 apache24 的包做过渡