当心服务器流量被刷,通过脚本实时监测,流量超过阀值进行限制,并按月归零。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
| #!/bin/bash
LIMIT_GB=${1:-1024} reset_day=${2:-1} CHECK_TYPE=${3:-4} INTERFACE=${4:-$(ip route | grep default | awk '{print $5}')} LIMIT=$(echo "$LIMIT_GB * 1024" | bc) echo "流量限制:$LIMIT MiB" echo "流量将在每月的第 $reset_day 天重置" current_day=$(date +'%-d') last_day_of_month=$(date -d "$(date +'%Y%m01') +1 month -1 day" +%d) if [ "$current_day" -eq "$reset_day" ] || ([ "$reset_day" -gt "$last_day_of_month" ] && [ "$current_day" -eq "$last_day_of_month" ]); then if [ ! -f "/tmp/vnstat_reset" ]; then touch /tmp/vnstat_reset rm /var/lib/vnstat/* sudo systemctl restart vnstat echo "流量已经重置,下次重置将在下个月的第 $reset_day 天" else echo "今天已经进行过流量重置,无需再次重置" fi else if [ -f "/tmp/vnstat_reset" ]; then rm /tmp/vnstat_reset fi if [ "$current_day" -lt "$reset_day" ]; then days_until_reset=$(($reset_day - $current_day)) echo "还有 $days_until_reset 天流量将会重置" else days_until_reset=$(( $last_day_of_month - $current_day + $reset_day )) echo "还有 $days_until_reset 天流量将会重置" fi fi if [ -z "$INTERFACE" ]; then echo "错误:无法自动检测网络接口。请手动指定。" exit 1 fi echo "正在监控的网络接口:$INTERFACE" DATA=$(vnstat -i $INTERFACE --oneline) CURRENT_DATE=$(echo $DATA | cut -d ';' -f 8) TRAFFIC_RX=$(echo $DATA | cut -d ';' -f 13 | tr -d ' ' | sed 's/MiB//;s/GiB/*1024/;s/KiB/\/1024/' | bc) TRAFFIC_TX=$(echo $DATA | cut -d ';' -f 14 | tr -d ' ' | sed 's/MiB//;s/GiB/*1024/;s/KiB/\/1024/' | bc) echo "当前月份:$CURRENT_DATE" if [ "$CHECK_TYPE" = "1" ]; then TRAFFIC_TO_CHECK=$TRAFFIC_TX echo "只检查上传流量。当前上传流量为:$TRAFFIC_TX MiB。" echo "当前对比项是:上传流量。" elif [ "$CHECK_TYPE" = "2" ]; then TRAFFIC_TO_CHECK=$TRAFFIC_RX echo "只检查下载流量。当前下载流量为:$TRAFFIC_RX MiB。" echo "当前对比项是:下载流量。" elif [ "$CHECK_TYPE" = "3" ]; then TRAFFIC_TO_CHECK=$(echo "$TRAFFIC_TX $TRAFFIC_RX" | awk '{print ($1>$2)?$1:$2}') if [ "$TRAFFIC_TO_CHECK" = "$TRAFFIC_TX" ]; then echo "当前上传流量为:$TRAFFIC_TX MiB,下载流量为:$TRAFFIC_RX MiB。" echo "作为比较的流量是:上传流量。" else echo "当前上传流量为:$TRAFFIC_TX MiB,下载流量为:$TRAFFIC_RX MiB。" echo "作为比较的流量是:下载流量。" fi elif [ "$CHECK_TYPE" = "4" ]; then TRAFFIC_TO_CHECK=$(echo "$TRAFFIC_TX + $TRAFFIC_RX" | bc) echo "检查上传和下载流量的总和。当前上传流量为:$TRAFFIC_TX MiB,下载流量为:$TRAFFIC_RX MiB。" echo "作为比较的流量是:上传和下载流量的总和($TRAFFIC_TO_CHECK MiB)。" else echo "错误:未提供有效的流量检查参数。参数应为1(只检查上传流量)、2(只检查下载流量)、3(检查上传和下载流量中的最大值) 或4(检查上传和下载流量的总和)。" exit 1 fi if (( $(echo "$TRAFFIC_TO_CHECK > $LIMIT" | bc -l) )); then iptables -F iptables -X iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT ACCEPT iptables -A INPUT -p tcp --dport 22 -j ACCEPT iptables -A INPUT -i lo -j ACCEPT iptables -A OUTPUT -o lo -j ACCEPT echo "警告:流量已超出限制!除SSH(端口22)外,所有端口已被阻止。" else iptables -P INPUT ACCEPT iptables -P OUTPUT ACCEPT iptables -P FORWARD ACCEPT iptables -F echo "流量在设定的限制内,所有流量都被允许。" fi
|
此脚本用于监控Linux服务器上的网络流量(出流量和入流量),并根据设定的流量阀值来阻止除SSH(端口22)以外的所有网络流量(通过阻断端口实现)。
这个脚本需要iptables,bc 和 vnstat 这三个软件包。iptables 配置 Linux 内核防火墙的工具,bc(Binary Calculator)用于实现任意精度计算(往往是高精度计算),vnstat 是网络流量监控工具。
安装上述三个软件包,
1 2
| sudo apt-get update sudo apt-get install -y iptables bc vnstat
|
运行脚本前,给脚本添加执行权限,
1
| chmod +x traffic_monitor.sh
|
运行脚本,
1
| bash traffic_monitor.sh 19 1 3 eth0
|
脚本有四个参数可设定,第一个LIMIT_GB,每月流量阀值,单位GB,默认1024(上面我设定为19GB);第二个reset_day,即每月的哪一天流量会被重置。默认值为1,即每月的第一天;第三个CHECK_TYPE,流量检测类型,默认值为4。1表示只检测入流量,2表示只检测出流量,3表示取入流量和出流量中的较大值,4表示检测入和出流量的总和;第四个INTERFACE:网络接口(上例中为eth0)。
脚本运行结果,
1 2 3 4 5 6 7 8
| 流量限制:19456 MiB 流量将在每月的第 1 天重置 还有 1 天流量将会重置 正在监控的网络接口:eth0 当前月份:Oct '24 当前上传流量为:29.39 MiB,下载流量为:7.90 MiB。 作为比较的流量是:上传流量。 流量在设定的限制内,所有流量都被允许。
|
通过crontab设定定时任务,使脚本每五分钟运行一次(即每5分钟监测一次流量,可以按需设定频率),并将脚本的输出重定向到 /root/traffic-log.txt 文件,以便随时查看。
1
| (crontab -l ; echo "*/5 * * * * /root/traffic_monitor.sh 19 1 3 eth0 > /root/trafficl-log.txt") | crontab -
|
评论