脚本(需要配yum)
#!/bin/bash
# 抓包监控脚本 - 捕获所有流量版(进出流量分离)
# 配置项
CAPTURE_DIR="/var/pcap" # 抓包存储目录
UPDATE_INTERVAL=60 # 抓包间隔(秒)
DISK_THRESHOLD=80 # 磁盘使用率阈值(%)
INTERFACE="$(ip -o link show | awk -F': ' '{if ($2 != "lo") print $2}' | head -n 1)" # 监听的网卡
IN_STATS_FILE="$CAPTURE_DIR/access_stats_in.txt" # 入方向统计文件
OUT_STATS_FILE="$CAPTURE_DIR/access_stats_out.txt" # 出方向统计文件
LOG_FILE="$CAPTURE_DIR/zhuabao.log" # 运行日志文件
MAX_LOG_SIZE=100 # 日志文件最大大小(MB)
LOG_RETENTION=7 # 日志保留天数
# 获取本机IP地址
LOCAL_IP=$(ip -o -4 addr list $INTERFACE | awk '{print $4}' | cut -d/ -f1)
if [ -z "$LOCAL_IP" ]; then
echo "无法获取本机IP地址,请检查网卡配置"
exit 1
fi
# 识别系统类型并安装依赖
install_dependencies() {
local distro=""
local pkg_manager=""
local install_cmd=""
# 检测系统类型
if [ -f /etc/os-release ]; then
source /etc/os-release
distro=$ID
elif type lsb_release >/dev/null 2>&1; then
distro=$(lsb_release -si | tr '[:upper:]' '[:lower:]')
else
log "WARN: 无法确定Linux发行版,将尝试通用安装方法"
distro="unknown"
fi
# 根据系统类型设置包管理器和安装命令
case $distro in
ubuntu|debian)
pkg_manager="apt-get"
install_cmd="sudo $pkg_manager install -y"
;;
centos|rhel|fedora|rocky|almalinux)
pkg_manager="yum"
[ "$distro" = "fedora" ] && pkg_manager="dnf"
install_cmd="sudo $pkg_manager install -y"
;;
opensuse*|sles)
pkg_manager="zypper"
install_cmd="sudo $pkg_manager install -y"
;;
arch)
pkg_manager="pacman"
install_cmd="sudo $pkg_manager -S --noconfirm"
;;
*)
log "ERROR: 不支持的Linux发行版: $distro"
return 1
;;
esac
log "INFO: 检测到系统: $distro, 使用包管理器: $pkg_manager"
# 检查并安装必要软件包
local required_pkgs=("tcpdump" "tshark" "wireshark-common" "coreutils")
local missing_pkgs=()
# 检查哪些包未安装
for pkg in "${required_pkgs[@]}"; do
if ! command -v $pkg >/dev/null 2>&1; then
missing_pkgs+=("$pkg")
fi
done
# 如果有缺失的包则安装
if [ ${#missing_pkgs[@]} -gt 0 ]; then
log "INFO: 正在安装缺失的软件包: ${missing_pkgs[*]}"
# 更新包索引
case $distro in
ubuntu|debian)
sudo $pkg_manager update
;;
centos|rhel|fedora|rocky|almalinux)
sudo $pkg_manager makecache
;;
esac
# 特殊处理不同系统的包名差异
local install_pkgs=()
for pkg in "${missing_pkgs[@]}"; do
case $pkg in
tshark)
case $distro in
ubuntu|debian)
install_pkgs+=("wireshark")
;;
centos|rhel|fedora|rocky|almalinux)
install_pkgs+=("wireshark")
;;
*)
install_pkgs+=("$pkg")
;;
esac
;;
*)
install_pkgs+=("$pkg")
;;
esac
done
# 执行安装
if ! $install_cmd "${install_pkgs[@]}"; then
log "ERROR: 软件包安装失败"
return 1
fi
log "INFO: 软件包安装完成"
else
log "INFO: 所有依赖已安装"
fi
return 0
}
# 日志管理
manage_logs() {
# 检查日志大小
if [ -f "$LOG_FILE" ]; then
log_size=$(du -m "$LOG_FILE" | cut -f1)
if [ "$log_size" -gt "$MAX_LOG_SIZE" ]; then
mv "$LOG_FILE" "${LOG_FILE}.old"
touch "$LOG_FILE"
fi
fi
# 清理旧日志
find "$CAPTURE_DIR" -name "zhuabao.log.old" -mtime +$LOG_RETENTION -delete
}
# 初始化目录和标题
init_files() {
sudo mkdir -p "$CAPTURE_DIR" || {
log "ERROR: 无法创建目录 $CAPTURE_DIR"
exit 1
}
sudo touch "$LOG_FILE" || {
log "ERROR: 无法创建日志文件"
exit 1
}
# 初始化入方向统计文件(如果不存在)
if [ ! -f "$IN_STATS_FILE" ]; then
echo "# 入方向流量统计" | sudo tee "$IN_STATS_FILE" >/dev/null
echo "# 源IP 目的IP 目的端口 访问次数" | sudo tee -a "$IN_STATS_FILE" >/dev/null
echo "# ===============================================" | sudo tee -a "$IN_STATS_FILE" >/dev/null
fi
# 初始化出方向统计文件(如果不存在)
if [ ! -f "$OUT_STATS_FILE" ]; then
echo "# 出方向流量统计" | sudo tee "$OUT_STATS_FILE" >/dev/null
echo "# 源IP 目的IP 目的端口 访问次数" | sudo tee -a "$OUT_STATS_FILE" >/dev/null
echo "# ===============================================" | sudo tee -a "$OUT_STATS_FILE" >/dev/null
fi
}
# 智能日志记录
log() {
manage_logs # 先检查日志状态
echo "[$(date +'%F %T')] $1" | sudo tee -a "$LOG_FILE"
}
# 检查网卡是否存在
check_interface() {
if ! ip link show "$INTERFACE" &>/dev/null; then
log "ERROR: 网卡 $INTERFACE 不存在! 可用网卡:"
ip -o link show | awk -F': ' '{print $2}' | sudo tee -a "$LOG_FILE"
return 1
fi
return 0
}
# 生成累计统计报告(分离进出流量)
generate_stats() {
local current_pcap="$CAPTURE_DIR/current_capture.pcap"
# 检查抓包文件是否有效
if [ ! -f "$current_pcap" ] || [ ! -s "$current_pcap" ]; then
log "WARN: 抓包文件不存在或为空"
return 1
fi
log "INFO: 正在生成进出流量统计..."
# 临时文件存储新解析的数据
local new_in_data=$(mktemp)
local new_out_data=$(mktemp)
sudo chmod 644 "$new_in_data" "$new_out_data"
# 捕获所有流量统计并分离进出流量
sudo tshark -r "$current_pcap" -T fields -E separator=, \
-e ip.src -e ip.dst -e tcp.dstport -e udp.dstport 2>/dev/null | \
awk -F, -v local_ip="$LOCAL_IP" '
{
if ($1 && $2) {
port = ($3 != "") ? $3 : ($4 != "") ? $4 : "N/A";
# 判断流量方向
if ($2 == local_ip) {
# 入方向流量:目的IP是本机
key = $1 "," $2 "," port;
in_count[key]++;
} else if ($1 == local_ip) {
# 出方向流量:源IP是本机
key = $1 "," $2 "," port;
out_count[key]++;
} else {
# 其他流量(经过流量)
key = $1 "," $2 "," port;
other_count[key]++;
}
}
}
END {
# 输出入方向流量
for (key in in_count) {
split(key, parts, ",");
printf "%-15s %-15s %-9s %d\n", parts[1], parts[2], parts[3], in_count[key];
}
}' > "$new_in_data"
sudo tshark -r "$current_pcap" -T fields -E separator=, \
-e ip.src -e ip.dst -e tcp.dstport -e udp.dstport 2>/dev/null | \
awk -F, -v local_ip="$LOCAL_IP" '
{
if ($1 && $2) {
port = ($3 != "") ? $3 : ($4 != "") ? $4 : "N/A";
# 判断流量方向
if ($1 == local_ip) {
# 出方向流量:源IP是本机
key = $1 "," $2 "," port;
out_count[key]++;
}
}
}
END {
# 输出出方向流量
for (key in out_count) {
split(key, parts, ",");
printf "%-15s %-15s %-9s %d\n", parts[1], parts[2], parts[3], out_count[key];
}
}' > "$new_out_data"
# 合并入方向数据
local merged_in_data=$(mktemp)
if [ -s "$IN_STATS_FILE" ]; then
awk '
NR == FNR && FNR > 3 { # 读取旧数据(跳过标题)
key = $1 " " $2 " " $3;
count[key] = $4;
next;
}
FNR != NR { # 读取新数据
key = $1 " " $2 " " $3;
count[key] += $4;
}
END {
for (key in count) {
split(key, parts, " ");
printf "%-15s %-15s %-9s %d\n", parts[1], parts[2], parts[3], count[key];
}
}' "$IN_STATS_FILE" "$new_in_data" | sort -k4nr > "$merged_in_data"
else
sort -k4nr "$new_in_data" > "$merged_in_data"
fi
# 合并出方向数据
local merged_out_data=$(mktemp)
if [ -s "$OUT_STATS_FILE" ]; then
awk '
NR == FNR && FNR > 3 { # 读取旧数据(跳过标题)
key = $1 " " $2 " " $3;
count[key] = $4;
next;
}
FNR != NR { # 读取新数据
key = $1 " " $2 " " $3;
count[key] += $4;
}
END {
for (key in count) {
split(key, parts, " ");
printf "%-15s %-15s %-9s %d\n", parts[1], parts[2], parts[3], count[key];
}
}' "$OUT_STATS_FILE" "$new_out_data" | sort -k4nr > "$merged_out_data"
else
sort -k4nr "$new_out_data" > "$merged_out_data"
fi
# 生成最终入方向统计文件
{
echo "# 入方向流量统计"
echo "# 源IP 目的IP 目的端口 访问次数"
echo "# ==============================================="
cat "$merged_in_data"
} | sudo tee "$IN_STATS_FILE" > /dev/null
# 生成最终出方向统计文件
{
echo "# 出方向流量统计"
echo "# 源IP 目的IP 目的端口 访问次数"
echo "# ==============================================="
cat "$merged_out_data"
} | sudo tee "$OUT_STATS_FILE" > /dev/null
# 清理临时文件
rm -f "$new_in_data" "$new_out_data" "$merged_in_data" "$merged_out_data" "$current_pcap"
local in_count=$(($(wc -l < "$IN_STATS_FILE") - 3))
local out_count=$(($(wc -l < "$OUT_STATS_FILE") - 3))
log "INFO: 进出流量统计更新完成"
log "INFO: 入方向记录: $in_count 条 | 出方向记录: $out_count 条"
return 0
}
# 主循环
main() {
# 先安装依赖
if ! install_dependencies; then
log "ERROR: 依赖安装失败,脚本终止"
exit 1
fi
init_files
log "INFO: ==== 启动监控 ===="
log "INFO: 网卡: $INTERFACE | 本机IP: $LOCAL_IP | 间隔: ${UPDATE_INTERVAL}s | 存储: $CAPTURE_DIR"
log "INFO: 入方向文件: $IN_STATS_FILE | 出方向文件: $OUT_STATS_FILE"
while true; do
# 磁盘检查
disk_usage=$(df --output=pcent "$CAPTURE_DIR" | tail -n1 | tr -d ' %')
if [ "$disk_usage" -ge "$DISK_THRESHOLD" ]; then
log "WARN: 磁盘使用率 ${disk_usage}% ≥ $DISK_THRESHOLD% 阈值"
break
fi
# 网卡检查
if ! check_interface; then
sleep 10
continue
fi
# 执行抓包(捕获所有流量,不限制过滤条件)
current_pcap="$CAPTURE_DIR/current_capture.pcap"
log "INFO: 开始抓包(捕获所有流量) -> $current_pcap"
if sudo tcpdump -i "$INTERFACE" -G $UPDATE_INTERVAL -W 1 -w "$current_pcap" -s0 -n 2>> "$LOG_FILE"; then
if [ -s "$current_pcap" ]; then
capture_size=$(du -h "$current_pcap" | awk '{print $1}')
log "INFO: 抓包完成 大小: $capture_size"
generate_stats
else
log "INFO: 无网络流量"
fi
else
tcpdump_exit=$?
[ $tcpdump_exit -eq 2 ] && log "WARN: 抓包被中断" || log "WARN: 抓包错误 (退出码: $tcpdump_exit)"
fi
sleep 1
done
log "INFO: ==== 监控停止 ===="
}
# 执行主函数
main
启动命令
chmod +x zhuabao.sh
sed -i 's/\r$//' zhuabao.sh
nohup ./zhuabao.sh > /dev/null 2>&1 &
评论区