feat: initial commit of clean multi-protocol singbox core script
This commit is contained in:
+339
@@ -0,0 +1,339 @@
|
||||
#!/usr/bin/env bash
|
||||
# ==============================================================================
|
||||
# 模块:多协议配置生成器 (VLESS-Reality / Hysteria2 / TUIC / VMess / AnyTLS)
|
||||
# ==============================================================================
|
||||
|
||||
# 获取或生成统一 UUID
|
||||
get_or_create_uuid() {
|
||||
local uuid="${1:-}"
|
||||
if [[ -z "$uuid" ]]; then
|
||||
if command -v "${BIN_PATH}" >/dev/null 2>&1; then
|
||||
uuid=$("${BIN_PATH}" generate uuid 2>/dev/null)
|
||||
fi
|
||||
if [[ -z "$uuid" && -f /proc/sys/kernel/random/uuid ]]; then
|
||||
uuid=$(cat /proc/sys/kernel/random/uuid)
|
||||
fi
|
||||
if [[ -z "$uuid" ]]; then
|
||||
uuid=$(openssl rand -hex 16 | sed -E 's/(.{8})(.{4})(.{4})(.{4})(.{12})/\1-\2-\3-\4-\5/')
|
||||
fi
|
||||
fi
|
||||
echo "$uuid"
|
||||
}
|
||||
|
||||
# 1. 组装 VLESS-Reality 入站 JSON
|
||||
build_vless_inbound() {
|
||||
local port="$1"
|
||||
local uuid="$2"
|
||||
local sni="$3"
|
||||
local priv_key="$4"
|
||||
local short_id="$5"
|
||||
|
||||
cat <<EOF
|
||||
{
|
||||
"type": "vless",
|
||||
"tag": "vless-in",
|
||||
"listen": "::",
|
||||
"listen_port": ${port},
|
||||
"sniff": true,
|
||||
"sniff_override_destination": true,
|
||||
"users": [
|
||||
{
|
||||
"uuid": "${uuid}",
|
||||
"flow": "xtls-rprx-vision"
|
||||
}
|
||||
],
|
||||
"tls": {
|
||||
"enabled": true,
|
||||
"server_name": "${sni}",
|
||||
"reality": {
|
||||
"enabled": true,
|
||||
"handshake": {
|
||||
"server": "${sni}",
|
||||
"server_port": 443
|
||||
},
|
||||
"private_key": "${priv_key}",
|
||||
"short_id": [
|
||||
"${short_id}"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
# 2. 组装 Hysteria 2 入站 JSON
|
||||
build_hy2_inbound() {
|
||||
local port="$1"
|
||||
local password="$2"
|
||||
|
||||
cat <<EOF
|
||||
{
|
||||
"type": "hysteria2",
|
||||
"tag": "hy2-in",
|
||||
"listen": "::",
|
||||
"listen_port": ${port},
|
||||
"sniff": true,
|
||||
"sniff_override_destination": true,
|
||||
"users": [
|
||||
{
|
||||
"password": "${password}"
|
||||
}
|
||||
],
|
||||
"ignore_client_bandwidth": false,
|
||||
"tls": {
|
||||
"enabled": true,
|
||||
"alpn": [
|
||||
"h3"
|
||||
],
|
||||
"certificate_path": "${CERT_FILE}",
|
||||
"key_path": "${KEY_FILE}"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
# 3. 组装 TUIC v5 入站 JSON
|
||||
build_tuic_inbound() {
|
||||
local port="$1"
|
||||
local uuid="$2"
|
||||
|
||||
cat <<EOF
|
||||
{
|
||||
"type": "tuic",
|
||||
"tag": "tuic-in",
|
||||
"listen": "::",
|
||||
"listen_port": ${port},
|
||||
"sniff": true,
|
||||
"sniff_override_destination": true,
|
||||
"users": [
|
||||
{
|
||||
"uuid": "${uuid}",
|
||||
"password": "${uuid}"
|
||||
}
|
||||
],
|
||||
"congestion_control": "bbr",
|
||||
"tls": {
|
||||
"enabled": true,
|
||||
"alpn": [
|
||||
"h3"
|
||||
],
|
||||
"certificate_path": "${CERT_FILE}",
|
||||
"key_path": "${KEY_FILE}"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
# 4. 组装 VMess-WS 入站 JSON
|
||||
build_vmess_inbound() {
|
||||
local port="$1"
|
||||
local uuid="$2"
|
||||
|
||||
cat <<EOF
|
||||
{
|
||||
"type": "vmess",
|
||||
"tag": "vmess-in",
|
||||
"listen": "::",
|
||||
"listen_port": ${port},
|
||||
"sniff": true,
|
||||
"sniff_override_destination": true,
|
||||
"users": [
|
||||
{
|
||||
"uuid": "${uuid}",
|
||||
"alterId": 0
|
||||
}
|
||||
],
|
||||
"transport": {
|
||||
"type": "ws",
|
||||
"path": "/${uuid}-vm",
|
||||
"max_early_data": 2048,
|
||||
"early_data_header_name": "Sec-WebSocket-Protocol"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
# 5. 组装 AnyTLS 入站 JSON
|
||||
build_anytls_inbound() {
|
||||
local port="$1"
|
||||
local password="$2"
|
||||
|
||||
cat <<EOF
|
||||
{
|
||||
"type": "anytls",
|
||||
"tag": "anytls-in",
|
||||
"listen": "::",
|
||||
"listen_port": ${port},
|
||||
"users": [
|
||||
{
|
||||
"password": "${password}"
|
||||
}
|
||||
],
|
||||
"padding_scheme": [],
|
||||
"tls": {
|
||||
"enabled": true,
|
||||
"certificate_path": "${CERT_FILE}",
|
||||
"key_path": "${KEY_FILE}"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
# 组合入站并生成最终完整服务配置与元数据
|
||||
generate_suite_config() {
|
||||
local mode="$1" # all | vless | hy2 | tuic | vmess | anytls
|
||||
shift
|
||||
|
||||
local uuid
|
||||
uuid=$(get_or_create_uuid)
|
||||
|
||||
local reality_sni="www.apple.com"
|
||||
local cert_sni="www.bing.com"
|
||||
|
||||
mkdir -p "${INSTALL_DIR}"
|
||||
|
||||
# 如涉及需证书的协议,预先生成自签证书
|
||||
if [[ "$mode" == "all" || "$mode" == "hy2" || "$mode" == "tuic" || "$mode" == "anytls" ]]; then
|
||||
generate_self_signed_cert "$cert_sni" || return 1
|
||||
fi
|
||||
|
||||
# 如涉及 Reality,预先生成密钥对
|
||||
local priv_key="" pub_key="" short_id=""
|
||||
if [[ "$mode" == "all" || "$mode" == "vless" ]]; then
|
||||
local keypair
|
||||
keypair=$("${BIN_PATH}" generate reality-keypair)
|
||||
priv_key=$(echo "$keypair" | awk '/PrivateKey/ {print $2}' | tr -d ' "\r\n')
|
||||
pub_key=$(echo "$keypair" | awk '/PublicKey/ {print $2}' | tr -d ' "\r\n')
|
||||
short_id=$("${BIN_PATH}" generate rand --hex 4 2>/dev/null || openssl rand -hex 4)
|
||||
short_id=$(echo "$short_id" | tr -d ' "\r\n')
|
||||
fi
|
||||
|
||||
local inbounds_arr=()
|
||||
local meta_protocols="{}"
|
||||
|
||||
case "$mode" in
|
||||
all)
|
||||
local p_vless="${1:-443}"
|
||||
local p_hy2="${2:-8443}"
|
||||
local p_tuic="${3:-9443}"
|
||||
local p_vmess="${4:-8080}"
|
||||
local p_anytls="${5:-10443}"
|
||||
|
||||
inbounds_arr+=("$(build_vless_inbound "$p_vless" "$uuid" "$reality_sni" "$priv_key" "$short_id")")
|
||||
inbounds_arr+=("$(build_hy2_inbound "$p_hy2" "$uuid")")
|
||||
inbounds_arr+=("$(build_tuic_inbound "$p_tuic" "$uuid")")
|
||||
inbounds_arr+=("$(build_vmess_inbound "$p_vmess" "$uuid")")
|
||||
inbounds_arr+=("$(build_anytls_inbound "$p_anytls" "$uuid")")
|
||||
|
||||
meta_protocols=$(cat <<EOF
|
||||
{
|
||||
"vless_reality": { "enabled": true, "port": ${p_vless}, "sni": "${reality_sni}", "public_key": "${pub_key}", "short_id": "${short_id}" },
|
||||
"hysteria2": { "enabled": true, "port": ${p_hy2}, "sni": "${cert_sni}" },
|
||||
"tuic": { "enabled": true, "port": ${p_tuic}, "sni": "${cert_sni}" },
|
||||
"vmess_ws": { "enabled": true, "port": ${p_vmess}, "path": "/${uuid}-vm" },
|
||||
"anytls": { "enabled": true, "port": ${p_anytls}, "sni": "${cert_sni}" }
|
||||
}
|
||||
EOF
|
||||
)
|
||||
;;
|
||||
vless)
|
||||
local port="${1:-443}"
|
||||
local custom_sni="${2:-$reality_sni}"
|
||||
inbounds_arr+=("$(build_vless_inbound "$port" "$uuid" "$custom_sni" "$priv_key" "$short_id")")
|
||||
meta_protocols=$(cat <<EOF
|
||||
{
|
||||
"vless_reality": { "enabled": true, "port": ${port}, "sni": "${custom_sni}", "public_key": "${pub_key}", "short_id": "${short_id}" }
|
||||
}
|
||||
EOF
|
||||
)
|
||||
;;
|
||||
hy2)
|
||||
local port="${1:-8443}"
|
||||
inbounds_arr+=("$(build_hy2_inbound "$port" "$uuid")")
|
||||
meta_protocols=$(cat <<EOF
|
||||
{
|
||||
"hysteria2": { "enabled": true, "port": ${port}, "sni": "${cert_sni}" }
|
||||
}
|
||||
EOF
|
||||
)
|
||||
;;
|
||||
tuic)
|
||||
local port="${1:-9443}"
|
||||
inbounds_arr+=("$(build_tuic_inbound "$port" "$uuid")")
|
||||
meta_protocols=$(cat <<EOF
|
||||
{
|
||||
"tuic": { "enabled": true, "port": ${port}, "sni": "${cert_sni}" }
|
||||
}
|
||||
EOF
|
||||
)
|
||||
;;
|
||||
vmess)
|
||||
local port="${1:-8080}"
|
||||
inbounds_arr+=("$(build_vmess_inbound "$port" "$uuid")")
|
||||
meta_protocols=$(cat <<EOF
|
||||
{
|
||||
"vmess_ws": { "enabled": true, "port": ${port}, "path": "/${uuid}-vm" }
|
||||
}
|
||||
EOF
|
||||
)
|
||||
;;
|
||||
anytls)
|
||||
local port="${1:-10443}"
|
||||
inbounds_arr+=("$(build_anytls_inbound "$port" "$uuid")")
|
||||
meta_protocols=$(cat <<EOF
|
||||
{
|
||||
"anytls": { "enabled": true, "port": ${port}, "sni": "${cert_sni}" }
|
||||
}
|
||||
EOF
|
||||
)
|
||||
;;
|
||||
esac
|
||||
|
||||
# 拼装 inbounds 数组逗号
|
||||
local inbounds_joined
|
||||
inbounds_joined=$(IFS=,; echo "${inbounds_arr[*]}")
|
||||
|
||||
# 写入最终 config.json
|
||||
cat > "${CONFIG_FILE}" <<EOF
|
||||
{
|
||||
"log": {
|
||||
"disabled": false,
|
||||
"level": "info",
|
||||
"timestamp": true
|
||||
},
|
||||
"inbounds": [
|
||||
${inbounds_joined}
|
||||
],
|
||||
"outbounds": [
|
||||
{
|
||||
"type": "direct",
|
||||
"tag": "direct"
|
||||
},
|
||||
{
|
||||
"type": "block",
|
||||
"tag": "block"
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
|
||||
# 原生语法校验
|
||||
if ! "${BIN_PATH}" check -c "${CONFIG_FILE}" >/dev/null 2>&1; then
|
||||
log_error "生成的配置文件未能通过 Sing-box 语法检测!请检查端口是否有冲突或参数错误。"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 写入持久化元数据
|
||||
cat > "${META_FILE}" <<EOF
|
||||
{
|
||||
"mode": "${mode}",
|
||||
"uuid": "${uuid}",
|
||||
"protocols": ${meta_protocols},
|
||||
"updated_at": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
|
||||
}
|
||||
EOF
|
||||
|
||||
chmod 600 "${CONFIG_FILE}" "${META_FILE}"
|
||||
log_success "Sing-box 核心配置部署成功,语法校验通过!"
|
||||
return 0
|
||||
}
|
||||
Reference in New Issue
Block a user