问题再现
由于 tomcat 被 Nginx 反向代理, 因此request.getRemoteAddr()
只能获取到本地回环地址,
Nginx 提供了变量 $remote_addr
, 可用于使用 proxy_set_header 设置头信息, 实现向上游的 tomcat 服务器提供远端客户端IP地址
proxy_set_header X-Real-IP $remote_addr;
但是, 一旦使用了 CDN 的话, 这个地址就变成了 CDN 节点的地址, 并且同一个用户不同时间发出的IP都不一样.
CDN 通常会在 Header 中提供客户端真实IP, 如 CloudFlare 在 x-forwarded-for
, cf-connecting-ip
中设置了此数据.
Nginx 提供了变量 $http_x_forwarded_for
用于获取 x-forwarded-for 的值, 因此可以在 Nginx 配置文件中为 X-Real-IP 设置以下两个值:
remote_addr
http_x_forwarded_for
它们分别代表了未使用 CDN 和使用了 CDN 的客户端真实IP.
# Nginx 配置实现
#CloudFlare
set $CDN "CloudFlare";
#set $CDN "NO"; # 如果未使用 CloudFlare, 则取消该行代码的注释
set $Real_IP $remote_addr;
if ($CDN = "CloudFlare") {
set $Real_IP $http_x_forwarded_for;
}
#设置代理 Header
proxy_set_header Host $host;
proxy_set_header X-Real-IP $Real_IP;
......
# 民间传说, 一个电信反代的 CF IP
104.25.183.205
这个IP的电信延迟非常低, 而且速度非常不错, 你懂的!
当自选该IP后, x-real-ip 也就是 x-forwarded-for 变成了 59.174.137.107,140.206.61.106
cf-connecting-ip 更是变成了被反代的 140.206.61.106
这种特殊情况应当被考虑.
所以我写了一个 static 方法, 用来从 HttpServlet 中获取 Real-IP:
package common;
import javax.servlet.http.HttpServletRequest;
/**
* 系统工具 & 配置
*/
public class Sys {
private static final CDN cdn;
private enum CDN {
Nginx, CloudFlare,
}
static {
cdn = CDN.Nginx;
}
public static String getRemoteIP(HttpServletRequest thiz) {
switch (cdn) {
case Nginx:
return thiz.getHeader("X-Real-IP");
case CloudFlare:
return thiz.getHeader("CF-Connecting-IP");
default:
return thiz.getRemoteAddr();
}
}
}
分类:
WEB
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· C++代码改造为UTF-8编码问题的总结
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· 【.NET】调用本地 Deepseek 模型
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
· 上周热点回顾(2.17-2.23)