第2章:网络层防护:DDoS攻击原理与防御、TCP/UDP洪水防护、IP黑白名单机制
大家好,我是你们的老朋友。今天咱们聊聊网络层防护,这是游戏服务器安全的第一道防线。说实话,我见过太多游戏刚上线就被打趴下的案例,原因就是网络层没守住。
DDoS攻击,说白了就是让服务器「忙死」。攻击者用大量垃圾流量塞满你的带宽,或者耗尽你的连接资源。正常玩家进不来,游戏直接瘫痪。我当年负责的一款MMO,开服当天就被打了200G的流量,那叫一个惨烈。
2.1 DDoS攻击原理
DDoS攻击分几种常见类型,咱们一个个说。
2.1.1 带宽耗尽型攻击
这种攻击最粗暴。攻击者用大量肉鸡(被控制的机器)同时向你的服务器发送大流量数据包。你的带宽是有限的,比如100Mbps,人家打过来1Gbps,那你的服务器就彻底堵死了。
我记得有一次,一个客户说他们的游戏突然卡得动不了。我一看流量监控,好家伙,UDP流量直接飙到了800Mbps。正常游戏哪有这么多UDP包?明显是攻击。
2.1.2 连接耗尽型攻击
这种更阴险。它不占你带宽,而是占你的连接数。比如TCP SYN Flood,攻击者发送大量伪造的SYN包,服务器会为每个SYN分配资源等待握手完成。但攻击者根本不完成握手,服务器资源就被耗尽了。
你想想看,一台服务器能同时处理的连接数是有限的。比如Linux默认的backlog是128,攻击者一秒发几万个SYN,你的服务器就再也无法接受新连接了。
2.1.3 应用层攻击
这种攻击针对游戏协议本身。比如发送大量合法的游戏请求,让服务器忙于处理这些请求而无法响应正常玩家。我遇到过有人写脚本模拟玩家登录,一秒发几千次登录请求,直接把认证服务器打崩了。
2.2 TCP/UDP洪水防护
好了,知道攻击原理了,咱们说说怎么防。我个人习惯把防护分成三层:网络层、传输层、应用层。今天重点说传输层。
2.2.1 TCP SYN Flood防护
SYN Flood是最常见的攻击方式。防御手段主要有以下几种:
| 防护手段 | 原理 | 优缺点 |
|---|---|---|
| SYN Cookie | 不分配资源,用Cookie验证 | 效果好,但增加CPU开销 |
| 缩短超时时间 | 减少半连接存活时间 | 简单有效,但可能误杀 |
| 反向探测 | 对可疑IP发送探测包 | 准确率高,但延迟大 |
我建议在Linux内核层面开启SYN Cookie:
# 开启SYN Cookie
echo 1 > /proc/sys/net/ipv4/tcp_syncookies
# 调整半连接队列大小
echo 1024 > /proc/sys/net/ipv4/tcp_max_syn_backlog
# 减少SYN-ACK重试次数
echo 3 > /proc/sys/net/ipv4/tcp_synack_retries
嗯,这里要注意:SYN Cookie虽然好用,但在高并发场景下会增加CPU开销。我建议只在检测到攻击时动态开启,平时关掉。
2.2.2 UDP Flood防护
UDP Flood更难防,因为UDP本身是无连接的。攻击者随便伪造源IP,发一堆UDP包过来。你的服务器得一个个处理,处理不过来就挂了。
我在项目中遇到过最狠的一次,攻击者用放大攻击。他伪造源IP为你的服务器IP,向DNS服务器发送查询请求,DNS服务器返回的数据比请求大几十倍,全部打到你服务器上。这叫反射放大攻击。
防御UDP Flood,我常用的手段:
- 限速:对单个IP的UDP流量做限速,超过阈值直接丢包
- 协议验证:只处理符合游戏协议的UDP包,其他全部丢弃
- 源IP验证:对可疑IP发送探测包,验证其真实性
代码层面,可以在游戏服务器入口做过滤:
// 伪代码:UDP包过滤
bool FilterUDPPacket(udp_packet_t* pkt) {
// 1. 检查包大小
if (pkt->size > MAX_UDP_SIZE || pkt->size < MIN_UDP_SIZE) {
return false; // 丢弃
}
// 2. 检查协议头
if (!IsValidGameProtocol(pkt->data)) {
return false; // 丢弃
}
// 3. 检查源IP频率
if (GetIPFrequency(pkt->src_ip) > MAX_FREQ) {
return false; // 丢弃
}
return true; // 放行
}
2.3 IP黑白名单机制
IP黑白名单是最基础也是最有效的防护手段。说白了就是:白名单里的IP随便进,黑名单里的IP直接拦。
2.3.1 白名单机制
白名单适用于内部系统、管理后台、测试环境。比如你的运维管理平台,只允许公司VPN的IP段访问。其他IP一律拒绝。
我曾经犯过一个错误:把白名单写死在代码里。结果公司换IP段了,所有运维人员都连不上服务器。后来我改成从配置文件读取,再后来改成从配置中心动态获取。
// 白名单配置示例
{
"whitelist": [
"10.0.0.0/8", // 内网段
"192.168.1.0/24", // 办公网段
"114.114.114.114" // 特定IP
],
"mode": "strict" // strict: 只允许白名单; loose: 白名单优先
}
2.3.2 黑名单机制
黑名单用于封禁恶意IP。比如检测到某个IP在短时间内发送了大量请求,就把它加入黑名单。
我建议黑名单分两级:
- 临时黑名单:自动触发,封禁一段时间(比如30分钟)后自动解封
- 永久黑名单:人工确认后加入,永久封禁
实现时要注意性能问题。黑名单如果太大,每次查表都会很慢。我一般用布隆过滤器(Bloom Filter)来做快速判断:
// 布隆过滤器示例
class IPBloomFilter {
bitset<1024*1024> bits; // 1M bits
hash_func_t hash_funcs[3];
public:
void Add(const string& ip) {
for (auto& h : hash_funcs) {
bits.set(h(ip) % bits.size());
}
}
bool MightContain(const string& ip) {
for (auto& h : hash_funcs) {
if (!bits.test(h(ip) % bits.size())) {
return false; // 一定不在
}
}
return true; // 可能在
}
};
2.3.3 动态黑白名单
静态黑白名单不够灵活。我建议实现动态黑白名单,根据实时流量自动调整。
比如,我写过一个简单的检测逻辑:
- 统计每个IP在1秒内的请求次数
- 如果超过阈值(比如100次/秒),加入临时黑名单
- 如果该IP在1小时内被加入黑名单超过3次,升级为永久黑名单
- 永久黑名单需要人工审核才能移除
这样做的好处是:攻击者刚动手就被封了,正常玩家偶尔手抖一下也不会被误伤。
2.4 实战经验总结
说了这么多,最后分享几点我的实战经验:
- 不要只依赖一种防护手段:DDoS攻击手段多样,你得组合使用多种技术
- 监控要到位:没有监控,你都不知道自己被打了。我习惯用Grafana搭实时流量看板
- 做好容量规划:服务器带宽和连接数要有余量,别刚好卡在极限
- 和云服务商配合:大流量攻击靠自己是扛不住的,得用云清洗服务
我曾经接手过一个项目,服务器被打了三天,运维团队居然没发现。为什么?因为他们没看流量监控。后来我加了告警,流量一异常就发短信、打电话。从那以后,再也没出现过被打不知道的情况。
好了,网络层防护就聊到这儿。下一章咱们讲传输层安全,聊聊如何防止中间人攻击和会话劫持。到时候见。