用 $_SERVER['SERVER_ADDR'] 获取本机IP最可靠,它由PHP从socket获取,是Web服务监听的真实IP;客户端真实IP需优先检查$_SERVER['HTTP_X_FORWARDED_FOR'](取首个非私有地址)并校验来源可信性。

PHP 中 $_SERVER['SERVER_ADDR'] 和 $_SERVER['REMOTE_ADDR'] 本质不同,不会自动混淆,但开发者常因忽略代理层而误判——真正混淆的不是变量,而是对请求链路的理解。
怎么拿到本机(服务器)IP?用 $_SERVER['SERVER_ADDR'] 最可靠
这个值由 PHP 在接受连接时从 socket 获取,是当前 Web 服务监听的真实 IP(如 192.168.1.100 或 127.0.0.1),不受 HTTP 头影响。
- 如果服务器绑定了多个 IP,
$_SERVER['SERVER_ADDR']返回实际响应请求的那个 IP - 在 CLI 模式下该值为空,因为不经过网络连接
- 不要用
gethostbyname(gethostname()),它可能返回127.0.0.1或内网 DNS 解析结果,不可靠
怎么拿到客户端真实 IP?不能只信 $_SERVER['REMOTE_ADDR']
$_SERVER['REMOTE_ADDR'] 是 TCP 连接发起方的 IP,在无反向代理时等于用户真实出口 IP;但只要前面有 Nginx、CDN、SLB,它就变成上一跳代理的内网 IP(如 10.0.0.5)。
- 必须检查代理是否设置了标准头:优先看
$_SERVER['HTTP_X_FORWARDED_FOR'],取逗号分隔后的第一个非私有地址 - Cloudflare 用户应读
$_SERVER['HTTP_CF_CONNECTING_IP'],它比X-Forwarded-For更可信 - 永远校验 IP 合法性:
filter_var($ip, FILTER_VALIDATE_IP),并排除私有网段(127.0.0.0/8、10.0.0.0/8、172.16.0.0/12、192.168.0.0/16)
为什么写个函数判断 IP 还总出错?
常见错误不是逻辑写错,而是信任了不该信的来源或没限定可信代理范围。
立即学习“PHP免费学习笔记(深入)”;
- 直接
explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])[0]忽略了伪造风险——攻击者可手动加X-Forwarded-For: 1.2.3.4头 - 没限制只从已知可信代理(如公司内网网段)读取转发头,导致公网请求也能注入
- 混淆了
HTTP_X_REAL_IP(Nginx 配置的自定义头)和HTTP_X_FORWARDED_FOR的优先级:前者更可控,但需运维配合配置 - 用
$_SERVER['REMOTE_ADDR'] === '127.0.0.1'判断本地请求?在 Docker 或 Kubernetes 环境中,它可能是宿主机或 Pod IP,未必准确
真正难的不是取哪个变量,而是厘清整个流量路径:客户端 → CDN → LB → Nginx → PHP。每层是否透传、是否可信、是否过滤恶意头,决定了你该信谁。











