应配置可信代理网段而非仅用c.RealIP():e.TrustProxyFunc = func(ip net.IP) bool { return ip.IsLoopback() || ip.To4() != nil && (ip.To4()[0] == 10 || ip.To4()[0] == 172 && ip.To4()[1] >= 16 && ip.To4()[1] <= 31 || ip.To4()[0] == 192 && ip.To4()[1] == 168) }。

如何在Echo中间件中获取真实客户端IP
直接用 c.RealIP() 通常拿不到真实IP,尤其在Nginx、Cloudflare或Kubernetes Ingress后。Echo默认信任 X-Forwarded-For,但必须显式配置可信代理段,否则会返回空或错误IP。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 在启动Echo实例后、注册路由前,调用
e.IPExtractor = echo.ExtractIPFromXFFHeader(仅当需要从XFF取IP时) - 更安全的做法是设置可信代理网段:
e.TrustProxyFunc = func(ip net.IP) bool { return ip.IsLoopback() || ip.To4() != nil && (ip.To4()[0] == 10 || ip.To4()[0] == 172 && ip.To4()[1] >= 16 && ip.To4()[1] - 之后统一用
c.RealIP()—— 它会自动跳过不可信代理,只取最后一个可信段IP
用sync.Map实现轻量级IP黑名单检查
高频请求下用map+mutex容易成为瓶颈,sync.Map 更适合读多写少的黑名单场景(比如手动封禁、临时限流)。但注意它不支持遍历和len(),不适合需要定期清理或统计的场景。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 定义全局黑名单:
var ipBlacklist = sync.Map{} - 检查逻辑放在中间件里:
if _, ok := ipBlacklist.Load(c.RealIP()); ok { return c.String(http.StatusForbidden, "Forbidden") } - 添加IP(如管理接口):
ipBlacklist.Store("192.168.1.100", struct{}{});删除用ipBlacklist.Delete("192.168.1.100") - 避免用字符串拼接IP加端口(如
192.168.1.100:54321),c.RealIP()返回纯IP,端口已剥离
持久化黑名单需注意时间格式与存储粒度
如果用Redis或文件存黑名单,常见坑是时间戳精度不一致导致过期失效,或把整个IP段(如 192.168.1.0/24)当成单个字符串存,后续匹配成本高。
Echo框架 5.1.0 版本源码包下载,适合关注 RealIP 行为变化、StartConfig.Listener、NewDefaultFS 和观测性中间件入口的开发团队。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 存储结构推荐:key为IP字符串,value为过期Unix时间戳(秒级足够),用
redis.SetEX(ctx, "blacklist:"+ip, "1", time.Until(expireTime)) - 匹配时先查是否存在,再查是否过期 —— 不要依赖Redis自动过期,因为
EXISTS和GET非原子,高并发下可能误放行 - 若需CIDR支持,不要在运行时做net.ParseCIDR+IP.In(),而应在写入时预计算所有可能IP(仅适用于/24及更大子网),或改用专用库如
go-netutils
为什么不能只靠HTTP头字段做IP校验
X-Forwarded-For、X-Real-IP 等头完全由客户端或上游代理控制,未经过滤就用它们做黑名单判断,等于把封禁逻辑暴露给攻击者 —— 只要伪造一个不在黑名单里的IP头,就能绕过。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 永远以
c.RealIP()为准,它已集成TrustProxyFunc逻辑 - 禁止在中间件里直接读
c.Request().Header.Get("X-Forwarded-For")做判断 - 如果上游是Cloudflare,确保在Nginx层已用
set_real_ip_from+real_ip_header CF-Connecting-IP设置可信源,否则c.RealIP()仍可能取错
真正难的不是加黑名单,而是确定“这个IP到底是谁”。代理链越长,IP可信度越低;IPv6地址长度和格式变化也会影响字符串匹配逻辑。别省略 TrustProxyFunc 配置,哪怕只是先写 return ip.IsLoopback() —— 至少比默认行为安全。

















