基于 Spring Boot 的客户端真实 IP 获取服务,通过 HAProxy + Nginx 多层代理架构验证 IP 透传。
Docker Bridge Network
┌──────────────────────────────────────┐
│ │
客户端 │ ┌──────────┐ ┌────────────────┐ │
(Real IP) │ │ │ │ │ │
│ │ │ HAProxy │ │ nginx1 :8080 │ │
│ TCP:9000 │ │ :9000 ├──►│ X-Real-IP │ │
└────────────┼─►│ │ │ X-Forwarded-For│ │
│ └──────────┘ └───┬────────┬───┘ │
│ │ roundrobin │ │ │
│ │ │ │ │
│ │ ┌──────────┘ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────────────────────────┐ │
│ │ nginx2 :8080 │ │
│ │ X-Real-IP / X-Forwarded-For │ │
│ └─────────────┬───────────────────┘ │
│ ▼ │
│ ┌─────────────────────────────────┐ │
│ │ Spring Boot Apps :8081 │ │
│ │ app1 / app2 │ │
│ └─────────────────────────────────┘ │
└──────────────────────────────────────┘
所有容器通过 Docker Bridge 网络内部通信,仅 HAProxy 的 9000 端口对外暴露。
客户端 HAProxy Nginx Spring Boot
(192.168.1.49) (:9000) (:8080) (:8081)
│ │ │ │
│ ① TCP 连接 │ │ │
│ 源IP:真实IP │ │ │
│────────────────►│ │ │
│ │ │ │
│ │ ② TCP连接 │ │
│ │ + PROXY │ │
│ │ Protocol │ │
│ │──────────────►│ │
│ │ │ │
│ │ │ 解析 PROXY │
│ │ │ $proxy_protocol │
│ │ │ _addr = 真实IP │
│ │ │ │
│ │ │ ③ HTTP 转发 │
│ │ │ X-Real-IP: │
│ │ │ X-Forwarded-For:│
│ │ │────────────────►│
│ │ │ │
│ │ │ ④ 读取 │
│ │ │ Header │
│ │ │ 返回JSON │
│◄──────────────────────────────────────────────────│
│ │
▼ │
{
"X-Forwarded-For": "192.168.1.49", ◄─ Nginx 写入真实IP
"X-Real-IP": "192.168.1.49", ◄─ Nginx 写入真实IP
"Proxy-Client-IP": "", ◄─ 未设置
"WL-Proxy-Client-IP": "", ◄─ 未设置
"RemoteAddr": "172.x.x.x" ◄─ Nginx 容器 IP
}
| 变量 | 值 | 说明 |
|---|---|---|
X-Real-IP |
客户端真实 IP | Nginx 通过 $proxy_protocol_addr 获取,写入 HTTP Header |
X-Forwarded-For |
客户端真实 IP | 同上,标准代理 IP 链 Header |
RemoteAddr |
Nginx 容器 IP | TCP 层连接来源,在 Bridge 网络下为 Nginx 容器地址,非客户端 IP |
生产环境中应使用
X-Real-IP或X-Forwarded-For获取客户端真实 IP,而非依赖RemoteAddr。
- Java 17 + Spring Boot 3.2.5
- HAProxy 2.8 — TCP 四层负载均衡,通过 PROXY Protocol 传递客户端真实 IP
- Nginx — 七层反向代理,解析 PROXY Protocol 后通过 HTTP Header 转发真实 IP
- Docker Compose — Bridge 网络,5 个容器编排,仅暴露 9000 端口
GET /api/ip
返回示例:
{
"X-Forwarded-For": "192.168.1.49",
"X-Real-IP": "192.168.1.49",
"Proxy-Client-IP": "",
"WL-Proxy-Client-IP": "",
"RemoteAddr": "172.18.0.4"
}- JDK 17
- Maven
- Docker & Docker Compose
# 打包
mvn clean package -DskipTests
# 启动所有容器
sudo docker-compose up -d
# 访问
curl http://localhost:9000/api/ipsudo docker-compose down| 层级 | 协议/方式 | 传递的 IP 信息 |
|---|---|---|
| 客户端 → HAProxy | TCP | 原始 TCP 源地址(真实 IP) |
| HAProxy → Nginx | PROXY Protocol | send-proxy 在 TCP 连接头注入真实 IP |
| Nginx | $proxy_protocol_addr |
解析 PROXY Protocol 还原真实 IP |
| Nginx → Spring Boot | HTTP Header | X-Real-IP / X-Forwarded-For |