监测服务器流量并进行限制脚本

当心服务器流量被刷,通过脚本实时监测,流量超过阀值进行限制,并按月归零。

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
# Parameter order: LIMIT_GB, reset_day, CHECK_TYPE, INTERFACE
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 -
给99元每年的阿里云经济型e实例开启IPv6访问享受大带宽免费流量

  评论