Nginx后端获取CDN用户真实IP

2025-07-28 60 0

https://www.alibabacloud.com/help/zh/cdn/user-guide/configure-custom-request-headers

客户端IP 1.1.1.1 -> 阿里云CDN 2.2.2.2 ->内部NGINX负载器3.3.3.3->Nginx后端4.4.4.4

real_ip_header X-Forwarded-For; # 指定真实IP头部,一般为X-Forwarded-For或X-Real-IP
real_ip_recursive off;
OFF: 从右向左只最多剥离一层信任层,先检查remote_addr,再检查real_ip_header是否为信任IP, 返回不信任
ON: 从右向左剥离所有信任层,返回不信任IP

real_ip_recursive示解

  • 客户端 IP: 1.1.1.1
  • CDN IP: 2.2.2.2
  • 内部 LB IP: 3.3.3.3
  • 后端 NGINX 接收到的原始 $remote_addr3.3.3.3 (即内部 LB 的 IP)。
  • X-Forwarded-For 头部内容1.1.1.1, 2.2.2.2, 3.3.3.3

1. real_ip_recursive off

后端 NGINX 配置:

set_real_ip_from 3.3.3.3; # 信任内部 LB
real_ip_header X-Forwarded-For;
real_ip_recursive off;

图示:

请求路径: 1.1.1.1 (客户端) --> 2.2.2.2 (CDN) --> 3.3.3.3 (内部LB) --> 后端 NGINX

后端 NGINX 收到:
原始 $remote_addr = 3.3.3.3
X-Forwarded-For = "1.1.1.1, 2.2.2.2, 3.3.3.3"

信任列表 (set_real_ip_from):{ 3.3.3.3 }
real_ip_recursive = off

处理步骤:
1. 检查原始 $remote_addr (3.3.3.3):在信任列表中。✅ 继续处理。

2. 处理 X-Forwarded-For 链 (从右往左):
   "1.1.1.1, 2.2.2.2, [3.3.3.3]"
                       ^
                       |
                       +-- 3.3.3.3 在信任列表。
                           由于 real_ip_recursive = off,只剥离这一层。

3. 剥离 3.3.3.3 后,链条变为:"1.1.1.1, 2.2.2.2"
                                      ^
                                      |
                                      +-- 将链中剩下的第一个IP (2.2.2.2) 设为 $remote_addr。

最终 $remote_addr = 2.2.2.2

2. real_ip_recursive on 示例图示

后端 NGINX 配置:

set_real_ip_from 3.3.3.3; # 信任内部 LB
set_real_ip_from 2.2.2.2; # 信任 CDN
real_ip_header X-Forwarded-For;
real_ip_recursive on;

图示:

请求路径: 1.1.1.1 (客户端) --> 2.2.2.2 (CDN) --> 3.3.3.3 (内部LB) --> 后端 NGINX

后端 NGINX 收到:
原始 $remote_addr = 3.3.3.3
X-Forwarded-For = "1.1.1.1, 2.2.2.2, 3.3.3.3"

信任列表 (set_real_ip_from):{ 2.2.2.2, 3.3.3.3 }
real_ip_recursive = on

处理步骤:
1. 检查原始 $remote_addr (3.3.3.3):在信任列表中。✅ 继续处理。

2. 处理 X-Forwarded-For 链 (从右往左,递归剥离):

   a. "1.1.1.1, 2.2.2.2, [3.3.3.3]"
                           ^
                           |
                           +-- 3.3.3.3 在信任列表。剥离。

   b. 链条变为:"1.1.1.1, [2.2.2.2]"
                          ^
                          |
                          +-- 2.2.2.2 在信任列表。剥离。

   c. 链条变为:"[1.1.1.1]"
                   ^
                   |
                   +-- 1.1.1.1 不在信任列表。停止剥离。

最终 $remote_addr = 1.1.1.1

NGINX负载器3.3.3.3

不经过CDN,直接请求源站,没有http_Ali_Cdn_Real_Ip,这里用map设置默认值为$remote_addr

http {
    map $http_Ali_Cdn_Real_Ip $ali_cdn_real_ip {
        default $remote_addr;
        "~^(?P<ip>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$" $ip;
    }
    server {
       location / {
           proxy_pass http://static.sundayhk.com;
           proxy_set_header Host static.sundayhk.com;
           proxy_set_header X-Real-IP $http_Ali_Cdn_Real_Ip;
           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
           proxy_redirect off; 
        }
    }
}

或者 http_x_forwarded_for,但要确保上游可信

http {
    map $http_x_forwarded_for $real_ip {
        default $remote_addr;
        "~^(?P<ip>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$" $ip;
        "~^(?P<first_ip>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}),.*$" $first_ip; # return the first of one or more IPs                                            
    } 
    server {
        location / {
           proxy_pass http://static.sundayhk.com;
           proxy_set_header Host static.sundayhk.com;
           proxy_set_header X-Real-IP $real_ip;
           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
           proxy_redirect off;
         }
     }
}

NGINX后端4.4.4.4

server {
    # 信任内部NGINX负载器IP, 因为会先检查上游再检查X-Real-IP是否信任
    set_real_ip_from 3.3.3.3; 
    real_ip_header X-Real-IP;
    real_ip_recursive off;
}

后端代码直接使用X-Real-IP做客户端IP, 虽然提取X-Forwarded-For第一位也可以实现,但不安全,因为它可以伪造。

后端NGINX 4.4.4.4 日志

# CDN过来
1.1.1.1 - - [27/Jul/2025:22:37:08 +0800] "GET /login HTTP/1.1" 200 85 "-" "Uptime-Kuma/1.23.16" "1.1.1.1, 2.2.2.2" 0.023 0.023 127.0.0.1:9000 200 -

# 请求源站,不经过CDN
1.1.1.1 - - [27/Jul/2025:22:37:16 +0800] "GET /login HTTP/1.1" 200 85 "-" "Uptime-Kuma/1.23.16" "1.1.1.1" 0.021 0.021 127.0.0.1:9000 200 

real_ip_header X-Forwarded-For + real_ip_recursive on;

这种方式需要set_real_ip_from 信任所有负载器IP段和CDN IP段

set_real_ip_from 2.2.2.0/24; # 信任CDN回源所有IP段
set_real_ip_from 3.3.3.0/24; # 信任内部NGINX负载器
real_ip_header X-Forwarded-For;
real_ip_recursive on;

相关文章

Nginx使用Geoip2模块 解析客户端IP地理信息 限定国家区域访问
Nginx 允许多个域名跨域访问
nginx-module-vts监控虚拟主机的流量
Nginx上传大文件慢 解决
nginx 1.22 编译webdav插件
ubuntu 22.04 编译 nginx 1.22

发布评论