IP黑名单中间件必须注册在UseGlobal或按需Use,不能靠路由匹配;因拦截本质是入口级控制,须在任何路由匹配前执行,UseGlobal最稳妥,部分路径可用Use("/api/*", middleware),禁用通配符路由拦截。

IP黑名单中间件必须注册在UseGlobal或按需Use,不能靠路由匹配
IP拦截本质是请求入口级控制,必须在任何路由匹配前执行。Iris 的 app.UseGlobal() 是最稳妥的位置;若只需保护部分路径(如 /api/*),则用 app.Use("/api/*", ipBlacklistMiddleware)。别试图用 app.Get("/*any", ...) 拦截——它优先级低于具体路由,/health 这类路径根本不会进这个 handler。
怎么安全提取客户端真实IP,避免X-Forwarded-For伪造
Iris 默认的 ctx.RemoteAddr() 只返回 TCP 层地址(可能是反向代理 IP)。要拿到真实用户 IP,得结合 X-Forwarded-For 或 X-Real-IP 头,但必须校验可信代理链:
- 若服务直连公网,直接用
ctx.RemoteAddr()解析出 IP 段即可 - 若前面有 Nginx / Envoy,需配置
app.ConfigureHost(iris.WithoutBodyConsumptionOnUnmarshal)并在中间件里手动解析:ctx.Request().Header.Get("X-Real-IP"),且只信任来自已知代理 IP 的该头 - 永远不要无条件信任
X-Forwarded-For的第一个值——攻击者可伪造整个字段
黑名单存储选内存 map 还是 Redis?性能与热更新怎么权衡
小规模(sync.Map 足够:启动时加载、运行时 Load/Store 安全;但无法热更新。若需运营后台实时增删,必须上 Redis + 中间件内异步查(注意加本地缓存和超时):
- Redis 查询必须设
context.WithTimeout,避免阻塞整个请求链 - 建议加一层 10 秒 TTL 的
sync.Map缓存,降低 Redis 压力 - 黑名单格式统一用 CIDR(如
"192.168.1.0/24"),别存单 IP 字符串,否则匹配慢
拦截后必须返回 403 且调用 StopExecution,别漏掉这两步
常见错误是只写日志或跳过 ctx.Next(),结果后续中间件和 handler 仍会执行:
- 正确做法:
ctx.StatusCode(403)+ctx.WriteString("Forbidden")+ctx.StopExecution() - 别用
ctx.Abort()—— Iris 里没有这个方法,StopExecution()才是终止链路的唯一方式 - 健康检查等白名单路径必须在中间件开头显式放过:
if ctx.Path() == "/health" { ctx.Next(); return }
X-Real-IP 就是开放的伪造入口;用字符串 == 匹配网段,10 万 IP 黑名单下延迟直接翻倍。


















