LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

详解Nginx获取客户端真实IP

admin
2025年8月28日 0:57 本文热度 65

目录

  • • 为什么需要获取真实IP
  • • 技术原理
  • • 核心配置指令
  • • 工作机制详解
  • • 实际场景配置
  • • 多值处理算法
  • • 安全考虑
  • • 简化方案:自定义真实 IP 头部
  • • 调试与验证
  • • 最佳实践
  • • 常见问题

为什么需要获取真实IP

几年前之前写过一篇类似文章k8s生产实践之获取客户端真实IP,本文更贴近基础,用某厂的话来说:苦练基本功!

在现代 Web 架构中,为了应对大量用户访问,网站通常会部署在以下架构之后:

  • • WAF(如 Cloudflare WAF、AWS WAF)
  • • 负载均衡器(如 AWS ALB/ELB、阿里云 SLB)
  • • CDN 服务(如 Cloudflare、AWS CloudFront)
  • • 反向代理(如 Nginx、Apache)

因此,一个典型的客户端请求流程如下:

真实用户(1.2.3.4)
CDN/WAF(103.x.x.x)
负载均衡器(10.0.1.100)
Nginx
应用服务器

如果没有特殊配置,Nginx 的访问日志只能记录到直接连接的上游设备 IP(负载均衡器或 CDN 的 IP),而不是真实用户的 IP 地址。这会导致:

  • • 日志分析困难:无法识别真实用户行为
  • • 安全防护失效:无法基于用户 IP 进行访问控制
  • • 地域限制失效:无法根据用户地理位置提供服务
  • • 监控告警不准确:无法准确识别攻击来源

技术原理

HTTP 头部传递机制

负载均衡器和 CDN 通常会在 HTTP 请求头中添加真实用户的 IP 信息:

头部字段
使用场景
示例
X-Forwarded-For
标准字段,大多数代理使用
X-Forwarded-For: 1.2.3.4, 172.16.1.10
X-Real-IP
简单代理环境
X-Real-IP: 1.2.3.4
CF-Connecting-IP
Cloudflare CDN 专用
CF-Connecting-IP: 1.2.3.4
Forwarded
RFC 7239 标准
Forwarded: for=1.2.3.4;proto=https

关于上述字段的详细介绍,可以参考:

  • • X-Forwarded-For
  • • CF-Connecting-IP
  • • Forwarded
  • • RFC 7239

连接来源 IP vs 真实客户端 IP

连接来源 IP

  • • 定义:与 Nginx 建立 TCP 连接的设备 IP
  • • 获取方式:通过系统调用 getpeername() 获得
  • • 特点:无法被应用层伪造,是真实的网络层信息
  • • 在 Nginx 中:对应 $realip_remote_addr 变量

真实客户端 IP

  • • 定义:最终用户的实际 IP 地址
  • • 获取方式:从 HTTP 头部解析
  • • 特点:可能被中间代理修改或伪造
  • • 在 Nginx 中:经过处理后的 $remote_addr 变量

核心配置指令

可以参考Nginx Real IP Module Documentation

real_ip_header

作用:指定从哪个 HTTP 头部获取真实 IP

# 常用配置
real_ip_header X-Forwarded-For;     # 标准配置
real_ip_header X-Real-IP;           # 简单代理
real_ip_header CF-Connecting-IP;    # Cloudflare CDN

set_real_ip_from

作用:定义可信任的代理 IP 范围(白名单机制)

# 基本语法
set_real_ip_from ip_address;
set_real_ip_from ip_address/netmask;
set_real_ip_from unix:;

# 实际示例
set_real_ip_from 10.0.0.0/8;        # 内网段
set_real_ip_from 172.16.0.0/12;     # 私有网络
set_real_ip_from 192.168.1.100;     # 特定 IP

real_ip_recursive

作用:启用递归处理多层代理

real_ip_recursive on;   # 启用(推荐)
real_ip_recursive off;  # 禁用(默认)

工作机制详解

白名单验证机制

set_real_ip_from 采用白名单机制

set_real_ip_from 10.0.0.0/8;
real_ip_header X-Forwarded-For;

工作流程

  1. 1. 检查连接来源 IP
  2. 2. 如果来源 IP 在白名单中 → 信任请求 → 解析 HTTP 头部
  3. 3. 如果来源 IP 不在白名单中 → 不信任请求 → 忽略 HTTP 头部

示例对比

来源 IP 在白名单中:

连接来源: 10.0.1.100 (✓ 在 10.0.0.0/8 范围内)
X-Forwarded-For: 1.2.3.4
结果: $remote_addr = 1.2.3.4

来源 IP 不在白名单中:

连接来源: 8.8.8.8 (✗ 不在白名单范围内)
X-Forwarded-For: 1.2.3.4
结果: $remote_addr = 8.8.8.8 (忽略头部信息)

多值 X-Forwarded-For 处理算法

X-Forwarded-For 格式

X-Forwarded-For: client_ip, proxy1_ip, proxy2_ip, proxy3_ip
                 ←────────── 从左到右:客户端到服务器 ──────────→

非递归模式 real_ip_recursive off

选择 最后一个(最右边) IP:

set_real_ip_from 192.168.1.0/24;
real_ip_header X-Forwarded-For;
real_ip_recursive off;

# X-Forwarded-For: 1.2.3.4, 172.16.1.10, 192.168.1.50
# 选择: 192.168.1.50

递归模式 real_ip_recursive on

从右到左检查,跳过可信 IP,选择第一个不可信 IP:

set_real_ip_from 192.168.1.0/24;    # 可信代理1
set_real_ip_from 172.16.1.0/24;     # 可信代理2
real_ip_header X-Forwarded-For;
real_ip_recursive on;

# X-Forwarded-For: 1.2.3.4, 172.16.1.10, 192.168.1.50
# 处理过程:
# 1. 检查 192.168.1.50 → 可信,跳过
# 2. 检查 172.16.1.10 → 可信,跳过
# 3. 检查 1.2.3.4 → 不可信,选择
# 结果: $remote_addr = 1.2.3.4

不同匹配程度的处理逻辑

假设 X-Forwarded-For: 1.2.3.4, 203.0.113.5, 172.16.1.10,连接来源为 172.16.1.10

情况1:只匹配最后一个

set_real_ip_from 172.16.0.0/12;  # 只信任 172.16.1.10
# 处理: 172.16.1.10(跳过) → 203.0.113.5(选择)
# 结果: $remote_addr = 203.0.113.5

情况2:匹配最后两个

set_real_ip_from 172.16.0.0/12;  # 信任 172.16.1.10
set_real_ip_from 203.0.113.0/24# 信任 203.0.113.5
# 处理: 172.16.1.10(跳过) → 203.0.113.5(跳过) → 1.2.3.4(选择)
# 结果: $remote_addr = 1.2.3.4

情况3:全部匹配

set_real_ip_from 172.16.0.0/12;  # 信任 172.16.1.10
set_real_ip_from 203.0.113.0/24# 信任 203.0.113.5
set_real_ip_from 1.2.3.0/24;     # 信任 1.2.3.4
# 处理: 所有IP都可信 → 选择最左边的IP
# 结果: $remote_addr = 1.2.3.4

除了上述情况,还有其他情况,比如:

情况4:连接来源不可信,也就是没有任何一个IP在可信列表中

set_real_ip_from 172.16.0.0/12;  # 信任 172.16.1.10
# 但连接来源是: 8.8.8.8 (不在可信列表中)
# X-Forwarded-For: 1.2.3.4, 203.0.113.5, 172.16.1.10
# 处理: 连接来源不可信 → 完全忽略 X-Forwarded-For 头部
# 结果: $remote_addr = 8.8.8.8

实际场景配置

AWS ALB/ELB 环境

http {
    # AWS ALB 通常使用 VPC 内网 IP
    set_real_ip_from10.0.0.0/8;
    set_real_ip_from172.16.0.0/12;
    set_real_ip_from192.168.0.0/16;
    
    real_ip_header X-Forwarded-For;
    real_ip_recursiveon;
    
    # 日志格式
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';
    
    server {
        listen80;
        access_log /var/log/nginx/access.log main;
        
        location / {
            # 应用逻辑
        }
    }
}

Cloudflare CDN 环境

http {
    # Cloudflare IP 段(需要定期更新)
    set_real_ip_from173.245.48.0/20;
    set_real_ip_from103.21.244.0/22;
    set_real_ip_from103.22.200.0/22;
    set_real_ip_from103.31.4.0/22;
    set_real_ip_from141.101.64.0/18;
    set_real_ip_from108.162.192.0/18;
    set_real_ip_from190.93.240.0/20;
    set_real_ip_from188.114.96.0/20;
    set_real_ip_from197.234.240.0/22;
    set_real_ip_from198.41.128.0/17;
    
    # 使用 Cloudflare 专用头部
    real_ip_header CF-Connecting-IP;
    real_ip_recursiveon;
    
    server {
        listen80;
        
        # 获取用户国家信息(Cloudflare 提供)
        location / {
            add_header X-Country-Code $http_cf_ipcountry;
            # 应用逻辑
        }
    }
}

混合环境(CDN + 负载均衡器)

http {
    # CDN 层 IP 段
    set_real_ip_from103.21.244.0/22;   # Cloudflare
    set_real_ip_from104.16.0.0/12;     # Cloudflare
    
    # 负载均衡器层
    set_real_ip_from10.0.0.0/8;        # AWS VPC
    set_real_ip_from172.31.0.0/16;     # AWS Default VPC
    
    # 内网代理层
    set_real_ip_from192.168.100.0/24;  # 内网代理
    
    real_ip_header X-Forwarded-For;
    real_ip_recursiveon;
    
    # 详细日志格式
    log_format detailed '$realip_remote_addr forwarded $remote_addr - $remote_user [$time_local] '
                        '"$request$status $body_bytes_sent '
                        '"$http_referer" "$http_user_agent" "$http_x_forwarded_for"';
    
    server {
        listen80;
        access_log /var/log/nginx/access.log detailed;
        
        location / {
            # 应用逻辑
        }
    }
}

内网多层代理环境

http {
    # 第一层:外部负载均衡器
    set_real_ip_from172.16.1.0/24;
    
    # 第二层:内网负载均衡器
    set_real_ip_from10.0.1.0/24;
    
    # 第三层:应用网关
    set_real_ip_from192.168.1.0/24;
    
    real_ip_header X-Forwarded-For;
    real_ip_recursiveon;
    
    server {
        listen80;
        
        # 基于真实 IP 的访问控制
        location /admin {
            allow192.168.0.0/16;    # 允许内网访问
            allow10.0.0.0/8;        # 允许 VPN 访问
            deny all;
            
            # 管理接口
        }
        
        # 基于真实 IP 的限流
        location /api {
            limit_req zone=per_ip burst=10 nodelay;
            # API 接口
        }
    }
}

# 限流配置
limit_req_zone$remote_addr zone=per_ip:10m rate=10r/s;

多值处理算法

算法实现伪代码

def nginx_select_real_ip(forwarded_for_header, trusted_proxies, recursive_mode, connection_ip):
    # 首先检查连接来源是否可信
    if connection_ip notin trusted_proxies:
        return connection_ip  # 不可信连接,直接返回连接 IP
    
    # 解析 X-Forwarded-For 头部
    ifnot forwarded_for_header:
        return connection_ip
    
    ips = [ip.strip() for ip in forwarded_for_header.split(',')]
    
    ifnot recursive_mode:
        # 非递归模式:返回最后一个 IP
        return ips[-1]
    else:
        # 递归模式:从右到左找第一个不可信的 IP
        for ip inreversed(ips):
            if ip notin trusted_proxies:
                return ip
        
        # 如果所有 IP 都是可信的,返回最左边的 IP
        return ips[0]

处理示例

示例 1:标准多层代理

set_real_ip_from 10.0.0.0/8;
set_real_ip_from 172.16.0.0/12;
set_real_ip_from 103.21.244.0/22;
real_ip_recursive on;

这样配置后,一个实际的举例以及处理过程如下:

连接来源: 10.0.1.100
X-Forwarded-For: 1.2.3.4, 103.21.244.50, 172.16.1.10, 10.0.1.100

处理步骤:
1. 连接来源 10.0.1.100 ∈ 10.0.0.0/8 → 可信 ✓
2. 从右到左检查:
   - 10.0.1.100 ∈ 可信列表 → 跳过
   - 172.16.1.10 ∈ 可信列表 → 跳过
   - 103.21.244.50 ∈ 可信列表 → 跳过
   - 1.2.3.4 ∉ 可信列表 → 选择 ✓

结果: $remote_addr = 1.2.3.4

示例 2:恶意请求检测

连接来源: 8.8.8.8 (不在可信列表中)
X-Forwarded-For: 1.2.3.4, 10.0.1.100

处理步骤:
1. 连接来源 8.8.8.8 ∉ 任何可信网段 → 不可信 ✗
2. 忽略 X-Forwarded-For 头部

结果: $remote_addr = 8.8.8.8

示例 3:边界情况 - 所有 IP 都可信

连接来源: 10.0.1.100
X-Forwarded-For: 10.0.2.50, 172.16.1.10, 10.0.1.100

处理步骤:
1. 连接来源可信 ✓
2. 从右到左检查:
   - 10.0.1.100 ∈ 可信列表 → 跳过
   - 172.16.1.10 ∈ 可信列表 → 跳过
   - 10.0.2.50 ∈ 可信列表 → 跳过
3. 所有 IP 都可信,选择最左边的

结果: $remote_addr = 10.0.2.50

安全考虑

白名单精确性

# 好的做法:精确指定
set_real_ip_from 10.0.1.100;        # 特定负载均衡器
set_real_ip_from 172.16.1.0/24;     # 特定代理网段

# 危险的做法:范围过大
set_real_ip_from 0.0.0.0/0;         # 信任所有 IP - 危险做法

定期更新 IP 列表

CDN 和云服务提供商的 IP 段会定期变化,需要及时更新:

#!/bin/bash
# 自动更新 Cloudflare IP 段的脚本

# 获取最新的 Cloudflare IP 段
curl -s https://www.cloudflare.com/ips-v4 > /tmp/cloudflare-ips-v4.txt
curl -s https://www.cloudflare.com/ips-v6 > /tmp/cloudflare-ips-v6.txt

# 生成 Nginx 配置片段
echo"# Cloudflare IP ranges - Updated $(date)" > /etc/nginx/conf.d/cloudflare-ips.conf
whileread ip; do
    echo"set_real_ip_from $ip;" >> /etc/nginx/conf.d/cloudflare-ips.conf
done < /tmp/cloudflare-ips-v4.txt

echo"real_ip_header CF-Connecting-IP;" >> /etc/nginx/conf.d/cloudflare-ips.conf

# 测试配置并重载
nginx -t && systemctl reload nginx

多层验证策略

http {
    # 基础 IP 验证
    set_real_ip_from10.0.0.0/8;
    real_ip_header X-Forwarded-For;
    real_ip_recursiveon;
    
    # 地理位置验证(需要 GeoIP 模块)
    geoip_country /usr/share/GeoIP/GeoIP.dat;
    
    server {
        listen80;
        
        # 结合真实 IP 和地理位置的访问控制
        location /admin {
            # 只允许来自特定国家的特定 IP 段
            if ($geoip_country_code != CN) {
                return403;
            }
            
            allow192.168.0.0/16;
            deny all;
        }
        
        # 异常检测:如果 X-Forwarded-For 和连接 IP 差异过大
        location /sensitive {
            access_by_lua_block {
                local forwarded = ngx.var.http_x_forwarded_for
                local remote = ngx.var.remote_addr
                local connection = ngx.var.realip_remote_addr
                
                -- 如果存在可疑的 IP 跳转,记录日志
                if forwarded and remote ~= connection then
                    ngx.log(ngx.WARN, "Suspicious IP forwarding: " .. 
                           "connection=" .. connection .. 
                           " forwarded=" .. forwarded .. 
                           " final=" .. remote)
                end
            }
        }
    }
}

简化方案:自定义真实 IP 头部

问题分析

X-Forwarded-For 的复杂匹配逻辑确实容易出错,特别是在多层代理环境中,我们经常听到一个叫做 HTTP头部伪造攻击 的安全问题,因为攻击者可以伪造 X-Forwarded-For 头部来绕过IP限制

一个更简单可靠的方案是:在架构最外层(如 WAF、CDN)设置自定义头部

解决方案

方案设计

客户端(1.2.3.4)
WAF/CDN
负载均衡器
Nginx
设置X-Client-True-IP
透传
读取

外层设置(WAF/CDN 配置)

# 在 WAF 或最外层代理设置
set $client_real_ip $remote_addr;  # 获取四层握手的真实 IP
proxy_set_header X-Client-True-IP $client_real_ip;
proxy_set_header Host $host;
proxy_pass http://backend;

Nginx 端配置(极简)

# 简化配置:只信任自定义头部
set_real_ip_from 10.0.0.0/8;      # 内网代理段
set_real_ip_from 172.16.0.0/12;   # 负载均衡器段
real_ip_header X-Client-True-IP;   # 使用自定义头部
real_ip_recursive off;             # 无需递归处理

方案对比

传统 X-Forwarded-For 方案

# 复杂配置
set_real_ip_from103.21.244.0/22;  # CDN IP段1
set_real_ip_from103.22.200.0/22;  # CDN IP段2
set_real_ip_from172.16.0.0/12;    # 负载均衡器
set_real_ip_from10.0.0.0/8;       # 内网段
real_ip_header X-Forwarded-For;
real_ip_recursiveon;               # 需要递归处理

# 潜在问题:
# - 需要维护多个可信 IP 段
# - 复杂的递归匹配逻辑
# - CDN IP 段变化需要更新

自定义头部方案

# 简化配置
set_real_ip_from 10.0.0.0/8;
real_ip_header X-Client-True-IP;   # 单一可信头部
real_ip_recursive off;             # 无需复杂逻辑

调试与验证

调试端点配置

server {
    listen80;
    
    # IP 信息调试端点
    location /debug-ip {
        return200"Connection IP: $realip_remote_addr\nProcessed IP: $remote_addr\nX-Forwarded-For: $http_x_forwarded_for\nX-Real-IP: $http_x_real_ip\nUser-Agent: $http_user_agent\n";
        add_header Content-Type text/plain;
    }
    
    # 详细的调试信息
    location /debug-detailed {
        access_by_lua_block {
            local headers = ngx.req.get_headers()
            local info = {
                connection_ip = ngx.var.realip_remote_addr,
                processed_ip = ngx.var.remote_addr,
                forwarded_for = headers["x-forwarded-for"],
                real_ip = headers["x-real-ip"],
                cf_connecting_ip = headers["cf-connecting-ip"],
                user_agent = headers["user-agent"],
                timestamp = ngx.time()
            }
            
            ngx.header.content_type = "application/json"
            ngx.say(require("cjson").encode(info))
        }
    }
}

日志分析配置

http {
    # 详细的日志格式
    log_format debug_ip '$time_local '
                        'connection_ip=$realip_remote_addr '
                        'processed_ip=$remote_addr '
                        'forwarded="$http_x_forwarded_for" '
                        'real_ip="$http_x_real_ip" '
                        'cf_ip="$http_cf_connecting_ip" '
                        'request="$request" '
                        'status=$status '
                        'user_agent="$http_user_agent"';
    
    server {
        access_log /var/log/nginx/debug_ip.log debug_ip;
    }
}

测试脚本

#!/bin/bash
# 测试真实 IP 获取的脚本

NGINX_HOST="your-nginx-server.com"
TEST_ENDPOINT="/debug-ip"

echo"=== 测试 1: 直接访问 ==="
curl -H "X-Forwarded-For: 1.2.3.4" http://$NGINX_HOST$TEST_ENDPOINT

echo -e "\n=== 测试 2: 多层代理模拟 ==="
curl -H "X-Forwarded-For: 1.2.3.4, 172.16.1.10, 10.0.1.100" http://$NGINX_HOST$TEST_ENDPOINT

echo -e "\n=== 测试 3: 恶意伪造检测 ==="
curl -H "X-Forwarded-For: 192.168.1.1" http://$NGINX_HOST$TEST_ENDPOINT

echo -e "\n=== 测试 4: 无头部信息 ==="
curl http://$NGINX_HOST$TEST_ENDPOINT

监控脚本

#!/bin/bash
# 监控真实 IP 获取异常的脚本

LOG_FILE="/var/log/nginx/access.log"
ALERT_THRESHOLD=100

# 检查可疑的 IP 跳转
suspicious_count=$(tail -10000 $LOG_FILE | grep -c "forwarded.*differ")

if [ $suspicious_count -gt $ALERT_THRESHOLD ]; then
    echo"ALERT: Detected $suspicious_count suspicious IP forwarding in recent logs"
    # 发送告警
fi

# 检查 IP 地理位置异常
geoip_anomaly=$(tail -10000 $LOG_FILE | awk '{print $1}' | sort | uniq -c | sort -nr | head -10)
echo"Top IP addresses by frequency:"
echo "$geoip_anomaly"

最佳实践

生产环境标准配置

http {
    # 真实 IP 获取配置
    include /etc/nginx/conf.d/real-ip.conf;
    
    # 限流配置
    limit_req_zone$remote_addr zone=per_ip:10m rate=10r/s;
    limit_req_zone$server_name zone=per_server:10m rate=100r/s;
    
    # 日志格式
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';
    
    log_format security '$time_local $remote_addr $realip_remote_addr '
                        '"$request$status "$http_user_agent"';
    
    server {
        listen80;
        server_name example.com;
        
        access_log /var/log/nginx/access.log main;
        access_log /var/log/nginx/security.log security;
        
        # 安全头部
        add_header X-Frame-Options "SAMEORIGIN" always;
        add_header X-Content-Type-Options "nosniff" always;
        add_header X-XSS-Protection "1; mode=block" always;
        
        # 基于真实 IP 的限流
        limit_req zone=per_ip burst=20 nodelay;
        
        location / {
            # 应用逻辑
        }
        
        # 管理接口访问控制
        location /admin {
            allow192.168.0.0/16;
            allow10.0.0.0/8;
            deny all;
            
            # 管理功能
        }
    }
}

真实 IP 配置文件

可单独放置一个文件/etc/nginx/conf.d/real-ip.conf

# 内网 IP 段
set_real_ip_from 10.0.0.0/8;
set_real_ip_from 172.16.0.0/12;
set_real_ip_from 192.168.0.0/16;

# 云服务商 IP 段(需要定期更新)
include /etc/nginx/conf.d/cloudflare-ips.conf;
include /etc/nginx/conf.d/aws-ips.conf;

# 配置真实 IP 头部
real_ip_header X-Forwarded-For;
real_ip_recursive on;

常见问题

配置后仍然显示代理 IP ?

可能原因:

  1. 1. 代理 IP 不在 set_real_ip_from 范围内
  2. 2. HTTP 头部字段名称不匹配
  3. 3. Nginx 配置未生效

解决方案:

# 1. 检查连接来源 IP
curl -H "X-Forwarded-For: 1.2.3.4" http://your-server/debug-ip

# 2. 验证配置语法
nginx -t

# 3. 重载配置
nginx -s reload

# 4. 检查错误日志
tail -f /var/log/nginx/error.log

如何处理 IPv6 地址 ?

# IPv6 地址配置
set_real_ip_from 2001:db8::/32;
set_real_ip_from ::1;

# 混合 IPv4/IPv6 环境
set_real_ip_from 10.0.0.0/8;
set_real_ip_from 2001:db8::/32;
real_ip_header X-Forwarded-For;

使用 X-Real-IP 能否正确获取真实 IP ?

X-Real-IP 和 X-Forwarded-For 的行为不同,需要了解其特点:

X-Real-IP 的特点

  • • 单值头部:只包含一个 IP,不像 X-Forwarded-For 包含多个
  • • 设置方:通常由简单的反向代理或某些负载均衡器设置
  • • 标准化程度:相比 X-Forwarded-For 标准化程度较低

实际效果对比

假设请求链路:用户(1.2.3.4) → CDN(103.x.x.x) → ALB(10.0.1.100) → Nginx

如果 ALB 设置了:

X-Real-IP: 1.2.3.4
X-Forwarded-For: 1.2.3.4, 103.21.244.50

使用 X-Real-IP:

real_ip_header X-Real-IP;
set_real_ip_from 10.0.0.0/8;
# 结果: $remote_addr = 1.2.3.4 ✓ 正确

使用 X-Forwarded-For(非递归):

real_ip_header X-Forwarded-For;
real_ip_recursive off;
set_real_ip_from 10.0.0.0/8;
# 结果: $remote_addr = 103.21.244.50 ✗ 拿到CDN IP

使用建议

简单环境(推荐 X-Real-IP):

# 只有一层代理,且确认设置了 X-Real-IP
real_ip_header X-Real-IP;
set_real_ip_from 10.0.0.0/8;
real_ip_recursive off;

复杂环境(推荐 X-Forwarded-For):

# 多层代理环境
real_ip_header X-Forwarded-For;
set_real_ip_from 10.0.0.0/8;
set_real_ip_from 172.16.0.0/12;
real_ip_recursive on;

检查方法

# 检查你的环境是否设置了 X-Real-IP
curl -H "Host: your-domain.com" http://your-nginx/debug-ip

多个 real_ip_header 如何处理 ?

Nginx 只能配置一个 real_ip_header,但可以通过 Lua 脚本处理多个头部:

location / {
    access_by_lua_block {
        -- 优先级:X-Real-IP > CF-Connecting-IP > X-Forwarded-For
        local real_ip = ngx.var.http_x_real_ip
        if not real_ip or real_ip == "" then
            real_ip = ngx.var.http_cf_connecting_ip
        end
        if not real_ip or real_ip == "" then
            local xff = ngx.var.http_x_forwarded_for
            if xff then
                real_ip = xff:match("([^,]+)")  -- 取第一个IP
            end
        end
        
        if real_ip then
            ngx.var.client_real_ip = real_ip
        end
    }
    
    proxy_set_header X-Client-IP $client_real_ip;
    proxy_pass http://backend;
}

如何验证配置是否正确 ?

测试步骤:

  1. 1. 创建测试端点
  2. 2. 模拟不同来源的请求
  3. 3. 检查日志输出
  4. 4. 验证安全策略
# 完整测试脚本
#!/bin/bash
SERVER="http://your-nginx-server.com"

echo"=== 测试真实 IP 获取配置 ==="

echo"1. 测试直接访问:"
curl -s "$SERVER/debug-ip" | grep -E "(Connection|Processed)"

echo -e "\n2. 测试代理转发:"
curl -s -H "X-Forwarded-For: 203.0.113.1""$SERVER/debug-ip" | grep -E "(Connection|Processed)"

echo -e "\n3. 测试多层代理:"
curl -s -H "X-Forwarded-For: 203.0.113.1, 172.16.1.10""$SERVER/debug-ip" | grep -E "(Connection|Processed)"

echo -e "\n4. 测试访问控制:"
curl -s -w "%{http_code}\n""$SERVER/admin" -o /dev/null

echo -e "\n配置测试完成!"

性能影响 ?

真实 IP 获取对性能的影响很小:

  • • CPU 开销:每个请求增加 < 0.1ms 处理时间
  • • 内存开销:忽略不计
  • • 网络开销:无额外网络请求

优化建议:

# 在 http 块中配置,避免重复解析
http {
    set_real_ip_from 10.0.0.0/8;
    real_ip_header X-Forwarded-For;
    real_ip_recursive on;
    # 使用高效的日志格式
    log_format optimized '$remote_addr [$time_local] "$request$status';
}

附:一些常见服务商的IP地址范围

  1. 1. Cloudflare IP Ranges
  2. 2. AWS IP Address Ranges


阅读原文:原文链接


该文章在 2025/8/28 16:48:43 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2025 ClickSun All Rights Reserved