什么是 DDoS 攻击?原理、层面与防护
一次 DDoS 攻击在技术上怎么进行,它占满哪四种有限资源,您如何从自己的测量值里认出它,以及服务器上的防守到哪里为止。附运行中真实发生过的攻击案例。
DDoS 攻击是指通过人为制造的超载让一项服务无法访问,并且由非常多不同的发送方同时执行。这个缩写代表 Distributed Denial of Service,也就是分布式拒绝服务。被攻击的既不是服务器上的内容,也不是它软件里的安全漏洞,而是一种有限的资源:线路的带宽、网卡的数据包速率、内核状态表里的一个位置,或者应用程序为单次请求花掉的计算时间。这四种资源里只要有一种被占满,真实用户就再也进不来,而且根本没有人闯入过系统。
本文是这个主题的入门。它讲清楚攻击发生在哪三个层面上、什么样的放大系数能让 1 字节的请求变成 5.1 万字节的回应、攻击能力从哪里来以及在市场上卖多少钱、您如何从自己的测量值里认出一次攻击、在服务器本身还能做些什么,以及这条界线具体划在哪里。所有数字都注明了来源,方便您自己核对。如果您的服务现在正停着,请先读“遭到攻击时该做什么”一节,先测量,不要动配置。
DDoS 攻击在技术上是什么
每一次 DDoS 攻击都靠一种不对称:发出一个数据包花在攻击者身上的成本,必须低于目标处理这个数据包的成本。其余的问题只是这种不对称在哪一处最大。这样的位置正好有四个,每一个都有可以算出来的硬上限。
线路的带宽。一条 1 Gbit/s 的接入每秒传输 125 兆字节,再多就没有了。发得更多的人只会造成丢失,而这些丢失会同样落在您用户的数据包和攻击者的数据包上,因为一条满了的线路不会挑选。
数据包速率。以太网允许的最小数据包长 64 字节,加上前导码和帧间隙在线路上占 84 字节。1 Gbit/s 里能装进每秒约 149 万个这样的包。普通的服务器内核视 CPU 和网卡而定,处理其中几十万个之后就会开始丢弃。因此数据包速率几乎总是比带宽先到达的那条界线。
状态表。内核会记住半开的 TCP 连接和数据包流。这些表的限制在数量上,而不在每秒比特数上。只要每个数据包都带一个新的发送方地址,用很少的带宽就能把它们填满。
应用程序的计算时间。一次搜索请求、一次带密码校验的登录尝试,或者一次返回整份 Mod 列表的服务器查询,对目标的开销比对发送方高上千倍。在这里,一次有效的攻击常常连 10 Mbit/s 都用不到。
DoS 与 DDoS:可以测量出来的区别
概念上的依据来自 RFC 4732,“Internet Denial-of-Service Considerations”,这是 IETF 在 2006 年 11 月发布的一份信息性文件。其中的原文是:“A Denial-of-Service (DoS) attack is an attack in which one or more machines target a victim and attempt to prevent the victim from doing useful work.”也就是说,DoS 攻击是通过效果来定义的,而不是通过来源的数量。当这些来源数量众多且彼此独立时,它就是分布式的,也就是 DDoS。
在实践中,这个区别只在一处起作用:在您封禁名单的长度上。来自单一来源的 DoS 攻击,您用一条规则就能结束。Cloudflare 在 2025 年 5 月记录了一次攻击,它来自 161 个国家、5433 个自治系统里的 12.2 万个不同源地址,平均每秒出现 2.69 万个新地址,峰值 4.51 万个。面对这种情况,没有哪份封禁名单能长得足够快,而且名单里的每一条都要在本已过载的设备上额外消耗内存和查找时间。
CISA、FBI 和 MS-ISAC 联合发布的指南“Understanding and Responding to Distributed Denial-of-Service Attacks”把攻击正好分成三种技术:流量型、协议型和应用型。这种三分法是现有分类里最有用的,因为它同时说明了您那四种资源里的哪一种正在被攻击,以及防守必须放在什么位置。
一次 DDoS 攻击的三个层面
针对第 3 层和第 4 层的流量型攻击
流量型攻击别无所求,只想把目标前面的线路填满。计量单位是每秒比特数。手段通常是 UDP 洪水攻击,因为 UDP 没有可以强制要求的连接建立过程,而且发送方地址可以伪造。
目前公开记录的最大例子:Cloudflare 报告在截至 2025 年底的时段里自动拦下了一次 31.4 Tbit/s 的攻击,持续 35 秒。这相当于约 3.14 万条 1 Gbit/s 的服务器接入同时满载,持续了半分多钟。同一份报告里还有第二个数字,它比峰值更能让人把量级拿在手里:2025 年内,同一家运营商拦下了 4710 万次 DDoS 攻击,比上一年增加 121%,平均每小时 5376 次。
2025 年 5 月那个记录得更细的案例,展示了把这样一次攻击拆开来看是什么样子:峰值 7.3 Tbit/s,45 秒内 37.4 太字节数据,平均每秒约 830 吉字节。同样的数据量,一条 1 Gbit/s 的线路要走三天多。其中 99.996% 的流量是纯粹的 UDP 洪水攻击,平均同时分散在约 2.19 万个目标端口上,峰值约 3.45 万个。这种在所有端口上的分散是典型做法:攻击者不知道哪个端口重要,于是把所有端口都拿下。
协议型攻击:打的是表,不是线路
协议型攻击利用的是内核必须记住状态这一点。标准例子是 SYN 洪水攻击:攻击者发送设置了 SYN 位、发送方地址伪造的 TCP 数据包,服务器为每一个都在它的半开连接队列里建一个条目,向一个从未回答过的地址回以 SYN-ACK,然后等待。这里的计量单位是每秒数据包数,而不是吉比特。
这个队列的长度写在 net.ipv4.tcp_max_syn_backlog 里,在一台普通服务器上是四位数。面对每秒 149 万个 SYN 数据包,一个有 1024 个位置的队列不到一毫秒就满了。纯从算术上说,1 Gbit/s 就够用了,而如果目标只是这张表,那么它的一小部分就够了。
同一类里还有一种到 2021 年才被描述的手法:通过有状态的中间设备做 TCP 反射攻击。论文“Weaponizing Middleboxes for TCP Reflected Amplification”表明,那些只半途跟踪 TCP 状态的防火墙和审查设施,会对一个伪造的数据包回以整页的响应。这使得 TCP 第一次也能被用来放大,而在此之前这被认为几乎不可能。
针对第 7 层的应用型攻击
应用型攻击看起来像普通流量,因为它就是普通流量,只是数量不对。计量单位是每秒请求数。它通过一条完整建立起来的连接进来,因此能通过任何只评估连接建立过程的检查,而且它只需要很少的带宽:每秒 1 万次 HTTP 请求,视请求大小而定不到 50 Mbit/s,却已经足以把一个数据库压垮。
这方面的标尺叫 HTTP/2 Rapid Reset,在 2023 年 10 月 10 日作为 CVE-2023-44487 公开。漏洞在 HTTP/2 的多路复用能力上:攻击者打开一条数据流,发出请求,然后立刻把这条流中断。服务器已经开始干活,而攻击者的窗口里马上又空出一个位置。由此达到的数值是每秒 2.01 亿次请求(Cloudflare)、3.98 亿次(Google)和 1.55 亿次(Amazon)。作为对比:Cloudflare 在此之前测到的最高第 7 层攻击是每秒 7100 万次请求。
在游戏服务器上,第 7 层就是连接建立过程本身。针对 Minecraft 网络的 Nullping、QuietException 和伪握手洪水攻击几乎不需要带宽,却能让整片代理集群瘫掉,因为每一个数据包都会迫使代理做一次昂贵的状态判断。这些模式具体是什么样子,见 Minecraft DDoS 防护与 Nullping 防护。
三个层面对比
| 层面 | 被攻击的对象 | 计量单位 | 典型手法 | 防守必须放在哪里 |
|---|---|---|---|---|
| 流量型(第 3 层和第 4 层) | 线路的带宽 | Gbit/s 和 Tbit/s | UDP 洪水攻击,通过 DNS、NTP、memcached、CLDAP 的放大攻击 | 只能放在服务器前面的网络里 |
| 协议型(第 3 层和第 4 层) | 内核、防火墙和负载均衡器的状态表 | 每秒数据包数 | SYN 洪水攻击、ACK 洪水攻击、分片数据包、通过中间设备的 TCP 反射攻击 | 一部分在服务器上,每秒超过几十万个数据包之后就得放在服务器前面 |
| 应用型(第 7 层) | 计算时间、数据库、应用的连接建立过程 | 每秒请求数 | HTTP 洪水攻击、HTTP/2 Rapid Reset、登录洪水攻击、查询洪水攻击、槽位耗尽 | 在应用里和它前面的过滤里,两者合起来 |
真实的攻击不会守这个分类。实践中最难受的情况是多层攻击:一部分是流量型,占住线路,再加上一部分第 7 层的流量,在注意力都放在带宽上的那一刻穿进来。下面会提到的、在 KernelHost 被过滤掉的攻击里,有一次同时由十二种以上不同的主要模式组成。
放大攻击:1 字节如何变成 5.1 万字节
放大攻击是这样一种攻击:攻击者不自己朝目标开火,而是让别人的、公网可达的服务替他去做。他向一个开放的服务发送一个很小的请求,并把受害者的 IP 地址填成发送方。这个服务按规矩回应,只不过回给了受害者,而回应比请求大出好几倍。
回应大小与请求大小之比叫做 Bandwidth Amplification Factor,简称 BAF,也就是带宽放大系数。BAF 为 50 意味着,一个自己只有 1 Gbit/s 接入的攻击者能把 50 Gbit/s 引到目标上。要让这件事成立,两样东西必须同时具备:一个走 UDP 的协议,它回应的比被问的多;以及伪造发送方地址的可能。因此 IP 伪造是每一次放大攻击的前提,而不只是一种掩饰手段。
对防守方来说,由此产生一个难办的性质:流量来自真实的、合法的服务器。它们是真实的 DNS 解析器、真实的时间服务器、真实的游戏服务器。因此按源地址做的封禁名单,要么把半个国家挡在门外,要么根本不起作用。
被滥用协议的放大系数
下面这些系数来自 US-CERT 也就是 CISA 的警报 TA14-017A,“UDP-Based Amplification Attacks”,这份文件自 2014 年起不断扩充。它是整个行业都在引用的参考。
| 协议 | 放大系数 | 被滥用的操作 |
|---|---|---|
| memcached(11211 端口) | 1 万到 5.1 万 | 取回缓存内容 |
| NTP(123 端口) | 556.9 | monlist 查询 |
| CharGEN(19 端口) | 358.8 | 字符生成器 |
| WS-Discovery(3702 端口) | 10 到 500 | 在网络里查找设备 |
| QOTD(17 端口) | 140.3 | 每日格言查询 |
| RIPv1(520 端口) | 131.24 | 错误的路由请求 |
| CLDAP(389 端口) | 56 到 70 | 错误的目录请求 |
| Quake 协议 | 63.9 | 服务器信息 |
| TFTP(69 端口) | 60 | 文件请求 |
| LDAP(389 端口) | 46 到 55 | 错误的目录请求 |
| DNS(53 端口) | 28 到 54 | 回应很大的查询 |
| SSDP(1900 端口) | 30.8 | SEARCH 请求 |
| Portmap / RPCbind(111 端口) | 7 到 28 | 错误的请求 |
| Kad | 16.3 | 交换节点列表 |
| mDNS(5353 端口) | 2 到 10 | 以单播方式查询 |
| SNMPv2(161 端口) | 6.3 | GetBulk 请求 |
| Steam 协议 | 5.5 | 服务器查询 |
| NetBIOS(137 端口) | 3.8 | 名称解析 |
| BitTorrent | 3.8 | 文件搜索 |
这张表解释了为什么每一台维护良好的防火墙里,被封端口的清单看起来都差不多。您自己能做的事不多,但很重要:用 ss -lnup 检查一下,您的服务器上是否有这张表里的服务开在公网上。一个没有绑定到 127.0.0.1 的 memcached 会把您的服务器变成打击第三方的武器,消耗您自己的出口带宽,还会让您的 IP 地址进到很难再出来的封禁名单里。
为什么游戏查询协议也算在内
游戏服务器在这张表里有两个角色。它们是放大器,因为它们的查询端口会用名称、地图、玩家数和完整的 Mod 列表来回应一个很小的数据包。它们又是受害者,因为同一次查询要消耗计算时间,而且常常正好落在承载游戏模拟的那个核心上。
Steam 协议的放大系数只有 5.5,偏低,更老的 Quake 协议是 63.9,偏高。但作用不只取决于系数,还取决于具体情况下的回应大小:一台带 200 个 Mod 的服务器给出的回应,明显比一台不带 Mod 的大。Bohemia Interactive 从 2015 年起在工单 T83469 中记录,对 Arma 3 来说,仅 4 Mbit/s 的伪造查询打到 Steam 查询端口,就足以让一台服务器冻住。每秒 4 兆比特比一条家庭宽带能拿出来的还少。
由此得出一条适用于每款游戏的规则:给查询端口限速,不要封掉它。封掉它的人会从服务器列表里消失,新玩家再也找不到他。每款游戏各自是哪个端口、能压得多紧,写在下面各款游戏的专门文章里,例如 Arma 3、CS2 与各 Source 作品或 Rust。
memcached 案例:1.35 Tbit/s 打向 GitHub
2018 年 2 月 28 日,GitHub 在 UTC 17:21 到 17:26 之间无法访问,直到 UTC 17:30 只能间断访问。这次攻击达到 1.35 Tbit/s、每秒 1.269 亿个数据包,来自 1000 多个不同的自治系统和数万个单独的端点。放大是通过 memcached 完成的,系数最高达 5.1 万:攻击者的 1 字节在目标方向上产生最多 51 千字节。
这个案例到今天仍然是最好的教材,因为它一次说明了三件事。第一:放大胜过僵尸网络的规模。攻击者不需要十万台设备,他需要的是开放的 memcached 实例,当时全世界有 9 万多个挂在网上。第二:每秒 1.269 亿个数据包大约是一条 1 Gbit/s 线路所能传输量的 85 倍。服务器上的任何设置都改变不了这一点。第三:防御之所以有效,是因为流量被引到了一个过滤网络里,宕机时间因此停在九分钟,而不是九小时。
DDoS 攻击的能力从哪里来
由被接管设备组成的僵尸网络
僵尸网络是一批被恶意软件接管的他人设备,由攻击者集中远程操控。设备的主人通常察觉不到,因为设备仍然在做它被买来做的事。被攻击的主要是长期挂在网上、很少更新、还带着默认密码的设备:路由器、监控摄像头、网络录像机、电视盒子。
标尺是 Mirai,它的源代码在 2016 年 9 月底被公开。论文“Understanding the Mirai Botnet”(USENIX Security 2017)跟踪了这个网络七个月,把最高规模定为 超过 60 万台被感染设备。2016 年 9 月针对 Brian Krebs 网站的攻击达到 620 Gbit/s,来自 17.5 万台以上的设备。2016 年 10 月 21 日针对 DNS 运营商 Dyn 的攻击让 Twitter、Spotify 和 Reddit 同时无法访问,当时数到约 10.7 万个发起攻击的 IP 地址。
九年之后,量级已经完全不同。Cloudflare 把那次 31.4 Tbit/s 的记录性攻击归因于一个估计规模为 100 万到 400 万台被感染设备的僵尸网络,其中以 Android 电视盒子为主。在 2025 年 12 月的那一波攻击里,数到 902 次超大流量攻击,平均每天 53 次,峰值达到每秒 90 亿个数据包、24 Tbit/s 和每秒 2.05 亿次请求。也就是说,僵尸网络的规模在十年里长了 5 倍,达到的带宽长了 50 倍。
booter 和 stresser 服务,以及一次攻击要花多少钱
在僵尸网络和委托方之间,坐着一个按订阅出售攻击能力的服务。这些服务以“booter”、“stresser”或“IP stresser”的名义出现,并在自己的使用条款里声称它们是用来对自有系统做压力测试的。它们从不检查填进去的目标是否属于使用者,而这正是一个工具和一份服务之间的区别。
操作界面是一个带三个输入框的网页:目标、端口、时长。有支付流程、有客户服务、有分销计划。入门套餐每月大约 10 到 20 欧元,带宽更大、攻击时长更久的套餐每月几百欧元。这就回答了为什么小项目也会中招:一次让某台游戏服务器丢掉整个周六晚上的攻击,对发起者来说花的钱不到两张电影票,而且不需要任何技术知识。
另一边则是持续的追查压力。在国际行动 PowerOFF 于 2026 年 4 月的集中行动周里,来自 21 个国家的执法机关接管了这类服务的 53 个域名,逮捕 4 人,执行 25 次搜查。调查人员由此拿到了 300 多万个用户账号的数据,并向 7.5 万多名已确认身份的使用者发出了通知。在同一行动中,2024 年 12 月已经关停过 27 个平台。也就是说,为这样一项服务付钱的人,会在一个早晚会被扣押的数据库里留下一条支付痕迹。
如何识别一次 DDoS 攻击
用户报上来的话,以及这些话已经说明了什么
第一条信息几乎总是来自用户,而且比听起来更有用。四种说法有明确的含义:
- “所有人同时掉线了。”所有用户同时中断指向线路或服务进程,而不是指向单个连接。负载问题会一个接一个地影响用户。
- “延迟从 20 跳到 400 再跳回来。”连接仍然保持而往返时间在波动,这是目标前面队列被填满的特征,不是某个进程过载的特征。
- “服务器列表把我们显示为离线,但我能连上去。”这明确指向一次查询洪水攻击:查询端口不再回应,游戏端口还在。
- “用移动网络我能进去,用我家的宽带不行。”不同接入网表现不同,说明被打满的不是您的服务器,而是通往它的某条路径。
服务器上的四个测量值
接下来就是测量,而且要按这个顺序:数据包速率、带宽、连接状态、丢包计数器。CPU 的占用显示放在最后,因为在一次网络攻击中它常常毫无异常。
sar -n DEV 1 10
ip -s link show eth0
ss -s
ss -tn state syn-recv | wc -l
nstat -az TcpExtListenDrops TcpExtListenOverflows TcpExtTCPReqQFullDrop UdpRcvbufErrors UdpInErrors UdpNoPorts
cat /proc/sys/net/netfilter/nf_conntrack_count /proc/sys/net/netfilter/nf_conntrack_max
sar -n DEV 1 10 给出十秒内每个接口每秒的数据包数和字节数。关键是二者的比例:数据包很多而字节很少意味着小包,也就是协议型攻击;数据包不多而字节非常多意味着大包,也就是放大攻击。ip -s link show 在 dropped 和 overrun 两列里显示内核是否已经在丢弃。ss -tn state syn-recv 统计半开连接:三位数是正常的,五位数就是 SYN 洪水攻击。而 nstat 给出的那些计数器,在攻击结束之后仍然留着。
最重要的一步是几乎没人事先做的那一步:在一切正常的时候先建立基线。没有正常值,您就说不清每秒 4 万个数据包是很多,还是就是个普通的周六晚上。用 apt-get install -y vnstat sysstat 让测量常驻运行。详细的解读说明见 识别 DDoS 攻击。
那些没有歧义的日志行
内核日志和 Web 服务器日志里的四条消息实际上就是证据。dmesg -T | tail -50 显示前三条:
kernel: TCP: request_sock_TCP: Possible SYN flooding on port 443. Sending cookies. Check SNMP counters.
kernel: nf_conntrack: nf_conntrack: table full, dropping packet
kernel: net_ratelimit: 2247 callbacks suppressed
nginx: [alert] 1123#1123: 768 worker_connections are not enough
第一行意味着半开连接的等待队列已经溢出,内核已切换到 SYN Cookie。如果那里写的是 Dropping request,那就是 net.ipv4.tcp_syncookies 被设成了 0,服务器正在丢弃请求,其中包括真实的请求。第二行意味着连接跟踪(conntrack)满了,从这一刻起服务器连合法流量也会丢弃。第三行是一个副作用:内核压下了消息,否则它会忙于记录日志。第四行把问题转移到了应用里。
在 Web 服务器的访问日志里有两点有说明力。状态码 499 的占比突然上升,意味着客户端在回应完成之前就关闭了连接,而这正是一次只想触发工作、并不想读取结果的第 7 层攻击所做的事。而几乎所有请求的 Referrer 字段都是空的,能把一次攻击和一次真实的访客涌入区分开来,因为后者会带来搜索引擎和社交网络的 Referrer。
反向验证:攻击、涌入,还是自己的错
| 观察到的现象 | 可能的原因 | 下一个测量步骤 |
|---|---|---|
| 入向数据包速率高,CPU 负载低 | 流量型或协议型攻击 | 用字节数除以数据包数算出包大小 |
| CPU 负载高,数据包速率正常 | 第 7 层攻击,或者应用里自己的错误 | 翻访问日志,找反复出现的 URL 和状态码 499 |
通过 127.0.0.1 服务回应很快,从外面不行 |
问题在网络上,不在应用上 | 检查接口的丢包计数器和从外面测的往返时间 |
| 服务重启之后负载立刻回来 | 来自外部的攻击 | 数源地址,不要数连接 |
| 连接非常多,来自非常少的地址 | 单个来源,可以封 | 按源地址设置速率限制 |
| 连接非常少,来自非常多的地址 | 分布式攻击,封不掉 | 在服务器前面过滤,让主机商介入 |
| 出向明显多于入向 | 真实的访客涌入,或者您的服务器正在放大去打第三方 | 用 ss -lnup 检查开放的 UDP 服务 |
| 恰好在一次重启、更新或 cron 运行之后开始 | 自己的错误 | 回退这次改动,再测一遍 |
在服务器本身能起作用的手段
在服务器上能做到的比常说的更多,而且对所有规模不大的东西都有效:不讲究的机器人、单个来源、查询洪水攻击和应用型攻击。为此的工具是 nftables、连接跟踪、SYN Cookie 和按源地址的速率限制。下面所有说明适用于 Debian 12、Debian 13、Ubuntu 22.04 LTS 和 Ubuntu 24.04 LTS,并且是以 root 身份书写的。
nftables:早丢弃,少计算
原则是:一个要被丢弃的数据包,应该尽可能早、尽可能便宜地被丢弃。在它之前跑的每一条规则,成本都是计算时间乘以数据包速率。下面这份给 /etc/nftables.conf 的规则集放行一台 Web 服务器和一个游戏服务,丢弃其余的,并对每个源地址的新建 TCP 连接做速率限制:
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
set adminips {
type ipv4_addr
flags interval
elements = { 203.0.113.10 }
}
set newconn {
type ipv4_addr
size 131072
flags dynamic,timeout
timeout 1m
}
chain input {
type filter hook input priority filter; policy drop;
iif lo accept
ct state established,related accept
ct state invalid counter drop
ip saddr @adminips tcp dport 22 accept
tcp dport { 80, 443 } ct state new add @newconn { ip saddr limit rate over 30/second burst 60 packets } counter drop
tcp dport { 80, 443 } accept
udp dport 25565 accept
icmp type echo-request limit rate 5/second accept
icmpv6 type { echo-request, nd-neighbor-solicit, nd-neighbor-advert, nd-router-solicit, nd-router-advert } accept
counter drop
}
chain forward { type filter hook forward priority filter; policy drop; }
chain output { type filter hook output priority filter; policy accept; }
}
在加载之前,请把您自己的固定地址填进 adminips,否则您会把自己从 SSH 关在外面。检查和启用这样做:
nft -c -f /etc/nftables.conf
systemctl enable --now nftables
nft list ruleset
nft list set inet filter newconn
有三点决定效果。ct state established,related accept 特意排在第二条,这样已有连接就不必跑完整套规则。ct state invalid counter drop 会清掉错误的标志位组合和迟到的分片,您不必逐个描述它们。而每个 drop 前面的 counter 是您事后能知道哪条规则起了作用的原因:计数器停在零就说明这条规则没被走到,而这和一套无效的规则集是完全不同的诊断。
SYN Cookie 和 backlog 的界线
SYN Cookie 是这样一种做法:服务器不去记住一条半开的连接,而是把需要的信息加密写进自己回应的序列号里。连接建立的第三个数据包回来时,它再从里面把状态算出来。这样等待队列就不会再溢出,因为对这些连接来说根本没有等待队列。
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_max_syn_backlog = 8192
net.core.somaxconn = 8192
net.core.netdev_max_backlog = 16384
net.core.rmem_max = 16777216
这些值应该放进 /etc/sysctl.d/ 下的一个文件里,用 sysctl --system 生效,否则下一次重启之后就没了。在 Debian 和 Ubuntu 上,tcp_syncookies 出厂就是 1,这是对的。值为 1 并不表示“总是用 Cookie”,而是“一旦等待队列溢出就用 Cookie”。
为此付的代价是真实存在的,而且很少被提到。一个 Cookie 里放不下对方的 TCP 选项。Linux 只有在 net.ipv4.tcp_timestamps 为 1 的情况下才能救回窗口扩大和选择性确认,因为这时相关信息会跟着时间戳一起走。没有时间戳,它们就丢了,这条连接在余下的生命里都会跑得更慢。此外,最大数据包大小只有三个比特可用,也就是八个粗略档位,而不是精确值。SYN Cookie 是一种救连接的应急状态,不是正常情况下的设置。
conntrack:最先满的那张表
内核的连接跟踪会为每一条数据包流建一个条目,UDP 也一样,尽管 UDP 没有连接这回事。在一次分布式攻击中,正是这张表第一个耗尽,而且耗尽得非常快:面对每秒 149 万个各带新发送方地址的数据包,一张有 262144 个位置的表不到五分之一秒就填满了。
net.netfilter.nf_conntrack_max = 524288
net.netfilter.nf_conntrack_udp_timeout = 10
net.netfilter.nf_conntrack_udp_timeout_stream = 60
net.netfilter.nf_conntrack_tcp_timeout_syn_recv = 20
一个条目约占 300 字节,524288 个条目也就是约 150 兆字节内核内存。哈希表的大小不通过 sysctl 设置,而是作为模块参数设置,通常设为上限的四分之一,写在 /etc/modprobe.d/nf_conntrack.conf 里:
options nf_conntrack hashsize=131072
对一台纯游戏服务器或语音服务器来说,更漂亮的办法是干脆不跟踪游戏流量。这样能完全省下这张表:
nft add table ip raw
nft add chain ip raw prerouting '{ type filter hook prerouting priority raw; }'
nft add rule ip raw prerouting udp dport 25565 notrack
注意:notrack 和有状态的规则互相排斥。把某个端口排除出跟踪的人,就不能再对这个端口使用带 ct state 的规则,否则放行不再生效,服务就关了。
按源地址做速率限制
按源地址做速率限制是服务器上最有效的单项措施,因为它正好命中攻击者所做的事,又正好放过用户所做的事。这个差别很大:一个真实的服务器浏览器每分钟查询几次,一个攻击者每秒查询几百次。用 nftables 时为此使用动态集合,就像上面那份规则集里那样;用传统的 iptables 时用 hashlimit:
iptables -I INPUT -p udp --dport 27015 -m hashlimit --hashlimit-name query --hashlimit-mode srcip --hashlimit-above 10/sec --hashlimit-burst 20 -j DROP
iptables -I INPUT -p udp --dport 27015 -m length --length 0:27 -j DROP
这类规则里的所有数字都是起始值,不是真理。请先在正常运行状态下测一周,否则您会把自己的用户赶出去,而且正好是在最糟的时刻。此外请注意,纯 iptables 规则在重启之后就没了(apt-get install -y iptables-persistent,然后 netfilter-persistent save),并且在 UFW 下它们应写进 /etc/ufw/before.rules,否则下一次 ufw reload 时就会消失。用于日常运行的完整规则集见 保护服务器免受 DDoS 攻击。
服务器上的过滤到哪里为止
现在说没有任何配置文件能解决的那一部分。前面所有措施都跑在您的服务器上,也就是线路的末端。防火墙规则处理的是已经跑过网线的数据包。您可以把它丢弃,但没法让它没被发出来。如果前面的线路已经满了,您用户的数据包在更早的地方就已经过不来了,而且与您的规则集写得多好完全无关。
| 接入 | 每秒有效数据 | 64 字节时每秒的数据包数 |
|---|---|---|
| 1 Gbit/s | 125 兆字节 | 约 149 万 |
| 2 条 1 Gbit/s | 250 兆字节 | 约 298 万 |
| 10 Gbit/s | 1250 兆字节 | 约 1488 万 |
| 25 Gbit/s | 3125 兆字节 | 约 3720 万 |
| 100 Gbit/s | 12500 兆字节 | 约 1.488 亿 |
这张表对每一个具体情形都能回答“自保够不够”这个问题。针对 GitHub 的那次每秒 1.269 亿个数据包的攻击,在数据包速率上刚好装得进一条 100 Gbit/s 的接入,但按 1.35 Tbit/s 的流量算,得同时有十四条这样的接入。31.4 Tbit/s 的记录性攻击相当于 314 条完全打满的 100 Gbit/s 接入。一台游戏服务器通常挂在 1 Gbit/s 或者两条 1 Gbit/s 上:自保的界线因此在每秒约 150 万到 300 万个数据包,实际上还明显更低,因为内核会更早放弃。
还有第二条、更难受的界线。一旦线路被打满,您本来想用来测量的那条 SSH 会话都可能到不了您手上。到那时如果没有一条不依赖网络的通道,比如客户中心里的 VNC 控制台,您连发生了什么都没法查看。
只有在服务器前面才起作用的:网络中的过滤与清洗
只有拥有比攻击更大容量的一方才能有效过滤。这需要一个有很多线路汇聚的位置,也就是一个网络,而不是一台机器。在那里有两种互相补充的做法。
网络中的实时过滤。全部流量持续经过一道过滤级,它在把每个数据包交给服务器之前都做判断。好处是不存在切换:防护不需要先识别出一次攻击才起作用。对游戏来说恰恰是这一点决定胜负,因为两分钟的切换时间等于输掉一局,而面对一次只持续 35 秒的攻击,两分钟的切换时间根本不算防守。
清洗。网络识别出一次大规模流量型攻击之后,受影响的流量会被引到清洗中心,在那里去掉有害部分,然后再送往目标。这种改道的意义在于就近:攻击流量在它进入的地方就终结,而不是到了数据中心才终结。为此过滤规则会在网络里分发,技术上在 RFC 8955 中作为 Flow Specification 描述。
顺便说一句,针对伪造发送方地址的结构性对策从 2000 年起就已经存在,写在 RFC 2827 也就是 BCP 38 里:谁接入一个客户,就在这个边界上丢弃所有发送方地址不属于这个客户的数据包。RFC 3704 把这一点扩展到多归属网络。如果所有网络运营商都实施这一条,整个放大攻击这一类就没了。它没有实现,因为只要有一些人不做就够了。
还有第三种方法必须知道,因为它常常被当成防护卖出去:黑洞路由,技术上是按 RFC 5635 的 Remote Triggered Black Hole Filtering。做法是在网络里把被攻击的 IP 地址宣告为不可达,所有去往它的流量都被丢弃,攻击流量和您用户的流量一起。这保护的是主机商的网络,对您来说结果和一次成功的攻击完全一样,而且通常在攻击结束后还要持续几个小时。有疑问时请直接问清楚:是过滤还是黑洞路由。这个答案对您可用性的影响,比任何硬件参数都大。
KernelHost 用什么来应对
每个服务器套餐里都标配的持续防护
KernelHost 的 DDoS 防护分两级,持续生效,您不需要开启、订购或配置任何东西:
- 第 1 级:全球清洗网络中 17 Tbps 的清洗能力。流量型攻击在靠近来源的地方就被清洗掉,不会到达数据中心。
- 第 2 级:法兰克福的 Arbor 实时过滤,容量 3.2 Tbps。就在服务器前面,逐个数据包地识别并丢弃与协议相关的攻击特征。
有两点是关键。防护持续运行,自服务器开通起即生效,所以一次攻击刚开始时不会有服务失联的那几分钟。而且不使用黑洞路由:您的 IP 地址留在网络里,被丢弃的只有恶意数据包。哪些游戏和协议有自己的防护策略,见 实时游戏服务器 DDoS 防护。
针对长期被攻击项目的 Advanced DDoS Protection
有些项目不是偶尔被打,而是被有针对性地连打几周,每天晚上同一时间,模式还不断变化。为此有 Advanced DDoS Protection,每月 50.00 欧元起,PrePaid 预付费,没有最低合约期,也没有开通费。区别不在于容量更大,而在于控制权:
- 专用防护 IP,来自法兰克福的核心网络,您的服务器会在我们自己的网络内切换到它。您这边不需要做任何改造。
- 按端口和协议自行管理的防护规则,就在客户中心里:您可以分别设置游戏端口上允许什么、查询端口上允许什么,从而正好利用查询协议那一节里说的那种不对称。
- 改动实时生效,因此您可以在攻击进行时随时调整,而不用等维护窗口。
- 与具体服务匹配的防护策略,同样适用于任意 TCP 或 UDP 端口上经过修改的程序和自研程序。
Advanced DDoS Protection 面向 KernelHost 的客户,前提是有一台放在 KernelHost 的服务器。如果您的项目目前在别处运行并且经常被攻击,路子是迁到这里来,而不是远程照看您原来的地址。
两级防护对比
| 对比项 | 标配的 DDoS 持续防护 | Advanced DDoS Protection |
|---|---|---|
| 价格 | 包含在每个服务器套餐中,不额外收费 | 每月 50.00 欧元起,PrePaid 预付费 |
| 过滤能力 | 17 Tbps 全球清洗,加上法兰克福 3.2 Tbps 的 Arbor 实时过滤 | 同样的两级过滤 |
| 生效起点 | 服务器开通 | 防护 IP 开通 |
| IP 地址 | 您服务器本身的 IP 地址 | 额外的专用防护 IP |
| 规则集 | 自动防护策略,无需配置 | 在客户中心里按端口和协议设置自己的规则 |
| 变更 | 自动跟进 | 实时生效,攻击进行时也可以 |
| 黑洞路由 | 否 | 否 |
| 合约期 | 与服务器套餐绑定 | PrePaid 预付费,没有最低合约期,没有退订通知期,也没有开通费 |
运行中真实被过滤掉的四次攻击
下面这四次攻击打的是 KernelHost 客户的服务器,全部被实时过滤掉,每一次都没有中断。图片来自防御系统的实时监控。
TeamSpeak 3 语音服务器,9987 UDP 端口。多种模式同时出现的复杂攻击,超过 473.4 Gbit/s,每秒超过 4150 万个数据包。这大约是一条 1 Gbit/s 接入数据包速率的 28 倍。

ARK 游戏服务器,7777 UDP 端口。没有复杂结构的简单 UDP 洪水攻击,但超过 112.2 Gbit/s,每秒超过 870 万个数据包。旁边一套 ARK 集群自己该怎么加固,见 保护 ARK 服务器免受 DDoS 攻击。

全端口攻击,0-65535 TCP 和 UDP 端口。十二种以上不同的主要攻击模式同时打向所有端口,总共超过 21.3 Gbit/s,每秒超过 390 万个数据包。这个例子显示了在所有端口上的分散,2025 年 5 月那个 Cloudflare 案例平均约 2.19 万个目标端口也是同样的情况。

Minecraft 和 OpenVPN,25565 TCP 和 1194 UDP 端口。十六种以上不同主要攻击模式的组合攻击,每秒超过 400 万个数据包,超过 8.6 Gbit/s。两项服务全程保持可达,尽管它们说的是不同的协议。

遭到攻击时该做什么,按这个顺序
顺序比单个步骤更重要,因为最常见的错误都发生在头五分钟里。
- 测量,不要动配置。先把
sar -n DEV 1 10、ip -s link show、ss -s和dmesg -T的数值存进一个文件。攻击过后它们就没了,而没有它们谁也帮不了您。 - 不要重启。一次重启会清掉所有计数器、所有连接状态和每一份证据,而负载在几秒之后又回来了。
- 确定这是哪个层面。字节数除以数据包数得到平均包大小。小于 100 字节指向协议型攻击,大于 1000 字节指向放大攻击,包大小正常而 CPU 负载高则指向第 7 层。
- 把管理端口关掉。面板、数据库、RCON 以及所有不必公开的东西,都应限制到您自己的地址。这会立刻缩小攻击面,而且对用户没有风险。
- 设置速率限制,查询端口紧,使用端口宽。不要封掉查询端口,否则您会从每一份服务器列表里消失。
- 不要急着换自己的地址。换地址只在新地址还没有再次公开时有效,而一条被遗忘的旧 DNS 记录会让这次更换失去意义。
- 带着数字把主机商拉进来。开一个工单,写上时间点、目标端口、数据包速率、带宽和平均包大小。这五项说明决定了为您的地址调整过滤规则能有多快。
- 事后记录下来。记下它什么时候开始、持续多久、是哪种模式。每天同一时间反复出现的攻击,是判断一个项目是否需要专用防护 IP 的标准。
面对一次严重且持续较久的攻击,详细流程见 遭遇严重 DDoS 攻击该怎么办?。
法律状况:DDoS 攻击是一种犯罪行为
在奥地利,DDoS 攻击适用《刑法典》第 126b 条“干扰计算机系统的功能”。基本构成要件规定最高六个月自由刑,或者最高 360 个日额罚金的罚金刑。如果干扰持续较长时间,则最高两年。如果用一个明显为此制作的程序攻击大量系统,则最高三年。而在损失超过 30 万欧元、攻击关键基础设施或作为犯罪团伙成员实施的情况下,量刑幅度是六个月到五年。作为补充,《刑法典》第 126c 条已经把制作、传播和提供此类专用程序本身列为犯罪。
在德国适用《刑法典》第 303b 条“计算机破坏”:最高三年自由刑或罚金刑;如果该数据处理服务于一个营业场所、一家企业或一个行政机关,最高五年;在特别严重的情况下,例如以营利方式实施或者损害关键基础设施,则是六个月到十年。未遂也要处罚,而对于预备行为,《刑法典》第 303b 条第 5 款指向第 202c 条。
因此 booter 和 stresser 服务不是灰色地带,而是一项犯罪中被付费的那一部分。其中有三点经常被误解。第一,“仅用于对自有系统做压力测试”这句说明并不能让任何事变得合法,因为这些服务不检查填进去的目标属于谁。第二,委托方同样构成犯罪,不只是运营者:Europol 在 2026 年 4 月的集中行动周之后,专门向 7.5 万多名已确认身份的使用者发出通知,就是为了把这一点讲清楚。第三,通过这样一项服务对自己的服务器做压力测试也不是办法,因为攻击流量会穿过主机商的网络,也就是走在其他客户的线路上,而任何主机托管合同都禁止这么做。真想测量自己服务承载能力的人,会提前报备并与主机商商定后再做。本节是对法律现状的转述,不构成法律咨询。
适合您服务的那份指南
本文讲的是原理。哪个端口该开着、哪条配置指令限制哪一种查询、每款游戏的界线在哪里:这些写在各项服务各自的文章里,每篇都带端口事实表。
- 基础与流程:识别 DDoS 攻击、保护服务器免受 DDoS 攻击、遭遇严重 DDoS 攻击该怎么办?、带实时过滤的游戏 DDoS 防护
- Minecraft 与语音:Minecraft 与 Nullping、Minecraft Bedrock、TeamSpeak 3、Hytale
- 以 GTA 为基础的角色扮演:FiveM、RedM、RAGE MP 与 alt:V、SA-MP 与 open.mp、MTA:SA
- 生存与建造:Rust、ARK、DayZ、Palworld(幻兽帕鲁)、Conan Exiles、Project Zomboid、Terraria、Unturned
- 战术与射击:CS2 与 Source、Arma 3、Call of Duty、Team Fortress 2、Left 4 Dead 2、Garry's Mod、Mordhau、Lineage 2
要点总结
- 一次 DDoS 攻击占满四种有限资源中的一种:带宽、数据包速率、内核的一张状态表,或者应用的计算时间。它不利用安全漏洞,所以单靠打补丁保护不了您。
- RFC 4732 通过效果而不是来源的数量来定义 DoS 攻击。来源数量众多时它就叫分布式:在 2025 年 5 月的 Cloudflare 案例里是来自 161 个国家的 12.2 万个地址。
- CISA、FBI 和 MS-ISAC 区分三种技术:流量型以 Gbit/s 计,协议型以每秒数据包数计,应用型以每秒请求数计。每一种都需要不同的防守。
- 放大攻击滥用开放的 UDP 服务。系数从 Steam 协议的 5.5、SSDP 的 30.8、NTP 的 556.9 一直到 memcached 的 5.1 万,可在 US-CERT TA14-017A 中查到。
- 能力来自被接管设备组成的僵尸网络,从 2016 年 Mirai 的 60 万台,到 31.4 Tbit/s 记录性攻击背后估计的 100 万到 400 万台,并且从每月约 10 欧元起被转卖出去。
- 在服务器上起作用的是
nftables、SYN Cookie、调整过的 conntrack 上限和按源地址的速率限制。它们止步于每秒约 150 万个数据包,因为一条 1 Gbit/s 的接入再多就传不了了。 - 在这条界线之上,起决定作用的只有服务器前面网络中的过滤。黑洞路由不是防守,而是攻击者本来就想要的那个结果。
- 在 KernelHost,两级持续防护包含在每个服务器套餐中,不额外收费,自服务器开通起即生效,并且不使用黑洞路由:全球清洗网络中 17 Tbps 的清洗能力,加上法兰克福 3.2 Tbps 的 Arbor 实时过滤。Advanced DDoS Protection 在此之上每月 50.00 欧元起,补上一个专用防护 IP 和可按端口自行管理的规则。
- DDoS 攻击在奥地利依《刑法典》第 126b 条、在德国依《刑法典》第 303b 条构成犯罪,委托方与这些服务的运营者同样受罚。
如果您的项目已经放在 KernelHost,过滤就已经在工作,您什么都不用做。若仍然发现异常,请带着第 7 步里的那五项说明开一个 支持工单,以便为您的 IP 地址调整过滤规则。攻击正在进行时,您还可以通过 WhatsApp 紧急聊天联系我们:+43 650 8209883。
常见问题
什么是 DDoS 攻击?
DoS 和 DDoS 有什么区别?
DDoS 攻击有哪些种类?
什么是放大攻击,放大系数有多高?
DDoS 攻击的能力从哪里来,一次攻击要花多少钱?
我怎么看出自己的服务器正在被攻击?
哪些日志行能证明一次 DDoS 攻击?
服务器上的防火墙足以应对 DDoS 攻击吗?
服务器上哪些设置对 DDoS 真正有用?
为什么不能干脆把查询端口封掉?
什么是黑洞路由,它为什么不算防守?
服务器正在被攻击时,我第一件事该做什么?
在 KernelHost,我的服务器会在攻击期间被关掉吗?
KernelHost 的 DDoS 防护要多少钱,什么时候需要 Advanced DDoS Protection?
DDoS 攻击违法吗?
2023-2026 KernelHost GmbH。保留所有权利。本教程受著作权法保护,未经我们书面同意,不得在其他网站上转载,节选转载或改写后转载同样不被允许。欢迎在注明出处并附上链接的前提下引用。

