保护 Call of Duty 服务器免受 DDoS 攻击

发布于 阅读时间 37 分钟

一台 Call of Duty 服务器真正需要哪些端口,为什么游戏、查询和 RCON 位于同一个端口,如何限制 getstatus 反射攻击和 RCON 攻击,以及攻击达到什么量级之后就只能靠服务器前面的网络过滤。

为 Call of Duty 服务器做好 DDoS 防护,在经典作品上是一件相当具体的工作:只涉及一个 UDP 端口、server.cfg 里的几个 Dvar,以及引擎从 2003 年起就带着的一个放大向量。相反,一台服务器如果在晚上局中把所有玩家同时丢掉,问题很少出在硬件上。多数情况下是有人正在攻击,而且时间恰好选在服务器满员的时候。

本文先讲它到底适用于哪些作品,然后讲您不花额外费用就能自己加固的部分,接着讲这些措施在技术上到哪里为止,最后讲服务器前面的网络里必须发生什么。命令针对 Debian 12、Debian 13、Ubuntu 22.04 LTS 和 Ubuntu 24.04 LTS 书写,并以 root 身份执行,普通用户请在前面加上 sudo。

如果攻击正在进行:现在不要改动 server.cfg,也不要重启服务器。请先保存测量数据(见“记录日志”一节),攻击结束后,这些数据就没有了。

哪些 Call of Duty 作品的服务器可以做 DDoS 防护

只有允许架设自己的独立服务器的作品,才谈得上为 Call of Duty 服务器做 DDoS 防护。这些作品是 Call of Duty(2003)、Call of Duty United Offensive、Call of Duty 2、Call of Duty 4 Modern Warfare 和 Call of Duty World at War 的原版,再加上社区平台 Plutonium(World at War、Black Ops、Black Ops II、Modern Warfare 3)、IW4x(Modern Warfare 2)和 CoD4X(Call of Duty 4)。所有这些作品都带着同一套模式:一个 server.cfg、一个开放的 UDP 端口,以及公开服务器列表里的一个条目。

本文明确不适用于现代作品。Warzone、Modern Warfare(2019)、Black Ops Cold War、Vanguard、Modern Warfare II、Modern Warfare III 和 Black Ops 6 都没有可租用的独立服务器:对局跑在 Activision 的匹配基础设施上,既没有 server.cfg,也没有服务器浏览器,更没有一个您能放行或加固的端口。Activision 为这些作品公布的端口清单(其中包括 TCP 3074 和 27014 到 27050,以及 UDP 3074、3478 和 27000 到 27031)描述的是客户端和平台端口,不是服务器端口。在 Warzone 里掉线的人,问题出在自己的线路上或者出在 Activision 那边,而不是一台租来的服务器能解决的。

为什么偏偏是 Call of Duty 服务器被攻击

Call of Duty 服务器身上集中了四个特点,使它成为称手的目标。第一,每一台列出的服务器都自己公开地址:服务器列表里的条目以明文写着 IP 地址和端口,否则谁也进不去。第二,全部流量都走 UDP,而 UDP 没有可以强制要求的连接建立过程,源地址也可以伪造。第三,引擎会回答任何人的状态查询,对方根本不必启动游戏。第四,远程控制 RCON 与游戏本身位于同一个端口上。

再加上社交层面的原因:被封禁的玩家、战队之间的竞争、一个彼此认识多年的社区内部的矛盾。发起一次攻击既不需要什么本事,也花不了多少钱,所谓的 booter 和 stresser 以每月几欧元的订阅形式出售,而通过游戏服务器发动的放大攻击在那里属于标准项目。DDoS 攻击具体是什么,请看文章 什么是 DDoS 攻击?。

真正相关的那些端口

一台经典的 Call of Duty 服务器只占用一个 UDP 端口,即 28960。在这一个端口上同时跑着三件事:游戏流量、服务器列表的状态查询,以及远程控制 RCON。没有单独的查询端口,也没有单独的 RCON 端口。独立服务器的启动命令在所有作品上都一样,只是可执行文件的名字不同:

+set dedicated 2 +set net_ip 0.0.0.0 +set net_port 28960 +set sv_maxclients 32 +exec server.cfg +map_rotate
作品或平台 服务 端口 协议
Call of Duty、United Offensive、Call of Duty 2、Call of Duty 4、World at War 游戏、查询和 RCON 共用 28960 UDP
同一台机器上的其他实例 游戏、查询和 RCON 共用 28961 到 28970 UDP
Plutonium T4(World at War) 游戏、查询和 RCON 共用 28960 UDP
Plutonium T5(Black Ops) 游戏、查询和 RCON 共用 28960 UDP
Plutonium T6(Black Ops II) 游戏、查询和 RCON 共用 4976 UDP
Plutonium IW5(Modern Warfare 3) 游戏、查询和 RCON 共用 27016 UDP
IW4x(Modern Warfare 2) 游戏、查询和 RCON 共用 28960 UDP
t7x(Black Ops III) 游戏、查询和 RCON 共用 27017 UDP
Call of Duty 4 主服务器(出站) 列表和授权 20810 和 20800 UDP
Call of Duty 2 主服务器(出站) 列表和授权 20710 和 20700 UDP
Call of Duty 1 主服务器(出站) 列表和授权 20510 和 20500 UDP
IW4MAdmin 用于管理的 Web 界面 1624 TCP
SSH 服务器访问 22 TCP

主服务器端口不属于您的防火墙放行范围。20810 和 20800 是对端的目标端口,不是您机器上的监听端口:是您的服务器主动去联系列表。尽管如此,很多端口放行教程仍然建议把它们对入站开放。这样做只会扩大攻击面,毫无用处。

Call of Duty 上常见的数量级

如果您想判断自己是否还能应付得过来,第二张表更重要。它把一台满员服务器的正常负载和一次攻击涉及的数字放在一起对比。

指标 数值
每名玩家的出站速率(sv_maxRate 的常用值) 每秒 25000 字节
32 个槽位全满时的出站负载 约每秒 800 千字节,即大约 6.4 Mbit/s
典型游戏服务器的线路 1 Gbit/s,相当于每秒 125 兆字节
64 字节包大小时 1 Gbit/s 上的数据包速率 约每秒 149 万个数据包
一次 getstatus 请求在线路上的大小 41 字节(20 字节 IP 头、8 字节 UDP 头、13 字节负载)
依据 CISA 公告 TA14-017A,Quake 网络协议的放大系数 63.9
由此推算出的 getstatus 回应大小 约 2600 字节
CoD4X 内置的 getstatus 上限 每 20 秒 20 个回应
CoD4X 内置的 getinfo 上限 每 100 秒 100 个回应
KernelHost 过滤过的针对游戏服务器的 UDP 洪水攻击 超过 112.2 Gbit/s
KernelHost 过滤过的针对语音服务器的攻击 超过 473.4 Gbit/s,每秒超过 4150 万个数据包

为什么游戏、查询和 RCON 位于同一个端口

这是 Call of Duty 上决定性的特殊之处。所有经典 Call of Duty 作品所基于的 id Tech 3 引擎,不区分游戏、查询和远程控制的端口。一切都以所谓的无连接数据包形式跑在那一个 UDP 端口上。无连接数据包是一种以四个 0xFF 字节开头、随后以明文携带命令名的 UDP 包:getstatus、getinfo、getchallenge、connect 或 rcon。

实际后果很不方便:您没法用防火墙把 RCON 和游戏分开,除非把游戏也一起关掉。一条针对 28960 端口的规则总是同时命中全部。想有针对性地筛掉查询洪水攻击和 RCON 攻击的人,就必须看数据包内容,而不只是端口号。正因如此,在 Call of Duty 上,基于端口的防火墙规则比在有独立查询端口的游戏上更早到达极限。

Call of Duty 上的 getstatus 反射攻击是什么?

getstatus 反射攻击是一种放大攻击:攻击者用伪造的源地址向许多游戏服务器发送小小的状态查询,让这些服务器明显更大的回应落到真正的受害者身上。游戏服务器在其中不是目标,而是放大器。这个向量在 id Tech 3 引擎上已有十多年的记录,它对 Call of Duty 的影响和对 Quake 3 及其其余衍生作一样。

它会从两个方向同时打到您。作为被攻击者,您会收到一大波 getstatus 请求,消耗计算时间和出站带宽,您的玩家会以延迟尖峰的形式察觉到。作为非自愿的放大器,您会把回应发给一个陌生的受害者,而滥用举报会落到您头上。两件事发生在同一个端口上,用的是同样的数据包,而且两者在负载图表里起初看起来都很无害。

一个 getstatus 数据包长什么样

请求由四个 0xFF 字节和 getstatus 这个词组成,合起来 13 字节负载。加上 IP 头和 UDP 头,在线路上是 41 字节。多年来在 Call of Duty 论坛里流传的防火墙规则,瞄的正是这个长度检查:

iptables -A INPUT -p udp -m length --length 41:45 -m recent --set --name getstatus_cod
iptables -A INPUT -p udp -m string --algo bm --string "getstatus" -m recent --update --seconds 1 --hitcount 20 --name getstatus_cod -j DROP

回应则大得多。一个 statusResponse 包含以字符串形式给出的整份服务器配置,再加上每名已连接玩家一行,服务器满员时就是好几千字节。CISA 在其 UDP 放大攻击总览(TA14-017A)中把 Quake 网络协议列为放大系数 63.9,并明确指出被滥用的命令就是服务器信息的交换。这样一来,1 Mbit/s 的伪造请求在受害者那边就变成约 64 Mbit/s。作为对比:同一份总览里 DNS 是 28 到 54,NTP 是 556.9。

内置的刹车:sv_queryIgnoreTime 和 sv_queryIgnoreMegs

Call of Duty 4 从服务器版本 1.7 起自带一个查询刹车。它会记住每一个发过状态查询的地址,并在可设置的一段时间内忽略同一地址的后续查询。四个 Dvar 控制这件事,默认值如下:

sv_queryIgnoreMegs        1
sv_queryIgnoreTime        2000
sv_queryBounceIgnoreTime  12000
sv_queryIgnoreDebug       0

sv_queryIgnoreMegs 决定忽略列表可以占用多少内存。1 兆字节能装约 6.5 万个地址,之后每增加一兆字节约多装 8.7 万个。值为 0 时完全关闭这个刹车,而很多服务器上正是这种情况,因为配置抄自一份老模板。sv_queryIgnoreTime 是以毫秒为单位的忽略时长。sv_queryBounceIgnoreTime 在回应带回“ICMP Port Unreachable”时生效,也就是恰好在您的服务器正被当作放大器去打陌生受害者的时候。sv_queryIgnoreDebug 1 会把命中写进日志,好让您能看出到底有没有事情发生。

使用 CoD4X 的人,在服务器代码里还有几个固定上限:每 20 秒最多 20 个 getstatus 回应,每 100 秒最多 100 个 getinfo 回应,每 100 毫秒最多一个 RCON 错误回应。源代码里的注释把意图写得很清楚:服务器不妨让自己被淹没,但不该因此浪费出站带宽。这个优先级取舍是对的,但它代替不了服务器前面的过滤。

为什么 RCON 在 Call of Duty 上历来是个问题

RCON 是服务器的远程控制,而在 Call of Duty 上它是游戏端口上一个未加密的 UDP 包。一条 RCON 命令在线路上是这样的:四个 0xFF 字节,然后是 rcon 这个词,然后是明文密码,最后才是真正的命令。没有加密,没有会话,没有用户账号,也没有第二因素。由此产生三个问题,而且全都真实存在:

  • 被读取。凡是能在途中任何一处看到这些流量的人,都会顺带读到您明文的 RCON 密码。这对您和服务器之间的每一个网络都成立,对每一个您交给它密码的工具也成立。
  • 被猜解。这里没有可以锁定的登录过程,也没有十次失败后的账号封锁。攻击者可以以任意速度逐个试密码。原版服务器完全不做限制,CoD4X 只是把错误回应限制到每 100 毫秒一个,并把这次尝试记为“Bad rcon”。
  • 反射攻击。一条 RCON 错误回应同样是对一个伪造数据包的回应。用伪造的 RCON 数据包打您服务器的人,是把它当成一个小放大器用,而您的服务器还顺带把日志写满。

实际的结论是:只有在真正需要 RCON 时才设置 rcon_password。如果需要,那就设得又长又随机。CoD4X 要求至少八个字符,那是下限,不是建议。日常管理请通过 SSH 和服务器控制台进行,而不要从开放的网络里用 RCON。而如果您运行像 IW4MAdmin 这样自身通过 RCON 通信的管理工具,它在 1624 端口上的 Web 界面就不该暴露在开放的网络里。

在花钱之前,您自己能做的事

这一节最长,而且是故意的。配置干净的 Call of Duty 服务器能靠自己扛住小型和中型攻击,无论它放在谁那里。

1. 清点:服务器上有什么在监听?

在写下第一条规则之前,先看清楚您的服务器对外提供了什么。不要猜,要查:

ss -lntup

要看的是本地地址那一列。0.0.0.0:28960 和 [::]:28960 表示“整个互联网都能访问”,127.0.0.1:3306 表示“仅本机”,不需要防火墙规则。除了游戏之外,这里经常还会出现 IW4MAdmin、用于 Fast Download(快速下载)的 Web 服务器、用于统计的数据库,以及一个被遗忘的第二个游戏实例。从外面做一次端口扫描,就能看到攻击者眼中的样子:

nmap -Pn -sU -p 28960-28970,4976,27016 YOUR.SERVER.IP.ADDRESS
nmap -Pn -p- --min-rate 1000 YOUR.SERVER.IP.ADDRESS

2. 只保留游戏真正需要的端口

对一台单独的 Call of Duty 服务器来说,对外只需要一条放行规则,其余一律收紧或者干脆不发布。用 UFW 的写法如下,而且顺序必须完全照此执行,以免把自己关在门外:

ufw allow 22/tcp comment 'SSH'
ufw allow 28960/udp comment 'Call of Duty'
ufw allow from 203.0.113.10 to any port 1624 proto tcp comment 'IW4MAdmin'
ufw default deny incoming
ufw default allow outgoing
ufw --force enable
ufw status verbose

请把 203.0.113.10 换成您自己的地址。在 Plutonium T6 上,4976/udp 取代 28960/udp;在 Plutonium IW5 上是 27016/udp。如果您运行多个实例,只放行实际使用的范围,例如 28960:28962/udp,而不要笼统地放行 28960 到 28970。没有任何东西在上面监听的端口虽然不是入口,但在遭到攻击时仍然会让内核白做工。包含自救办法的完整说明见 设置 UFW 防火墙而不把自己关在门外。

3. 打开 server.cfg 里的查询刹车

这四行属于每一台 Call of Duty 4 服务器的 server.cfg,除了几兆字节内存之外不花任何代价:

set sv_queryIgnoreMegs "4"
set sv_queryIgnoreTime "2000"
set sv_queryBounceIgnoreTime "12000"
set sv_queryIgnoreDebug "0"

4 兆字节能装约 32.6 万个地址,就算面对一次认真的洪水攻击也够用。把 sv_queryIgnoreTime 提高到默认的 2000 毫秒以上时要谨慎:服务器列表和每一个服务器浏览器都通过同一套机制查询您的服务器,忽略时长设得太高的人会从列表里消失。想知道刹车到底有没有起作用时,可以临时把 sv_queryIgnoreDebug 设为 1,之后再设回 0,免得日志把磁盘写满。

4. 在防火墙里筛掉查询洪水攻击

引擎里的刹车只有在数据包已经到达游戏进程之后才起作用。一条防火墙规则决定得更早,代价也更小。下面这两行按源地址限制 getstatus:

iptables -A INPUT -p udp --dport 28960 -m length --length 41:45 -m recent --set --name cod_query --rsource
iptables -A INPUT -p udp --dport 28960 -m string --algo bm --string "getstatus" -m recent --update --seconds 2 --hitcount 4 --name cod_query --rsource -j DROP

第一行记住每一个发来典型状态查询长度数据包的源地址。第二行在同一地址两秒内发出超过四个 getstatus 请求之后,丢弃其余每一个请求。每两秒四次请求对任何服务器浏览器都够用。论坛里也流传着每秒 20 次请求的版本,它明显宽松得多,更适合对付粗糙的机器人,而不是一波干净的反射攻击。

纯 iptables 规则在重启后就没了,在 Debian 和 Ubuntu 下这样保存:

apt-get install -y iptables-persistent
netfilter-persistent save

在 UFW 下,这类规则应写进 /etc/ufw/before.rules,否则下一次 ufw reload 时就会消失。之后请用 iptables -L INPUT -n -v 检查命中计数器是否在增长。如果一直是零,说明规则没有被匹配到。

5. 关掉 RCON 或者管得很严

最安全的 RCON 通道是不存在的那一个。空的 rcon_password 会拒绝每一个 RCON 数据包:

set rcon_password ""

这里要注意一处细节:服务器那时仍然会回应,也就是回一条错误提示,因此依旧是个小放大器。想排除这一点、而且本来只需要从一个固定地址使用 RCON 的人,可以提前把这些数据包丢掉:

iptables -A INPUT -p udp --dport 28960 ! -s 203.0.113.10 -m string --algo bm --string "rcon " -j DROP

这条规则有一个您应该知道的副作用:字符串 rcon 理论上也可能出现在一名已连接玩家的聊天数据包里,那个数据包同样会被丢弃。实践中这是可以接受的。不想要这个副作用的人就不用这条规则,只用一个空密码或者一个很长的密码。

6. 抵御连接洪水攻击和槽位耗尽

连接洪水攻击打的不是线路,而是游戏逻辑:攻击者快速连续发送 getchallenge 和 connect 数据包,直到所有槽位都被半成品连接占满。真正的玩家这时会看到“Server is full”,而游戏里一个人也没有。下面这些设置对此有效:

set sv_maxclients "32"
set sv_reconnectLimit "3"
set sv_floodProtect "1"
set sv_connectTimeout "30"
set sv_timeout "120"

sv_reconnectLimit 限制同一名玩家可以连续重连多少次。sv_floodProtect 限制服务器为每名玩家处理多少客户端命令,从而防止单个客户端用命令拖慢服务器。sv_connectTimeout 和 sv_timeout 决定一个半成品连接或者一个沉默的连接能占住一个槽位多久:把老模板里那些宽松的值留着不动的人,等于让攻击者更容易耗尽槽位。

在 CoD4X 上还多一个 sv_authorizemode。值为 1 时只让持有有效游戏拷贝的玩家进来,值为 0 时只让没有的进来,值为 -1 时两者都放进来。设为 1 的人会把很大一部分一次性客户端挡在门外,但也会失去一些没有正版拷贝的真实玩家。最强硬的手段是用 g_password 设一个服务器密码,它对所有走正规加入途径的东西都有效。而有一点必须清楚:密码保护的是您的游戏逻辑,不是您的线路。灌包攻击您服务器的人根本不想加入。他的数据包会被拒绝,但已经到了,而这才是关键。

7. 服务器列表里的条目和您自己的地址

这里值得诚实,而不是抱幻想:您的 IP 地址无法保密。每一个曾经连过的玩家都知道它,而列表条目本来就连端口一起把它公布出去。您可以通过在 server.cfg 里不设置主服务器来关掉这个条目(相关 Dvar 叫 sv_master1、sv_master2 等等)。不过这会让您对新玩家完全失去可见性,而且只对最省事的那类攻击者有用。

关于这些列表现状的一点说明:Activision 原来的主服务器(20510 上的 codmaster.activision.com、20710 上的 cod2master.activision.com、20810 上的 cod4master.activision.com)对这些老作品已经不再回应任何东西。今天想被列出来的人用的是社区列表:CoD4X 自己运营一个,为此要求在 sv_authtoken 里填一个 token;Plutonium 自带一个服务器列表。这件事本身没有变化,地址在那里同样是明文。

尽管如此,有两个习惯是有用的。不要自己在任何地方公布裸 IP 地址,也就是不要发在 Discord 频道里,也不要写在战队页面上。并且让您的玩家通过一个主机名连接,这样万一出事时您可以更换地址,而不必让所有引用失效。这里的经典错误是一条指向旧地址、被遗忘的 A 记录:它会让任何更换都失去意义。

8. 把 Web 界面、数据库和 Fast Download 从开放网络上撤下来

除了游戏之外,大多数 Call of Duty 服务器上还跑着更多东西:IW4MAdmin 及其 1624 端口上的 Web 界面、用于地图 Fast Download 的 Web 服务器,有时还有一个用于统计的数据库。这些服务每一个都是独立的攻击面,而且没有一个应该无限制地放在开放网络里。

请把 1624 限制到您自己的地址,或者通过 SSH 转发访问这个界面,之后在本地打开 http://127.0.0.1:1624:

ssh -N -L 1624:127.0.0.1:1624 root@YOUR.SERVER.IP.ADDRESS

数据库请绑定到 127.0.0.1,它在开放网络里无论如何都没有存在的理由。并且请把 Fast Download 放到一个独立的 Web 服务器上,而不要放进游戏进程:一台承压的 Web 服务器否则会抢走游戏用于模拟的那部分计算时间。

9. 记录日志,让您在关键时刻有数据

最重要的一步是几乎没人事先做的那一步:在一切正常的时候先建立基线。没有正常值,事后您就说不清每秒 4 万个数据包是很多,还是就是个普通的周五晚上。用 apt-get install -y vnstat sysstat 让测量常驻运行。事件发生时四条命令就够了:

sar -n DEV 1 10
ip -s link show eth0
dmesg -T | tail -50
tcpdump -ni eth0 udp port 28960 -c 200 -q

对 Call of Duty 来说还有第五条,它回答的是决定性的问题。这条抓包只显示无连接数据包,也就是恰好 getstatus、getinfo、getchallenge、connect 和 rcon:

tcpdump -ni eth0 'udp port 28960 and udp[8:4] = 0xffffffff' -c 200 -A

如果那里成百上千次出现来自不断变化地址的 getstatus,您遇到的是查询洪水攻击。如果那里出现 rcon,有人正在试您的密码。如果那里只有 getchallenge 和 connect,那是连接洪水攻击。用 tcpdump 时有一条铁律:一定要用 -c 限制数量,满载状态下抓包会让本来已经过载的服务器更吃力。如何解读这些数值,见 识别 DDoS 攻击。

这些措施到哪里为止

现在说没有任何配置文件能解决的那一部分。前面所有措施都跑在您的服务器上,也就是线路的末端。防火墙规则处理的是已经跑过网线的数据包。您可以把它丢弃,但没法让它没被发出来。

算一下就清楚了。一台满员的 32 槽位服务器出站产生约 6.4 Mbit/s,不到一条千兆线路的百分之一。而同一条线路只要有人每秒发来 125 兆字节就满了,那些每月十欧元就能订到的攻击,瞄的正是这个。到那时,您后面的 iptables 规则写得好不好已经无关紧要,因为您玩家的数据包在更早的地方就已经过不来了。

第二个量是数据包速率,而在 Call of Duty 上它经常比带宽先出事。在 64 字节的小包情况下,1 Gbit/s 的线路里能装进每秒约 149 万个数据包。普通的服务器内核视 CPU 和网卡而定,处理其中几十万个之后就会开始丢弃。而一个 getstatus 请求只有 41 字节,比这还小:一次连您线路三分之一都填不满的攻击,仍然能让您的服务器瘫掉,因为全部计算时间都花在丢弃上。运营者的体验是“负载根本不高,可是什么都没了”。

在 Call of Duty 上还多一个特殊之处,让这笔账更难看。因为游戏、查询和 RCON 位于同一个端口,您没法在紧急时把 28960 关掉:那等于把服务器关机。而且因为引擎对每一次状态查询的回应都是请求大小的好几倍,攻击者要达到同样的效果,需要的自有带宽比在别的游戏上更少。

为了有个参照,说明真实出现过的数量级:在 KernelHost 的服务器上,过滤过的攻击包括一次针对语音服务器、超过 473.4 Gbit/s、每秒超过 4150 万个数据包的攻击,以及一次针对游戏服务器、超过 112.2 Gbit/s 的 UDP 洪水攻击。对此没有任何本地设置可用。流量型攻击必须在服务器前面的网络里就被终结。

KernelHost 用什么来应对

每台服务器都标配的持续防护

KernelHost 的 DDoS 防护分两级,持续生效,您不需要开启、订购或配置任何东西:

  • 第 1 级:全球清洗网络中 17 Tbps 的清洗能力。流量型攻击在靠近来源的地方就被清洗掉,不会到达数据中心。
  • 第 2 级:法兰克福的 Arbor 实时过滤,容量 3.2 Tbps。就在服务器前面,逐个数据包地识别并丢弃与协议相关的攻击特征。

有两点是关键。防护持续运行,不需要先对攻击做出反应,所以开头不会有服务器失联的那几分钟。而且不使用黑洞路由:您的 IP 地址留在网络里,被丢弃的只有恶意数据包。把 IP 地址从网络里撤下来的做法,对您而言和攻击者达到的结果一样。哪些游戏和协议在覆盖范围内,见 实时游戏服务器 DDoS 防护。

针对长期被攻击项目的 Advanced DDoS Protection

有些战队和社区不是偶尔被打,而是被有针对性地连打几周。为此有 Advanced DDoS Protection,每月 50.00 欧元起,PrePaid 预付费,没有最低合约期。区别不在于容量更大,而在于控制权:

  • 专用防护 IP,来自法兰克福的核心网络,您的服务器会在我们自己的网络内切换到它。您这边不需要做任何改造。
  • 按端口和协议自行管理的防护规则,就在客户中心里:您可以设置 28960 UDP 上允许什么,不必为此开工单;运行多个实例时还能按端口分别设置。
  • 改动实时生效,因此您可以在攻击进行时随时调整。
  • 与具体游戏匹配的防护策略,同样适用于任意 TCP 或 UDP 端口上经过修改的程序和自研程序。对 Plutonium 和 CoD4X 来说这一点很关键,因为它们的端口可能和默认值不同。

Advanced DDoS Protection 面向放在 KernelHost 的服务器。如果您的 Call of Duty 服务器目前跑在别处,而且在那里经常被从网络里撤下来,那么搬到 KernelHost 才是真正能改变现状的做法。

两级防护对比

对比项 标配的 DDoS 持续防护 Advanced DDoS Protection
价格 包含在每个服务器套餐中,不额外收费 每月 50.00 欧元起,PrePaid 预付费
过滤能力 17 Tbps 全球清洗,加上法兰克福 3.2 Tbps 的 Arbor 实时过滤 同样的两级过滤
IP 地址 您服务器本身的 IP 地址 额外的专用防护 IP
规则集 自动防护策略,无需配置 在客户中心里按端口和协议设置自己的规则
变更 自动跟进 实时生效,攻击进行时也可以
游戏策略 针对常见游戏的优化策略 与游戏匹配的策略,也适用于 Plutonium、CoD4X 和自定义端口
黑洞路由 否 否
合约期 与服务器套餐绑定 PrePaid 预付费,没有最低合约期,没有退订通知期,也没有开通费

对大多数 Call of Duty 服务器来说,标配的持续防护配上一份干净的 server.cfg 就够了。Advanced DDoS Protection 针对的是有人把这件事当成私人恩怨的情况。

常见错误及解决办法

“我换了 IP 地址,两小时后又离线了”:攻击者从和旧地址同一个来源拿到了新地址,多数是列表条目、一个带状态显示的 Discord 机器人,或者一条旧的 DNS 记录。换地址是争取时间,不是解决办法。

“我的主机商给我发了滥用举报,可我才是受害者”:那说明您的服务器不是目标,而是放大器。有人在发伪造的 getstatus 请求,而您的服务器老老实实地回应给一个陌生的受害者。请先检查 sv_queryIgnoreMegs 是否为 0,然后把那四个查询 Dvar 以及第 4 节里的防火墙规则都设上。

“服务器在列表里显示满员,实际却是空的”:这是连接洪水攻击,它打的是游戏逻辑,不是线路。对此有效的是 sv_reconnectLimit、把 sv_connectTimeout 和 sv_timeout 设得短一些,必要时再加一个服务器密码。

“服务器在攻击期间从服务器列表里消失了”:这是结果,不是原因。服务器列表通过同样的状态查询来判断您的服务器是否还活着。回应过不来,或者被您自己的刹车丢弃了,服务器就被视为离线。在怀疑防火墙之前,请先检查 sv_queryIgnoreTime 是不是设得太高。

“我的 iptables 规则不起作用”:常见原因有三个。规则排在 UFW 的链后面,永远轮不到它;规则在上次重启后就没了(这时用 netfilter-persistent save,或者写进 /etc/ufw/before.rules);或者攻击是流量型的,而规则在一条已经满了的线路上正常工作。请用 iptables -L INPUT -n -v 检查命中计数器是否在增长。

“服务器在跑,但所有玩家都有延迟尖峰”:请先看接口的数据包速率,而不是 CPU 负载。如果 sar -n DEV 1 10 没什么异常却依然卡顿,原因多半在某个 Mod、一个过大的 sv_maxRate,或者干脆是局里的机器人太多。

“我原来的主机商把我的 IP 地址封了”:那就是黑洞路由。主机商用它保护自己的网络,对您来说结果和一次成功的攻击完全一样,而且通常在攻击结束后还要持续几个小时。有疑问时请直接问清楚:是过滤还是黑洞路由。这个答案对您可用性的影响,比任何硬件参数都大。

“我在 tcpdump 里看不到任何异常”:如果流量已经在前面的网络里被过滤掉了,服务器上当然就什么都收不到。这在过滤正常工作时是常态。反过来说:线路一旦被打满,您甚至可能连用来测量的那条 SSH 会话都进不来。这时请使用客户中心里的 VNC 控制台,它独立于虚拟机自身的网络运行。

要点总结

  • 一台经典的 Call of Duty 服务器只需要一个开放端口:28960 UDP。Plutonium T6 上是 4976 UDP,Plutonium IW5 上是 27016 UDP。
  • 在 Call of Duty 上,游戏、状态查询和 RCON 位于同一个端口。您没法用端口规则把 RCON 和游戏分开,为此需要一条查看数据包内容的规则。
  • getstatus 反射攻击是这类游戏特有的放大向量:请求 41 字节,按 CISA 公告 TA14-017A,Quake 网络协议的系数为 63.9,也就是约 2600 字节的回应。
  • 请打开查询刹车:sv_queryIgnoreMegs 4、sv_queryIgnoreTime 2000、sv_queryBounceIgnoreTime 12000。很多服务器上它是 0,也就是关着的。
  • 只有在真正需要 RCON 时才设置 rcon_password:密码以未加密方式走 UDP,而且在没有账号封锁的情况下可以被无限次猜解。
  • 主服务器端口 20810 和 20800 是出站的目标端口,不属于您的入站放行范围。
  • 从大约 1 Gbit/s 或每秒几十万个数据包起,起决定作用的只有服务器前面的网络,而不再是您的配置。

如果您的服务器已经放在 KernelHost,过滤就已经在工作,您什么都不用做。若仍然发现异常,请开一个 支持工单,以便为您的 IP 地址调整过滤规则。攻击正在进行时,您还可以通过 WhatsApp 紧急聊天联系我们:+43 650 8209883。

常见问题

一台 Call of Duty 服务器需要哪些端口?
一台经典的 Call of Duty 服务器只需要一个开放端口:28960 UDP。游戏流量、状态查询和远程控制 RCON 共用这一个端口,既没有单独的查询端口,也没有单独的 RCON 端口。在 Plutonium 平台上默认值有所不同:World at War 和 Black Ops 同样使用 28960 UDP,Black Ops II 使用 4976 UDP,Modern Warfare 3 使用 27016 UDP。主服务器端口 20810 和 20800 是出站的目标端口,入站不需要开放。
本文也适用于 Warzone、Modern Warfare 或 Black Ops 6 吗?
不适用。Warzone、Modern Warfare(2019)、Black Ops Cold War、Vanguard、Modern Warfare II、Modern Warfare III 和 Black Ops 6 都没有可租用的独立服务器。对局跑在 Activision 的匹配基础设施上,既没有 server.cfg,也没有服务器浏览器,更没有一个您能放行或加固的端口。只有经典作品才能有自己的服务器,从而有自己的 DDoS 防护:Call of Duty、United Offensive、Call of Duty 2、Call of Duty 4 和 World at War,以及社区平台 Plutonium、IW4x 和 CoD4X。
Call of Duty 上的 getstatus 反射攻击是什么?
getstatus 反射攻击是一种放大攻击:用伪造的源地址把小小的状态查询发给许多游戏服务器,让这些服务器的大回应落到真正的受害者身上。一次 getstatus 请求的大小是 41 字节,而回应包含整份服务器配置,再加上每名已连接玩家一行。CISA 在公告 TA14-017A 中把 Quake 网络协议列为放大系数 63.9,相当于每个请求约 2600 字节的回应。受影响的是 id Tech 3 引擎,所有经典 Call of Duty 作品都基于它。
我的服务器被当作放大器去攻击第三方,该怎么办?
请先打开内置的查询刹车。在 server.cfg 里把 sv_queryIgnoreMegs 设为 4,把 sv_queryIgnoreTime 设为 2000,把 sv_queryBounceIgnoreTime 设为 12000。如果 sv_queryIgnoreMegs 为 0,这个刹车就完全关着,而很多服务器上正是这种情况。再补上一条防火墙规则,把每个源地址两秒内的 getstatus 请求限制到几个之内。用 sv_queryIgnoreDebug 1 可以在日志里看到刹车是否起作用,之后再把值设回 0。
为什么 rcon_password 在 Call of Duty 上有风险?
因为在 Call of Duty 上,RCON 是游戏端口上一个未加密的 UDP 包。命令由四个 0xFF 字节、rcon 这个词、明文密码和真正的指令组成。没有加密,没有会话,没有用户账号,失败之后也没有封锁:能在途中任何一处看到这些流量的人会顺带读到密码,看不到的人则可以无限次猜解。只有在真正需要 RCON 时才设置 rcon_password,否则就留空,改用 SSH 管理。
我的 Call of Duty 服务器刚刚离线了。怎么判断是不是 DDoS 攻击?
请看接口的数据包速率,而不是 CPU 负载。用 sar -n DEV 1 10 可以看到每秒的数据包数和字节数,用 ip -s link show eth0 可以看到丢包计数器。如果入站数据包远远超过正常值,而服务器本身几乎没在干活,那就是一次攻击。是哪一种,可以用 tcpdump 加上过滤条件 udp port 28960 and udp[8:4] = 0xffffffff 抓取无连接数据包来判断。如果那里大量出现 getstatus,那就是查询洪水攻击。
我能用 iptables 或 UFW 抵御 DDoS 攻击吗?
对付小型攻击和不讲究的机器人可以,对付流量型攻击不行。服务器上的防火墙规则处理的是已经跑过您线路的数据包。线路一旦被打满,您玩家的数据包在更早的地方就已经过不来了,跟您的规则集写得多好完全无关。在 Call of Duty 上还要加一点:您没法在紧急时把 28960 端口关掉,因为游戏也在那上面。流量型攻击必须在服务器前面的网络里就被终结。
在 KernelHost,我的服务器会在攻击期间离线吗?
不会。我们不使用黑洞路由。您的 IP 地址留在网络里,被丢弃的只有恶意数据包。防护分两级:全球清洗网络中 17 Tbps 的清洗能力,以及法兰克福 3.2 Tbps 的 Arbor 实时过滤。它持续运行,不需要先对攻击做出反应,因此开头不会有服务器从服务器列表里掉出去的那几分钟。
DDoS 防护要额外付费吗?什么时候需要 Advanced DDoS Protection?
两级持续防护包含在每个服务器套餐中,不额外收费,自服务器开通起即生效,您既不用订购也不用开启。当您的服务器不是偶尔被打,而是被有针对性地连打几周,并且您想自己掌控过滤时,就需要 Advanced DDoS Protection。您会获得一个专用防护 IP,并在客户中心里自行按端口和协议管理防护规则,改动实时生效。价格每月 50.00 欧元起,PrePaid 预付费,没有最低合约期,也没有开通费。

Call of Duty Call of Duty DDoS 防护 游戏服务器防护 28960 端口 Plutonium CoD4X getstatus 反射攻击 RCON Advanced DDoS Protection