Ubuntu服务器带宽失控最常见的表现不是被DDoS打满,而是出方向的流量被大量消耗。很多运维只监控入站流量,结果服务器变成扫描肉鸡或者被用来对外发包,出站带宽跑满后连SSH都连不上。处理这个问题要先把tc这个内核自带的流量控制工具用起来。Ubuntu默认就带tc,不需要额外安装,但很多管理员从来没碰过它。先看当前网卡队列规则:

tc qdisc show dev eth0

默认输出一般是pfifo_fast,也就是先进先出,没有任何带宽限制。要对出站流量做整体限速,先删掉现有规则再重新添加htb队列:

tc qdisc del dev eth0 root
tc qdisc add dev eth0 root handle 1: htb default 30
tc class add dev eth0 parent 1: classid 1:1 htb rate 100mbit ceil 100mbit
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 80mbit ceil 100mbit
tc class add dev eth0 parent 1:1 classid 1:30 htb rate 10mbit ceil 20mbit

上面的规则把eth0的总出站带宽限制在100mbit,其中正常业务流量走1:10这个类,最多能用到100mbit,其他所有流量走1:30默认类,基础速率只有10mbit,突发最高20mbit。这样即使有异常进程在对外发包,也不会把整条带宽全部占死,SSH管理通道始终能保留住。注意这里的rate是保证速率,ceil是最大可借用的速率,两个参数要理解清楚,否则限速会不符合预期。

光有限速还不够,必须知道是哪个进程在消耗带宽。nethogs是排查带宽占用的利器,安装很简单:

apt install nethogs -y
nethogs eth0

nethogs会实时显示每个进程的上下行速率,按出站流量排序,一眼就能看出是哪个程序在疯狂发包。如果是某个PHP进程或者node进程异常,直接找到对应的服务去处理。但nethogs只能看实时数据,如果流量是间歇性爆发,需要用iftop配合抓包来分析。iftop可以按连接对来显示带宽:

apt install iftop -y
iftop -i eth0 -P

iftop的输出里能看到源IP、目标IP、端口和实时速率,如果发现服务器在向某个陌生IP的奇怪端口大量发包,基本可以确定是被入侵了。这时候不要只想着限速,要先隔离处理。用ss命令查看对应连接对应的进程:

ss -tnp | grep 目标IP

找到进程PID后,用ps和lsof确认进程路径和文件来源,判断是不是挖矿木马或者发包工具。确认异常后直接kill掉进程,然后检查crontab、systemd timer、/tmp目录、隐藏目录这些常见持久化位置。很多挖矿木马会把启动项写在/var/spool/cron/crontabs/root或者/etc/cron.d下面,用grep搜一下最近修改的文件:

find /etc/cron* /var/spool/cron* -type f -mtime -3 -exec ls -l {} \;

处理完异常进程后,要立刻加固SSH。检查/var/log/auth.log里有没有暴力破解的痕迹:

grep "Failed password" /var/log/auth.log | awk '{print $(NF-3)}' | sort | uniq -c | sort -nr | head

如果某个IP有大量失败尝试,直接用ufw或者iptables封掉。Ubuntu默认有ufw,启用后加规则:

ufw allow from 你的管理IP to any port 22
ufw default deny incoming
ufw default allow outgoing
ufw enable

把SSH的默认端口22改掉也是必要的,修改/etc/ssh/sshd_config里的Port参数,同时把PasswordAuthentication改成no,只允许密钥登录。改完重启sshd服务。这些基础加固做完,带宽被异常消耗的概率会大幅降低。

对于正常的业务流量,也需要做精细化的带宽分配。比如服务器同时跑Web服务和数据库,Web服务需要保证响应速度,数据库备份任务会占用大量带宽。可以用tc的过滤器把不同端口的流量分到不同的类里面:

tc filter add dev eth0 parent 1: protocol ip u32 match ip sport 80 0xffff flowid 1:10
tc filter add dev eth0 parent 1: protocol ip u32 match ip sport 443 0xffff flowid 1:10
tc filter add dev eth0 parent 1: protocol ip u32 match ip sport 3306 0xffff flowid 1:20

这样80和443端口的出站流量走1:10这个高优先级类,3306端口的流量走1:20这个类,可以给数据库备份单独设置一个较低的速率上限。tc的过滤器规则是从上往下匹配的,顺序很重要,先匹配到的规则生效。用u32匹配端口时要注意,sport是源端口,dport是目标端口,出站流量的源端口才是服务的监听端口,不要写反了。

入站流量的管控比出站更难,因为入站流量在到达服务器之前已经消耗了带宽,tc只能在数据包进入网卡后做处理,对于已经占满带宽的攻击流量,tc能起到的作用有限。但如果是针对特定端口的SYN Flood或者CC攻击,可以在iptables层面做限制。用limit模块限制单个IP的并发连接数:

iptables -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 50 -j DROP
iptables -A INPUT -p tcp --dport 443 -m connlimit --connlimit-above 50 -j DROP

再用recent模块限制单个IP的请求频率:

iptables -A INPUT -p tcp --dport 80 -m state --state NEW -m recent --set
iptables -A INPUT -p tcp --dport 80 -m state --state NEW -m recent --update --seconds 1 --hitcount 20 -j DROP

这两条规则配合使用,能挡住大部分简单的CC攻击。对于更复杂的应用层攻击,需要上nginx层面的limit_req和limit_conn模块,在应用层做更精细的请求速率控制。nginx的配置示例:

limit_req_zone $binary_remote_addr zone=web_req:10m rate=10r/s;
limit_conn_zone $binary_remote_addr zone=web_conn:10m;

server {
    location / {
        limit_req zone=web_req burst=20 nodelay;
        limit_conn web_conn 10;
    }
}

limit_req控制每秒请求数,burst允许短时间突发,nodelay让超出部分立即返回503而不是排队。limit_conn控制单个IP的并发连接数。这两个参数要根据实际业务调整,设太严会误伤正常用户,设太松又起不到防护作用。建议先用日志分析出正常用户的请求分布,再设置阈值。

带宽监控是持续运维的关键环节。vnstat是一个轻量级的流量统计工具,可以按小时、天、月记录流量数据:

apt install vnstat -y
vnstat -i eth0 -d

vnstat会持续在后台记录流量,不需要root权限常驻进程,数据存在/var/lib/vnstat下面。定期查看流量趋势,如果某天流量突然翻倍,就要警觉是不是有异常。配合cacti或者zabbix这样的监控系统,可以设置流量阈值告警,超过预设值就发通知。zabbix的监控项里直接选net.if.out[eth0]和net.if.in[eth0],触发器设置流量超过带宽的80%持续5分钟就告警,这样能在带宽被打满之前发现问题。

还有一个容易被忽视的点是DNS流量。如果服务器上跑了DNS服务,或者被当作DNS反射攻击的放大器,UDP 53端口的流量会异常巨大。检查方法:

tcpdump -i eth0 -n udp port 53 -c 100

如果看到大量响应包发往同一个IP或者大量请求来自伪造的源地址,说明DNS服务被滥用了。BIND的配置里要关闭递归查询,只对信任的网段开放:

options {
    allow-recursion { none; };
    allow-query { any; };
    recursion no;
};

如果不需要对外提供DNS服务,直接在防火墙层面把53端口的UDP和TCP全部封掉,从根源上杜绝被利用的可能。

Ubuntu服务器带宽管控的核心思路是:先限速保底,再定位异常进程,然后做安全加固,最后建立持续监控。tc限速是最后一道防线,保证服务器不会因为流量异常而完全失联;nethogs和iftop是排查工具,帮助快速定位问题;iptables和nginx的限流是主动防御手段;vnstat和监控系统是长期运维的保障。这几层配合起来,才能把带宽安全管控做到位。很多运维只关注CPU和内存,带宽往往被忽视,但带宽一旦出问题,影响的是整个服务的可用性,比单台服务器负载过高更严重。