nginx + php-fpm 架构中需通过 fastcgi_param 显式传递真实客户端 ip 给 php,推荐用 set $real_client_ip 配合可信头(x-real-ip/x-forwarded-for)并启用 real_ip_header,php 应用即可通过 $_server['remote_addr'] 获取真实 ip。

在 Nginx + PHP-FPM 架构中,默认日志(如 access.log 或 PHP 的 error_log)记录的客户端 IP 往往是 Nginx 的本地地址(如 127.0.0.1),而非用户真实 IP。这是因为 PHP-FPM 本身不直接接收 HTTP 请求,而是由 Nginx 转发 FastCGI 请求,真实 IP 需通过 Nginx 显式传递给 PHP。
确保 Nginx 正确传递真实 IP 到 PHP-FPM
PHP 无法自动识别原始客户端 IP,必须依赖 Nginx 将其作为 FastCGI 参数传入。关键配置是 fastcgi_param,常用字段为 REMOTE_ADDR 和自定义变量(如 HTTP_X_REAL_IP):
- 在 Nginx 的
location ~ \.php$块中,添加或确认以下参数:
fastcgi_param REMOTE_ADDR $remote_addr;
# 若使用了 CDN、反向代理(如 Cloudflare、SLB),应改用可信头:
fastcgi_param REMOTE_ADDR $http_x_real_ip;
# 或更稳妥地:优先取 X-Real-IP, fallback 到 X-Forwarded-For 第一个非内网 IP
set $real_client_ip $remote_addr;
if ($http_x_real_ip) {
set $real_client_ip $http_x_real_ip;
}
if ($http_x_forwarded_for) {
set $real_client_ip $http_x_forwarded_for;
}
fastcgi_param REMOTE_ADDR $real_client_ip;⚠️ 注意:$http_x_forwarded_for 可被伪造,务必配合 set_real_ip_from 和 real_ip_header 在 Nginx 全局启用可信源 IP 解析,否则该变量不可信。
让 PHP 应用记录真实 IP(如 Laravel、WordPress、自定义脚本)
PHP 脚本需主动读取传入的 FastCGI 参数,而不是直接用 $_SERVER['REMOTE_ADDR'](它已被 Nginx 覆盖为真实 IP,前提是上一步配置正确):
- 确认
$_SERVER['REMOTE_ADDR']已为真实 IP:可在 PHP 中临时打印验证 - 若框架/应用有独立日志组件(如 Monolog、Laravel Log),默认通常已使用
$_SERVER['REMOTE_ADDR'],无需额外改动 - 若需记录到自定义日志(如
error_log("访问来自 {$_SERVER['REMOTE_ADDR']}")),直接使用即可
PHP-FPM 自身错误日志不记录客户端 IP,但可间接实现
PHP-FPM 的 error_log(如 /var/log/php-fpm/www-error.log)只记录 PHP 解析错误、启动失败等,**不包含请求上下文(如 IP、URI)**。它不是访问日志,无法直接格式化输出客户端 IP。
若你希望“PHP 错误也带真实 IP”,可行方案是:
- 在 PHP 应用层捕获错误(
set_error_handler/register_shutdown_function),手动拼接$_SERVER['REMOTE_ADDR']写入自定义日志文件 - 用 Nginx 的
log_format在access.log中记录完整请求信息(含真实 IP、状态码、响应时间),与 PHP 错误日志关联排查 - 借助工具如
php-syslog-facility将 PHP 错误发往 syslog,并配合结构化日志系统(如 Fluentd + Elasticsearch)做字段提取
验证是否生效的简单方法
写一个 ip.php 放在 Web 根目录:
<?php echo "REMOTE_ADDR: " . ($_SERVER['REMOTE_ADDR'] ?? 'N/A') . "\n"; echo "HTTP_X_REAL_IP: " . ($_SERVER['HTTP_X_REAL_IP'] ?? 'N/A') . "\n"; echo "HTTP_X_FORWARDED_FOR: " . ($_SERVER['HTTP_X_FORWARDED_FOR'] ?? 'N/A') . "\n"; ?>
用 curl -H "X-Real-IP: 203.0.113.5" http://yoursite/ip.php 测试;再从公网真实访问,检查输出是否为你期望的真实 IP。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











