我发现只要统计filter链中forward表的数据就可以了，所以我简化了一下脚本，你再看看有没有问题：#!/bin/bash

# 全局变量定义区域
CONFIG_FILE="/etc/traffic_monitor.conf"
CHAIN_NAME_FILTER="TRAFFIC_MONITOR_FILTER"
CHAIN_NAME_MANGLE="TRAFFIC_MONITOR_MANGLE"

#===============================================================================
# 函数定义区域
#===============================================================================

# 初始化环境的函数
initialize_environment() {
    # 设置语言环境
    export LANG=en_US.UTF-8
    export LC_ALL=en_US.UTF-8

    # 手动设置 PATH
    export PATH=/usr/sbin:/usr/bin:/sbin:/bin

    # 加载配置文件
    if [ -f "$CONFIG_FILE" ]; then
        source "$CONFIG_FILE"
    else
        echo "配置文件 $CONFIG_FILE 未找到，脚本退出" >> /var/log/traffic_monitor.log
        exit 1
    fi

    # 检查必要的配置变量是否已定义
    check_config_variables
}

# 检查配置文件中必要的变量是否已定义
check_config_variables() {
    if [ -z "$LOG_DIR" ] || [ -z "$TARGET_IP" ] || [ -z "$INTERVAL" ] || [ -z "$MAX_TIME" ] || [ -z "$THRESHOLD_RATE" ]; then
        echo "配置文件中缺少必要的变量定义，脚本退出" >> /var/log/traffic_monitor.log
        exit 1
    fi
}

# 创建自定义链并添加规则的函数
setup_iptables_rules() {

    # 检查并创建自定义链
    if ! iptables -t filter -L $CHAIN_NAME_FILTER >/dev/null 2>&1; then
        iptables -t filter -N $CHAIN_NAME_FILTER
    fi

    # 添加规则到相应的系统链中
    add_iptables_rule filter FORWARD "-s $TARGET_IP" "-j $CHAIN_NAME_FILTER"
    add_iptables_rule filter FORWARD "-d $TARGET_IP" "-j $CHAIN_NAME_FILTER"

    # 在自定义链中添加 RETURN 规则
    add_return_rule filter "$CHAIN_NAME_FILTER" "-s $TARGET_IP"
    add_return_rule filter "$CHAIN_NAME_FILTER" "-d $TARGET_IP"
}

# 添加 iptables 规则的函数
add_iptables_rule() {
    local table="$1"
    local chain="$2"
    local rule="$3"
    local action="$4"

    if ! iptables -t "$table" -C "$chain" $rule $action 2>/dev/null; then
        iptables -t "$table" -A "$chain" $rule $action
    fi
}

# 添加 RETURN 规则的函数
add_return_rule() {
    local table="$1"
    local chain="$2"
    local rule="$3"

    add_iptables_rule "$table" "$chain" "$rule" "-j RETURN"
}

# 检查并处理流量限制的函数
check_and_handle_limits() {
    # 获取当前日期和时间
    CURRENT_HOUR=$(date +'%H')
    CURRENT_DATE=$(date +'%Y-%m-%d')

    # 创建日志目录
    mkdir -p "$LOG_DIR"

    # 初始化日志文件路径
    CURRENT_HOUR_LOG="$LOG_DIR/hour_$CURRENT_HOUR.log"
    CURRENT_DAILY_LOG="$LOG_DIR/$CURRENT_DATE.log"

    # 读取已使用时间
    read_usage_time

    # 检查是否超过最大使用时间
    if (( DAILY_USED_TIME >= MAX_TIME )); then
        block_traffic
        exit 0
    fi
}

# 读取使用时间的函数
read_usage_time() {
    DAILY_USED_TIME=$(cat "$CURRENT_DAILY_LOG" 2>/dev/null || echo 0)
    HOUR_USED_TIME=$(cat "$CURRENT_HOUR_LOG" 2>/dev/null || echo 0)

    # 确保变量为整数
    DAILY_USED_TIME=${DAILY_USED_TIME:-0}
    HOUR_USED_TIME=${HOUR_USED_TIME:-0}
}

# 删除 iptables 规则的函数
remove_iptables_rule() {
    local table="$1"
    local chain="$2"
    local rule="$3"
    local action="$4"

    if iptables -t "$table" -C "$chain" $rule $action 2>/dev/null; then
        iptables -t "$table" -D "$chain" $rule $action
        logger -t traffic_monitor "Removed iptables rule: -t $table -D $chain $rule $action"
    fi
}

# 添加 DROP 规则的函数
add_drop_rule() {
    local table="$1"
    local chain="$2"
    local rule="$3"
    local action="-j DROP"

    if ! iptables -t "$table" -C "$chain" $rule $action 2>/dev/null; then
        iptables -t "$table" -A "$chain" $rule $action
        logger -t traffic_monitor "Added DROP rule: -t $table -A $chain $rule $action"
    fi
}

# 阻止指定 IP 流量的函数
block_traffic() {
    # 删除相关的 iptables 规则
    remove_iptables_rule filter FORWARD "-s $TARGET_IP" "-j $CHAIN_NAME_FILTER"
    remove_iptables_rule filter FORWARD "-d $TARGET_IP" "-j $CHAIN_NAME_FILTER"

    # 添加 DROP 规则
    add_drop_rule filter FORWARD "-s $TARGET_IP"
    add_drop_rule filter FORWARD "-d $TARGET_IP"

    # 记录日志
    logger -t traffic_monitor "Traffic blocked for $TARGET_IP: daily limit of $((MAX_TIME/60)) hours exceeded at $(date)" >> /var/log/traffic_monitor.log
}

# 计算当前流量的函数
calculate_current_rate() {
    # 获取当前流量字节数
    OUT_BYTES=$(iptables -L $CHAIN_NAME_FILTER -v -x -n | grep "$TARGET_IP" | awk 'BEGIN {SUM=0} {SUM += $2} END {print SUM}')

    # 确保字节数为整数
    BYTES=${BYTES:-0}

    # 重置流量统计
    iptables -Z $CHAIN_NAME_FILTER

    # 将字节数转换为速率（kbps）
    CURRENT_RATE=$(( (BYTES * 8) / ( INTERVAL * 60) ))
}

# 更新使用时间并保存的函数
update_usage_time() {
    # 如果当前流量大于阈值，则增加已用时间
    if (( CURRENT_RATE > THRESHOLD_RATE * 1000 )); then
        DAILY_USED_TIME=$((DAILY_USED_TIME + INTERVAL))
        HOUR_USED_TIME=$((HOUR_USED_TIME + INTERVAL))
    fi

    # 保存使用时间到日志文件
    echo "$HOUR_USED_TIME" > "$CURRENT_HOUR_LOG"
    echo "$DAILY_USED_TIME" > "$CURRENT_DAILY_LOG"
}

#===============================================================================
# 主函数
#===============================================================================

main() {
    initialize_environment       # 初始化环境
    setup_iptables_rules         # 设置 iptables 规则
    check_and_handle_limits      # 检查并处理流量限制
    calculate_current_rate       # 计算当前流量速率
    update_usage_time            # 更新并保存使用时间
}

#===============================================================================
# 脚本执行入口
#===============================================================================

main  # 调用主函数开始执行脚本