Nginx 经过代理获取真实IP - 基于 aliyun ddos

这里仅仅对获取到的header 进行解析学习, 方便我们做最少的配置和最优化的服务器配置 , 首先贴出来我们的一个拓扑结构
image.png
我们仅仅在防护及设置host, 其他均不设置, 并且在服务机打印所有的 header 信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?php
$headers = [
// 真实IP, 可以透传下发
'x-real-ip' => '58.11.11.42',
'x-client-ip' => '58.11.11.42',
'x-true-ip' => '58.11.11.42',

// 阿里云的鹰眼 ddos 防护
'eagleeye-rpcid' => '0.1',
'eagleeye-traceid' => '2f63148c16612233768404397ec0b0',
'web-server-type' => 'nginx',
'x-forwarded-cluster' => 'gf,', # 高防集群

// forwarded 的 ip 和策略
'x-forwarded-proto' => 'http',
'x-forwarded-for' => '58.11.11.42',
'wl-proxy-client-ip' => '58.11.11.42',


// 普通的 header 信息
'upgrade-insecure-requests' => '1',
'user-agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.134 Safari/537.36 Edg/103.0.1264.77',
'connection' => 'close',
'host' => 'hidden.domain.com',
'content-length' => '',
'content-type' => '',
'cache-control' => 'no-cache',
'pragma' => 'no-cache',
'cookie' => '...',
'accept-language' => 'en',
'accept-encoding' => 'gzip, deflate',
'accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
];

x-forwarded-for 说明

可以看到 x-forwarded-for 里边只有一层ip 信息, 如果我们向下透传的话, 如果没有赋值, 我们则是不可能获取到真实链路的 ip 信息的, 但同时经过了多重代理之后, 服务器的 $remote_addr 已经不可信, 因为获取到的是上一层代理的ip 地址, 这里我们需要用到这两个变量来保证链路稳定和获取 ip 稳定

1
2
$proxy_add_x_forwarded_for
$http_x_forwarded_for

这两个的变量的值的区别,就在于,$proxy_add_x_forwarded_for$http_x_forwarded_for 多了一个 $remote_addr 的值
但是 $remote_addr 只能获取到与服务器本身直连的上层请求ip,所以设置 $remote_addr一般都是设置第一个代理上面
但是问题是,有时候是通过cdn访问过来的,那么后面web服务器获取到的,永远都是cdn 的ip 而非真是用户ip

那么这个时候就要用到 x-forwarded-for了,这个变量的意思,其实就像是链路反追踪,从客户的真实ip为起点,穿过多层级的proxy ,最终到达web 服务器,都会记录下来,所以在获取用户真实ip的时候,
一般就可以设置成

1
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

这样就能获取所有的代理ip 客户ip 

1
'x-forwarded-for' =>  '58.11.11.42, 47.111.111.119',

x-real-ip 真实 IP 信息

这里 代理机器种提供了三个 header 信息来提供了真实 ip 信息

1
2
3
x-real-ip
x-client-ip
x-true-ip

我们在日志中直接使用即可, 对于真实的运维环境中如何获取真实的Ip 应当按照当时的拓扑结构来进行实际的考察再确定

全局流量管理下的整合方案

image.png
对于全局流量管理, 我们需要支持线路1 和 线路2 访问的切换, 因为线路1 的优势是 ddos 防护, 但是对网络速度有限制, 线路二则无此问题, 所以将线路 1 设为备选方案, 但是用户直接通过线路 2 到达高防机之后则是无法获取到 x-real-ip 的, 因为这个 header 并非标准代理约定, 是 ddos 防护机加上的 header, 所以为了支持两种不同的入口,需要在防护机中增加相关配置支持获取用户真实IP

防护机器记录真实IP

1
2
3
4
5
6
7
8
9
10
11
12
# DDOS 流量清洗
if ($http_x_client_ip != '') {
set $clientIp $http_x_client_ip;
}
# 直接访问
if ($http_x_client_ip = ''){
set $clientIp $remote_addr;
}

log_format main '$clientIp - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
...;

服务机记录真实IP

防护机器转发

1
2
3
4
5
6
7
8
9
10
# DDOS 流量清洗
if ($http_x_client_ip != '') {
set $clientIp $http_x_client_ip;
}
# 直接访问
if ($http_x_client_ip = ''){
set $clientIp $remote_addr;
}
# 设置 Header 头
proxy_set_header X-Client-Ip $clientIp;

服务机器记录
这样在服务机中只需要使用 $http_x_client_ip变量便可以获取到真实的用户IP

1
2
3
log_format  main  '$http_x_client_ip - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
...;

参考


原文地址 : Nginx 经过代理获取真实IP - 基于 aliyun ddos
本站是作者语雀文档的镜像站, 如对文章有任何疑问请移步语雀进行 提问

Nginx 经过代理获取真实IP - 基于 aliyun ddos

https://wulicode.com/ops/nginx-with-real-ip.html

作者

Duoli

发布于

2022-08-23

更新于

2022-08-24

许可协议

评论