保护 Left 4 Dead 2 服务器免受 DDoS 攻击

发布于 阅读时间 32 分钟

Left 4 Dead 2 服务器真正需要哪些端口,如何在 27015/UDP 上给 A2S 查询减压而不把自己的玩家关在门外,大厅系统作为访问过滤手段能做到什么,以及攻击规模到什么程度就只有服务器前面的网络过滤才有用。

Left 4 Dead 2 服务器很少在方便的时候掉线。它掉在一场战役的最后一个章节里,掉在对抗模式的第二回合里,或者正好掉在一个被封禁的玩家第三次被拒之门外的时候。正在被攻击的人不需要一场关于网络技术的原理讨论,而需要一个处理顺序。本文先讲在自带手段还够用的范围内,怎样为 Left 4 Dead 2 服务器做好 DDoS 防护,然后讲这些办法在物理上到哪里为止,最后讲服务器前面的网络里必须发生什么。

本文所有内容针对通过 SteamCMD 以应用编号 222860 安装的独立服务器(srcds),运行在 Debian 12、Debian 13、Ubuntu 22.04 LTS 或 Ubuntu 24.04 LTS 上。命令以 root 身份书写,普通用户请在前面加上 sudo。有一点要先说,因为它决定了处理顺序:攻击进行时不要盲目改动任何东西,也不要在保存好测量数据之前重启服务器。攻击结束后,这些数据就没有了。

Left 4 Dead 2 服务器为什么是值得下手的 DDoS 目标

与一款有 64 个槽位的射击游戏相比,区别在于一局的规模。一场合作战役有四个幸存者槽位,一场对抗模式两边加起来一共八个槽位。因此一次宕机从来不是只打到个别玩家,而总是打掉整场对局:一场战役在五个章节中的第三个中断,就等于替所有参与者结束了这个晚上。这正是攻击对发起者有吸引力的地方,因为它既不需要什么本事,也花不了多少钱,却能在对面毁掉一个小时的游戏时间。

再加上构造本身。Left 4 Dead 2 跑在 Source 引擎上,而一台 Source 服务器带着 IP 地址和端口是公开可查的。这是前提,不是失误:一台不回答查询的服务器不会出现在任何列表里,也不会被任何大厅找到。所以问题从来不是攻击者是否知道您的地址,而只是他朝它开火时会发生什么。游戏流量走 UDP,而 UDP 没有可以强制要求的连接建立过程,源地址也可以伪造。这里面技术上发生了什么,请看文章 什么是 DDoS 攻击?。

第三点是 Left 4 Dead 2 独有的,在 Counter-Strike、Garry's Mod 或 Team Fortress 2 上没有对应物:大多数玩家不是通过服务器浏览器进来的,而是通过大厅系统。一个最多四人的大厅经由 Steam 匹配被分配到一台独立服务器上,服务器为此得到一份预留。这套机制同时是您最有效的访问过滤手段和一块额外的攻击面。两者下面都会详细讲。

真正相关的那些端口

Left 4 Dead 2 服务器把构成这款游戏的一切都放在正好一个 UDP 端口上。默认是 27015,通过启动行里的 -port 或者 +hostport 设定:

./srcds_run -game left4dead2 -console -nohltv \
  -port 27015 \
  +ip 203.0.113.10 \
  +maxplayers 4 \
  +exec server.cfg \
  +map c1m1_hotel
端口和协议 用途 是否必须对公网开放
27015/UDP 游戏流量和 A2S 服务器查询,共用同一个端口 是,没有这个端口就没有游戏
27015/TCP RCON,前提是设置了 rcon_password 否,只为自己的地址放行
27005/UDP 客户端端口,由玩家一侧发出 否,服务器上不需要放行
27020/UDP SourceTV,仅在使用 -hltv 或 +tv_enable 1 时 只有您真的在转播时才需要
27016、27017 及以后 同一台主机上的其他实例 每个实例单独放行,不要按端口段放行
80/TCP 和 443/TCP 快速下载(sv_downloadurl),如果就放在同一台主机上 只有 Web 服务器跑在那里时才需要
22/TCP SSH 访问 否,限制到自己的地址

这张表的第一行就是问题的核心。游戏流量和服务器查询共用 27015/UDP,Left 4 Dead 2 没有单独的查询端口。谁一刀切地封掉这个端口,或者粗略地对它限速,就会在同一个动作里把自己的玩家赶出去,并按攻击者的意愿结束这次攻击。

一次 A2S 查询是一个只有几十字节的数据包,回应却是它的好几倍。UDP 的源地址可以伪造,于是您的服务器不只是受害者,还成了放大器:攻击者用目标的地址去查询别人的游戏服务器,把这些服务器的回应引到那里。Valve 在 2020 年 12 月为 A2S_INFO 加上了一道前置质询(S2C_CHALLENGE),查询方必须把它回送回来,才能拿到回应。这让反射攻击缓和了,但没有终结,因为较早的查询程序仍然会被照应到。

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

下面这部分不花钱,而且无论您的服务器放在谁那里都值得做。它替不了您挡下流量型攻击,但能让小型和中型攻击落空,并且能消除那些被误报成 DDoS 攻击的宕机。

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

在写下一条规则之前,先弄清楚哪些服务是可以访问的。在一台长年累积下来的 Left 4 Dead 2 服务器上,这几乎总是比预想的多,因为除了 srcds 之外,还跑着一个用于战役的 Web 服务器、一个统计数据库,有时还有第二台用于对抗模式的服务器:

ss -lntup

凡是绑定到 127.0.0.1 或 ::1 的,都不需要放行。凡是在 0.0.0.0 或 [::] 上监听的,都能从互联网访问到。攻击者眼中的样子由一次从外面做的端口扫描给出,而按经验,它和自己的预期并不一致:

nmap -Pn -sU -sT -p 27000-27050,80,443,3306 YOUR.SERVER.IP.ADDRESS

如果底层是刚装好的,或者您想把它重新走一遍,文章 用 SteamCMD 安装游戏服务器 描述了从 SteamCMD 到 srcds 跑起来的整条路。

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

对外一个 UDP 端口,对自己的地址一个 TCP 端口,再没有别的。RCON 不属于开放的互联网,因为拿到 RCON 的人可以换地图、封掉所有玩家并停掉服务器:

ufw allow 27015/udp comment "L4D2 游戏端口和 A2S"
ufw allow from 203.0.113.10 to any port 27015 proto tcp comment "RCON"
ufw allow from 203.0.113.10 to any port 22 proto tcp comment "SSH"
ufw default deny incoming
ufw default allow outgoing
ufw --force enable

请把 203.0.113.10 换成您自己的地址。如果它经常变动,正确的路子是走 SSH 端口转发,而不是做一条长期放行。启用时的顺序决定了您会不会把自己关在门外,完整顺序连同自救办法见文章 设置 UFW 防火墙而不把自己关在门外。万一还是出了事:KernelHost 的 KVM 根服务器和独立服务器没有 IPMI,也没有 iDRAC,您通过客户中心里的 VNC 控制台连上服务器,而它不依赖客户机系统的网络栈。

3. 给 A2S 查询减压,又不从大厅搜索里掉出去

这个题目里最贵的错误就在这里。因为游戏流量和服务器查询占用同一个端口,所以这道限制必须区分两类数据包,而不是区分端口。

自 2020 年 12 月的改动以来,Steam 游戏服务器底层为此自带了一个限制,它要在启动前作为环境变量设置。STEAM_GAMESERVER_RATE_LIMIT_200MS=N 会在 200 毫秒的窗口内,某个源地址发来的无连接数据包(A2S_INFO、A2S_RULES、A2S_PLAYERS)超过 N 个时,把它们丢弃。Valve 给出 25 到 75 是可用区间,默认这个限制是关闭的:

export STEAM_GAMESERVER_RATE_LIMIT_200MS=50
./srcds_run -game left4dead2 -console -port 27015 +exec server.cfg +map c1m1_hotel

在 systemd 单元里,同一个值要以 Environment=STEAM_GAMESERVER_RATE_LIMIT_200MS=50 的形式写进 [Service] 小节,否则下一次重启后它就没了。这道限制只在您的服务器构建自带当前的 Steamworks 底层时才生效,而且它保护的是您服务器的计算时间,不是您的线路:数据包已经到了。

再往下一层,同样的流量可以在内核里分出来。Source 引擎所有的无连接数据包,也就是服务器查询和连接建立,都以四个全置位的字节(0xffffffff)开头,而已经连上的玩家的流量没有这个头。基于这一点,可以用 nftables 按源地址加一条速率限制:

table inet l4d2 {
    chain input {
        type filter hook input priority -10; policy accept;
        udp dport 27015 @th,64,32 0xffffffff \
            meter a2sflood { ip saddr limit rate over 10/second burst 20 packets } drop
    }
}

这个文件用 nft -f 加载。优先级 -10 保证规则在 UFW 的过滤链之前生效,@th,64,32 读取 UDP 头后面的前四个字节。请先设得宽松,等到确认正规查询确实能通过之后再收紧:您自己在服务器列表里的条目就挂在这上面。

4. 把大厅系统用作访问过滤手段

这是只有 Left 4 Dead 2 和它的前作才有的抓手。服务器自己决定是否接受匹配之外的连接。server.cfg 中的四条指令决定这一点:

sv_allow_lobby_connect_only 1
sv_search_key "your-own-key"
sv_steamgroup "103582791400000000"
sv_steamgroup_exclusive 2
  • sv_allow_lobby_connect_only 1 只允许来自匹配大厅的加入。开发者控制台里的 connect 203.0.113.10:27015 和一份 Steam 邀请都会被拒绝。值为 0 时两者都允许。
  • sv_search_key 是一个可以自由选择的搜索密钥。只有设置了同一个密钥的大厅,才能通过匹配找到这台服务器。没有这个密钥,它不会出现在公开搜索里。
  • sv_steamgroup 把服务器绑定到一个 Steam 组,并让它出现在该组的组服务器里。
  • sv_steamgroup_exclusive 有三档:0 允许所有人,1 的行为和 0 一样,但要求通过大厅加入,2 则只让组成员和通过 IP 地址的直接访问进来。

对一个固定的社区来说,搜索密钥加上 sv_steamgroup_exclusive 2 是这款游戏里最有效的免费访问过滤手段。公开服务器用不了它,因为一台谁都找不到的服务器,和一台离线的服务器一样空。

现在讲广告文案爱省掉的那一部分:这些指令保护的是您的游戏逻辑,不是您的线路。一个灌满 27015/UDP 的攻击者根本不想加入。他的数据包会被拒绝,但依然已经到了,已经消耗了带宽,也已经花掉了一遍网络栈的处理。对付用一次性账号发起的连接洪水攻击,sv_allow_lobby_connect_only 1 非常有效;对付一个 booter,它完全不起作用。

5. 大厅预留,以及什么时候 sv_force_unreserved 是更好的选择

大厅预留是一个匹配大厅在有限时间内对您服务器的占用。只要它还在,这台服务器对其他大厅就算已被占用,而且它要过一会儿才会自己失效。对一台只有四个槽位的服务器来说,这是一项紧张的资源:不像有 32 或 64 个槽位的射击游戏,这里很少的量就足以让一局开不起来。

不通过匹配来运营服务器的人,可以把这块面整个去掉:

sv_force_unreserved 1
sv_allow_lobby_connect_only 0

sv_force_unreserved 1 会让服务器不再回应来自大厅系统的预留请求,并拒绝带预留标记的加入。如果您用 L4DToolZ 运行超过四个合作槽位,这个设置本来也少不了,否则只要前四个槽位被占满,大厅就会拿到一份预留,剩下的槽位就变得进不去。反面很明确:这时您的玩家只能通过服务器浏览器或者 connect 进来。

请有意识地在两种运营方式中选一种。半开的匹配加上半开的直接加入,是把两边缺点都集齐的那个组合。

6. 加固 RCON

一个开放的 RCON 端口配上弱密码,不是 DDoS 问题,而是被接管。rcon_password 绝不要留空,也绝不要设成能猜到的值,openssl rand -base64 32 出来的值就够了。Source 系列还自带一道针对登录尝试的限制:

rcon_password "A_RANDOM_VALUE_HERE"
sv_rcon_minfailures 3
sv_rcon_maxfailures 5
sv_rcon_minfailuretime 30
sv_rcon_banpenalty 1440

这样一来,一个地址在 30 秒内失败三次之后会被封禁一天;在服务器控制台里执行 find sv_rcon,可以看到您的构建认识其中哪些变量。不过第 2 步里的防火墙限制仍然更有效,因为它根本不让这类尝试到达应用层。如果您不需要 RCON,就把密码留空:这时 27015 的 TCP 部分不会监听。

7. 把自制战役挪出去,而不是通过游戏端口分发

自制战役是 Left 4 Dead 2 过了十五年还有人玩的原因,同时也是一个负载来源,这种形式在 Counter-Strike 上并不存在。一份战役是一个 VPK 包,里面装着地图、模型、贴图和声音,也就是一张单独的比赛地图重量的好几倍。

对玩家来说方便的路子是 Steam 创意工坊:这样这个包来自 Steam,不是来自您的服务器,也就不花您的带宽。如果您自己分发散装文件,那么分发应该放在一台 Web 服务器上,而不是放在游戏端口上:

sv_allowdownload 1
sv_allowupload 0
sv_downloadurl "https://cdn.example.org/l4d2/"
sv_consistency 1

给 sv_downloadurl 用的文件要以 bzip2 压缩包的形式放到 Web 服务器上,也就是 mymap.bsp 变成 mymap.bsp.bz2。没有 sv_downloadurl 时,srcds 会自己通过游戏连接发送这些文件,于是就成了:每一个新玩家的连接尝试都要花掉您一次完整的下载,每一次下载中途中断也一样。这是一种特别便宜的填满线路的办法,而且它在任何统计里都不像一次攻击。

关于这一点有三处在实际运行中会疼。sv_allowupload 0 应该设上,因为从客户端到服务器的上传您用不到。如果 sv_downloadurl 指向的 Web 服务器和游戏在同一台主机上,那么下载和游戏流量共用同一条线路和同一个 IP 地址,这时一次针对 443/TCP 的攻击也会打到您正在进行的对局。还有 sv_consistency 1 不是防攻击的,而是防客户端文件不一致的;只有在确实证明某份战役否则起不来时,才应该把它关掉。

8. SourceMod、Metamod 和各种扩展

被报成 DDoS 的宕机里有相当一部分并不是。它们是单个客户端触发的崩溃和负载尖峰,原因是服务器程序或某个扩展里有一个口子没关。这种情况靠带宽没用,靠的是维护:

  • 把 Metamod:Source 和 SourceMod 与引擎版本对上。Left 4 Dead 2 仍然在更新,而一个版本不匹配的扩展是更新之后立刻崩溃的最常见原因。
  • 用 Left4DHooks,而不是自己动手改。L4D2 特有的那些事件都打包放在这个扩展里。自己去改同一批函数,是通往一个在特定数据包序列下罢工的服务器程序的最快路径。
  • L4DToolZ 只在有意识的前提下使用。这个扩展会抬高写死在程序里的槽位上限。每一个多出来的槽位都是一个多出来的玩家,会产生计算时间,而且配合大厅系统时它需要 sv_force_unreserved 1。
  • 扩展越少越好。每个插件都是同一个进程里的代码。带自己 Web 服务的扩展会额外开端口,而且常常正好把您想保护的那个地址公布出去。

封禁要持久保存下来,否则重启之后就没了。Source 系列为此有 banid 配 writeid,以及 addip 配 writeip,生成的文件通过 exec banned_user.cfg 和 exec banned_ip.cfg 再读回来。

9. 给连接跟踪和接收缓冲区减压

这一点常被忽略,而它能解释那些看起来像流量攻击、其实不是的宕机。内核会为 UDP 流量在连接跟踪(conntrack)里建立条目,而在源地址被伪造的情况下,每一个地址都意味着一条新条目。表一满,内核就不加区分地丢弃数据包:攻击和您的玩家一起被丢出去。当前数量和上限看一眼就知道:

sysctl net.netfilter.nf_conntrack_count net.netfilter.nf_conntrack_max

最有效的一步是干脆不让游戏流量被跟踪,因为引擎自己管理它的会话:

table inet raw {
    chain prerouting {
        type filter hook prerouting priority raw; policy accept;
        udp dport 27015 notrack
    }
    chain output {
        type filter hook output priority raw; policy accept;
        udp sport 27015 notrack
    }
}

用 iptables 的对应写法是 iptables -t raw -A PREROUTING -p udp --dport 27015 -j NOTRACK,以及针对 OUTPUT 用 --sport 的同一行。之后这个端口需要一条明确的放行规则,因为没有跟踪之后,凡是检查已有状态的规则都不再生效。如果数据包到得比 srcds 取走的速度更快,接收缓冲区还会溢出,而这在玩家看来就像是一条空闲线路上的丢包:

net.core.rmem_max = 16777216
net.core.rmem_default = 1048576
net.core.netdev_max_backlog = 16384

这个文件放在 /etc/sysctl.d/ 下,用 sysctl -p 生效。这些值到底有没有必要,内核自己会说:如果 nstat -az 里的 UdpRcvbufErrors 在涨,那它们就起作用。如果这个计数器一直停在零,调整就什么也不改变。这是余量,不是防护。

10. 做测量,让您在攻击中不必猜

攻击中最重要的问题是:来了多少,落在哪个端口上,是查询流量还是游戏流量。四条命令就够了:

ip -s link show eth0
nstat -az | grep -i udp
sar -n DEV 1 10
tcpdump -ni eth0 -c 200 "udp port 27015 and udp[8:4] = 0xffffffff"

第一条命令请间隔十秒执行两次,这样得到的是一个速率,而不是一个绝对值。最后一行只显示无连接数据包,也就是查询洪水攻击滥用的那一类;如果在几乎没人连接的情况下,计数器几秒钟就跑满,答案就有了。抓包时间要短,因为它在满载下本身也要花计算时间。这些数值怎么解读,见文章 在服务器上识别 DDoS 攻击。

不过最重要的一步是几乎没人事先做的那一步:在一切正常的时候先建立基线。没有正常值,事后您就说不清每秒 4 万个数据包是很多,还是就是一个对抗模式服务器满员的周五晚上。

这些措施到哪里为止

现在说实话的部分。到目前为止讲的一切,都要等数据包已经到了您的网卡上才起作用。一条防火墙规则决定的是一个已经跑过网线的数据包。您可以把它丢弃,但没法让它没被发出来。

算一下就清楚了。一台典型的游戏服务器挂在 1 Gbit/s 上,也就是每秒 125 兆字节。在最小可能的数据包大小下,这条线路每秒能承载约 149 万个数据包,一条 10 Gbit/s 的线路约 1488 万个。这是物理上限,与 CPU、内核和防火墙无关。普通的服务器内核视处理器和网卡而定,每秒处理几十万个数据包之后就会开始丢弃。所以一次连您线路三分之一都没填满的攻击,也能让您的服务器瘫掉,因为计算时间都花在丢弃上了。运营者的体验是“负载根本不高,可是什么都没了”。

与此相对的是真实发生过的攻击。KernelHost 运行中的两个例子,都是实时过滤掉的:一次针对 7777/UDP 上游戏服务器的 UDP 洪水攻击,超过 112.2 Gbit/s,每秒超过 870 万个数据包;以及一次针对 9987/UDP 上语音服务器的多向量攻击,超过 473.4 Gbit/s,每秒超过 4150 万个数据包。拿这个对着您的线路算:473.4 Gbit/s 约为一条 1 Gbit/s 接入的 470 倍,即使对一条 10 Gbit/s 的接入,也还是约 47 倍。

所以两种常见的紧急刹车都不令人满意。黑洞路由把被攻击的 IP 地址从网络里撤下来,这确实结束了攻击,但也结束了您的服务器:对您的玩家来说,结果和一次成功的攻击完全一样。而被动的引流在切换时间里花掉的,正好是决定这场战役的那几分钟。真正有效的只有一种过滤:长期运行在服务器前面网络里的过滤。

KernelHost 用什么来应对

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

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

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

有两点是关键。第一,过滤持续运行,因此不存在让您玩家掉线的切换时间。第二,不使用黑洞路由:被攻击的 IP 地址留在网络里,被丢弃的只有恶意数据包。这份防护包含在每个服务器套餐中,不额外收费,没有单独的防护套餐,也不需要任何安装,并且自服务器开通起即生效。服务器位于法兰克福的 maincubes Premium Datacenter。哪些游戏和协议在覆盖范围内,见文章 实时游戏服务器 DDoS 防护。

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

有些项目不是偶尔被打,而是被有针对性地连打几周,手法不断变化,而且总是正好在约好的战役之夜。针对这些情况有 Advanced DDoS Protection,每月 50.00 欧元起,PrePaid 预付费,没有最低合约期。区别不在于容量更大,而在于控制权:

  • 一个专用防护 IP。您的服务器会在我们的网络内切换到这个地址,您这边不需要做任何改造。
  • 按端口和协议自行管理的防护规则。您在客户中心里决定哪个端口用哪套防护策略过滤,也就是让 27015/UDP 和分发您战役文件的 Web 服务器分开。
  • 改动实时生效,不用开工单,也不用等。所以您可以在攻击进行时随时调整。
  • 一套与具体游戏匹配的防护策略。Left 4 Dead 2 和其余 Source 系列有,另外 40 多款游戏和协议也有,此外还有供修改过的服务器使用的自由 TCP 和 UDP 策略。

这里同样是 PrePaid 预付费模式:没有最低合约期,没有退订通知期,没有合同,也没有开通费。攻击这一波过去了,您只要不续费就行。

两级防护对比

对比项 标配的持续防护 Advanced DDoS Protection
价格 包含在每个服务器套餐中,不额外收费 每月 50.00 欧元起,PrePaid 预付费,没有最低合约期
启用 自服务器开通起即生效,没有什么要设置 下单,拿到防护 IP,服务器被切换过去
过滤能力 17 Tbps 全球清洗,加上法兰克福 3.2 Tbps 的 Arbor 实时过滤 同样的两级过滤,另加自己的规则
IP 地址 您服务器本身的 IP 地址 额外的专用防护 IP
改动规则 由 KernelHost 维护,微调通过工单 自己在客户中心里改,实时生效
游戏策略 40 多款游戏和协议,含 Source 系列 每个端口可选策略,也适用于修改过的服务器
攻击时的黑洞路由 否 否
适合 每一台服务器,从第一场战役起 被长期且有针对性攻击的项目

对大多数 Left 4 Dead 2 项目来说,标配的持续防护配上干净的服务器配置就够了。Advanced DDoS Protection 针对的是有人把这件事当成私人恩怨的情况。

常见错误及解决办法

服务器从大厅搜索里消失了,但还在运行:多数情况是 27015/UDP 被一刀切封掉,或者限速设得太紧,而因为游戏流量和查询共用这个端口,一条粗略的规则会同时打到两边。请改成针对无连接数据包做匹配。如果端口可以访问而服务器依然不可见,请检查 sv_search_key、sv_steamgroup_exclusive、sv_lan 0 和 sv_region 255,以及启动时是不是不小心带上了 -nomaster。

服务器控制台里不停出现“Invalid split packet length”:这不是流量型攻击,而是拼装错误的网络数据包被快速连续地发过来。流量始终很小,服务器却照样卡顿。请先看带宽到底是否异常,并把服务器程序和各个扩展更新到最新。这里带宽帮不上忙。

所有玩家延迟都很高,但线路并没有满:这指向数据包速率,而不是流量。请看 ip -s link show 里被丢弃的数据包和 nstat -az 里的 UDP 计数器。如果系统日志里写着 nf_conntrack: table full,就用 notrack 把游戏端口摘出来。

防火墙规则是对的,却照样不起作用:请用 iptables -L INPUT -n -v 检查命中计数器是否在增长。如果一直是零,说明规则没有被匹配到,因为它排在 UFW 的链后面,或者在上次重启后就没了。如果它在涨而情况没有变化,那就是服务器前面的线路已经被打满,从那里开始只有网络中的过滤才有用。

服务器明明有空位却不再接受玩家:多数情况是有一份大厅预留卡住了。要么您就一贯通过匹配来运营服务器,要么设置 sv_force_unreserved 1,让您的玩家通过服务器浏览器加入。如果用 L4DToolZ 开了超过四个合作槽位,这个设置本来就是必须的。

新玩家一直在加载,而线路同时被打满:那就是 srcds 自己在通过游戏端口分发战役文件。请把 sv_downloadurl 指向一台 Web 服务器,并把文件以 bzip2 压缩包的形式放在那里,或者让您的玩家去 Steam 创意工坊拿。

攻击在换 IP 之后停了,一两天后又回来:这是正常情况,因为您的服务器一旦重新注册,就会自己把新地址公布出去,而一条被遗忘的 DNS 记录或者一个带状态显示的 Discord 机器人会把剩下的事做完。换 IP 争取到的是几个小时,不是解决办法。

服务器上有别人的管理命令在运行:这不是 DDoS 攻击,而是 RCON 访问被攻破了。请立刻改密码,并把 27015 的 TCP 部分限制到自己的地址。

要点总结

  • Left 4 Dead 2 服务器对外正好需要一个开放端口:27015/UDP。游戏流量和 A2S 查询共用它,没有单独的查询端口。
  • 27015/TCP 是 RCON,只属于自己的地址。不需要 RCON 的人,就把 rcon_password 留空。
  • 大厅系统是这款游戏里最有效的免费访问过滤手段:sv_allow_lobby_connect_only 1、一个自己的 sv_search_key 和 sv_steamgroup_exclusive 2 会挡掉一切不经过匹配进来的东西。它过滤的是加入,不是数据包。
  • 自制战役属于 Steam 创意工坊,或者放在 sv_downloadurl 后面,绝不要走游戏端口。否则每一次中断的连接尝试都要用您的带宽来付账。
  • 速率限制必须区分无连接数据包(以 0xffffffff 开头)和游戏流量。一条粗略地加在 27015/UDP 上的规则会把您自己的玩家赶出去。
  • 在 64 字节的数据包下,一条 1 Gbit/s 的线路每秒能承载约 149 万个数据包。超过这个量,就只由服务器前面的网络决定,服务器本身的任何设置都不起作用。
  • 在 KernelHost,17 Tbps 全球清洗和法兰克福 3.2 Tbps 的 Arbor 实时过滤持续工作,不额外收费,不使用黑洞路由,也没有切换时间。

如果您的项目已经放在 KernelHost,过滤就已经在工作,您什么都不用做。若仍然发现异常,请开一个 支持工单,以便我们的团队为您的 IP 地址调整过滤规则。攻击正在进行时,您还可以通过 WhatsApp 紧急聊天联系我们:+43 650 8209883。联系时请直接给出四项信息:IP 地址、端口、您所在时区的时间段,以及您看到的现象(玩家掉线、服务器不在大厅搜索里、延迟很高)。这样能省掉一轮回问,而在一场战役正在进行时,这一轮是要紧的。

如果您托管在别处并且经常被打,那么迁移到 KernelHost 比在一台线路更早到头的服务器上再加一条规则要近得多。持续防护是每个服务器套餐的一部分,不是一个等到出事才去订购的附加项。

常见问题

Left 4 Dead 2 服务器需要对外开放哪些端口?
正好一个:27015/UDP。游戏流量和 A2S 服务器查询共用这个端口,Left 4 Dead 2 没有单独的查询端口。27015/TCP 是 RCON,只应放行给您自己的地址。27005/UDP 是客户端端口,它由玩家一侧发出,服务器上不需要放行。27020/UDP 是 SourceTV,只有当您真的用 -hltv 或 tv_enable 1 转播时才需要。同一台主机上的其他实例按 27016、27017 依次往上排。
我的 L4D2 服务器卡顿,可线路是空的。这是 DDoS 攻击吗?
多半不是。先看服务器控制台:如果那里反复出现 Invalid split packet length 这一行,说明来的是拼装错误的网络数据包,而这种包很少几个就够。流量始终很小,服务器却照样卡顿。请同时用 sar -n DEV 1 10 查数据包速率,用 ip -s link show eth0 查丢包计数器。如果两者都不异常,那就不是流量型攻击,而是引擎或某个 SourceMod 扩展里的崩溃或负载模式。这种情况靠带宽没用,靠的是一个最新的服务器程序。
sv_allow_lobby_connect_only 1 能防住 DDoS 攻击吗?
不能,这条指令过滤的是加入,不是数据包。设置 sv_allow_lobby_connect_only 1 之后,只有经 Steam 匹配大厅分配进来的玩家能进服;开发者控制台里的 connect 和 Steam 邀请都会被拒绝。对付捣乱者、一次性账号和连接洪水攻击,这非常有效。但一个灌满 27015/UDP 的攻击者根本不想加入:他的数据包会被拒绝,却依然已经到了,已经消耗了带宽,也已经花掉了计算时间。对流量型攻击,这个设置不起作用。
服务器被攻击时,我可以直接对 27015 端口限速吗?
不能一刀切。因为游戏流量和服务器查询共用 27015/UDP,粗略的速率限制会把您自己的玩家赶出去,并按攻击者的意愿结束这次攻击。这道限制必须区分数据包类别:Source 引擎所有的无连接数据包都以四个全置位的字节(0xffffffff)开头,已经连上的玩家的流量没有这个头。正好可以据此用 nftables 或 iptables 按源地址设一个上限。此外,环境变量 STEAM_GAMESERVER_RATE_LIMIT_200MS 会在 200 毫秒内某个地址发来的无连接数据包超过设定值时,把它们丢弃。
什么是大厅预留,它为什么会把我的服务器堵住?
大厅预留是一个匹配大厅在有限时间内对您服务器的占用。只要它还在,这台服务器对其他大厅就算已被占用,而且它要过一会儿才会自己失效。在四个合作槽位的情况下,这是一项紧张的资源。不通过匹配来运营服务器的人,就设置 sv_force_unreserved 1:这时服务器不再回应预留请求,并拒绝带预留标记的加入。如果用 L4DToolZ 开了超过四个合作槽位,这个设置本来就是必须的,否则多出来的槽位一直进不去。
自制战役会让我的服务器更容易被攻击吗?
它们会让服务器变贵。一份自制战役是一个 VPK 包,里面装着地图、模型、贴图和声音,也就是单张地图的好几倍。如果 srcds 自己通过游戏端口分发这些文件,那么每一个新玩家的连接尝试都要花掉您一次完整的下载,每一次下载中途中断也一样。这是一种便宜的填满线路的办法,而且它在任何统计里都不像一次攻击。请让您的玩家去 Steam 创意工坊,或者通过 sv_downloadurl 把文件放到一台 Web 服务器上,在那里存成 bzip2 压缩包。
攻击到多大规模,防火墙规则就帮不上忙了?
只要服务器前面的线路被打满就帮不上了。一台典型的游戏服务器挂在 1 Gbit/s 上,也就是每秒 125 兆字节,在 64 字节的数据包下约为每秒 149 万个数据包。普通的服务器内核能处理其中几十万个,之后就开始丢弃。您的规则决定的永远是一个已经跑过网线的数据包;您可以把它丢弃,但没法让它没被发出来。超过这条界限,只有长期运行在服务器前面网络里的过滤才有用。
在 KernelHost,我的服务器会在攻击期间离线吗?
不会。我们不使用黑洞路由。您的 IP 地址留在网络里,被丢弃的只有恶意数据包。防护分两级:全球清洗网络中 17 Tbps 的清洗能力在靠近来源的地方拦住流量型攻击,法兰克福 3.2 Tbps 的 Arbor 实时过滤则在服务器前面丢弃与协议相关的特征。两级都持续运行,不需要先对攻击做出反应,因此不存在让您玩家掉线的切换时间。
KernelHost 的 DDoS 防护要额外付费吗?
不需要。两级持续防护包含在每个服务器套餐中,不额外收费,并且自服务器开通起即生效。您既不用订购,也不用开启或配置,而且没有单独的防护套餐。服务器位于法兰克福的 maincubes Premium Datacenter。如果您的 Left 4 Dead 2 服务器目前放在别处并且经常被打,那么解决办法不是在一台线路更早到头的服务器上再加一条规则,而是迁移。
什么时候我还需要 Advanced DDoS Protection?
当您的项目不是偶尔被打,而是被有针对性地连打几周,并且您想自己掌控过滤时。您会获得一个专用防护 IP,并在客户中心里自行按端口和协议管理防护规则,也就是让 27015/UDP 和分发您战役文件的 Web 服务器分开。改动实时生效,所以您可以在攻击进行时随时调整。价格每月 50.00 欧元起,PrePaid 预付费,没有最低合约期,也没有开通费。

Left 4 Dead 2 L4D2 DDoS 防护 Source 引擎 srcds 大厅系统 27015 端口 游戏服务器防护 Advanced DDoS Protection