ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

PHP 获取客户端真实IP地址

PHP 获取客户端真实IP地址 PHP获取客户端真实IP地址需要根据具体的服务器环境来确定使用哪种方法。目前搜索到的方法大多是直接贴代码没有针对不同情况作出说明有可能导致系统被假IP骗过IP欺骗。很多文章都提到“无法保证获取到的访客IP地址100%准确”是否意味着PHP获取访客IP一定有漏洞可钻呢只要根据实际部署情况选择相对应的代码获取访客IP地址是可以确保程序不被假IP欺骗的。PHP的运行方式PHP支持非常多的运行方式例如php-cgi、php-fpm、swoole、php-cli、php-mod等。其中php-fpm是php的fast-cgi的进程管理器。php-mod通常配合Apache使用而php-fpm通常配合Nginx使用。从PHP5.4开始PHP甚至可以以内置PHP服务Buid-in web server方式运行。逐渐的PHP形成了很多经典搭配例如LAMP、LNMP、LNMPA、IISPHP。无论采用哪种PHP运行方式分清是谁传递IP给PHP程序即可。这里对几种常见环境进行分析。无代理层PHP内置服务器/swoole由于客户端IP数据是从TCP/IP协议层传递过来的因此在没有中间代理客户端和服务器直连的情况下可以直接通过标准方法REMOTE_ADDR获得与PHP直接通讯的IP地址。例如$_SERVER[REMOTE_ADDR]或getenv(REMOTE_ADDR)。而在swoole中可以通过$request-server[remote_addr]获得客户端IP地址。在这种情况下REMOTE_ADDR不可以显式的伪造获取到的是实际与服务器连接的IP地址是可靠的。Nginx代理Nginx php-fpm / Nginx swoole常见的LNMP方案属于Nginx反向代理。Nginx与php的通讯无论unix socket方式还是tcp socket方式都跟Nginx的Header配置有关系。1234567proxy_http_version 1.1;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header Host $http_host;proxy_set_header X-NginX-Proxy true;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection upgrade;可以在第一层nginx代理设置proxy_set_header X-Forwarded-For $remote_addr其他层nginx代理设置proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for这样就可以通过X-Forwarded-For获取客户端真实IP地址。如果设置了X-Real-IP $remote_addr则通过X-Real-IP获取客户端IP地址。PHP代码12345// php-fpm等$_SERVER[HTTP_X_FORWARDED_FOR]);// swoole$this-http_input-header(x-real-ip);总结来说当有Nginx代理的情况下需要根据具体配置来选择获取的Header从而正确获取客户端IP地址此时PHP中的的REMOTE_ADDR可能是最后一级代理的IP地址。Apache代理Apache php_mod / Apache php-fpm通常在Apache PHP方案中获取IP地址取决于Apache配置信息。绝大部分情况可以使用$_SERVER[REMOTE_ADDR]获取到真实客户端IP地址。如果Apache上级存在Nginx那么可以在Apache中使用mod_rpaf模块将客户端IP地址传递到X-Forwarded-For头中。1PAFheader X-Forwarded-For负载均衡/云虚拟机/Serverless在负载均衡条件下需要查阅对应负载均衡程序的文档来决定使用哪种方法获取真实客户端IP地址。在大部分虚拟主机、负载均衡及无服务器中可以通过HTTP_CLIENT_IP、HTTP_X_FORWARDED_FOR或X-REAL-IP其一得知客户端IP地址。但是不建议对多种来源进行空值判断这样容易被伪造者利用从而实现IP欺骗。目前并未有标准规定将客户端IP地址放入名为CLIENT_IP的环境变量但是有不少老虚拟主机供应商这样做。新的提供商都不再使用该环境变量。网上大量的PHP文章中都是优先获取HTTP_CLIENT_IP的值因此导致网上存在大量的服务器可以被伪造IP欺骗。可能有该漏洞的代码123456?phpif(!empty($_SERVER[HTTP_CLIENT_IP])) {$ip$_SERVER[HTTP_CLIENT_IP];}elseif(isset($_SERVER[REMOTE_ADDR]) $_SERVER[REMOTE_ADDR] strcasecmp($_SERVER[REMOTE_ADDR],unknown)) {$ip$_SERVER[REMOTE_ADDR];}IIS PHP这种情况下直接使用$_SERVER[REMOTE_ADDR]方法即可。总结无论是哪种情况如果用户使用匿名代理访问服务器只能获取到代理服务器的IP地址其IP地址仍然具有参考意义。获取客户端真实IP地址此事需要查阅相关资料根据具体情况选用某一个方法而不是复制粘贴。部分方法获取到的值可能是一个数组。不建议对获取到的IP地址进行正则过滤有可能你获取到的是一个IPv6地址。
返回列表