应使用c.ClientIP()并配置可信代理,而非直接用c.RemoteAddr();它按序检查X-Forwarded-For等头,结合WithTrustedProxies校验防伪造,未配置则易被攻击者绕过。

怎么获取客户端真实IP地址
直接用 c.RemoteAddr() 拿到的通常是代理或负载均衡器的地址,不是真实用户IP。Iris 默认不自动解析 X-Forwarded-For,得自己处理。
推荐用 c.ClientIP() —— 它会按顺序检查 X-Forwarded-For、X-Real-IP 等头,并结合 TrustedProxies 配置做可信校验。但注意:必须提前配置可信代理列表,否则可能被伪造。
- 若服务直连用户(无 Nginx/Cloudflare),
c.ClientIP()和c.RemoteAddr()效果一致,可直接用 - 若有反向代理,启动时必须设置:
app.Run(..., iris.WithTrustedProxies([]string{"10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"})) - Cloudflare 用户要加
"173.245.48.0/20"等网段,否则c.ClientIP()会返回 Cloudflare 节点 IP
怎么实现IP黑白名单中间件
核心逻辑是:在请求进入业务 handler 前,拿到 IP,查表判断是否放行。建议封装成可复用中间件,避免每个路由重复写。
白名单优先级高于黑名单;两者共存时,白名单匹配即放行,不继续检查黑名单。
- 用
map[string]struct{}存 IP(O(1) 查找),别用切片遍历 - 黑名单示例:
blacklist := map[string]struct{}{"192.168.1.100": {}, "203.0.113.5": {}} - 白名单示例:
whitelist := map[string]struct{}{"127.0.0.1": {}, "10.10.0.0/16": {}}—— 注意 CIDR 支持需额外解析 - 检查时先调
c.ClientIP(),再用net.ParseIP()+ipNet.Contains()处理网段
简单中间件示例:
func IPFilter(whitelist, blacklist map[string]struct{}) iris.Handler {
return func(c iris.Context) {
ip := c.ClientIP()
if len(whitelist) > 0 {
if isWhitelisted(ip, whitelist) {
c.Next()
return
}
c.StatusCode(403)
c.WriteString("Forbidden: IP not in whitelist")
return
}
if _, ok := blacklist[ip]; ok {
c.StatusCode(403)
c.WriteString("Forbidden: IP blocked")
return
}
c.Next()
}
}
怎么支持CIDR网段匹配(比如192.168.0.0/16)
Iris 自带的字符串匹配不支持子网判断,必须手动解析。Go 标准库 net 包能搞定,但要注意 IPv4/IPv6 兼容性和性能。
关键点:把白名单中的 "10.0.0.0/8" 转成 *net.IPNet,再用 ipNet.Contains(net.ParseIP(ip)) 判断。
- 预解析所有 CIDR 字符串为
*net.IPNet,别在每次请求里重复net.ParseCIDR() - IPv6 地址如
::1或2001:db8::/32同样适用,net.ParseIP()和net.ParseCIDR()都支持 - 注意:某些代理头可能传 IPv4 映射的 IPv6 地址(如
::ffff:192.168.1.1),c.ClientIP()默认返回规范化 IPv4,一般不用额外处理
常见错误和绕过风险
黑白名单容易被绕过,不是银弹。最常踩的坑是信任了不可控的 HTTP 头。
- 没配
WithTrustedProxies却依赖X-Forwarded-For→ 攻击者可伪造任意 IP - 把
RemoteAddr当真实 IP → 实际拿到的是代理出口 IP,导致误杀或漏放 - 白名单只写
"127.0.0.1",但本地调试走localhost或::1→ IPv6 地址不匹配 - 黑名单用正则或前缀匹配(如
strings.HasPrefix(ip, "192.168."))→ 无法正确识别192.168.100.1这类边界情况
CIDR 解析和可信代理配置这两步,漏掉任何一个,整个黑白名单机制就形同虚设。


















