修改文件名

This commit is contained in:
Olia Lisa
2026-05-19 10:44:29 +08:00
parent aa5bcdd5b7
commit 3b00c2719f
4 changed files with 0 additions and 0 deletions
+208
View File
@@ -0,0 +1,208 @@
#!/bin/bash
# 查找随机空闲端口
# 用途:
# 在指定端口范围内,随机选择一个当前未被监听(TCP/UDP)的端口
# 参数:
# $1: 起始端口(默认 10001)
# $2: 结束端口(默认 65535)
# $3: 最大随机尝试次数(默认 100)
find_free_port() {
local start="${1:-10001}"
local max="${2:-65535}"
local attempts="${3:-100}"
# ------------------------------------------------------------
# 收集当前正在监听的端口(TCP + UDP)
# 优先使用 ss,其次 netstat
# ------------------------------------------------------------
local used_ports raw
if command -v ss >/dev/null 2>&1; then
# ss 输出示例:
# LISTEN 0 128 0.0.0.0:22
raw=$(ss -lntu 2>/dev/null || true)
used_ports=$(printf "%s\n" "$raw" \
| awk '{print $5}' \
| sed -E 's/.*[:]//g')
elif command -v netstat >/dev/null 2>&1; then
# netstat 输出示例:
# tcp 0 0 0.0.0.0:22
raw=$(netstat -lntu 2>/dev/null || true)
used_ports=$(printf "%s\n" "$raw" \
| awk '{print $4}' \
| sed -E 's/.*[:]//g')
else
echo "Error: ss or netstat is required to check listening ports." >&2
return 2
fi
# ------------------------------------------------------------
# 将已占用端口存入关联数组,便于 O(1) 判断
# 需要 bash 4+
# ------------------------------------------------------------
declare -A used_map
local p
for p in $used_ports; do
# 过滤非数字字段(如 *、:::
if [[ $p =~ ^[0-9]+$ ]]; then
used_map["$p"]=1
fi
done
# ------------------------------------------------------------
# 随机尝试若干次
# 每次随机生成一个端口,只要未被监听就立即返回
# ------------------------------------------------------------
local port i
for ((i=0; i<attempts; i++)); do
# 在 [start, max] 范围内生成随机端口
port=$(( RANDOM % (max - start + 1) + start ))
# 如果端口不在已监听表中,则认为可用
if [[ -z "${used_map[$port]}" ]]; then
echo "$port"
return 0
fi
done
# ------------------------------------------------------------
# 多次随机尝试后仍未找到可用端口
# 通常意味着端口范围过小或已被大量占用
# ------------------------------------------------------------
echo "Error: no free port found after $attempts random attempts." >&2
return 1
}
# ==========================================
# 函数名: port_manage
# 功能: 开放端口和关闭端口
# 参数1: allow 或 deny (操作类型)
# 参数2: 端口号
# --- 使用示例 ---
# 开启端口 8888
# port_manage allow 8888
# 关闭端口 8888
# port_manage deny 8888
# ==========================================
port_manage() {
local ACTION=$1
local PORT=$2
if [[ -z "$PORT" ]]; then
echo "错误: 未提供端口号"
return 1
fi
# 统一转换为小写,增强鲁棒性
ACTION=$(echo "$ACTION" | tr '[:upper:]' '[:lower:]')
echo "--- 正在对端口 $PORT 执行 $ACTION 操作 ---"
# 1. 防火墙 (Firewall) 逻辑处理
if command -v firewall-cmd >/dev/null 2>&1 && systemctl is-active --quiet firewalld; then
# CentOS/RHEL/Fedora (firewalld)
if [ "$ACTION" == "allow" ]; then
sudo firewall-cmd --zone=public --add-port=${PORT}/tcp --permanent
sudo firewall-cmd --zone=public --add-port=${PORT}/udp --permanent
elif [ "$ACTION" == "deny" ]; then
sudo firewall-cmd --zone=public --remove-port=${PORT}/tcp --permanent
sudo firewall-cmd --zone=public --remove-port=${PORT}/udp --permanent
fi
sudo firewall-cmd --reload
echo "[OK] firewalld 规则已更新 ($ACTION)"
elif command -v ufw >/dev/null 2>&1 && systemctl is-active --quiet ufw; then
# Ubuntu/Debian (ufw)
if [ "$ACTION" == "allow" ]; then
sudo ufw allow ${PORT}/tcp
sudo ufw allow ${PORT}/udp
elif [ "$ACTION" == "deny" ]; then
sudo ufw delete allow ${PORT}/tcp
sudo ufw delete allow ${PORT}/udp
fi
echo "[OK] ufw 规则已更新 ($ACTION)"
else
# 兜底方案 (iptables)
# allow 使用 -I (Insert) 插入到规则首行,deny 使用 -D (Delete)
local FLAG=$([ "$ACTION" == "allow" ] && echo "-I" || echo "-D")
sudo iptables $FLAG INPUT -p tcp --dport ${PORT} -j ACCEPT 2>/dev/null
sudo iptables $FLAG INPUT -p udp --dport ${PORT} -j ACCEPT 2>/dev/null
echo "[OK] iptables 规则已执行 ($ACTION)"
fi
# 2. SELinux 逻辑处理
if command -v getenforce >/dev/null 2>&1; then
local SELINUX_STATUS=$(getenforce)
if [ "$SELINUX_STATUS" == "Enforcing" ]; then
if command -v semanage >/dev/null 2>&1; then
if [ "$ACTION" == "allow" ]; then
# 尝试添加,若存在则尝试修改
sudo semanage port -a -t http_port_t -p tcp ${PORT} 2>/dev/null || \
sudo semanage port -m -t http_port_t -p tcp ${PORT}
elif [ "$ACTION" == "deny" ]; then
sudo semanage port -d -t http_port_t -p tcp ${PORT} 2>/dev/null
fi
echo "[OK] SELinux 端口权限已更新 ($ACTION)"
else
# 如果没装 semanage,在 allow 时开启全局布尔值,deny 时通常保持不变以防影响其他业务
if [ "$ACTION" == "allow" ]; then
echo "[!] 警告: 未找到 semanage,尝试开启全局网络连接开关..."
sudo setsebool -P httpd_can_network_connect 1
fi
fi
fi
fi
}
# ==========================================
# 更新 sing-box 配置文件中的监听端口,并开放对应防火墙规则
# 参数1: 端口号(可选,不传则在指定范围内随机选取空闲端口)
# 参数2: 随机端口起始值(可选,默认 5000)
# 参数3: 随机端口结束值(可选,默认 15000)
# --- 使用示例 ---
# 指定端口
# update_port 8080
#
# 自动随机端口(默认范围 5000-15000)
# update_port
#
# 自动随机端口(自定义范围)
# update_port "" 20000 30000
# ==========================================
update_port(){
local script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # 脚本文件夹绝对路径
local config_dir="$script_dir/../config"
local port=$1
# 如果没有提供端口参数,则自动查找一个随机空闲端口
if [[ -z "$port" ]]; then
port=$(find_free_port 5000 15000)
fi
modify_json_file "$config_dir/config.json" ".inbounds[0].listen_port" "$port"
port_manage allow "$port"
echo "设置端口成功"
}
# 通过交互方式更新端口
ask_update_port(){
local script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
local config_file="$script_dir/../config/config.json"
local current_port=$(get_listen_port)
local new_port=$(ask_update "请输入新的端口号" "$current_port")
update_port "$new_port"
}
# 获取当前配置的监听端口
get_listen_port(){
local script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
local config_file="$script_dir/../config/config.json"
local port=$(jq -r ".inbounds[0].listen_port" "$config_file")
echo $port
}