Ubuntu系统下限制SSH用户总流量使用量的方法咨询
你好!确实SSH本身没有内置的总流量限制功能,不过在Ubuntu上我们可以通过一些工具组合来实现这个需求,下面给你几个可行的方案:
方案一:利用iptables+流量统计脚本
这个思路是通过iptables针对特定用户的SSH流量做统计,然后配合脚本定期检查流量使用情况,达到阈值就断开用户连接或者阻止后续流量。
首先,为目标用户(比如User1)的SSH流量添加iptables规则,统计上传和下载流量:
# 统计User1的SSH下载流量(从服务器到用户) iptables -A OUTPUT -p tcp --sport 22 -m owner --uid-owner User1 -j ACCEPT -m comment --comment "User1 SSH download" iptables -A OUTPUT -p tcp --sport 22 -m owner --uid-owner User1 -j RETURN -m comment --comment "Count User1 SSH download" # 统计User1的SSH上传流量(从用户到服务器) iptables -A INPUT -p tcp --dport 22 -m owner --uid-owner User1 -j ACCEPT -m comment --comment "User1 SSH upload" iptables -A INPUT -p tcp --dport 22 -m owner --uid-owner User1 -j RETURN -m comment --comment "Count User1 SSH upload"这里可以直接用用户UID代替用户名(比如
--uid-owner 1001),匹配会更准确。编写一个简单的bash脚本,定期检查iptables的流量统计:
#!/bin/bash USER="User1" LIMIT_GB=1 LIMIT_BYTES=$((LIMIT_GB * 1024 * 1024 * 1024)) # 获取下载流量(单位:字节) DOWNLOAD=$(iptables -L OUTPUT -v -n -x | grep "$USER SSH download" | awk '{print $2}') # 获取上传流量 UPLOAD=$(iptables -L INPUT -v -n -x | grep "$USER SSH upload" | awk '{print $2}') TOTAL=$((DOWNLOAD + UPLOAD)) if [ $TOTAL -ge $LIMIT_BYTES ]; then # 阻止该用户的SSH流量 iptables -I INPUT -p tcp --dport 22 -m owner --uid-owner $USER -j DROP iptables -I OUTPUT -p tcp --sport 22 -m owner --uid-owner $USER -j DROP # 断开现有连接并记录日志 pkill -u $USER sshd echo "User $USER has exceeded $LIMIT_GB GB SSH traffic limit." >> /var/log/ssh_traffic_limit.log fi给脚本添加执行权限并保存到系统目录:
chmod +x /usr/local/bin/ssh_traffic_check.sh用crontab设置定期执行,比如每分钟检查一次:
crontab -e添加一行定时任务:
* * * * * /usr/local/bin/ssh_traffic_check.sh另外记得用
iptables-save > /etc/iptables/rules.v4保存规则,避免重启后丢失。
方案二:使用cgroup v2限制进程总流量
Ubuntu 21.04及以上版本默认支持cgroup v2,我们可以为特定用户的SSH进程创建专属控制组,设置流量配额。
先确认cgroup v2已启用:
mount | grep cgroup2如果没有输出,需要编辑
/etc/default/grub,修改GRUB_CMDLINE_LINUX为:GRUB_CMDLINE_LINUX="systemd.unified_cgroup_hierarchy=1"执行
update-grub后重启系统即可启用。为User1创建cgroup目录:
USER_UID=$(id -u User1) mkdir -p /sys/fs/cgroup/user.slice/user-${USER_UID}.slice/ssh-traffic-limit设置总流量限制(这里是1GB,单位为字节):
# 统一限制上传+下载总流量 echo $((1 * 1024 * 1024 * 1024)) > /sys/fs/cgroup/user.slice/user-${USER_UID}.slice/ssh-traffic-limit/io.max # 若要分别限制上传下载,可指定设备(替换/dev/sda为你的网卡对应设备) # echo "/dev/sda:rbytes=1073741824,wbytes=1073741824" > /sys/fs/cgroup/user.slice/user-${USER_UID}.slice/ssh-traffic-limit/io.max将User1的现有SSH进程加入控制组:
for pid in $(pgrep -u User1 sshd); do echo $pid > /sys/fs/cgroup/user.slice/user-${USER_UID}.slice/ssh-traffic-limit/cgroup.procs done想要让新登录的SSH进程自动加入控制组,可以编写PAM规则或者修改sshd配置,实现登录时自动移入cgroup。
方案三:使用专门的流量配额工具
可以尝试系统自带的第三方工具,比如bwctl,安装后通过配置文件快速设置用户流量配额:
apt update && apt install bwctl
这类工具会帮你处理流量统计和限制的逻辑,不需要自己编写脚本,适合不想折腾的场景。
方案对比
- 方案一灵活度高,无需额外安装工具,但需要维护脚本和规则,适合临时需求或自定义场景。
- 方案二更偏向系统级管控,稳定性强,适合长期固定的流量限制需求。
- 方案三操作最简单,但需要学习工具的配置逻辑。
备注:内容来源于stack exchange,提问作者shayan

