必须为每个ip绑定独立rate.limiter实例,用sync.map或lru缓存管理并定期清理,解析真实ip需校验可信代理,避免复用全局限流器或忽略ipv6/端口处理。

用 golang.org/x/time/rate 做 IP 级请求限流,但别复用同一个限流器
限流不是“加个中间件就完事”,关键在粒度和复用方式。rate.Limiter 是线程安全的,但它本身不带键(key),你不能拿一个实例去管所有 IP —— 那等于全站共享桶,攻击者换 IP 就绕过。
- 必须按
r.RemoteAddr提取纯 IP:用strings.Split(r.RemoteAddr, ":")[0],否则 IPv4/IPv6 + 端口会导致同一客户端被算作多个 key - 限流器实例要复用,不能每次请求 new 一个:初始化时预建 map[string]*rate.Limiter,用
sync.RWMutex或sync.Map管理,避免高频写冲突 - 令牌桶参数得区分路径:登录接口用
(2, 3)(严控),API 列表页可用(10, 20)(防刷不误伤)
黑白名单必须支持 CIDR,且热更新不能直接替换 map
map[string]bool 看似简单,但存不了 192.168.0.0/16 这种网段,而且并发读写要锁,热加载时直接赋值新 map,正在执行的请求可能看到旧规则和新规则混用的状态。
- 改用
github.com/marcel-dempers/ipset或自己封装基于net.IPNet的结构,支持Contains判断 - 规则更新走
atomic.Value:先构造新规则集,再Store()替换,读侧用Load().(*IPSet),零停顿无锁读 - 中间件里查顺序固定:先黑名单(命中即拒),再白名单(豁免健康检查等路径),最后放行
真实 IP 解析必须配合 SetTrustedProxies,否则 c.ClientIP() 是废的
线上服务基本都走 Nginx / CDN / Traefik,c.ClientIP() 默认只信 127.0.0.1,返回的往往是代理内网地址,不是用户真实出口 IP。
Colly 是一个用于 Go 语言的快速开源爬取和爬虫框架。它适用于从简单的页面提取到异步爬虫处理大量页面集合,支持请求回调和结构化解析。
- 反向代理要透传头:Nginx 配
proxy_set_header X-Real-IP $remote_addr;多层代理则用X-Forwarded-For并取最左非信任地址 - Gin 必须显式设可信网段:
engine.SetTrustedProxies([]string{"192.168.0.0/16", "10.0.0.0/8"}),否则伪造X-Forwarded-For可绕过所有过滤 - 别依赖
c.Request.Header.Get("X-Real-IP")就完事——没配SetTrustedProxies,这个头就是攻击者的输入字段
超时配置不是可选项,IdleTimeout 才是防 Slowloris 的命门
ReadTimeout 和 WriteTimeout 控制单次读写,对保持连接不发数据的 Slowloris 类攻击完全无效。真正起作用的是 IdleTimeout,它决定空闲连接存活多久。
- Go 1.8+ 的
http.Server必须设:IdleTimeout: 30 * time.Second,否则恶意连接可永久占着 fd 和 goroutine - 长连接服务(如 WebSocket)还需额外计数:用
atomic.Int64统计当前活跃连接,Accept 后立刻判断是否超限,超了直接conn.Close() - 别关
Keep-Alive一了百了——浏览器、移动端依赖复用,合理设IdleTimeout比粗暴关闭更平衡
真实攻击从来不是单点突破,IP 限流挡不住扫描器,黑白名单绕不开 CDN 伪造,超时配错照样被慢速攻击拖垮。每个模块都得在正确位置、用正确参数、配合基础设施才能生效。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










