go微服务防ddos核心是让恶意流量在抵达业务逻辑前失败:按ip复用rate.limiter、accept阶段拒长连接、显式设置read/write/idle三重超时、禁用keep-alive滥用、上传接口强制maxbytesreader限流。

Go微服务防DDoS不是靠“拦住所有坏请求”,而是让恶意流量在抵达业务逻辑前就失败——连接未建立就被拒、请求头没读完就超时、IP还没走到handler就限流失败。应用层能做的有限,关键在时机和粒度。
按IP复用rate.Limiter,别碰全局单例或每次new
rate.NewLimiter(10, 20)本身没问题,但用法错就等于没限。
-
rate.Limiter必须按清洗后的IP复用:从r.RemoteAddr取IP得用strings.Split(r.RemoteAddr, ":")[0],否则192.168.1.100:54321和192.168.1.100:54322被当成两个客户端 - 不能在
http.HandlerFunc里每次new rate.Limiter——内存泄漏+锁竞争;也不能全用同一个实例——所有IP共享桶,限流失效 - 正确结构是
sync.RWMutex保护map[string]*rate.Limiter,key为纯IP;登录页等敏感路径建议rate.NewLimiter(2, 3),普通API可设(10, 20) - 判断用
limiter.AllowN(time.Now(), 1)而非Wait(),避免goroutine阻塞;返回false时直接http.Error(w, "", http.StatusTooManyRequests),不进下游
HTTP Server三重超时必须显式设,IdleTimeout最易漏
Slowloris类攻击不发完整请求,只维持低速发送或空闲连接,专吃read buffer和连接表。context.WithTimeout对这类无效。
-
ReadTimeout:控制读取请求头和body的时间,建议≤5s;太短会误杀大表单,太长留空窗 -
WriteTimeout:响应写入时限,建议≤10s;注意它包含TLS握手后整个响应过程 -
IdleTimeout:空闲连接最大存活时间,默认0(永不超时),必须设——推荐30–60s,且要小于前置Nginx的keepalive_timeout - 禁用Keep-Alive滥用:在
http.Server响应中加Header.Set("Connection", "close"),尤其对IoT设备或爬虫客户端
长连接服务(如Livego/WS)必须在Accept阶段拒连
rate.Limiter对RTMP、WebSocket无效——攻击者建1000个空TCP连接就能耗尽net.Conn和goroutine,连HTTP handler都进不去。
- 防护必须下沉到
net.Listener.Accept()之后、协议解析之前;Livego的max_connections: 1000只是内部统计,不自动拒绝新连接 - 用
atomic.Int64做活跃连接计数:atomic.LoadInt64查当前数,超限时立刻conn.Close()并记录日志 - 绝对避免
sync.WaitGroup或全局int计数器——万级并发下Add/Done争抢严重,Load/Store/Add更轻量 - RTMP配置里
read_timeout: 10和write_timeout: 10作用于protocol/rtmp/rtmp.go,但它们晚于Accept,只能防已建立连接的慢速攻击
上传接口必须套http.MaxBytesReader,别信前端校验
前端限制文件大小形同虚设,攻击者直接绕过发大payload,触发GC风暴甚至OOM。
- 对
/upload等接口,必须用http.MaxBytesReader包装r.Body,例如http.MaxBytesReader(w, r.Body, 5(5MB上限) - 该限制在read body时生效,比业务层校验早得多;配合
ReadTimeout可防慢速大文件上传 - 不要依赖
Content-Length头做判断——攻击者可伪造或分块发送,MaxBytesReader才是硬边界 - 若用gRPC,对应的是
grpc.MaxRecvMsgSize和grpc.MaxSendMsgSize,同样需显式设
最易被忽略的一点:所有这些应用层措施,都建立在源站IP不暴露的前提下。哪怕rate.Limiter调得再细、atomic计数写得再稳,只要CDN或反向代理没配好,攻击流量直打Go进程,防线就从第一层开始崩。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











