保护 Minecraft Bedrock 服务器免受 DDoS 攻击

发布于 阅读时间 37 分钟

一台 Minecraft Bedrock 服务器真正需要哪些端口,基于 UDP 又没有握手保护的 RakNet 为什么格外脆弱,如何加固 Query、RCON 和数据包速率,以及攻击到多大规模就只能靠服务器前面的网络过滤。

一台 Minecraft Bedrock 服务器如果每到晚上就从服务器列表里消失几分钟、随后又自己回来,问题很少出在硬件上。多数情况下是有人正在攻击,而且时间恰好选在玩家最多的时候。本文讲的是如何保护 Minecraft Bedrock 服务器免受 DDoS 攻击:先讲您不花额外费用就能自己加固的部分,接着讲这些措施在物理上到哪里为止,最后讲服务器前面的网络里必须发生什么。

本文所有内容针对运行在 Debian 12、Debian 13、Ubuntu 22.04 LTS 或 Ubuntu 24.04 LTS 上的 Bedrock Dedicated Server、PocketMine-MP 或 Nukkit。命令以 root 身份书写,普通用户请在前面加上 sudo。运行 Java Edition 的运营者,可以在 Minecraft DDoS 防护与 Nullping 防护 中找到那一侧典型的协议攻击。Bedrock 服务器本身的安装过程见 用 Nukkit 安装 Minecraft Bedrock 服务器。

如果攻击正在进行:现在不要改动任何配置,也不要重启服务器。请先保存测量数据(“在出事之前先收集测量数据”一节),攻击结束后这些数据就再也找不回来了。

Minecraft Bedrock 服务器为什么经常成为 DDoS 攻击的目标

Bedrock Edition 是运行在主机、智能手机、平板和 Windows 上的那个版本,它拥有 Minecraft 所有版本中最大的玩家群体。服务器多的地方,攻击的动机也最强:互相竞争的服务器网络、被封禁的玩家、内部矛盾。而发起一次攻击,对下手的人来说既不需要什么本事,也花不了多少钱,服务器 booter 是按订阅卖的。

技术上的原因更深一层。Bedrock 服务器说的是 UDP,不是 TCP,而且它会回答任何来询问的人,远在任何登录发生之前。正是这两个特性让 19132 UDP 端口成了一个称手的目标。DDoS 攻击本质上是什么,请看文章 什么是 DDoS 攻击?。

RakNet:一个在任何人登录之前就已经开始回应的 UDP 协议

RakNet 是 Minecraft Bedrock Edition 用来承载全部游戏流量的 UDP 网络库。UDP 没有服务器可以强制要求的连接建立过程,因此源地址可以伪造。RakNet 在它之上自建了一层可靠性机制:序列号、确认(ACK)和否定确认(NAK),客户端可以用它们重新索要丢失的数据包。

连接建立过程由七个数据包组成,四个来自客户端,三个来自服务器:

Client  -> Server   Open Connection Request 1
Server  -> Client   Open Connection Reply 1
Client  -> Server   Open Connection Request 2
Server  -> Client   Open Connection Reply 2
Client  -> Server   Connection Request
Server  -> Client   Connection Request Accepted
Client  -> Server   New Incoming Connection

只有在这之后,客户端才会发出带着 Xbox Live 凭据的登录数据包。对每一个想加固自己 Bedrock 服务器的人来说,下面这句话是决定性的:服务器已经处理了七个数据包,花掉了计算时间和内存,并且多次回应过,然后才知道敲门的是谁。因此任何从登录环节入手的措施,都只能在负载已经产生之后才起作用。

此外还有第二个、更早的入口。为了让服务器带着名称、版本和玩家数出现在玩家的服务器列表里,它会用 Unconnected Pong(数据包 ID 0x1C)回答 Unconnected Ping(数据包 ID 0x01,即未连接状态查询)。这次交换发生在真正的连接建立之前,不要求任何凭据,而且在 Bedrock Dedicated Server 上无法关闭,除非让服务器从所有服务器列表里消失。

Unconnected Ping 作为放大向量:具体数字

放大攻击指的是攻击者用伪造的源地址向别人的服务器发送小请求,让这些服务器更大的回应落到受害者身上。在这个过程里,Bedrock 服务器不是被攻击,而是被利用。在 Unconnected Ping 上,这笔账是这样算的:

指标 数值
Unconnected Ping(0x01) 33 字节负载:1 字节数据包 ID、8 字节时间戳、16 字节 Magic、8 字节客户端标识
Unconnected Pong(0x1C) 35 字节基础结构,加上作为字符串的服务器标识
标准配置下的服务器标识 约 96 字节,因此回应约为 131 字节
负载层面的放大系数 约 4
服务器标识的上限 长度字段是一个 16 位值,技术上可达 65535 字节
回应的内容 Edition 版本类型、服务器名称、协议版本、版本名称、当前和最大玩家数、服务器标识、世界名称、游戏模式、两个端口
2024 年的 RakNet 放大缺陷 52 字节的请求触发了 8000 多个各 134 字节的回应数据包
该缺陷的系数 理论上最高可达 2.2 万,实际环境中测得约 1000

由此直接得出两点。第一,服务器名称越长,回应就越大,您提供给外部攻击者的放大系数也就越大。短名称不是装饰,而是一项防护措施。第二,标准配置下的系数 4 足够小,使您的服务器作为反射器没什么吸引力,但也足够大,使一场 Ping 洪水攻击会让您自己的出方向线路承受四倍于进来的流量。

2024 年的放大缺陷说明,一旦可靠性机制本身被滥用,事情能坏到什么程度。在当时使用的 RakNet 库中,Connection Request Accepted 数据包被标记为可靠。攻击者可以用伪造的源地址把连接建立过程走到这一步,随后只需发出一条覆盖 0 到 8191 区间的否定确认。服务器于是向那个伪造的地址发出成千上万个数据包,而攻击者不必再做任何事。修复的办法是:把这个数据包改为不可靠,在 Open Connection Reply 1 中附带一个 cookie 让真正的客户端回传,并且引入数据包上限,即每个源地址在 10 毫秒的周期里 120 个数据包,每个周期总共 1000 个数据包。

Bedrock Edition 还是 Java Edition:DDoS 防护上有什么不同

加固过 Java 服务器的人,几乎会把所有经验都用错。这两个版本共用一个名字,但网络协议并不相同:

特性 Bedrock Edition Java Edition
传输方式 基于 RakNet 的 UDP TCP
默认端口 IPv4 用 19132 UDP,IPv6 用 19133 UDP 25565 TCP
连接建立 在应用里完成的七个 RakNet 数据包,没有密码学校验 操作系统内核中的三次握手
源地址可否伪造 可以,UDP 不要求建立连接 不可以,三次握手阻止了这一点
内核中的对策 没有,UDP 不存在 SYN Cookie SYN Cookie,net.ipv4.tcp_syncookies
身份验证 Xbox Live,在 RakNet 建立完成之后才在登录数据包里进行 Microsoft 账号,在 TCP 建立之后才进行
DNS 中的 SRV 记录 不支持,玩家需要分别输入地址和端口 支持
服务器列表 条目保存在每个玩家的客户端里,没有公开的主服务器 各种公开的列表服务

SYN Cookie 那一行最重要。在 Java Edition 上,Linux 内核会挡住 SYN 洪水攻击,而 Minecraft 进程对此毫无感觉。在 Bedrock Edition 上没有这个帮手:每一个 UDP 数据包都会被一路送进服务器进程,并在那里被解析。Bedrock 服务器面对 19132 端口上的洪水攻击,在操作系统里没有任何内置防护,因为 UDP 本身就没有这种机制。

缺少 SRV 记录那一行有一个实际后果,很多人会感到意外:在 Bedrock Edition 上,您没法把端口藏在一条 DNS 记录后面。玩家要手工填写地址和端口。谁改了端口,就得把新端口通知每一个玩家。

真正相关的那些端口

Bedrock Dedicated Server 正好绑定两个端口,而且两个都走 UDP。在 server.properties 中:

server-port=19132
server-portv6=19133
enable-lan-visibility=true
online-mode=true
allow-list=false
max-players=10
player-idle-timeout=30
max-threads=8

这些是 Microsoft 的默认值,可以在 Bedrock Dedicated Server 的参考文档里查到。围绕这两个端口,还有一些随服务器软件一起运行的服务:

端口 协议 用途 是否应对公网开放
19132 UDP 基于 RakNet 的 Bedrock 游戏流量,IPv4(server-port) 是,这是唯一必须开放的端口
19133 UDP 基于 RakNet 的 Bedrock 游戏流量,IPv6(server-portv6) 仅当您要服务 IPv6 玩家时
19132 UDP PocketMine-MP 和 Nukkit 的 GS4 查询,与游戏同一个端口(enable-query,默认开启) 否,关掉
19132 TCP Nukkit 的 RCON:rcon.port 没有单独取值时会回落到 server-port(enable-rcon,默认关闭) 否,绝对不要
19144 TCP Bedrock Dedicated Server 的脚本调试器(force-inbound-debug-port) 否
25565 TCP Geyser 后面的 Java Edition 服务器(remote.port) 否,绑定到 127.0.0.1
22 TCP SSH 访问 限制到固定地址

第三行和第四行是 Bedrock 服务器上最常见、也最容易避免的错误。在 Nukkit 和 PocketMine-MP 上,enable-query 出厂就是开启的;在 Nukkit 上,一个无意中打开的 RCON 会落在 19132 TCP 上,也就是和游戏相同的端口号。只盯着“19132 是开着的,没问题”看的人,会漏掉这一点。

官方 Bedrock Dedicated Server 的一个特点也属于这里:它没有 server-ip 这条指令。PocketMine-MP 和 Nukkit 有(server-ip,PocketMine 还额外有 server-ipv6),官方服务器没有。因此它总是在系统的所有地址上监听,而防火墙是您唯一能够限制它的手段。

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

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

1. 清点:到底有什么在 19132 上监听?

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

ss -lntup
ss -lnup sport = :19132

要看的是本地地址那一列。0.0.0.0:19132 和 [::]:19133 表示“整个互联网都能访问”。如果旁边还出现了同一个端口号的 TCP 条目,说明 RCON 正在运行。从外面做一次端口扫描就能看到攻击者眼中的样子,UDP 要加 -sU:

nmap -Pn -sU -p 19132,19133 YOUR.SERVER.IP.ADDRESS
nmap -Pn -p- --min-rate 1000 YOUR.SERVER.IP.ADDRESS

2. 只开放 19132 UDP,其余全部关闭

一台 Bedrock 服务器对外只需要一条放行规则,用上 IPv6 就是两条。用 UFW 的写法如下,而且顺序必须完全照此执行,以免把自己关在门外:

ufw allow 22/tcp comment 'SSH'
ufw allow 19132/udp comment 'Bedrock IPv4'
ufw allow 19133/udp comment 'Bedrock IPv6'
ufw default deny incoming
ufw default allow outgoing
ufw --force enable
ufw status verbose

如果您没有 IPv6 玩家,就去掉 19133 那一行,并在 PocketMine-MP 上额外设置 enable-ipv6=false。每一个您没有放行的端口,都是一个您不必防守的端口。包含自救办法的完整说明见 设置 UFW 防火墙而不把自己关在门外。

3. 关掉局域网可见性,否则 19132 一直是开着的

这是几乎每个想改端口的人都会踩的坑。指令 enable-lan-visibility 出厂就是 true,它让服务器回应本地网络里的搜索请求。Microsoft 为此明确写道,服务器因此会额外绑定到默认端口 19132 和 19133 上,即使 server-port 和 server-portv6 设的是别的值。

所以,把端口改到 19140 并因此感到安全的人,实际上仍然在 19132 上监听。对于放在互联网上的服务器,server.properties 里应该写上:

enable-lan-visibility=false

之后用 ss -lnup 复查 19132 是否真的消失了。顺带一提,同一个设置还能解决两台 Bedrock 服务器在同一主机上互相抢占端口的问题。

4. 关掉 Query 和 RCON

PocketMine-MP 和 Nukkit 自带 GS4 查询,这是一种按 UT3 协议样式设计的 UDP 服务器查询,而它们回答这些查询用的是与游戏相同的 19132 端口。详细回应里包含服务器名称、版本、世界名称、白名单状态、地址和端口、玩家数、所有已连接玩家的名字,在 PocketMine-MP 上还可以附带完整的插件列表。这对状态页面和 Discord 机器人很方便,但也正好告诉攻击者什么时候值得动手,而且每次查询都要消耗计算时间。

enable-query=off
enable-rcon=off

在 PocketMine-MP 上,取值是 false 而不是 off,插件列表则在 pocketmine.yml 里用 settings.query-plugins: false 关掉。有一点很少有人写到:PocketMine-MP 的 GS4 查询会校验一个用源地址加盐的令牌,因此那个很大的回应无法被反射到伪造的地址上。但查询依然要消耗计算时间,而公开出去的数据会帮攻击者挑选目标。官方 Bedrock Dedicated Server 既没有 Query 也没有 RCON,这一条对它不适用。

如果您确实需要 RCON,在 Nukkit 上务必把 rcon.port 设成一个单独的值,并且只对您自己的地址放行。否则回落到 server-port 就意味着,您服务器的远程控制正监听在 19132 TCP 上,也就是您到处都标注为“开放”的那个数字。

5. 强制启用 Xbox Live 身份验证

Xbox Live 身份验证检查的是,一个要加入的玩家是否持有真实的、由 Microsoft 签名的账号。三种服务器软件出厂都是开启的,而且应当保持开启。

在 Bedrock Dedicated Server 上,这条指令叫 online-mode;在 PocketMine-MP 和 Nukkit 上叫 xbox-auth。两种情况下 true 都是出厂状态,也是正确的取值:

online-mode=true
xbox-auth=true

Microsoft 为此写明了一条重要限制:与本地网络之外的服务器建立连接的客户端,无论这个设置如何,始终都需要 Xbox Live 身份验证。凭据以签名令牌链的形式在登录数据包里传输,一同传输的还有 Xbox 标识(XUID)和显示名称。

接下来这部分有助于避免误解:Xbox Live 身份验证保护的是您的游戏逻辑,不是您的线路。它发生在登录数据包里,也就是在完整的 RakNet 连接建立之后。向您服务器灌包的攻击者根本不想进服。他的数据包会被拒绝,但已经到了,这才是关键。

6. Allowlist 和玩家上限,以及它们做不到的事

Allowlist(以前叫 Whitelist,白名单)是允许加入的玩家名单。在 Bedrock Dedicated Server 上用 allow-list=true 开启,条目写在 allowlist.json 里,包含名称、XUID 和字段 ignoresPlayerLimit。在 Nukkit 和 PocketMine-MP 上,这条指令仍然叫 white-list。

allow-list=true
max-players=60
player-idle-timeout=15

用 player-idle-timeout 设一个较短的空闲时间,对付槽位耗尽是有效的:只占着位置的玩家会在指定的分钟数之后被踢出去。取值 0 意味着没有人会因为不活动而被断开,而这正是那种用真实账号堵住您槽位的攻击者要利用的。

这里同样适用上一节的界限,而且这是最常被忽视的一点:Allowlist 只有在登录数据包被处理之后才会被检查。它阻止的是加入,不是数据包。

7. 按源地址限制数据包速率

对付小型攻击和不讲究的机器人,按源地址设上限就有效。UDP 要用 hashlimit,不是 connlimit,因为 UDP 没有连接:

iptables -I INPUT -p udp --dport 19132 -m hashlimit --hashlimit-name bedrock_udp --hashlimit-mode srcip --hashlimit-above 400/sec --hashlimit-burst 600 -j DROP

只要同一个源地址持续每秒发出超过 400 个数据包,这条规则就会丢弃它的 UDP 数据包。这个值是起始值,不是真理:一台有 60 名玩家、视距又大的满员服务器产生的数据包,比一台空服务器多得多,设得太严会把自己的玩家踢出去。请先在正常运行状态下测一周。

对 Unconnected Ping 您可以设得明显更严,因为真正的客户端只在服务器列表打开着的时候查询服务器状态,而且是每秒一次的节奏。用 nftables 可以正好命中这一个数据包,因为数据包 ID 就是 UDP 头后面的第一个字节:

nft add table inet bedrock
nft add chain inet bedrock prerouting '{ type filter hook prerouting priority -150 ; policy accept ; }'
nft add rule inet bedrock prerouting udp dport 19132 @th,64,8 0x01 limit rate over 500/second drop

表达式 @th,64,8 从传输头的第 64 位起读取八位,也就是 UDP 负载的第一个字节。值 0x01 是 Unconnected Ping 的数据包 ID。在丢弃任何东西之前,同一个位置也可以用来观察:

tcpdump -ni eth0 'udp dst port 19132 and udp[8] = 0x01' -c 200 -q
tcpdump -ni eth0 'udp src port 19132 and udp[8] = 0x1c' -c 200 -q

第一行统计进来的状态查询,第二行统计您自己的回应。如果几乎没人在玩,两者却都以每秒上千的数量出现,那您看到的是 Ping 洪水攻击,而不是您的玩家。

关于持久化有两点提示。纯 iptables 规则在重启后就没了,在 Debian 和 Ubuntu 下这样保存:

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

在 UFW 下,这类规则应写进 /etc/ufw/before.rules,否则下一次 ufw reload 时就会消失。

8. 给内核的连接跟踪减压

有一个瓶颈在 UDP 游戏上比在 TCP 上出现得早得多:内核会为每一对 UDP 数据包在连接跟踪里建立一个条目。在一场使用伪造源地址的洪水攻击中,每个数据包都是一个新的源地址,也就是一个新的条目。表一满,服务器连正常的数据包也会丢弃,日志里会出现“nf_conntrack: table full, dropping packet”。

sysctl net.netfilter.nf_conntrack_count net.netfilter.nf_conntrack_max

如果计数持续接近上限,您可以把游戏流量从跟踪中排除。这样做有效,但并非没有后果,因此要双向设置,并在之后做一次连接测试:

iptables -t raw -I PREROUTING -p udp --dport 19132 -j NOTRACK
iptables -t raw -I OUTPUT -p udp --sport 19132 -j NOTRACK

之后基于状态的规则对这部分流量就不再生效了。所以您给 19132 UDP 的放行必须是真正的端口放行,不能依赖 ESTABLISHED 状态。设置完成后请用 conntrack -L | grep 19132 确认不再产生条目,并在永久保存规则之前用游戏连接一次。

9. 干净地运行 Geyser 和 Floodgate

Geyser 是一座桥,它让 Bedrock 客户端能在 Java Edition 服务器上游玩:它在 19132 UDP 上接受 Bedrock 连接,翻译协议,并在另一侧通过 25565 TCP 与 Java 服务器通信。Floodgate 是配套的补充,让这些 Bedrock 玩家无需 Java 账号即可加入。对 DDoS 防护来说,这意味着三件事。

第一:请让 Geyser 保持最新。正是这座桥两次成为已记录攻击的原因。2024 年 3 月,上面描述的 RakNet 库放大缺陷被大规模利用,自 Build 478 起修复。2025 年 7 月出现了第二起:一个被重复发送的资源包确认数据包,会为每名玩家生成多个会话,而且已断开的客户端还能继续发包,因为网络通道没有被关闭。自 Build 897 起修复。这两起案例都由项目自己带时间线公开过。

第二:Java 服务器不该放在公网上。在 Geyser 配置里,remote.address 指向 auto 或者 127.0.0.1,remote.port 指向 25565。请相应地把 Java 服务器绑定在本机,并且不要对外放行 25565 TCP。否则您就有了两个攻击面而不是一个,而第二个恰恰是您从来没有为它想过规则的那个。

第三:文件 key.pem 是机密。它是 Floodgate 用来为 Bedrock 账号跳过 Java 身份验证的密钥。谁把它放进公开仓库、复制到支持工单里或者在截图上露出来,就等于把自己服务器的登录送了出去。项目对此有明确警告。

10. 在出事之前先收集测量数据

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

sar -n DEV 1 10
ip -s link show eth0
ss -lunp sport = :19132
nstat -az | grep -E 'UdpInDatagrams|UdpNoPorts|UdpInErrors|UdpRcvbufErrors'
dmesg -T | tail -50

其中三个数值在 Bedrock 服务器上特别有说明力。19132 的 UDP 套接字上 Recv-Q 持续不为零,意味着服务器进程已经来不及把到达的数据包取走。UdpRcvbufErrors 统计的正是因此被丢弃的数据包,也是“瓶颈不在线路而在进程”的最有力证据。UdpNoPorts 上升,说明有人在打根本没有东西监听的端口,这是真正攻击之前大范围端口扫描的典型画面。

用 tcpdump 时有一条铁律:一定要用 -c 限制数量,满载状态下抓包会让本来已经过载的服务器更吃力。如何解读这些数值,见 识别 DDoS 攻击。

这些措施到哪里为止:带宽和数据包速率

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

指标 数值
游戏服务器常见的接入带宽 1 Gbit/s,也就是每秒 125 兆字节
64 字节包在 1 Gbit/s 里能装下多少数据包 每秒约 149 万个
普通服务器内核能处理其中多少 每秒几十万个数据包
针对 Minecraft 项目的典型攻击 5 到 50 Gbit/s
针对某个 Minecraft 服务器网络、公开记录的最大攻击 2022 年第三季度 2.5 Tbit/s,来自一个 Mirai 僵尸网络,UDP 与 TCP 混合的洪水攻击
在 KernelHost 服务器上实时过滤过的 对一台语音服务器超过 473.4 Gbit/s,每秒超过 4150 万个数据包
同样过滤过的 对一台游戏服务器超过 112.2 Gbit/s 的 UDP 洪水攻击

算一下就清楚了。只要有人发出超过每秒 125 兆字节,您的线路就满了。一场 5 到 50 Gbit/s 的攻击是它的五到五十倍。这时您后面的 hashlimit 规则写得多好都不再重要,因为您玩家的数据包在更早的地方就已经过不来了。

第二个量是数据包速率,而在 Bedrock 服务器上几乎总是它先出事。全部游戏流量都由许多小 UDP 数据包组成,而攻击者恰恰在这门项目上花费最少。一场连您线路三分之一都填不满的攻击,仍然可能让您的服务器瘫痪,因为计算时间全花在解析和丢弃上。运营者的体验是“负载根本不高,可是所有人都掉了”。在游戏里,同一件事表现为延迟尖峰、橡皮筋效应,以及正在建造时的连接中断。

对此没有任何本地设置可用。流量型攻击必须在服务器前面的网络里就被终结。

KernelHost 用什么来应对针对 Bedrock 服务器的 DDoS 攻击

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

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

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

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

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

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

  • 专用防护 IP,来自法兰克福的核心网络,您的服务器会在我们自己的网络内切换到它。您这边不需要做任何改造。
  • 按端口和协议自行管理的防护规则,就在客户中心里:您可以设置 19132 UDP 上允许什么、19133 UDP 上允许什么,以及在您改过端口的情况下那个端口上允许什么。
  • 改动实时生效,因此您可以在攻击进行时随时调整,而不用等维护窗口。
  • 与具体游戏匹配的防护策略。Minecraft 有现成的策略,任意 TCP 或 UDP 端口上经过修改的程序和自研程序同样有,因此 Nukkit、PocketMine-MP 或运行在自选端口上的 Geyser 实例也都涵盖在内。

两级防护对比

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

对大多数 Bedrock 项目来说,标配的持续防护配上干净的服务器配置就够了。Advanced DDoS Protection 针对的是有人把这件事当成私人恩怨的情况。目前把服务器放在别处的人,最直接的解法是搬过来:过滤发生在服务器前面的网络里,而这张网必须属于我们自己。

常见错误及解决办法

“我把端口改成了 19140,19132 还是开着的”:这就是 enable-lan-visibility=true。Bedrock Dedicated Server 会额外绑定 19132 和 19133,不管 server-port 里写的是什么。把它设成 false,重启服务器,再用 ss -lnup 复查。

“我改了 allowlist.json,结果自己也进不去了”:常见原因有两个。目录里还留着一个旧的 whitelist.json,服务器读的是它;或者 XUID 条目缺失或写错了。在 Xbox Live 身份验证开启的情况下,仅凭名称并不可靠。

“我明明是被攻击的一方,主机商却把我的服务器停了”:请检查您的服务器自己是不是也在往外发包。2024 年的 RakNet 放大缺陷发生时正是如此:受影响的服务器向别人的地址发出成千上万个数据包,而滥用举报里写的源端口就是 19132。用 tcpdump -ni eth0 'udp src port 19132' -c 200 -q 可以看到您的服务器在往哪里回应。换成最新的 Build 就能消除根因。

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

“服务器在列表里,可是没人能进来”:如果条目显示了名称和玩家数,说明 Unconnected Pong 是通的,端口基本上可以访问。加入仍然失败的话,多半卡在 Xbox Live 登录或 Allowlist 上。反过来,如果只有 IPv6 玩家进不来,那是缺了 19133 UDP 的放行。

“服务器在跑,可所有人都有延迟尖峰”:这更常是某个插件的问题,而不是攻击。先看 UDP 套接字上的 Recv-Q 是否在增长,以及 UdpRcvbufErrors 是否在上升。如果两者都平静、sar -n DEV 1 10 也没有异常,那就不是 DDoS 攻击,而是服务器进程本身。在 Bedrock Dedicated Server 上,这时可以借助脚本看门狗,它们的阈值写在 server.properties 的 script-watchdog-hang-threshold 和 script-watchdog-slow-threshold 里。

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

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

要点总结

  • 一台 Minecraft Bedrock 服务器对外只需要一个开放端口:19132 UDP,只有 IPv6 玩家才额外需要 19133 UDP。Query、RCON、19144 TCP 上的脚本调试器,以及 Geyser 后面 25565 TCP 上的 Java 服务器,都不该放在公网上。
  • 改端口的人必须设置 enable-lan-visibility=false,否则 Bedrock Dedicated Server 会继续额外绑定 19132 和 19133。
  • Xbox Live 身份验证和 Allowlist 只在登录数据包里起作用,也就是在完整的 RakNet 连接建立之后。它们保护的是您的游戏逻辑和您的槽位,不是您的线路。
  • Unconnected Ping 的请求是 33 字节,回应约 131 字节,放大系数约为四。服务器名称短,这个系数就小。
  • 在 UDP 上要用 hashlimit 而不是 connlimit,而面对伪造的源地址时,内核的连接跟踪是最先被填满的。这两项您都应该在第一次被攻击之前就测过。
  • 大约到 1 Gbit/s,您的线路就满了,而在 64 字节包大小时那里只装得下每秒约 149 万个数据包。超过这个量,就只有服务器前面网络中的过滤能起作用。
  • 在 KernelHost,两级持续防护包含在每个服务器套餐中,自服务器开通起即生效,并且不使用黑洞路由。Advanced DDoS Protection 在此之上补充一个专用防护 IP,以及可按端口自行管理的规则。

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

常见问题

我的 Minecraft Bedrock 服务器刚刚离线了。怎么判断是不是 DDoS 攻击?
请看数据包速率,而不是 CPU 负载。用 sar -n DEV 1 10 可以看到每秒的数据包数和字节数,用 ss -lunp 可以看到 19132 端口上 UDP 套接字的队列。Recv-Q 持续不为零,加上 nstat -az 里的 UdpRcvbufErrors 在上升,说明服务器进程已经来不及把到达的数据包取走。如果入方向数据包远远高于正常值,而服务器本身几乎没在干活,那就是攻击。如果所有网络计数器都平静,却依然什么都卡,原因在服务器进程或某个插件上。
一台 Minecraft Bedrock 服务器需要开放哪些端口?
正好一个:19132 UDP,通过 server.properties 里的 server-port 设置。如果您要服务 IPv6 玩家,再加上通过 server-portv6 设置的 19133 UDP。其余全部关闭。PocketMine-MP 和 Nukkit 的 GS4 查询跑在同一个 19132 UDP 端口上,用 enable-query 关掉。Nukkit 的 RCON 在没有单独的 rcon.port 时会回落到 19132 TCP。Bedrock Dedicated Server 的脚本调试器在 19144 TCP 上,而 Geyser 后面的 Java Edition 服务器应该绑定在 127.0.0.1 的 25565 端口上。
为什么 Bedrock Edition 比 Java Edition 更容易被 DDoS 攻击?
因为它说的是 UDP。Java Edition 通过 TCP 跑在 25565 端口上,Linux 内核用 SYN Cookie 就能挡住 SYN 洪水攻击,而 Minecraft 进程对此毫无感觉。Bedrock Edition 通过 RakNet 跑在 19132 UDP 上,而 UDP 既没有可以强制要求的连接建立过程,也没有 SYN Cookie。源地址可以伪造,而且每一个数据包都会被一路送进服务器进程并在那里被解析。因此一台 Bedrock 服务器面对 19132 端口上的数据包洪水,在操作系统里没有任何内置防护。
什么是 Unconnected Ping,它为什么是一个放大向量?
Unconnected Ping(RakNet 数据包 ID 0x01)是 Bedrock 客户端为自己的服务器列表获取名称、版本和玩家数的状态查询。服务器会用 Unconnected Pong(数据包 ID 0x1C)回应,而不需要任何人登录。请求是 33 字节,回应由 35 字节的基础结构加上服务器标识组成,在标准配置下约为 131 字节。这样得出的放大系数约为四:攻击者可以用伪造的源地址来问,让四倍的数据量落到受害者身上。服务器名称短,就能把这个系数压小。
Xbox Live 身份验证能防住 DDoS 攻击吗?
不能,它保护的是您的游戏逻辑,不是您的线路。校验发生在登录数据包里,而客户端只有在由七个数据包组成的完整 RakNet 连接建立完成之后才会发出这个数据包。此时服务器已经花掉了计算时间和内存,并且多次回应过。这个设置在 Bedrock Dedicated Server 上叫 online-mode,在 PocketMine-MP 和 Nukkit 上叫 xbox-auth,三者出厂都是 true,也应当保持不变。但它挡不住数据包洪水,因为攻击者根本不想进服。
Allowlist 对我 Bedrock 服务器上的 DDoS 攻击有用吗?
没有用。Allowlist 对付的是一切走正规加入途径进来的东西:捣乱的人、被封禁的玩家、一次性账号。但它只有在登录数据包被处理之后才会被检查,也就是在 RakNet 连接建立和 Xbox Live 校验之后。向您服务器灌包的攻击者根本不想进服。他的数据包会被拒绝,但已经到了。不过对付槽位耗尽它确实有效,前提是配上一个现实的 max-players 和一个不设成 0 的 player-idle-timeout。
我改了端口,19132 还是开着的。这是怎么回事?
是 server.properties 里的 enable-lan-visibility,它出厂就是 true。Microsoft 明确写明,Bedrock Dedicated Server 会因此额外绑定到默认端口 19132 和 19133 上,即使 server-port 和 server-portv6 设的是别的值。请把这条指令设成 false,重启服务器,再用 ss -lnup 确认 19132 真的消失了。同一个设置也能解决两台 Bedrock 服务器跑在同一主机上时的端口冲突。
用 Geyser 和 Floodgate 时要注意什么?
三件事。请让 Geyser 保持最新:2024 年 3 月,它所用 RakNet 库中的一个放大缺陷被大规模利用,自 Build 478 起修复;2025 年 7 月出现了第二起,围绕连接建立早期被重复发送的数据包,自 Build 897 起修复。请把 Java Edition 服务器绑定在本机,因为 remote.address 和 remote.port 指向 127.0.0.1 的 25565 端口,并且不要对外放行 25565 TCP。还要把文件 key.pem 当作机密:它是 Floodgate 用来为 Bedrock 账号跳过 Java 身份验证的密钥。
攻击到多大规模,我的服务器就撑不住了?
典型的游戏服务器挂在 1 Gbit/s 上,也就是每秒 125 兆字节。针对 Minecraft 项目的攻击通常在 5 到 50 Gbit/s 之间,即您线路的五到五十倍。同样重要的是数据包速率:在 64 字节包大小时,1 Gbit/s 里装得下每秒约 149 万个数据包,而普通的服务器内核只能处理其中的几十万个。在 Bedrock 服务器上几乎总是数据包速率先出事,因为全部游戏流量都由许多小 UDP 数据包组成。
在 KernelHost,我的 Bedrock 服务器会在攻击期间离线吗?
不会。我们不使用黑洞路由。您的 IP 地址留在网络里,被丢弃的只有恶意数据包。防护分两级:全球清洗网络中 17 Tbps 的清洗能力,以及法兰克福 3.2 Tbps 的 Arbor 实时过滤。它持续运行,不需要先对攻击做出反应,因此开头不会有那几分钟,让服务器从您玩家的服务器列表里消失。
KernelHost 的 DDoS 防护要额外付费吗?什么时候需要 Advanced DDoS Protection?
两级持续防护包含在每个服务器套餐中,不额外收费,自服务器开通起即生效,您既不用订购,也不用开启或配置。当您的项目不是偶尔被打,而是被有针对性地连打几周,并且您想自己掌控过滤时,就需要 Advanced DDoS Protection。您会获得一个专用防护 IP,并在客户中心里自行按端口和协议管理防护规则,也就是把 19132 UDP 和任何改动过的端口分开设置。改动实时生效。价格每月 50.00 欧元起,PrePaid 预付费,没有最低合约期,也没有开通费。

Minecraft Bedrock Minecraft Bedrock DDoS 防护 游戏服务器防护 RakNet 19132 端口 Geyser Advanced DDoS Protection 实时过滤