ctx.Request().RemoteAddr不能直接使用,因为它返回的是与Iris服务直连的对端地址(如Nginx、CDN或云LB的内网IP,例如10.0.0.5),而非用户真实出口IP;必须先校验该地址是否属于可信代理网段,再安全解析X-Forwarded-For中首个合法公网IP。

为什么 ctx.Request().RemoteAddr 不能直接用
它返回的是和 Iris 服务**直连的对端地址**——99% 的情况是 Nginx、CDN 或云 LB 的内网 IP(比如 10.0.0.5:42193),不是用户真实出口 IP。本地开发时甚至可能是 127.0.0.1。Iris 没做任何特殊处理,它只是原样暴露了底层 TCP 连接的 RemoteAddr,和标准库 net/http 行为完全一致。
必须校验可信代理后再解析 X-Forwarded-For
攻击者能随意伪造 X-Forwarded-For: 1.2.3.4,所以不能无条件取第一个。核心逻辑是:只有当 ctx.Request().RemoteAddr 解析出的 IP 属于你明确信任的代理网段(如 Nginx 部署在 10.0.0.0/8 或 172.16.0.0/12),才去解析该 header。
具体步骤:
- 从
ctx.Request().RemoteAddr提取 IP(用net.SplitHostPort) - 检查该 IP 是否在你配置的可信代理 CIDR 列表中(用
net.IPNet.Contains) - 若可信,再读
X-Forwarded-For,strings.Split(..., ",")后逐个strings.TrimSpace+net.ParseIP().IsPrivate()判断 - 取最左第一个**非私有、非回环、非保留**的 IP(即排除
127.0.0.0/8、10.0.0.0/8、172.16.0.0/12、192.168.0.0/16、::1等) - 若全不合法,fallback 到
X-Real-IP(前提是 Nginx 配置了proxy_set_header X-Real-IP $remote_addr)
X-Real-IP 和 X-Forwarded-For 在 Iris 中怎么选
Iris 不干预 header 读取,所以行为完全取决于你如何调用 ctx.Request().Header.Get。但二者语义不同,不能混用:
-
X-Real-IP是单值 header,Nginx 用$remote_addr填充,只反映“直接连 Nginx 的上一跳”——单层代理可用;前有 CDN 时,这里可能已是 CDN 边缘节点 IP -
X-Forwarded-For是逗号分隔链(client, proxy1, proxy2),Nginx 用$proxy_add_x_forwarded_for追加自身 IP,Go 必须取第一个合法公网 IP,且必须校验代理可信性 - 推荐优先走
X-Forwarded-For+ 可信代理校验;X-Real-IP仅作 fallback,且需确认代理链长度稳定
Iris 中别误用 ctx.FormValue 或 ctx.QueryParam
这两个方法和客户端 IP 完全无关:ctx.FormValue("X-Forwarded-For") 永远返回空,因为它是从 POST/PUT 请求体(application/x-www-form-urlencoded 或 multipart/form-data)里读的,不是从 HTTP header;ctx.QueryParam("X-Forwarded-For") 是从 URL query string(如 ?X-Forwarded-For=...)里读的,header 名永远进不来。
正确做法只有一条路径:ctx.Request().Header.Get("X-Forwarded-For") 或 ctx.Request().Header.Get("X-Real-IP")。
最易被忽略的一点:可信代理网段必须硬编码或从配置加载,不能写死成 "127.0.0.1" 就完事——生产环境 Nginx 很可能部署在 10.100.0.0/16,而你校验时漏掉这个网段,就会把所有流量 fallback 到 RemoteAddr,等于白做。


















