VNStat 服务器流量限制实战

用 VNStat 监控服务器流量使用,当超出指定限制时自动禁止所有连接,只允许 SSH 进入。此脚本可用于按量付费公网 IP 的资费控制,防止当服务器遭到攻击或意外的流量高峰出现,导致流量超限最后收到天价账单。

可用于阿里云 CDT 等场景。

1. 安装必要组件

sudo apt-get install vnstat bc jq && \
sudo systemctl start vnstat && \
sudo systemctl enable vnstat

2. 配置 UFW 防火墙

目前手中的云服务器主要使用安全组进行端口管控,不用 ufw,因此这里将 ufw 用来便捷地对整机进行流量限制

(注:需要正常使用 ufw 的用户可以使用 iptables/nftables 实现同样效果)

首先安装 ufw:

sudo apt-get install ufw

然后设置当防火墙启用时,默认 deny 所有请求,仅允许 SSH 连接

sudo ufw allow <SSH端口>/tcp
sudo ufw default deny

配置完毕后执行 sudo ufw enable 启用 ufw 防火墙观察效果,是否除了 SSH 以外其他所有端口都无法再连接。确实有效后执行 sudo ufw disable 禁用 ufw 防火墙。

3. 监控脚本、重置脚本

监控脚本 TrafficMonitor-Check.sh

(此脚本需要定期执行,对流量进行检查,一旦超限则禁用所有连接)

#!/bin/bash

# 日志路径
LOG_FILE="/var/log/traffic_monitor.log"
# 监控网卡名称
INTERFACE="eth0"
# 单月流量限制(单位:GB)
LIMIT=19

# ==========================================

# Logger
log() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE"
}

# 检查是否以 root 权限运行
if [ "$(id -u)" -ne 0 ]; then
    log "错误:此脚本需要 root 权限。请在 root 用户的 crontab 中运行。"
    exit 1
fi

# ==========================================

# 获取当月流量数据(单位:字节)
TX=$(vnstat -i $INTERFACE --json | jq '.interfaces[0].traffic.total.tx')
RX=$(vnstat -i $INTERFACE --json | jq '.interfaces[0].traffic.total.rx')

# 格式转换与累加计算
TX_VALUE=$(echo "scale=2; $TX / 1024 / 1024 / 1024" | bc)
TX_VALUE=$(printf "%.2f" $TX_VALUE)
log "本月已流出流量:$TX_VALUE GB"

RX_VALUE=$(echo "scale=2; $RX / 1024 / 1024 / 1024" | bc)
RX_VALUE=$(printf "%.2f" $RX_VALUE)
log "本月已流入流量:$RX_VALUE GB"

TOTAL_VALUE=$(echo "$TX_VALUE + $RX_VALUE" | bc)
TOTAL_VALUE=$(printf "%.2f" $TOTAL_VALUE)
log "本月总流量:$TOTAL_VALUE GB"


# 检查是否超过流量限制
if (( $(echo "$TOTAL_VALUE >= $LIMIT" | bc -l) )); then
  log "流量超出限制!已禁止除SSH以外其他所有连接"
  ufw --force enable			# 如果流量超限,则启用ufw防火墙,阻断除SSH外所有连接
fi

重置脚本 TrafficMonitor-Reset.bat

(此脚本每月初执行一次,重置当月流量统计,如果处于流量限制状态则进行解除)

#!/bin/bash

# 日志路径
LOG_FILE="/var/log/traffic_monitor.log"
# 监控网卡名称
INTERFACE="eth0"

# ==========================================

# Logger
log() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE"
}

# 检查是否以 root 权限运行
if [ "$(id -u)" -ne 0 ]; then
    log "错误:此脚本需要 root 权限。请在 root 用户的 crontab 中运行。"
    exit 1
fi

# ==========================================

# 重置 vnStat 数据
if vnstat --remove --force -i $INTERFACE && vnstat --add -i $INTERFACE; then
    log "vnStat 数据已重置"
else
    log "错误:重置 vnStat 数据失败"
    exit 1
fi

# 重置流量保护状态
if ufw disable; then
        log "流量保护已重置"
else
    log "错误:流量保护重置失败"
fi

两个脚本均在开头处有配置项,需要按实际情况设置好。每次脚本运行时,日志都会记录到配置的日志文件中

4. 配置 crontab

通过 crontab 实现每 5 分钟运行一次监控脚本,每月初执行一次重置脚本。

执行 sudo crontab -e,选择熟悉的编辑器进行编辑,然后在文件最后追加如下内容,保存即可:

# Traffic Monitor
*/5 * * * * /<path>/<to>/TrafficMonitor-Check.sh
0 0 1 * * /<path>/<to>/TrafficMonitor-Reset.sh

VNStat 服务器流量限制实战
https://blog.openyq.top/posts/1614/
作者
yqs112358
许可协议