ufw allow from 1.2.3.4 to any port 7890 proto tcp comment "SOCKS5-用户A" ufw allow from 1.2.3.4 to any port 7890 proto udp comment "SOCKS5-用户A"
1 2 3 4
# 不指定协议,自动同时支持 TCP + UDP ufw allow from 1.2.3.4 to any port 7890 comment "SOCKS5-用户A" ufw allow from 5.6.7.8 to any port 7890 comment "SOCKS5-用户B" ufw allow from 10.20.30.0/24 to any port 7890 comment "SOCKS5-用户C子网"
if [[ -n "$RULE_INFO" ]]; then echo"发现以下待删除的规则(按编号降序):" echo"$RULE_INFO" | while IFS='|'read -r num ip line; do # 判断 IP 类型 if [[ "$ip" =~ : ]]; then type="IPv6" else type="IPv4" fi comment=$(echo"$line" | sed -n 's/.*# //p') echo" 编号 $num : $ip ($type) 注释: $comment" done
if$DRY_RUN; then echo"(试运行:不会实际删除)" else echo"开始倒序删除..." BACKUP_FILE="/tmp/ufw_status_backup_$(date +%s).txt" ufw status numbered > "$BACKUP_FILE" echo"已备份当前 UFW 状态到 $BACKUP_FILE"
echo"$RULE_INFO" | cut -d'|' -f1 | whileread -r num; do echo" 删除规则编号 $num" if ! ufw --force delete "$num" 2>/dev/null; then echo" ⚠️ 删除规则 $num 失败,可能已不存在或编号变动" fi done echo"规则删除完成。" fi else echo"未找到任何匹配给定注释模式的规则。" if ! $DRY_RUN; then echo"如果确认规则存在,请使用 --debug 运行查看详细信息。" fi fi
# ---------- 重载 ---------- echo -e "\n==================== 重载防火墙 ====================" if$DRY_RUN; then echo"(试运行:不会实际重载)" else if ufw reload; then echo"✅ UFW 重载成功" else echo"❌ UFW 重载失败,请手动执行 'sudo ufw reload'" exit 1 fi fi
echo -e "\n==================== 完成 ====================" if$DRY_RUN; then echo"试运行结束,如需正式执行,请去掉 --dry-run 参数。" else echo"所有匹配的静态规则(IPv4 和 IPv6)已删除。" fi
# 默认行为:如果没有指定 --ipv4 或 --ipv6,则两者都处理 if [[ "$DO_IPV4" == false && "$DO_IPV6" == false ]]; then DO_IPV4=true DO_IPV6=true fi
if$DRY_RUN; then echo"⚠️ 试运行模式(--dry-run):仅显示操作,不会实际修改防火墙" fi if$DEBUG; then echo"🔍 调试模式已开启" fi echo"将要处理的类型:IPv4=${DO_IPV4} IPv6=${DO_IPV6}"
# ---------- 前置检查 ---------- if [[ $EUID -ne 0 ]]; then echo"错误:请使用 sudo 运行此脚本" exit 1 fi
if ! command -v ufw &>/dev/null; then echo"错误:未找到 ufw 命令" exit 1 fi
if ! ufw status | grep -q "Status: active"; then echo"⚠️ 警告:UFW 未激活,规则可能不会生效" fi
# ---------- 函数:稳健提取规则编号(使用临时文件,防管道阻塞) ---------- get_rule_numbers() { local comment="$1" local tmpfile tmpfile=$(mktemp) if$DEBUG; then >&2 echo"DEBUG: 正在执行 ufw status numbered(超时 10 秒)..." fi timeout 10 ufw status numbered > "$tmpfile" 2>/dev/null || true if [[ ! -s "$tmpfile" ]]; then if$DEBUG; then >&2 echo"DEBUG: ufw status numbered 无输出或超时,跳过旧规则查找" fi rm -f "$tmpfile" return fi # 提取编号,管道末尾添加 || true 防止无匹配时因 pipefail 退出 grep -F "$comment""$tmpfile" \ | awk -F'[][]''{print $2}' \ | tr -d ' ' \ | grep -E '^[0-9]+$' \ | sort -nr || true rm -f "$tmpfile" }
# ---------- 函数:清理指定注释的规则 ---------- clean_old_rules() { local comment="$1" local type_name="$2" echo"--- 清理 ${type_name} 旧规则 ---" local old_rules old_rules=$(get_rule_numbers "$comment") if [[ -n "$old_rules" ]]; then echo"发现旧规则编号:" echo"$old_rules" | sed 's/^/ /' if$DRY_RUN; then echo"(试运行:不会实际删除)" else echo"开始倒序删除..." for num in$old_rules; do echo" 删除规则 $num" if ! ufw --force delete "$num" 2>/dev/null; then echo" ⚠️ 删除规则 $num 失败,跳过" fi done echo"${type_name} 旧规则清理完成。" fi else echo"未找到 ${type_name} 旧规则。" fi }
# ---------- 函数:检查 CIDR 是否已存在 ---------- cidr_exists() { local cidr="$1" ufw status | grep -q -F "$cidr" }
# ---------- 函数:添加 CIDR 列表(IPv4 用 insert 1,IPv6 用 prepend) ---------- add_cidrs() { local -n cidr_array="$1" local comment="$2" local type_name="$3"# "IPv4" 或 "IPv6" echo"--- 添加 ${type_name} 新规则(${#cidr_array[@]} 条)---" if$DRY_RUN; then echo"将要添加以下 CIDR:" for cidr in"${cidr_array[@]}"; do echo" deny from $cidr" done else # 倒序插入,保持数组顺序(先添加的排在前面) for ((i=${#cidr_array[@]}-1; i>=0; i--)); do local cidr="${cidr_array[i]}" if cidr_exists "$cidr"; then echo" $cidr 已存在,跳过" continue fi # 根据类型选择命令 local cmd if [[ "$type_name" == "IPv6" ]]; then cmd="ufw prepend deny from $cidr comment '$comment'" else cmd="ufw insert 1 deny from $cidr comment '$comment'" fi if$DEBUG; then echo" 执行: $cmd" fi ifeval"$cmd" 2>/dev/null; then echo" ✅ 添加 $cidr 成功" else echo" ❌ 添加 $cidr 失败(未知错误)" fi done echo"${type_name} 新规则添加完成。" fi }
# ---------- 执行清理和添加 ---------- echo"==================== 开始处理 Internet Measurement 静态规则 ===================="
# 清理旧规则(根据类型) if$DO_IPV4; then clean_old_rules "$COMMENT_IPV4""IPv4" fi
if$DO_IPV6; then clean_old_rules "$COMMENT_IPV6""IPv6" fi
# 默认行为:如果没有指定任何 --ipv4/--ipv6,则只处理 IPv4 if [[ "$DO_IPV4" == false && "$DO_IPV6" == false ]]; then DO_IPV4=true fi
if$DRY_RUN; then echo"⚠️ 试运行模式(--dry-run):仅显示操作,不会实际修改防火墙" fi echo"将要处理的类型:IPv4=${DO_IPV4} IPv6=${DO_IPV6}" if$DEBUG; then echo"🔍 调试模式已开启" fi
# ---------- 前置检查 ---------- if [[ $EUID -ne 0 ]]; then echo"错误:请使用 sudo 运行此脚本" exit 1 fi
if ! command -v ufw &>/dev/null; then echo"错误:未找到 ufw 命令" exit 1 fi
if ! ufw status | grep -q "Status: active"; then echo"⚠️ 警告:UFW 未激活,规则可能不会生效" fi
# ---------- 函数:获取匹配注释的所有规则(编号|IP|整行) ---------- get_rules_info() { local raw raw=$(ufw status numbered 2>/dev/null | grep -F "$COMMENT" || true) if [[ -z "$raw" ]]; then return fi if$DEBUG; then echo"DEBUG: 匹配到的旧规则原始行:" >&2 echo"$raw" | sed 's/^/ /' >&2 fi echo"$raw" | while IFS= read -r line; do num=$(echo"$line" | grep -oP '\[\s*\K\d+(?=\])' || true) ip=$(echo"$line" | grep -oP 'DENY IN\s+\K[0-9a-fA-F.:/]+' || true) if [[ -n "$num" && -n "$ip" ]]; then echo"$num|$ip|$line" fi done }
# ---------- 函数:根据类型过滤规则编号 ---------- get_filtered_numbers() { local want_ipv4="$1" local want_ipv6="$2" local rules_info rules_info=$(get_rules_info) if [[ -z "$rules_info" ]]; then return fi if$DEBUG; then echo"DEBUG: 提取到的规则(编号|IP):" >&2 fi echo"$rules_info" | while IFS='|'read -r num ip line; do if$DEBUG; then echo"DEBUG: $num -> $ip" >&2 fi if [[ "$ip" =~ : ]]; then type="ipv6" else type="ipv4" fi if [[ "$type" == "ipv4" && "$want_ipv4" == true ]]; then echo"$num" elif [[ "$type" == "ipv6" && "$want_ipv6" == true ]]; then echo"$num" fi done | sort -nr }
# ---------- 函数:查询 AS 网段(带调试输出) ---------- fetch_cidrs() { local asn="$1" localtype="$2"# "route" for IPv4, "route6" for IPv6 local cidrs="" local whois_output="" if$DEBUG; then echo"DEBUG: 查询 $asn ($type) from $WHOIS_SERVER ..." >&2 fi whois_output=$(whois -h "$WHOIS_SERVER" -- "-i origin $asn" 2>/dev/null || true) if$DEBUG; then echo"DEBUG: WHOIS 原始输出(包含 $type):" >&2 echo"$whois_output" | grep -E "^($type):" | sed 's/^/ /' >&2 fi cidrs=$(echo"$whois_output" | grep -E "^($type):" | awk '{print $2}' | sort -u || true) if [[ -z "$cidrs" ]]; then if$DEBUG; then echo"DEBUG: 主源无结果,尝试备用 $BACKUP_WHOIS" >&2 fi whois_output=$(whois -h "$BACKUP_WHOIS" -- "-i origin $asn" 2>/dev/null || true) if$DEBUG; then echo"DEBUG: 备用 WHOIS 输出($type):" >&2 echo"$whois_output" | grep -E "^($type):" | sed 's/^/ /' >&2 fi cidrs=$(echo"$whois_output" | grep -E "^($type):" | awk '{print $2}' | sort -u || true) fi if$DEBUG; then echo"DEBUG: 最终提取的 $type CIDR 列表:" >&2 echo"$cidrs" | sed 's/^/ /' >&2 fi echo"$cidrs" }
if [[ -n "$OLD_RULES" ]]; then echo"发现以下旧规则编号(将被删除):" echo"$OLD_RULES" | sed 's/^/ /' if$DRY_RUN; then echo"(试运行:不会实际删除)" else echo"开始倒序删除..." BACKUP_FILE="/tmp/ufw_status_backup_$(date +%s).txt" ufw status numbered > "$BACKUP_FILE" echo"已备份到 $BACKUP_FILE" for num in$OLD_RULES; do echo" 删除规则 $num" if ! ufw --force delete "$num" 2>/dev/null; then echo" ⚠️ 删除规则 $num 失败,跳过" fi done echo"旧规则清理完成。" fi else echo"未找到需要清理的旧规则(类型匹配)。" fi
declare -a ALL_CIDRS=() if [[ "$DO_IPV4" == true ]]; then for ASN in"${AS_LIST[@]}"; do echo"查询 $ASN 的 IPv4 网段..." CIDRS=$(fetch_cidrs "$ASN""route") if [[ -n "$CIDRS" ]]; then whileread -r cidr; do [[ -n "$cidr" ]] && ALL_CIDRS+=("$cidr") done <<< "$CIDRS" else echo"⚠️ 未获取到 $ASN 的 IPv4 网段" fi done fi
if [[ "$DO_IPV6" == true ]]; then for ASN in"${AS_LIST[@]}"; do echo"查询 $ASN 的 IPv6 网段..." CIDRS6=$(fetch_cidrs "$ASN""route6") if [[ -n "$CIDRS6" ]]; then whileread -r cidr; do [[ -n "$cidr" ]] && ALL_CIDRS+=("$cidr") done <<< "$CIDRS6" else echo"⚠️ 未获取到 $ASN 的 IPv6 网段" fi done fi
if [[ ${#ALL_CIDRS[@]} -eq 0 ]]; then echo"❌ 未获取到任何网段,退出。" exit 1 fi
# 去重(保留首次出现的顺序) declare -a UNIQ_CIDRS=() declare -A SEEN for cidr in"${ALL_CIDRS[@]}"; do if [[ -z "${SEEN[$cidr]+x}" ]]; then SEEN[$cidr]=1 UNIQ_CIDRS+=("$cidr") fi done ALL_CIDRS=("${UNIQ_CIDRS[@]}")
echo"共获取 ${#ALL_CIDRS[@]} 个不重复网段(将按倒序插入,最终顺序与列表一致)" if$DEBUG; then echo"DEBUG: 完整网段列表(按 AS 查询顺序,已去重):" for idx in"${!ALL_CIDRS[@]}"; do echo" [$idx] ${ALL_CIDRS[idx]}" done fi
if$DRY_RUN; then for cidr in"${ALL_CIDRS[@]}"; do echo" 将添加:deny from $cidr" done else # 倒序插入以保证列表顺序(先添加的排在最前) for ((i=${#ALL_CIDRS[@]}-1; i>=0; i--)); do cidr="${ALL_CIDRS[i]}" # 根据 IP 类型选择命令 if [[ "$cidr" =~ : ]]; then cmd="ufw prepend deny from $cidr comment '$COMMENT'" else cmd="ufw insert 1 deny from $cidr comment '$COMMENT'" fi echo" 添加规则:$cmd" if$DEBUG; then echo" -> 执行: $cmd" fi # 执行命令,忽略重复插入错误 if ! eval"$cmd" 2>/dev/null; then echo" ⚠️ 添加 $cidr 失败(可能已存在),跳过" fi done echo"所有新规则已添加。" fi
# ---------- 第三步:重载防火墙 ---------- echo -e "\n==================== 第三步:重载防火墙生效 ====================" if$DRY_RUN; then echo"(试运行:不会实际重载)" else if ufw reload; then echo"✅ UFW 重载成功" else echo"❌ UFW 重载失败,请手动执行 'sudo ufw reload'" exit 1 fi fi
echo -e "\n==================== 完成 ====================" if$DRY_RUN; then echo"试运行结束,如需正式执行,请去掉 --dry-run 参数。" else echo"Censys 网段屏蔽已更新。" echo"查看规则:sudo ufw status verbose | grep '$COMMENT'" fi
日志会看到Hello from Palo Alto Networks, find out more about our scans in https://docs-cortex.paloaltonetworks.com/r/1/Cortex-Xpanse/Scanning-activity也有仿冒的;
147.185.133.243 - - [25/Jun/2026:10:22:45 +0800] "GET / HTTP/1.1" 444 0 "-" "Hello from Palo Alto Networks, find out more about our scans in https://docs-cortex.paloaltonetworks.com/r/1/Cortex-Xpanse/Scanning-activity" "-" 147.185.133.106 - - [25/Jun/2026:13:57:19 +0800] "GET / HTTP/1.1" 444 0 "-" "Hello from Palo Alto Networks, find out more about our scans in https://docs-cortex.paloaltonetworks.com/r/1/Cortex-Xpanse/Scanning-activity" "-" 220.196.160.84 - - [25/Jun/2026:14:01:28 +0800] "GET / HTTP/1.1" 444 0 "-" "Hello from Palo Alto Networks, find out more about our scans in https://docs-cortex.paloaltonetworks.com/r/1/Cortex-Xpanse/Scanning-activity" "-" 180.101.245.250 - - [25/Jun/2026:14:01:28 +0800] "GET / HTTP/1.1" 444 0 "-" "Hello from Palo Alto Networks, find out more about our scans in https://docs-cortex.paloaltonetworks.com/r/1/Cortex-Xpanse/Scanning-activity" "-"
# 默认行为:如果没有指定 --ipv4 或 --ipv6,则两者都处理 if [[ "$DO_IPV4" == false && "$DO_IPV6" == false ]]; then DO_IPV4=true DO_IPV6=true fi
if$DRY_RUN; then echo"⚠️ 试运行模式(--dry-run):仅显示操作,不会实际修改防火墙" fi if$DEBUG; then echo"🔍 调试模式已开启" fi echo"将要处理的类型:IPv4=${DO_IPV4} IPv6=${DO_IPV6}"
# ---------- 前置检查 ---------- if [[ $EUID -ne 0 ]]; then echo"错误:请使用 sudo 运行此脚本" exit 1 fi
if ! command -v ufw &>/dev/null; then echo"错误:未找到 ufw 命令" exit 1 fi
if ! ufw status | grep -q "Status: active"; then echo"⚠️ 警告:UFW 未激活,规则可能不会生效" fi
# ---------- 函数:稳健提取规则编号(使用临时文件,防管道阻塞) ---------- get_rule_numbers() { local comment="$1" local tmpfile tmpfile=$(mktemp) if$DEBUG; then >&2 echo"DEBUG: 正在执行 ufw status numbered(超时 10 秒)..." fi timeout 10 ufw status numbered > "$tmpfile" 2>/dev/null || true if [[ ! -s "$tmpfile" ]]; then if$DEBUG; then >&2 echo"DEBUG: ufw status numbered 无输出或超时,跳过旧规则查找" fi rm -f "$tmpfile" return fi # 提取编号,管道末尾添加 || true 防止无匹配时因 pipefail 退出 grep -F "$comment""$tmpfile" \ | awk -F'[][]''{print $2}' \ | tr -d ' ' \ | grep -E '^[0-9]+$' \ | sort -nr || true rm -f "$tmpfile" }
# ---------- 函数:清理指定注释的规则 ---------- clean_old_rules() { local comment="$1" local type_name="$2" echo"--- 清理 ${type_name} 旧规则 ---" local old_rules old_rules=$(get_rule_numbers "$comment") if [[ -n "$old_rules" ]]; then echo"发现旧规则编号:" echo"$old_rules" | sed 's/^/ /' if$DRY_RUN; then echo"(试运行:不会实际删除)" else echo"开始倒序删除..." for num in$old_rules; do echo" 删除规则 $num" if ! ufw --force delete "$num" 2>/dev/null; then echo" ⚠️ 删除规则 $num 失败,跳过" fi done echo"${type_name} 旧规则清理完成。" fi else echo"未找到 ${type_name} 旧规则。" fi }
# ---------- 函数:检查 CIDR 是否已存在 ---------- cidr_exists() { local cidr="$1" ufw status | grep -q -F "$cidr" }
# ---------- 函数:添加 CIDR 列表(IPv4 用 insert 1,IPv6 用 prepend) ---------- add_cidrs() { local -n cidr_array="$1" local comment="$2" local type_name="$3"# "IPv4" 或 "IPv6" echo"--- 添加 ${type_name} 新规则(${#cidr_array[@]} 条)---" if$DRY_RUN; then echo"将要添加以下 CIDR:" for cidr in"${cidr_array[@]}"; do echo" deny from $cidr" done else # 倒序插入,保持数组顺序(先添加的排在前面) for ((i=${#cidr_array[@]}-1; i>=0; i--)); do local cidr="${cidr_array[i]}" if cidr_exists "$cidr"; then echo" $cidr 已存在,跳过" continue fi # 根据类型选择命令 local cmd if [[ "$type_name" == "IPv6" ]]; then cmd="ufw prepend deny from $cidr comment '$comment'" else cmd="ufw insert 1 deny from $cidr comment '$comment'" fi if$DEBUG; then echo" 执行: $cmd" fi ifeval"$cmd" 2>/dev/null; then echo" ✅ 添加 $cidr 成功" else echo" ❌ 添加 $cidr 失败(未知错误)" fi done echo"${type_name} 新规则添加完成。" fi }
# ---------- 执行清理和添加 ---------- echo"==================== 开始处理 Internet Measurement 静态规则 ===================="
# 清理旧规则(根据类型) if$DO_IPV4; then clean_old_rules "$COMMENT_IPV4""IPv4" fi
if$DO_IPV6; then clean_old_rules "$COMMENT_IPV6""IPv6" fi
# 默认行为:如果没有指定 --ipv4 或 --ipv6,则两者都处理 if [[ "$DO_IPV4" == false && "$DO_IPV6" == false ]]; then DO_IPV4=true DO_IPV6=true fi
if$DRY_RUN; then echo"⚠️ 试运行模式(--dry-run):仅显示操作,不会实际修改防火墙" fi if$DEBUG; then echo"🔍 调试模式已开启" fi echo"将要处理的类型:IPv4=${DO_IPV4} IPv6=${DO_IPV6}"
# ---------- 前置检查 ---------- if [[ $EUID -ne 0 ]]; then echo"错误:请使用 sudo 运行此脚本" exit 1 fi
if ! command -v ufw &>/dev/null; then echo"错误:未找到 ufw 命令" exit 1 fi
if ! ufw status | grep -q "Status: active"; then echo"⚠️ 警告:UFW 未激活,规则可能不会生效" fi
# ---------- 函数:稳健提取规则编号(使用临时文件,防管道阻塞) ---------- get_rule_numbers() { local comment="$1" local tmpfile tmpfile=$(mktemp) if$DEBUG; then >&2 echo"DEBUG: 正在执行 ufw status numbered(超时 10 秒)..." fi timeout 10 ufw status numbered > "$tmpfile" 2>/dev/null || true if [[ ! -s "$tmpfile" ]]; then if$DEBUG; then >&2 echo"DEBUG: ufw status numbered 无输出或超时,跳过旧规则查找" fi rm -f "$tmpfile" return fi # 提取编号,管道末尾添加 || true 防止无匹配时因 pipefail 退出 grep -F "$comment""$tmpfile" \ | awk -F'[][]''{print $2}' \ | tr -d ' ' \ | grep -E '^[0-9]+$' \ | sort -nr || true rm -f "$tmpfile" }
# ---------- 函数:清理指定注释的规则 ---------- clean_old_rules() { local comment="$1" local type_name="$2" echo"--- 清理 ${type_name} 旧规则 ---" local old_rules old_rules=$(get_rule_numbers "$comment") if [[ -n "$old_rules" ]]; then echo"发现旧规则编号:" echo"$old_rules" | sed 's/^/ /' if$DRY_RUN; then echo"(试运行:不会实际删除)" else echo"开始倒序删除..." for num in$old_rules; do echo" 删除规则 $num" if ! ufw --force delete "$num" 2>/dev/null; then echo" ⚠️ 删除规则 $num 失败,跳过" fi done echo"${type_name} 旧规则清理完成。" fi else echo"未找到 ${type_name} 旧规则。" fi }
# ---------- 函数:检查 CIDR 是否已存在 ---------- cidr_exists() { local cidr="$1" ufw status | grep -q -F "$cidr" }
# ---------- 函数:添加 CIDR 列表(IPv4 用 insert 1,IPv6 用 prepend) ---------- add_cidrs() { local -n cidr_array="$1" local comment="$2" local type_name="$3"# "IPv4" 或 "IPv6" echo"--- 添加 ${type_name} 新规则(${#cidr_array[@]} 条)---" if$DRY_RUN; then echo"将要添加以下 CIDR:" for cidr in"${cidr_array[@]}"; do echo" deny from $cidr" done else # 倒序插入,保持数组顺序(先添加的排在前面) for ((i=${#cidr_array[@]}-1; i>=0; i--)); do local cidr="${cidr_array[i]}" if cidr_exists "$cidr"; then echo" $cidr 已存在,跳过" continue fi # 根据类型选择命令 local cmd if [[ "$type_name" == "IPv6" ]]; then cmd="ufw prepend deny from $cidr comment '$comment'" else cmd="ufw insert 1 deny from $cidr comment '$comment'" fi if$DEBUG; then echo" 执行: $cmd" fi ifeval"$cmd" 2>/dev/null; then echo" ✅ 添加 $cidr 成功" else echo" ❌ 添加 $cidr 失败(未知错误)" fi done echo"${type_name} 新规则添加完成。" fi }
# ---------- 执行清理和添加 ---------- echo"==================== 开始处理 Internet Measurement 静态规则 ===================="
# 清理旧规则(根据类型) if$DO_IPV4; then clean_old_rules "$COMMENT_IPV4""IPv4" fi
if$DO_IPV6; then clean_old_rules "$COMMENT_IPV6""IPv6" fi
# 默认行为:如果没有指定 --ipv4 或 --ipv6,则两者都处理 if [[ "$DO_IPV4" == false && "$DO_IPV6" == false ]]; then DO_IPV4=true DO_IPV6=true fi
if$DRY_RUN; then echo"⚠️ 试运行模式(--dry-run):仅显示操作,不会实际修改防火墙" fi if$DEBUG; then echo"🔍 调试模式已开启" fi echo"将要处理的类型:IPv4=${DO_IPV4} IPv6=${DO_IPV6}"
# ---------- 前置检查 ---------- if [[ $EUID -ne 0 ]]; then echo"错误:请使用 sudo 运行此脚本" exit 1 fi
if ! command -v ufw &>/dev/null; then echo"错误:未找到 ufw 命令" exit 1 fi
if ! ufw status | grep -q "Status: active"; then echo"⚠️ 警告:UFW 未激活,规则可能不会生效" fi
# ---------- 函数:稳健提取规则编号(使用临时文件,防管道阻塞) ---------- get_rule_numbers() { local comment="$1" local tmpfile tmpfile=$(mktemp) if$DEBUG; then >&2 echo"DEBUG: 正在执行 ufw status numbered(超时 10 秒)..." fi timeout 10 ufw status numbered > "$tmpfile" 2>/dev/null || true if [[ ! -s "$tmpfile" ]]; then if$DEBUG; then >&2 echo"DEBUG: ufw status numbered 无输出或超时,跳过旧规则查找" fi rm -f "$tmpfile" return fi # 提取编号,管道末尾添加 || true 防止无匹配时因 pipefail 退出 grep -F "$comment""$tmpfile" \ | awk -F'[][]''{print $2}' \ | tr -d ' ' \ | grep -E '^[0-9]+$' \ | sort -nr || true rm -f "$tmpfile" }
# ---------- 函数:清理指定注释的规则 ---------- clean_old_rules() { local comment="$1" local type_name="$2" echo"--- 清理 ${type_name} 旧规则 ---" local old_rules old_rules=$(get_rule_numbers "$comment") if [[ -n "$old_rules" ]]; then echo"发现旧规则编号:" echo"$old_rules" | sed 's/^/ /' if$DRY_RUN; then echo"(试运行:不会实际删除)" else echo"开始倒序删除..." for num in$old_rules; do echo" 删除规则 $num" if ! ufw --force delete "$num" 2>/dev/null; then echo" ⚠️ 删除规则 $num 失败,跳过" fi done echo"${type_name} 旧规则清理完成。" fi else echo"未找到 ${type_name} 旧规则。" fi }
# ---------- 函数:检查 CIDR 是否已存在 ---------- cidr_exists() { local cidr="$1" ufw status | grep -q -F "$cidr" }
# ---------- 函数:添加 CIDR 列表(IPv4 用 insert 1,IPv6 用 prepend) ---------- add_cidrs() { local -n cidr_array="$1" local comment="$2" local type_name="$3"# "IPv4" 或 "IPv6" echo"--- 添加 ${type_name} 新规则(${#cidr_array[@]} 条)---" if$DRY_RUN; then echo"将要添加以下 CIDR:" for cidr in"${cidr_array[@]}"; do echo" deny from $cidr" done else # 倒序插入,保持数组顺序(先添加的排在前面) for ((i=${#cidr_array[@]}-1; i>=0; i--)); do local cidr="${cidr_array[i]}" if cidr_exists "$cidr"; then echo" $cidr 已存在,跳过" continue fi # 根据类型选择命令 local cmd if [[ "$type_name" == "IPv6" ]]; then cmd="ufw prepend deny from $cidr comment '$comment'" else cmd="ufw insert 1 deny from $cidr comment '$comment'" fi if$DEBUG; then echo" 执行: $cmd" fi ifeval"$cmd" 2>/dev/null; then echo" ✅ 添加 $cidr 成功" else echo" ❌ 添加 $cidr 失败(未知错误)" fi done echo"${type_name} 新规则添加完成。" fi }
# ---------- 执行清理和添加 ---------- echo"==================== 开始处理 Internet Measurement 静态规则 ===================="
# 清理旧规则(根据类型) if$DO_IPV4; then clean_old_rules "$COMMENT_IPV4""IPv4" fi
if$DO_IPV6; then clean_old_rules "$COMMENT_IPV6""IPv6" fi
if [[ -n "$OLD_RULES" ]]; then echo"发现以下旧静态规则(编号):" echo"$OLD_RULES" | sed 's/^/ /'
if [[ "$DRY_RUN" == true ]]; then echo"(试运行:不会实际删除)" else echo"开始倒序删除..." BACKUP_FILE="/tmp/ufw_status_backup_$(date +%s).txt" ufw status numbered > "$BACKUP_FILE" echo"已备份当前 ufw 状态到 $BACKUP_FILE"
for num in$OLD_RULES; do echo" 删除规则编号 $num" if ! ufw --force delete "$num" 2>/dev/null; then echo" ⚠️ 删除规则 $num 失败,可能已不存在或编号变动,继续处理其余规则" fi done echo"旧规则清理完成。" fi else echo"未找到任何匹配 '$COMMENT_STATIC' 的旧规则,无需清理。" fi
if [[ "$DRY_RUN" == true ]]; then echo"将要添加以下 CIDR(试运行):" for cidr in"${STATIC_CIDR[@]}"; do echo" deny from $cidr (comment: $COMMENT_STATIC)" done else # 倒序插入,以保证数组第一个最终排在规则列表最前面(因为 insert 1 会把新规则放到最前面) for ((i=${#STATIC_CIDR[@]}-1; i>=0; i--)); do cidr="${STATIC_CIDR[i]}" echo" 添加规则:deny from $cidr" if ! ufw insert 1 deny from "$cidr" comment "$COMMENT_STATIC" 2>/dev/null; then echo" ⚠️ 添加规则 $cidr 失败,跳过" fi done echo"所有新规则已添加。" fi
if [[ "$DRY_RUN" == true ]]; then echo"(试运行:不会实际重载)" else if ufw reload; then echo"✅ UFW 重载成功" else echo"❌ UFW 重载失败,请手动执行 'sudo ufw reload'" exit 1 fi fi
echo -e "\n==================== 完成 ====================" if [[ "$DRY_RUN" == true ]]; then echo"试运行结束,如需正式执行,请去掉 --dry-run 参数再运行。" else echo"静态黑名单已更新。查看当前规则:" echo"sudo ufw status verbose | grep '$COMMENT_STATIC'" fi
if [[ -n "$OLD_RULES" ]]; then echo"待删除旧静态规则编号:" echo"$OLD_RULES" | sed 's/^/ /' if [[ "$DRY_RUN" == false ]]; then for num in$OLD_RULES; do echo"删除规则 $num" if ! ufw --force delete "$num" 2>/dev/null; then echo" ⚠️ 删除规则 $num 失败,跳过" fi done else echo"(试运行:不会实际删除)" fi else echo"无旧静态黑名单规则" fi
if [[ "$DRY_RUN" == true ]]; then echo"将要添加以下 IPv6 CIDR(试运行):" for cidr in"${STATIC_CIDR[@]}"; do echo" 置顶屏蔽:$cidr" done else # 倒序插入,使数组第一个最终排在最前面 for ((i=${#STATIC_CIDR[@]}-1; i>=0; i--)); do cidr="${STATIC_CIDR[i]}" echo"置顶屏蔽:$cidr" if ! ufw insert 1 deny from "$cidr" comment "$COMMENT_STATIC" 2>/dev/null; then echo" ⚠️ 添加 $cidr 失败,跳过" fi done fi
# ---------- 第三步:重载 ---------- echo -e "\n==================== 第三步:重载防火墙生效 ====================" if [[ "$DRY_RUN" == true ]]; then echo"(试运行:不会实际重载)" else if ufw reload; then echo"✅ UFW 重载成功" else echo"❌ UFW 重载失败,请手动执行 'sudo ufw reload'" exit 1 fi fi
echo -e "\n===== 静态黑名单加载完成 =====" if [[ "$DRY_RUN" == true ]]; then echo"试运行结束,如需正式执行,请去掉 --dry-run 参数。" else echo"查看全部静态屏蔽规则:sudo ufw status verbose | grep '$COMMENT_STATIC'" fi
# 默认行为:如果没有指定 --ipv4 或 --ipv6,则两者都处理 if [[ "$DO_IPV4" == false && "$DO_IPV6" == false ]]; then DO_IPV4=true DO_IPV6=true fi
if$DRY_RUN; then echo"⚠️ 试运行模式(--dry-run):仅显示操作,不会实际修改防火墙" fi if$DEBUG; then echo"🔍 调试模式已开启" fi echo"将要处理的类型:IPv4=${DO_IPV4} IPv6=${DO_IPV6}"
# ---------- 前置检查 ---------- if [[ $EUID -ne 0 ]]; then echo"错误:请使用 sudo 运行此脚本" exit 1 fi
if ! command -v ufw &>/dev/null; then echo"错误:未找到 ufw 命令" exit 1 fi
if ! ufw status | grep -q "Status: active"; then echo"⚠️ 警告:UFW 未激活,规则可能不会生效" fi
# ---------- 函数:稳健提取规则编号(使用临时文件,防管道阻塞) ---------- get_rule_numbers() { local comment="$1" local tmpfile tmpfile=$(mktemp) if$DEBUG; then >&2 echo"DEBUG: 正在执行 ufw status numbered(超时 10 秒)..." fi timeout 10 ufw status numbered > "$tmpfile" 2>/dev/null || true if [[ ! -s "$tmpfile" ]]; then if$DEBUG; then >&2 echo"DEBUG: ufw status numbered 无输出或超时,跳过旧规则查找" fi rm -f "$tmpfile" return fi # 提取编号,管道末尾添加 || true 防止无匹配时因 pipefail 退出 grep -F "$comment""$tmpfile" \ | awk -F'[][]''{print $2}' \ | tr -d ' ' \ | grep -E '^[0-9]+$' \ | sort -nr || true rm -f "$tmpfile" }
# ---------- 函数:清理指定注释的规则 ---------- clean_old_rules() { local comment="$1" local type_name="$2" echo"--- 清理 ${type_name} 旧规则 ---" local old_rules old_rules=$(get_rule_numbers "$comment") if [[ -n "$old_rules" ]]; then echo"发现旧规则编号:" echo"$old_rules" | sed 's/^/ /' if$DRY_RUN; then echo"(试运行:不会实际删除)" else echo"开始倒序删除..." for num in$old_rules; do echo" 删除规则 $num" if ! ufw --force delete "$num" 2>/dev/null; then echo" ⚠️ 删除规则 $num 失败,跳过" fi done echo"${type_name} 旧规则清理完成。" fi else echo"未找到 ${type_name} 旧规则。" fi }
# ---------- 函数:检查 CIDR 是否已存在 ---------- cidr_exists() { local cidr="$1" ufw status | grep -q -F "$cidr" }
# ---------- 函数:添加 CIDR 列表(IPv4 用 insert 1,IPv6 用 prepend) ---------- add_cidrs() { local -n cidr_array="$1" local comment="$2" local type_name="$3"# "IPv4" 或 "IPv6" echo"--- 添加 ${type_name} 新规则(${#cidr_array[@]} 条)---" if$DRY_RUN; then echo"将要添加以下 CIDR:" for cidr in"${cidr_array[@]}"; do echo" deny from $cidr" done else # 倒序插入,保持数组顺序(先添加的排在前面) for ((i=${#cidr_array[@]}-1; i>=0; i--)); do local cidr="${cidr_array[i]}" if cidr_exists "$cidr"; then echo" $cidr 已存在,跳过" continue fi # 根据类型选择命令 local cmd if [[ "$type_name" == "IPv6" ]]; then cmd="ufw prepend deny from $cidr comment '$comment'" else cmd="ufw insert 1 deny from $cidr comment '$comment'" fi if$DEBUG; then echo" 执行: $cmd" fi ifeval"$cmd" 2>/dev/null; then echo" ✅ 添加 $cidr 成功" else echo" ❌ 添加 $cidr 失败(未知错误)" fi done echo"${type_name} 新规则添加完成。" fi }
# ---------- 执行清理和添加 ---------- echo"==================== 开始处理 Internet Measurement 静态规则 ===================="
# 清理旧规则(根据类型) if$DO_IPV4; then clean_old_rules "$COMMENT_IPV4""IPv4" fi
if$DO_IPV6; then clean_old_rules "$COMMENT_IPV6""IPv6" fi