vim /usr/local/bin/traffic_guard.sh
#!/bin/bash
# 安全阈值配置
INTERFACE="eth0" # 请根据实际修改网络接口名 (使用 `ip link` 查看)
THRESHOLD_MBPS=50 # 流量差阈值 (MB/s)
DURATION_SECONDS=10 # 持续超过阈值的时间 (秒)
CHECK_INTERVAL=1 # 采样间隔 (秒)
LOG_FILE="/var/log/traffic_monitor.log"
# 检查是否为 root
if [[ $EUID -ne 0 ]]; then
echo "错误:此脚本必须以 root 权限运行" >&2
exit 1
fi
# 检查必要工具
for cmd in awk date grep shutdown ip; do
if ! command -v "$cmd" &> /dev/null; then
echo "错误:未找到命令 '$cmd'" >&2
exit 1
fi
done
# 日志函数
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
log "开始监控接口 $INTERFACE,阈值:${THRESHOLD_MBPS}MB/s 持续 ${DURATION_SECONDS}秒"
consecutive_count=0
while true; do
# 获取当前时间点的 RX/TX 字节数(从 /sys/class/net 读取,更精确高效)
if ! rx_bytes=$(cat /sys/class/net/"$INTERFACE"/statistics/rx_bytes 2>/dev/null); then
log "错误:无法读取接口 $INTERFACE 的接收字节,请检查接口是否存在"
sleep $CHECK_INTERVAL
continue
fi
if ! tx_bytes=$(cat /sys/class/net/"$INTERFACE"/statistics/tx_bytes 2>/dev/null); then
log "错误:无法读取接口 $INTERFACE 的发送字节"
sleep $CHECK_INTERVAL
continue
fi
# 第一次循环只记录,不计算
if [[ -z $prev_rx ]]; then
prev_rx=$rx_bytes
prev_tx=$tx_bytes
prev_time=$(date +%s.%N)
sleep $CHECK_INTERVAL
continue
fi
# 计算时间差和流量差(单位:字节)
current_time=$(date +%s.%N)
elapsed=$(echo "$current_time - $prev_time" | bc -l)
prev_time=$current_time
rx_diff=$((rx_bytes - prev_rx))
tx_diff=$((tx_bytes - prev_tx))
# 转换为 MB/s (1 MB = 1000^2 字节,使用十进制符合网络速率标准)
rx_mbps=$(echo "scale=2; $rx_diff / $elapsed / 1000000" | bc -l)
tx_mbps=$(echo "scale=2; $tx_diff / $elapsed / 1000000" | bc -l)
diff_mbps=$(echo "scale=2; if ($rx_mbps > $tx_mbps) $rx_mbps - $tx_mbps else $tx_mbps - $rx_mbps" | bc -l)
# 更新前值
prev_rx=$rx_bytes
prev_tx=$tx_bytes
# 日志记录当前速率
log "RX: ${rx_mbps}MB/s | TX: ${tx_mbps}MB/s | 差值: ${diff_mbps}MB/s | 连续计数: ${consecutive_count}s"
# 检查差值是否超过阈值
if (( $(echo "$diff_mbps > $THRESHOLD_MBPS" | bc -l) )); then
consecutive_count=$((consecutive_count + CHECK_INTERVAL))
if [ $consecutive_count -ge $DURATION_SECONDS ]; then
log "警告:流量差值 ${diff_mbps}MB/s 已持续 ${DURATION_SECONDS} 秒超过阈值 ${THRESHOLD_MBPS}MB/s,即将关闭服务器!"
shutdown -h +1 "因网络流量异常关闭服务器" # 1分钟后关机,给管理员留出反应时间
# 若需立即关机,请改用:shutdown -h now "流量异常触发关机"
exit 0
fi
else
consecutive_count=0 # 重置计数器
fi
sleep $CHECK_INTERVAL
done
apt-get install bc -y
vim /etc/systemd/system/traffic-guard.service
[Unit]
Description=Network Traffic Anomaly Guard
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/traffic_guard.sh
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now traffic-guard.service
vim /etc/logrotate.d/traffic_guard
/var/log/traffic_monitor.log {
size 10M # 日志达到10MB立即轮转
hourly # 兜底:每小时检查一次(即使未达10MB)
rotate 5 # 最多保留5份历史日志(50MB总空间)
missingok # 日志缺失时不报错
notifempty # 空文件不轮转
compress # 压缩旧日志节省空间
delaycompress # 下次轮转时再压缩(避免当前写入中断)
dateext # 添加日期后缀
dateformat .%Y%m%d%H%M # 精确到分钟的时间戳
copytruncate # 复制后截断原文件(避免服务重启)
maxsize 20M # 紧急兜底:防止单文件突破size限制(需logrotate v3.15+)
}
crontab -e
*/5 * * * * /usr/sbin/logrotate /etc/logrotate.d/traffic_guard --state /var/lib/logrotate/status
tail -f /var/log/traffic_monitor.log