12、网络层防护:TCP/UDP异常流量检测、IP代理/VPN识别、DDoS与CC攻击防护
网络层防护,说白了就是游戏服务器的第一道大门。我做了这么多年安全,见过太多游戏上线第一天就被打趴下的案例。你想想看,玩家还没进来,攻击者先到了。这章我就聊聊怎么把这扇门守好。
12.1 TCP/UDP异常流量检测
游戏服务器最常用的就是TCP和UDP。TCP讲究可靠,UDP讲究速度。但攻击者偏偏喜欢利用这些特性搞事情。
12.1.1 TCP异常行为识别
TCP协议本身有一套完整的状态机。正常玩家连接,三次握手,数据传输,四次挥手。但攻击者不会按套路出牌。
我在项目中遇到过一种情况:某个区服突然大量出现半连接状态。查了下,是典型的SYN Flood攻击。攻击者只发SYN包,不完成握手,把服务器的连接队列塞满了。
核心检测指标:
- SYN包与ACK包的比例异常(正常约1:1,攻击时可达到10:1以上)
- 单个IP的并发半连接数超过阈值(我一般设50-100)
- TCP重传率突然飙升(超过5%就要警惕)
- RST包异常增多(可能是扫描行为)
// 伪代码:TCP异常检测逻辑
function detectTCPAnomaly(packet):
if packet.isSYN and not packet.isACK:
halfOpenCount[packet.srcIP]++
if halfOpenCount[packet.srcIP] > MAX_HALF_OPEN:
alert("SYN Flood 嫌疑: " + packet.srcIP)
blockIP(packet.srcIP, 60) // 临时封禁60秒
if packet.isRST:
rstCount[packet.srcIP]++
if rstCount[packet.srcIP] > MAX_RST_PER_MIN:
alert("端口扫描嫌疑: " + packet.srcIP)
12.1.2 UDP异常行为识别
UDP就更有意思了。它无连接,攻击者可以伪造源IP,你根本不知道谁打的你。
我记得有一次,一个MMO游戏突然延迟爆炸。查了半天,发现是UDP Flood。攻击者用僵尸网络发大量小包,每个包只有几十字节,但每秒几百万个,直接把带宽打满了。
我的经验:UDP防护不能只靠服务器端。一定要在网关层做限速。我习惯的做法是:
- 按IP统计UDP包速率,超过1000pps(包每秒)就丢包
- 对UDP payload长度做校验,小于20字节的包直接丢弃
- 建立UDP会话表,只有通过认证的玩家才转发数据
12.2 IP代理/VPN识别
为什么要识别代理和VPN?因为攻击者几乎都躲在代理后面。正常玩家用家庭宽带直连,攻击者用各种跳板。
识别方法主要有三种:
| 方法 | 原理 | 准确率 | 我踩过的坑 |
|---|---|---|---|
| IP黑名单库 | 维护已知代理/VPN的IP段 | 70%左右 | 更新不及时,漏掉新节点 |
| 行为特征分析 | 检测延迟、路由跳数、TLS指纹 | 85%左右 | 误伤CDN节点 |
| 协议特征检测 | 识别OpenVPN、WireGuard等协议特征 | 90%以上 | 加密流量难识别 |
注意:我曾经把某云游戏的加速器节点误判为VPN,导致一批付费玩家无法登录。后来加了白名单机制,对已知的合法代理放行。记住,宁可漏过,不要误伤。
12.3 DDoS与CC攻击防护
DDoS和CC是游戏服务器最头疼的两种攻击。DDoS打带宽,CC打应用层。我见过最狠的一次,攻击流量达到800Gbps,直接把整个机房的出口打瘫了。
12.3.1 DDoS防护策略
DDoS防护讲究分层防御。你不能指望单点扛住所有攻击。
我个人的习惯是:云清洗扛大流量(100Gbps以上),硬件防火墙做第一道过滤,网关层做精细控制。三层下来,大部分攻击都被挡在外面了。
12.3.2 CC攻击防护
CC攻击比DDoS更阴险。它不占带宽,但占你的CPU和数据库连接。攻击者模拟正常玩家行为,发大量业务请求。
举个例子:一个登录接口,正常玩家每秒请求1-2次。攻击者用几百个代理,每秒发几万次登录请求。你的数据库连接池瞬间被占满,正常玩家登录不了。
CC防护三板斧:
- 频率限制:每个IP每秒最多N次请求。N根据业务定,登录接口我设5次/秒,游戏内操作设20次/秒
- 验证码:触发频率限制后,弹出滑块验证。攻击者一般不会过验证码
- 行为分析:检测鼠标轨迹、点击间隔。真人玩家有随机性,脚本是机械的
// 频率限制实现(Go语言示例)
type RateLimiter struct {
visitors map[string]*Visitor
mu sync.Mutex
}
type Visitor struct {
count int
lastSeen time.Time
}
func (rl *RateLimiter) Allow(ip string, limit int) bool {
rl.mu.Lock()
defer rl.mu.Unlock()
v, exists := rl.visitors[ip]
if !exists {
rl.visitors[ip] = &Visitor{count: 1, lastSeen: time.Now()}
return true
}
if time.Since(v.lastSeen) > time.Second {
v.count = 1
v.lastSeen = time.Now()
return true
}
v.count++
return v.count <= limit
}
避坑指南:我曾经把频率限制设得太死,导致游戏内公会战期间大量玩家被误封。后来我加了动态阈值——根据当前在线人数自动调整限制值。在线人数多的时候放宽限制,少的时候收紧。
12.4 实战经验总结
说了这么多,最后分享几个我在实战中总结的要点:
- 不要过度依赖单一方案。云清洗、硬件防火墙、软件检测,三者缺一不可。我见过只买云清洗的,结果云清洗节点被打穿后,服务器直接裸奔。
- 日志一定要全。没有日志,攻击过后你连谁打的都不知道。我习惯把所有网络层的日志存到Elasticsearch,保留30天。
- 自动化响应。检测到攻击后,自动触发防护策略。人工响应太慢了,等你登录服务器,攻击已经持续了10分钟。
- 定期演练。每个月做一次红蓝对抗。我让运维团队模拟攻击,安全团队防守。只有实战才能发现问题。
最后提醒一句:网络层防护不是一劳永逸的。攻击手段在进化,你的防护也要跟着升级。我每个月都会review一次防护策略,看看有没有新的攻击手法需要应对。
公众号:蓝海资料掘金营,微信deep3321