nginx的http_realip_module模块识别真实用IP
nginx使用limit_req模块
nginx使用limit_req模块时,如果使用CDN的话,能按真实的用户IP来限流吗?如果使用的是CDN的IP,从而把CDN直接限流了,影响正常访问:
http_limit_req 模块文档:
https://nginx.org/en/docs/http/ngx_http_limit_req_module.html
limit_req 模块配置实例:
http {
limit_conn_zone $binary_remote_addr zone=perip:10m;
limit_conn_zone $server_name zone=perserver:10m;
server {
...
limit_conn perserver 300;
limit_conn perip 25;
limit_rate 512k;
...
}
}在使用 Nginx 的 limit_req 模块时,如果你使用了 CDN,默认情况下限流是基于 CDN 的 IP 地址的,而不是真实用户的 IP 地址。这是因为 CDN 会将请求转发到你的 Nginx 服务器时,源 IP 地址通常是 CDN 的 IP。
要按真实用户 IP 限流,你需要配置 Nginx 以正确识别用户的真实 IP 地址。通常,这可以通过设置 real_ip 模块来实现。你需要确保 Nginx 从 CDN 请求头(如 X-Forwarded-For 或 X-Real-IP)中提取真实用户 IP 地址,并将其用于限流。
http_realip 模块文档:
https://nginx.org/en/docs/http/ngx_http_realip_module.html
确保nginx有这个模块,查看命令(包含有 --with-http_realip_module 字样):
nginx -V
nginx version: nginx/1.18.0
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC)
built with OpenSSL 1.1.1g 21 Apr 2020
TLS SNI support enabled
configure arguments: --user=www --group=www --prefix=/www/server/nginx --add-module=srclib/ngx_devel_kit --add-module=srclib/lua_nginx_module --add-module=srclib/ngx_cache_purge --add-module=srclib/nginx-sticky-module --with-openssl=srclib/openssl --with-pcre=srclib/pcre-8.43 --with-http_v2_module --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --with-http_stub_status_module --with-http_ssl_module --with-http_image_filter_module --with-http_gzip_static_module --with-http_gunzip_module --with-ipv6 --with-http_sub_module --with-http_flv_module --with-http_addition_module --with-http_realip_module --with-http_mp4_module --with-ld-opt=-Wl,-E --with-cc-opt=-Wno-error --with-http_dav_module --add-module=srclib/nginx-dav-ext-module示例配置
set_real_ip_from 192.168.1.0/24;
set_real_ip_from 192.168.2.1;
set_real_ip_from 2001:0db8::/32;
real_ip_header X-Forwarded-For;
real_ip_recursive on;匹配项说明:
- set_real_ip_from 指定了哪些 IP 地址可以作为信任的代理来源,通常可以设置为 CDN 提供的 IP 范围。 0.0.0.0/0; # 允许所有 IP 的 CDN 代理
- real_ip_header 设置了使用哪个请求头来获取真实 IP 地址。
- real_ip_recursive 使 Nginx 从请求头链中递归提取真实 IP 地址。
嵌入变量
$realip_remote_addr
保留原始客户端地址 (1.9.7)
$realip_remote_port
保留原始客户端端口 (1.11.0)
常见配置实例:
http {
# 信任的代理 IP 范围
set_real_ip_from 192.168.0.0/24; # 负载均衡器或 CDN 的 IP 范围
set_real_ip_from 10.0.0.0/8;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
server {
location / {
# 其他配置
}
}
}
当使用 real_ip 模块时,$remote_addr 变量将反映真实的客户端 IP 地址,而不是中间代理或负载均衡器的 IP 地址。这是因为 real_ip 模块会根据你配置的规则修改 $remote_addr 变量的值。
**如何工作**
没有代理的情况: $remote_addr 直接表示客户端的 IP 地址,无需 real_ip 模块的干预。
有代理或 CDN 的情况: 当你配置了 real_ip 模块并正确设置了信任的代理 IP 地址和请求头(如 X-Forwarded-For),Nginx 会从这些请求头中提取真实的客户端 IP 地址,并将其赋值给 $remote_addr。这使得 $remote_addr 始终反映真实的客户端 IP,而不是代理或负载均衡器的 IP。log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
另一种得到真实IP的方法
map $http_x_forwarded_for $clientRealIp {
"" $remote_addr;
~^(?P<firstAddr>[0-9\.]+),?.*$ $firstAddr;
}
$clientRealIp就得到了真实IP 