凌晨一点四十七分,我的手机连着震了三次。腾讯云App的告警推送显示,我那台4核8G的云服务器,出带宽从平时的几Mbps一路冲到了接近打满,监控图上几乎是一条直线顶在顶部。好多年前我第一次遇到这种情况时,第一反应是怀疑自己中了挖矿木马,登录上去top一看CPU根本没异常,后来才明白这不是机器本身的问题,而是有人正冲着这台服务器的带宽下手。
如果你也跑着腾讯云的服务器,突然有一天发现带宽被打满、网站打不开、SSH卡到怀疑人生,这篇文章就是为你写的。我会完整还原我从发现异常、定位攻击类型、紧急处置、恢复业务,到事后加固和溯源的全过程,包括每一步为什么这么做、用什么命令、控制台上怎么点,以及我踩过的坑。
1. 事发当夜:先别慌,花十分钟搞清楚现状
1.1 第一现场:告警、登录和直觉判断
我当时的服务器配置在腾讯云里算很标准的一档:4核8G内存、5Mbps固定带宽、系统盘50G,跑着一个个人项目站点、两个API接口,还顺手给朋友搭过一台rtmp推流测试机。日常出带宽峰值也就2到3Mbps,入带宽基本可以忽略。所以当告警提示出带宽拉满、入带宽也异常增高时,我心里已经基本确认不是正常业务流量。
第一件事不是瞎查,而是先确认自己还能不能登录。带宽被打满时,最常见的情况是SSH压根连不上去,或者连上了敲命令都卡顿。我试了一次SSH,果然连握手都困难。这时候千万别反复重试,而是改走腾讯云控制台的VNC登录方式,只要控制台还在,就能绕过网络层直接操作操作系统,这是我们保住操作入口的关键一步。
登录进去后,我按顺序快速做了三个动作:
uptime确认系统没重启过,运行时间正常,说明不是被入侵后重启。free -h和df -h看内存和磁盘,排除内存耗尽和日志把盘写满的情况。top看CPU和进程列表,确认没有可疑进程在跑。
这三个动作都是排除法。攻击分很多种,有些是打系统漏洞,有些是打应用层的,有些就是纯粹打带宽。CPU、内存、磁盘都正常,进程列表里也没有陌生的东西,那基本可以锁定:这是一场针对带宽的攻击,也就是典型的DDoS流量型攻击。
1.2 用四类命令快速定位"流量从哪来"
确认是带宽型攻击后,接下来要把攻击流量看明白,才知道怎么堵。我建议你按照下面这套顺序来排查,都是最常用的工具,如果系统里没有就先装一下:
# 安装常用网络排查工具(CentOS/Rocky用yum,Ubuntu/Debian用apt) apt install -y iftop nload sysstat tcpdump # 或 yum install -y iftop nload sysstat tcpdump第一类命令是看实时带宽和网卡流量。iftop -i eth0 -nNB和nload可以直观看到当前哪个IP在大量占用带宽。注意先把网卡名确认清楚,ip addr看一下,腾讯云服务器网卡可能是eth0也可能是ens5,名字搞错了命令就直接报错。
第二类命令是查TCP连接状态。netstat -antp | awk '{print $6}' | sort | uniq -c | sort -rn可以看到所有连接的分布,正常服务器连接数可能只有几百,被打时你会发现同一状态的数量异常大,比如几千个SYN_RECV、几万个ESTABLISHED或不正常的TIME_WAIT。
第三类命令是抓包。tcpdump -i eth0 -nn port 80 -c 200抓200个包看看载荷,能快速判断是SYN包、UDP包还是确实在发HTTP请求。这里的细节很关键,不同攻击类型在tcpdump里的表现完全不一样。
第四类命令是看系统整体网络统计:sar -n DEV 1 5,连续采样几次,能看出入方向还是出方向被打,以及是哪个网卡在扛压力。
1.3 判断攻击类型的三个关键特征
我把这次排查中判断攻击类型的经验总结成三个特征,这三个特征几乎是通用的:
第一个特征是连接状态分布。如果SYN_RECV数量暴增,大概率是SYN Flood,攻击者发大量不完成握手的SYN包,把你的半连接队列塞满;如果是ESTABLISHED大量堆积,且后续请求都没响应,有可能是TCP连接耗尽或者应用层CC攻击。
第二个特征是端口和协议分布。理论上UDP流量占比突然变得非常高,往往是UDP Flood,攻击者随机向服务器端口发垃圾UDP包;如果80或者443端口上流量特别大,那可能是针对Web服务的攻击。
第三个特征是来源IP的规律。netstat -antp | grep ':80' | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -20可以直接列出最活跃的来源IP。如果排名靠前的只有少数几个IP,那就是少数源头在打;如果来源IP成千上万且非常分散,那基本是僵尸网络发起的分布式攻击,这种单靠封IP是封不完的,后续必须上流量清洗。
我这次的情况是:入带宽持续跑满,UDP流量占了大头,来源IP极为分散。结论非常明确,UDP Flood,而且是分布式的,服务器本身没被打穿,但带宽已经被垃圾流量吃干净了。
2. 带宽为什么会瞬间失守:常见攻击与影响链路
2.1 带宽耗尽型攻击的底层逻辑
很多人第一次遇到被攻击时的困惑是:我服务器CPU还好好的,内存也好好的,为什么网站就是打不开?要理解这个问题,得先搞清楚带宽在云服务器里扮演的角色。
云服务器的带宽可以理解为一条水管,你的业务流量正常通过水管流动,用户请求进来、响应出去,都靠它在走。而带宽耗尽型攻击的本质,就是在水管里灌满垃圾水。当入带宽被垃圾流量占满,正常用户的请求包就进不来,服务自然就断了;当出带宽被打满,即使服务器处理完了请求,响应也发不出去。
这就是为什么DDoS攻击里有一大类叫"带宽耗尽型攻击",它不关心你服务器的CPU有多强、内存有多大,它只关心你的带宽有多大。哪怕你用的是64核高性能实例,只要带宽是5Mbps,对方用超过5Mbps的流量打进来,你就断了。云服务器和传统物理机的差别在于,它的出入口带宽是在云厂商侧限定的,超过配置值之后流量要么被丢弃、要么触发黑洞,所以"带宽被打满"这个状态在云上特别明显,也特别好用。
2.2 主流攻击流量的特征对比
实际操作中你会遇到各种各样的攻击流量,我把最常见的几种整理成了对照表,方便你按特征去判断:
| 攻击类型 | 攻击目标 | 特征表现 | 判断方法 |
|---|---|---|---|
| SYN Flood | TCP半连接队列 | SYN_RECV数量暴增 | netstat统计连接状态 |
| UDP Flood | 带宽 | 入带宽打满,UDP包猛涨 | iftop/tcpdump看协议和端口 |
| ICMP Flood | 带宽/CPU | 大量ping包 | tcpdump看到大量ICMP |
| CC攻击(HTTP Flood) | 应用层/带宽 | 80/443大量真实HTTP请求 | Web日志里请求暴增、UA异常 |
| DNS Query Flood | DNS服务 | DNS端口流量异常 | 专门针对DNS服务器的场景 |
这次我的服务器遇上的就是第二类,UDP Flood。它的特点就是量大、粗暴、不需要维护连接状态,攻击者用脚本生成海量随机端口的UDP包发给你,你的网卡接收缓冲区瞬间被塞满。而且UDP无法通过三次握手来识别真伪,服务器几乎无法单方面拒绝,所以特别难缠。
2.3 黑洞机制与腾讯云基础防护阈值
说到DDoS防御,必须聊一聊黑洞。腾讯云为每台云服务器默认开启了基础DDoS防护,但这部分防护是有额度的。当攻击流量超过免费额度之后,云平台为了保护整个物理网络不被拖垮,会触发黑洞策略,直接把这个IP的流量全部丢弃,持续时间通常以小时计。
很多新手第一次遇到黑洞时以为是服务器坏了,其实不是。黑洞触发是有告警的,进入控制台看到"被封堵"状态就明白了。这里有个非常实际的经验:基础带宽越小,被小流量打爆的风险越高,但这些小流量又达不到触发免费清洗的量级,所以你会发现带宽被打满时,腾讯云并没有自动清流,因为攻击流量还没到它开始贴心"照顾"你的量级。这不代表云厂商不作为,而是免费防护的阈值设计就是这样的。
我自己在处置过程中的感受是:理解了带宽和黑洞的这层逻辑之后,处置方案就清晰了。要么临时把带宽降下来并尽快接受"断我几分钟"的现实,要么直接上付费的流量清洗服务。后者是要花钱的,但业务连续性优先的话,这钱不省。
3. 应急处置:从控制台到命令行的完整操作记录
3.1 优先用VNC保住操作入口
如果此刻你还没被攻击到SSH掉线,只是有点卡,那我建议你先开一个tmux或者screen会话再操作,防止命令执行到一半连接断开导致半途而废。如果已经被打到我当初那种状态,SSH基本连不上,就直接去腾讯云控制台,云服务器实例那页的"登录"按钮里有VNC登录,这是独立于外网带宽的通道,即使公网打满也能进去。
进系统后我先做了一次快照,不是装样子,而是真心建议:攻击过程中产生的包和日志是很好的分析材料,但系统状态是动态的,先拍快照可以避免后续误操作把现场搞丢。有需要的话,之后还能在快照里翻出更早的日志来对比。
我这次进去之后,先用下面这套命令把网络情况完整记录了一遍,等于给攻击现场拍照:
# 记录连接状态分布 netstat -antp | awk '{print $6}' | sort | uniq -c | sort -rn # 记录与80/443端口相关的活跃来源IP ss -antp | grep -E ':(80|443)' | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -20 # 记录UDP连接概况 ss -uanp | head -30 # 抓200个包看流量特征,保留成文件供后续分析 tcpdump -i eth0 -nn -c 200 -w /var/tmp/attack_dump.pcap这些输出我都用重定向存到了文件里。当时觉得麻烦,后来溯源时发现这些记录帮了大忙,攻击结束后很多状态就没了,有pcap文件在可以反复分析。
3.2 安全组紧急封禁:先阻断再深挖
控制台里最立竿见影的处置动作不是改服务器内部配置,而是改安全组。安全组是腾讯云在虚拟机外层的防火墙,流量到达系统之前就会在这里被过滤,所以它是成本最低、速度最快的阻断手段。
我当时的思路分两条腿走:
第一条腿是封来源。如果查出来攻击源IP是少数几个固定的IP,直接在安全组加一条"拒绝"规则,来源填对应IP,协议和端口选全部,策略选拒绝,优先级放到最前面。注意安全组规则是有顺序匹配的,从上到下第一条命中的规则生效,所以拒绝规则必须放在放行规则前面。
第二条腿是封端口。对于UDP Flood这种无差别攻击,通常攻击都打在某些特定端口上,如果你对外业务不需要UDP端口,可以直接在安全组里把对应UDP端口全部拒绝。比如我这次UDP流量大量集中在随机高位端口,我就先加了一条拒绝全部UDP入站的规则。这一步做完,服务器的压力立刻降了不少,至少SSH能顺畅用了。
这里有个经验教训:不要贪心把安全组规则删光来"清净",更不要在没确认自己IP的情况下把自己IP也封了。我第一次搞安全组时把自己当前IP顺手加进了拒绝列表,结果VNC回不去、SSH也连不上,折腾了十几分钟才意识到问题。改安全组之前,先确认自己的出口IP是什么,加完规则后留一个VNC窗口在控制台别关,防止操作失误被锁在门外。
3.3 临时止血后如何恢复业务
安全组封掉UDP后,我的SSH恢复了,但业务还没有完全恢复,因为安全组规则的生效存在一点时间差,而且之前堆积的连接还在。这时候我在服务器内部又做了一层快速的iptables加固,作为双保险。注意iptables规则是立刻生效的,如果稍后改了安全组,也不冲突。
# 丢弃所有入站UDP包(根据实际业务自行调整,如果业务本身用UDP则不能这么干) iptables -I INPUT -p udp -j DROP # 限制单个IP对本机80端口的并发连接数,缓解可能存在的连接耗尽 iptables -I INPUT -p tcp --dport 80 -m connlimit --connlimit-above 200 -j REJECT这一步做完之后,带宽监控曲线开始明显回落。我建议你在确认攻击高峰过去之后,花几分钟观察一下,不要急着把所有规则撤掉。你得先确认业务恢复正常了,再去慢慢放开限制,每一步改动都小步快跑,观察几分钟再动下一步。
恢复业务还有一个容易被忽略的点:DNS和缓存。如果你的域名之前解析到的IP被攻击了,即使攻击停了,部分地区的DNS缓存可能还指向旧IP。我自己当时在腾讯云控制台把DNS记录刷新了一下,同时等了几分钟让运营商DNS缓存自然过期,全国的访问就逐渐恢复了。如果你是自建DNS或者用了多级CDN,这一步更要注意。
3.4 高防与流量清洗:什么情况必须花钱
安全组和iptables能挡一部分攻击,但挡不住大流量DDoS,因为UDP Flood的流量在到达服务器之前就已经把你的带宽占满了,安全组在流量进到VPC之后才生效,等于说垃圾流量已经在你的网络里跑了一遍,带宽已经消耗了。真要防住这种攻击,必须把清洗动作放在云厂商的骨干网络上完成,也就是购买DDoS高防产品。
腾讯云的方案我实际对比过,大概两条路:
一条是DDoS高防IP。你买一个高防IP,把域名的解析切到高防IP上,所有流量先经过高防机房的流量清洗,清洗干净之后,正常流量再转发到你原来的服务器IP。这种方式效果最好,缺点是会引入转发延迟,而且配置域名切换也需要一点时间。
另一条是DDoS高防包。直接给现有IP叠加防护能力,不用换IP,配置比较简单。我当时考虑过,但后来分析发现我这种小流量攻击用高防包有点大材小用,而且按年付费也是一笔开销,就没有立马上。但如果你跑的是正式业务,或者被攻击的频率已经超过一周一次,我的建议是别犹豫,直接上高防IP。跟停机损失比起来,防护成本真的不高。
这次攻击量级其实不算大,属于那种"很烦但不至于搞挂云平台"的级别,所以我临时用安全组和iptables顶住了,后面再做的加固动作,才是真正让攻击成本变高的核心。
4. 事后加固:让下一次被攻击的成本变高
4.1 SSH与登录层的三条硬规则
每次被攻击之后,我都会顺手检查一下服务器的登录暴露面,因为攻击者不会平白无故盯上一台机器,很多时候是因为扫描到了你的SSH端口是默认的22,密码强度又不够,先试探性地爆破一波,爆破不成就顺手报个攻击,让你焦头烂额。所以第一项加固就是SSH。
三条硬规则,缺一不可:
修改SSH默认端口。把
/etc/ssh/sshd_config里的Port 22改成比如Port 2222,改完重启sshd服务。这个动作能挡掉90%以上的扫描流量,因为绝大多数自动化攻击脚本只会扫默认端口。禁用密码登录,改用密钥登录。先在本地执行
ssh-keygen -t ed25519生成密钥对,然后把公钥内容追加到服务器~/.ssh/authorized_keys里,确认密钥登录没问题后,再把PasswordAuthentication设为no。这一步是挡暴力破解最狠的招,没有密码可猜,攻击者再怎么做字典都没用。限制root远程登录。日常操作用一个普通用户加sudo来管理,
PermitRootLogin设为prohibit-password,只在需要时通过密钥以非root身份登录。这能大幅降低一旦密钥泄露后的破坏范围。
改配置之前我强烈建议多开一个SSH窗口,或者先起一个tmux会话再改,因为如果配置写错、密钥没配好,你在新端口上连不上,又因为禁用了密码登录,可能连sshd都起不来,那只能VNC进去抢救了。我经历过一次,很痛苦,别重蹈覆辙。
4.2 安全组与防火墙的精细化收敛
解封应急规则后,不能又把所有端口敞开恢复原样,否则就是白加固了。精确到端口的收敛原则是:只放行业务真正需要的端口,其他全部默认拒绝。
我最终的安全组规则大概长这样:
| 方向 | 来源 | 协议端口 | 策略 | 说明 |
|---|---|---|---|---|
| 入站 | 我的固定IP | TCP 2222 | 允许 | SSH管理端口,只对自己的IP开 |
| 入站 | 0.0.0.0/0 | TCP 80/443 | 允许 | Web服务端口 |
| 入站 | 0.0.0.0/0 | TCP 1935 | 允许 | rtmp推流测试端口 |
| 入站 | 0.0.0.0/0 | ICMP | 拒绝 | 防止ping探测和ICMP Flood |
| 入站 | 0.0.0.0/0 | UDP ALL | 拒绝 | 非业务需要,直接全拒 |
服务器内部的iptables规则也和这个对齐了,做到双层防护。这里有个细节:安全组是平台层的,iptables是系统层的,两者不冲突但某种程度上是冗余关系。为什么要双层?因为有些攻击会绕过一层防御打在另一层上,双保险能显著提高拦截率。
4.3 监控告警的补课:提前发现异常
被攻击的第一个告警来自云监控,说明我之前的告警策略是有的,但粒度太粗了,只有"出带宽超过5Mbp持续5分钟"这一条。等到这个告警出来时,其实攻击已经开始一段时间了,所以我又补了几个更早的告警点:
- 入带宽超过正常值持续3分钟。
- SSH登录失败次数出现突刺,比如1分钟内超过10次。
- 安全组被修改后触发操作审计通知。
- 主机CPU或内存使用率异常飙升。
腾讯云控制台的"云监控-告警策略"里都能配置,按实例选好维度、填好阈值、选上通知渠道就行。我自己的习惯是把告警阈值设置得比正常峰值高一点点,宁可偶尔误报,也好过毫无知觉地被小流量打到服务不可用。
另外,我还在服务器本地装了fail2ban,针对SSH做暴力破解防护。它会在一定时间内统计某个IP的登录失败次数,超过阈值就自动拉黑。这个工具在腾讯云上可以直接apt/yum安装,配置默认就够了,我建议每个跑公网的服务器都装上。
5. 攻击溯源与复盘:到底是谁在打我
5.1 从系统日志里翻出攻击源
攻击结束后,我花了不少时间做溯源分析。首先要有一个认知:对于UDP Flood这种没有连接的攻击,你很难真正追溯到"幕后黑手",能追到的只是攻击流量来源的IP,而这些IP大多是僵尸网络成员或被伪造了源地址。但即使如此,日志分析依然有价值,它能告诉你攻击发生的时间线、流量特征、可能的攻击工具,防止下一次被打个措手不及。
看系统日志的重点是SSH认证记录。CentOS/Rocky系统的/var/log/secure、Ubuntu/Debian系统的/var/log/auth.log里,记录了所有登录企图:
# 统计登录失败次数最多的IP grep "Failed password" /var/log/secure | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head -20跑完这个命令,你会发现一些非常有趣的规律。我这次在日志里看到,攻击发生前约两小时就有几个IP在持续尝试SSH登录,虽然不是主流攻击流量,但把时间线串起来之后,基本能判断这不是随机扫描,而是有人先把靶机名单整理好、先做了一轮试探,随后才发起的流量型攻击。这些IP和UDP Flood来源IP并不重合,说明流量攻击大概率用了代理或僵尸网络做跳板。
5.2 从Web日志还原攻击行为
除了系统日志,Web服务的访问日志也非常重要。我跑的是Nginx,日志在/var/log/nginx/access.log,攻击当天这文件膨胀了好几倍。
先看请求量变化:
# 统计某一天的请求总数 awk '{print $4}' /var/log/nginx/access.log | cut -d: -f1 | sort | uniq -c再按IP和路径统计请求分布:
# 定义攻击时间段,统计来源IP Top 10 grep "2025-06" /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -10 # 统计请求最多的URL,识别是否被针对特定接口打 awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10如果攻击是CC类型,日志里能看出UA非常随机、请求频率极高、路径集中在某个API上。如果只是流量型攻击,Web日志反而不会太夸张,因为大部分攻击流量根本没进入Web层就被带宽挡在外面了。我这次的情况属于后者,所以Nginx日志信息量有限,真正的证据都在pcap抓包里。
5.3 一次实战复盘得到的三个经验
复盘这件事,我个人认为比处置本身更重要,所以专门留了一节来说。经过这次被攻击,我总结了三条经验,可以说每条都是用时间和流量换来的:
第一,基础防护额度不够用的时候,不要硬扛。我当时纠结了很久要不要买高防,觉得只是个人项目没必要花钱,结果下一次攻击又来了,还是要面对。如果你的业务有收入、有用户、有稳定流量,请把DDoS高防当作基础设施成本的一部分,和服务器费用一样正常。
第二,提前把"运维手册"写好,省得半夜慌乱。我这次能在一小时内完成从发现到基本止血,很大程度上是因为平时积累了一些排查命令和处置流程。建议你把自己的服务器情况梳理一份简单的SOP,放在本地或云端笔记里,告警响起时直接照着执行,省去现场思考的时间。
第三,攻击并不可怕,被同一块石头绊倒两次才可怕。每次攻击都留下了日志和抓包文件,建议归档到本地或对象存储里,命名带上日期和攻击类型。下次再发生类似情况,先翻旧资料对比,往往几分钟就能判断出攻击手法的相同点和变化,处置效率会高非常多。
写到这里,这场"带宽保卫战"算是阶段性结束了。我个人的体会是:服务器被攻击这件事,在云时代几乎每个站长或运维都会遇到一次,它不是末日,而是一次很有价值的安全演练。关键是别慌、按流程走、事后认真加固和复盘。如果你也被攻击打过一次,希望你看到这篇文章时,能少走一些弯路,睡得更安稳一点。