Add proxy protocol installer mirror

This commit is contained in:
mango
2026-04-27 21:56:29 +08:00
commit 893e36d8b6
6 changed files with 1817 additions and 0 deletions

27
README.md Normal file
View File

@@ -0,0 +1,27 @@
# proxy-installer
顶尖自己的协议一键脚本镜像入口,统一选择:
- ss2022 + shadowtls
- anytls
- snell v5
- Reality (Xray)
## 推荐用法
```bash
curl -fsSL https://mjjtop.com/proxy -o proxy.sh && chmod +x proxy.sh && ./proxy.sh
```
## 直接指定协议
```bash
curl -fsSL https://mjjtop.com/proxy | bash -s -- ss
curl -fsSL https://mjjtop.com/proxy | bash -s -- anytls
curl -fsSL https://mjjtop.com/proxy | bash -s -- snell
curl -fsSL https://mjjtop.com/proxy | bash -s -- reality
```
## 说明
这里镜像的是安装脚本本身,不再依赖 `*.shuijiao.de`。脚本内部仍会从官方 GitHub / Surge CDN 拉取对应二进制;如果要完全离线/完全不依赖外部下载源,需要下一步再镜像二进制 release。

69
proxy.sh Executable file
View File

@@ -0,0 +1,69 @@
#!/usr/bin/env bash
# 顶尖协议一键脚本统一入口
# Mirror: https://mjjtop.com/proxy
# Protocols: ss2022+shadowtls / anytls / snell v5 / reality
set -euo pipefail
BASE_URL="${MIRROR_BASE_URL:-https://mjjtop.com/raw/proxy-installer}"
TMP_DIR="/tmp/mjjtop-proxy-installer"
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m'
info(){ echo -e "${GREEN}[INFO]${NC} $*"; }
warn(){ echo -e "${YELLOW}[WARN]${NC} $*"; }
err(){ echo -e "${RED}[ERROR]${NC} $*" >&2; exit 1; }
if [[ "${PROXY_INSTALLER_SKIP_ROOT_CHECK:-0}" != "1" ]]; then
[[ ${EUID:-$(id -u)} -eq 0 ]] || err "请用 root 运行"
fi
command -v curl >/dev/null 2>&1 || err "缺少 curl请先安装: apt install -y curl"
mkdir -p "$TMP_DIR"
run_remote() {
local name="$1" path="$2" file="$TMP_DIR/$path"
info "下载 $name 脚本:$BASE_URL/scripts/$path"
curl -fsSL "$BASE_URL/scripts/$path" -o "$file"
chmod +x "$file"
info "开始执行 $name"
exec bash "$file"
}
show_menu() {
clear 2>/dev/null || true
echo -e "${CYAN}========================================${NC}"
echo -e "${CYAN} 顶尖协议一键脚本 / mjjtop proxy${NC}"
echo -e "${CYAN}========================================${NC}"
echo "1) ss2022 + shadowtls"
echo "2) anytls"
echo "3) snell v5"
echo "4) Reality (Xray)"
echo "0) 退出"
echo
}
case "${1:-}" in
ss|ss2022|shadowtls) run_remote "ss2022 + shadowtls" "ss2022-shadowtls.sh" ;;
anytls|any) run_remote "anytls" "anytls.sh" ;;
snell|snell5) run_remote "snell v5" "snell-v5.sh" ;;
reality|xray) run_remote "Reality (Xray)" "reality.sh" ;;
"") ;;
*) err "未知参数:$1,可用: ss | anytls | snell | reality" ;;
esac
while true; do
show_menu
read -rp "请选择协议 [0-4]: " choice
case "$choice" in
1) run_remote "ss2022 + shadowtls" "ss2022-shadowtls.sh" ;;
2) run_remote "anytls" "anytls.sh" ;;
3) run_remote "snell v5" "snell-v5.sh" ;;
4) run_remote "Reality (Xray)" "reality.sh" ;;
0|q|Q) exit 0 ;;
*) warn "无效选择"; sleep 1 ;;
esac
done

343
scripts/anytls.sh Executable file
View File

@@ -0,0 +1,343 @@
#!/bin/bash
# =================================================================
# anytls 管理脚本 (修复 Mihomo 缩进版)
# 描述: 自动获取 GitHub 最新版本安装,同时显示 Surge 和 Mihomo 配置。
# =================================================================
# 定义输出颜色
GREEN='\033[0;32m'
RED='\033[0;31m'
NC='\033[0m' # 无颜色
# --- 函数: 检查 anytls 安装和运行状态 ---
check_anytls_status() {
if [ -f /usr/local/bin/anytls-server ] && [ -f /etc/systemd/system/anytls.service ]; then
echo -e "${GREEN}anytls 状态: 已安装${NC}"
else
echo -e "${RED}anytls 状态: 未安装${NC}"
fi
if systemctl is-active --quiet anytls; then
echo -e "${GREEN}服务状态: 运行中${NC}"
else
echo -e "${RED}服务状态: 未运行${NC}"
fi
}
# --- 函数: 显示菜单 ---
show_menu() {
clear
echo "=================================================="
echo " anytls-go 综合管理脚本 (v1.3)"
echo "=================================================="
check_anytls_status
echo "--------------------------------------------------"
echo "1. 安装 anytls"
echo "2. 卸载 anytls"
echo "3. 修改 anytls 配置 (端口/密码)"
echo "4. 查看 anytls 配置"
echo "5. 启动 anytls 服务"
echo "6. 停止 anytls 服务"
echo "7. 重启 anytls 服务"
echo "8. 查看 anytls 运行状态"
echo "0. 退出脚本"
echo "=================================================="
echo -n "请输入选项 [0-8]: "
}
# --- 函数: 检查 root 权限 ---
check_root() {
if [ "$(id -u)" -ne 0 ]; then
echo -e "${RED}错误:此脚本需要以 root 权限运行。${NC}" >&2
exit 1
fi
}
# --- 函数: 显示配置信息 (通用模块) ---
# 参数: $1=ip, $2=port, $3=password
display_configuration() {
local ip=$1
local port=$2
local pwd=$3
echo "------------------------------------------"
echo " anytls 配置详情"
echo "------------------------------------------"
echo -e "地址 (IP) : ${GREEN}${ip}${NC}"
echo -e "端口 (Port) : ${GREEN}${port}${NC}"
echo -e "密码 (Password) : ${GREEN}${pwd}${NC}"
echo "------------------------------------------"
echo "1. Surge 配置文件:"
echo -e "${GREEN}VPS = anytls, ${ip}, ${port}, password=\"${pwd}\", skip-cert-verify=true, udp-relay=true, reuse=false${NC}"
echo ""
echo "2. Mihomo (Clash Meta) 配置文件:"
# 注意:下面这一行前面已经加了两个空格
echo -e "${GREEN} - {\"name\":\"VPS\",\"server\":\"${ip}\",\"port\":${port},\"password\":\"${pwd}\",\"skip-cert-verify\":true,\"reuse\":false,\"type\":\"anytls\"}${NC}"
echo "------------------------------------------"
}
# --- 函数: 安装 anytls ---
install_anytls() {
if [ -f /usr/local/bin/anytls-server ]; then
echo -e "${GREEN}anytls 似乎已经安装,无需重复安装。${NC}"
return
fi
echo "--> 正在准备安装环境..."
if ! command -v curl &> /dev/null || ! command -v unzip &> /dev/null || ! command -v shuf &> /dev/null || ! command -v grep &> /dev/null; then
echo "--> 检测到依赖缺失,正在尝试自动安装..."
if command -v apt-get &> /dev/null; then
apt-get update && apt-get install -y curl unzip coreutils grep
elif command -v yum &> /dev/null; then
yum install -y curl unzip coreutils grep
else
echo -e "${RED}无法确定包管理器,请手动安装 curl, unzip, coreutils, grep 后再运行此脚本。${NC}"
exit 1
fi
fi
echo "--> 正在获取 anytls 最新版本信息..."
LATEST_URL=$(curl -s https://api.github.com/repos/anytls/anytls-go/releases/latest | grep "browser_download_url" | grep "linux_amd64.zip" | head -n 1 | cut -d '"' -f 4)
if [ -z "$LATEST_URL" ]; then
echo -e "${RED}获取最新版本失败,尝试使用备用版本 (v0.0.12)...${NC}"
LATEST_URL="https://github.com/anytls/anytls-go/releases/download/v0.0.12/anytls_0.0.12_linux_amd64.zip"
else
echo -e " 检测到最新版本下载地址: ${GREEN}$LATEST_URL${NC}"
fi
echo "--> 正在下载 anytls..."
if ! curl -sL -o anytls.zip "$LATEST_URL"; then
echo -e "${RED}下载 anytls 失败!请检查网络连接。${NC}"
exit 1
fi
echo "--> 正在解压并部署..."
if ! unzip -o anytls.zip; then
echo -e "${RED}解压 anytls 失败!${NC}"
rm anytls.zip
exit 1
fi
if [ -f anytls-server ]; then
mv anytls-server /usr/local/bin/
else
FIND_SERVER=$(find . -maxdepth 1 -name "anytls*server*" | head -n 1)
if [ -n "$FIND_SERVER" ]; then
mv "$FIND_SERVER" /usr/local/bin/anytls-server
else
echo -e "${RED}错误:解压后未找到 anytls-server 文件。${NC}"
exit 1
fi
fi
rm -f anytls-client* readme.md anytls.zip anytls*.zip
chmod +x /usr/local/bin/anytls-server
echo " anytls 程序部署完成。"
read -p "请输入 anytls 的监听端口 (留空则随机生成 10000-65535): " PORT
if [ -z "$PORT" ]; then
PORT=$((RANDOM % 55536 + 10000))
echo -e " 使用随机端口: ${GREEN}$PORT${NC}"
fi
read -p "请输入 anytls 的密码 (留空则随机生成): " PASSWORD
if [ -z "$PASSWORD" ]; then
ALPHANUM=$(< /dev/urandom tr -dc 'A-Za-z0-9' | head -c 14)
SPECIAL_CHARS='-/@'
S1_INDEX=$(($RANDOM % 3))
S1=${SPECIAL_CHARS:$S1_INDEX:1}
REMAINING_CHARS=${SPECIAL_CHARS//$S1/}
S2_INDEX=$(($RANDOM % 2))
S2=${REMAINING_CHARS:$S2_INDEX:1}
COMBINED_CHARS="${ALPHANUM}${S1}${S2}"
PASSWORD=$(echo "$COMBINED_CHARS" | grep -o . | shuf | tr -d '\n')
echo -e " 使用随机密码: ${GREEN}$PASSWORD${NC}"
fi
echo "--> 正在创建 systemd 服务..."
cat > /etc/systemd/system/anytls.service <<EOF
[Unit]
Description=AnyTLS Service
After=network.target
[Service]
Type=simple
User=root
Group=root
ExecStart=/usr/local/bin/anytls-server -l 0.0.0.0:${PORT} -p ${PASSWORD}
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
EOF
echo "--> 正在启动服务..."
systemctl daemon-reload
systemctl enable anytls > /dev/null 2>&1
systemctl start anytls
echo "--> 正在获取 IP..."
local ip_address=$(curl -s https://ipv4.icanhazip.com || curl -s https://api.ipify.org)
[ -z "$ip_address" ] && ip_address="<您的服务器IP>"
echo -e "${GREEN}🎉 anytls 安装成功!${NC}"
display_configuration "$ip_address" "$PORT" "$PASSWORD"
}
# --- 函数: 卸载 anytls ---
uninstall_anytls() {
if [ ! -f /usr/local/bin/anytls-server ]; then
echo -e "${RED}anytls 未安装。${NC}"
return
fi
echo -e "${RED}警告:将停止服务并删除所有文件。${NC}"
read -p "确认继续? [y/N]: " confirm
if [[ $confirm != [yY] && $confirm != [yY][eE][sS] ]]; then
echo "操作取消。"
return
fi
systemctl stop anytls
systemctl disable anytls > /dev/null 2>&1
rm -f /etc/systemd/system/anytls.service
rm -f /usr/local/bin/anytls-server
systemctl daemon-reload
echo -e "${GREEN}anytls 已卸载。${NC}"
rm -- "$0"
echo "脚本已自毁,退出。"
exit 0
}
# --- 函数: 修改配置 ---
modify_config() {
if [ ! -f /etc/systemd/system/anytls.service ]; then
echo -e "${RED}anytls 未安装。${NC}"
return
fi
read -p "新端口 (留空随机): " PORT
if [ -z "$PORT" ]; then
PORT=$((RANDOM % 55536 + 10000))
fi
read -p "新密码 (留空随机): " PASSWORD
if [ -z "$PASSWORD" ]; then
ALPHANUM=$(< /dev/urandom tr -dc 'A-Za-z0-9' | head -c 14)
SPECIAL_CHARS='-/@'
S1_INDEX=$(($RANDOM % 3))
S1=${SPECIAL_CHARS:$S1_INDEX:1}
REMAINING_CHARS=${SPECIAL_CHARS//$S1/}
S2_INDEX=$(($RANDOM % 2))
S2=${REMAINING_CHARS:$S2_INDEX:1}
COMBINED_CHARS="${ALPHANUM}${S1}${S2}"
PASSWORD=$(echo "$COMBINED_CHARS" | grep -o . | shuf | tr -d '\n')
fi
cat > /etc/systemd/system/anytls.service <<EOF
[Unit]
Description=AnyTLS Service
After=network.target
[Service]
Type=simple
User=root
Group=root
ExecStart=/usr/local/bin/anytls-server -l 0.0.0.0:${PORT} -p ${PASSWORD}
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl restart anytls
local ip_address=$(curl -s https://ipv4.icanhazip.com || curl -s https://api.ipify.org)
[ -z "$ip_address" ] && ip_address="<您的服务器IP>"
echo -e "${GREEN}🎉 配置已更新!${NC}"
display_configuration "$ip_address" "$PORT" "$PASSWORD"
}
# --- 函数: 查看配置 ---
view_config() {
if [ ! -f /etc/systemd/system/anytls.service ]; then
echo -e "${RED}anytls 未安装。${NC}"
return
fi
local exec_start_line=$(grep 'ExecStart' /etc/systemd/system/anytls.service)
local port=$(echo "$exec_start_line" | sed -n 's/.*-l 0\.0\.0\.0:\([0-9]*\).*/\1/p')
local password=$(echo "$exec_start_line" | sed -n 's/.*-p \(.*\)/\1/p')
echo "--> 正在获取 IP..."
local ip_address=$(curl -s https://ipv4.icanhazip.com || curl -s https://api.ipify.org)
[ -z "$ip_address" ] && ip_address="<您的服务器IP>"
# 调用通用显示函数
display_configuration "$ip_address" "$port" "$password"
}
# --- 服务管理函数 ---
start_anytls() {
if systemctl is-active --quiet anytls; then
echo -e "${GREEN}服务已在运行。${NC}"
else
systemctl start anytls && echo -e "${GREEN}启动成功。${NC}" || echo -e "${RED}启动失败。${NC}"
fi
}
stop_anytls() {
if ! systemctl is-active --quiet anytls; then
echo -e "${GREEN}服务未运行。${NC}"
else
systemctl stop anytls && echo -e "${GREEN}停止成功。${NC}" || echo -e "${RED}停止失败。${NC}"
fi
}
restart_anytls() {
if [ ! -f /etc/systemd/system/anytls.service ]; then
echo -e "${RED}anytls 未安装。${NC}"
return
fi
systemctl restart anytls && echo -e "${GREEN}重启成功。${NC}" || echo -e "${RED}重启失败。${NC}"
}
check_anytls_running() {
if [ ! -f /etc/systemd/system/anytls.service ]; then
echo -e "${RED}anytls 未安装。${NC}"
return
fi
systemctl status anytls
}
# --- 主程序 ---
check_root
while true; do
show_menu
read choice
case $choice in
1) install_anytls ;;
2) uninstall_anytls ;;
3) modify_config ;;
4) view_config ;;
5) start_anytls ;;
6) stop_anytls ;;
7) restart_anytls ;;
8) check_anytls_running ;;
0) echo "退出。"; exit 0 ;;
*) echo -e "${RED}无效选项。${NC}" ;;
esac
echo ""
echo "按 Enter 键返回菜单..."
read -r
done

438
scripts/reality.sh Executable file
View File

@@ -0,0 +1,438 @@
#!/bin/bash
# =================================================================
# Xray (xtls-rprx-vision Reality) 服务器端管理脚本
# =================================================================
# 定义输出颜色
GREEN='\033[0;32m'
RED='\033[0;31m'
NC='\033[0m' # 无颜色
XRAY_CONFIG_FILE="/usr/local/etc/xray/config.json"
XRAY_KEYS_FILE="/usr/local/etc/xray/reality.keys"
# --- 通用函数 ---
check_root() {
if [ "$(id -u)" -ne 0 ]; then
echo -e "${RED}错误:此脚本需要以 root 权限运行。${NC}" >&2
exit 1
fi
}
# --- 函数: 确保 jq 已安装 ---
ensure_jq() {
if ! command -v jq &> /dev/null; then
echo "--> 检测到依赖工具 jq 未安装,正在尝试自动安装..."
if command -v apt-get &> /dev/null; then
apt-get update >/dev/null && apt-get install -y jq
elif command -v yum &> /dev/null; then
yum install -y jq
else
echo -e "${RED}无法自动安装 jq。请手动安装 (sudo apt install jq / sudo yum install jq) 后再试。${NC}"
return 1
fi
if ! command -v jq &> /dev/null; then
echo -e "${RED}jq 安装失败,请检查包管理器或手动安装。${NC}"
return 1
fi
echo " jq 安装成功。"
fi
return 0
}
# --- 函数: 检查 Xray 安装和运行状态 ---
check_xray_status() {
if [ -f /usr/local/bin/xray ]; then
echo -e "${GREEN}Xray 核心: 已安装${NC}"
else
echo -e "${RED}Xray 核心: 未安装${NC}"
fi
if [ -f "${XRAY_CONFIG_FILE}" ]; then
echo -e "${GREEN}配置状态 : 已配置${NC}"
if systemctl is-active --quiet xray; then
echo -e "${GREEN}服务状态 : 运行中${NC}"
else
echo -e "${RED}服务状态 : 未运行${NC}"
fi
else
echo -e "${RED}配置状态 : 未配置${NC}"
fi
}
# --- 函数: 生成 Reality 配置 ---
generate_reality_simple_config() {
echo "--> 正在配置 Reality 配置..."
read -p "请输入监听端口 (例如 443, 留空随机): " PORT
[ -z "$PORT" ] && PORT=$((RANDOM % 55536 + 10000))
read -p "请输入伪装域名 (留空则默认为 icloud.com): " SNI_DOMAIN
[ -z "$SNI_DOMAIN" ] && SNI_DOMAIN="icloud.com"
local sni_domain_cleaned=$(echo "${SNI_DOMAIN}" | cut -d':' -f1)
echo "--> 正在生成 UUID 和 Reality 密钥对..."
local uuid=$(/usr/local/bin/xray uuid)
local key_pair=$(/usr/local/bin/xray x25519)
local private_key=$(echo "$key_pair" | grep 'PrivateKey' | awk '{print $2}')
local public_key=$(echo "$key_pair" | grep 'Password' | awk '{print $2}')
echo "PrivateKey: ${private_key}" > "${XRAY_KEYS_FILE}"
echo "PublicKey: ${public_key}" >> "${XRAY_KEYS_FILE}"
echo "--> 正在创建配置文件 ${XRAY_CONFIG_FILE}..."
cat > "${XRAY_CONFIG_FILE}" <<EOF
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"port": ${PORT},
"protocol": "vless",
"settings": {
"clients": [
{
"id": "${uuid}",
"flow": "xtls-rprx-vision"
}
],
"decryption": "none"
},
"streamSettings": {
"network": "tcp",
"security": "reality",
"realitySettings": {
"dest": "${sni_domain_cleaned}:443",
"serverNames": [ "${sni_domain_cleaned}" ],
"privateKey": "${private_key}",
"shortIds": [ "", "0123456789abcdef" ]
}
},
"sniffing": {
"enabled": true,
"destOverride": [ "http", "tls", "quic" ],
"routeOnly": true
}
}
],
"outbounds": [
{
"protocol": "freedom",
"tag": "direct"
}
]
}
EOF
}
# --- 函数: 生成 Reality (防偷) 配置 ---
generate_reality_dokodemo_config() {
echo "--> 正在配置 Reality (防偷)..."
read -p "请输入外部监听端口 (例如 443, 留空随机): " EXT_PORT
[ -z "$EXT_PORT" ] && EXT_PORT=$((RANDOM % 55536 + 10000))
read -p "请输入内部 VLESS 端口 (留空随机): " INT_PORT
[ -z "$INT_PORT" ] && INT_PORT=$((RANDOM % 55536 + 10000))
read -p "请输入伪装域名 (留空则默认为 icloud.com): " SNI_DOMAIN
[ -z "$SNI_DOMAIN" ] && SNI_DOMAIN="icloud.com"
local sni_domain_cleaned=$(echo "${SNI_DOMAIN}" | cut -d':' -f1)
echo "--> 正在生成 UUID 和 Reality 密钥对..."
local uuid=$(/usr/local/bin/xray uuid)
local key_pair=$(/usr/local/bin/xray x25519)
local private_key=$(echo "$key_pair" | grep 'PrivateKey' | awk '{print $2}')
local public_key=$(echo "$key_pair" | grep 'Password' | awk '{print $2}')
echo "PrivateKey: ${private_key}" > "${XRAY_KEYS_FILE}"
echo "PublicKey: ${public_key}" >> "${XRAY_KEYS_FILE}"
echo "--> 正在创建配置文件 ${XRAY_CONFIG_FILE}..."
cat > "${XRAY_CONFIG_FILE}" <<EOF
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"tag": "dokodemo-in",
"port": ${EXT_PORT},
"protocol": "dokodemo-door",
"settings": {
"address": "127.0.0.1",
"port": ${INT_PORT},
"network": "tcp"
},
"sniffing": {
"enabled": true,
"destOverride": [ "tls" ],
"routeOnly": true
}
},
{
"listen": "127.0.0.1",
"port": ${INT_PORT},
"protocol": "vless",
"settings": {
"clients": [
{
"id": "${uuid}",
"flow": "xtls-rprx-vision"
}
],
"decryption": "none"
},
"streamSettings": {
"network": "tcp",
"security": "reality",
"realitySettings": {
"dest": "${sni_domain_cleaned}:443",
"serverNames": [ "${sni_domain_cleaned}" ],
"privateKey": "${private_key}",
"shortIds": [ "", "0123456789abcdef" ]
}
},
"sniffing": {
"enabled": true,
"destOverride": [ "http", "tls", "quic" ],
"routeOnly": true
}
}
],
"outbounds": [
{ "protocol": "freedom", "tag": "direct" },
{ "protocol": "blackhole", "tag": "block" }
],
"routing": {
"rules": [
{
"inboundTag": [ "dokodemo-in" ],
"domain": [ "${sni_domain_cleaned}" ],
"outboundTag": "direct"
},
{
"inboundTag": [ "dokodemo-in" ],
"outboundTag": "block"
}
]
}
}
EOF
}
# --- 函数: 安装 Xray 核心 ---
install_xray_core() {
if [ -f /usr/local/bin/xray ]; then
echo -e "${GREEN}Xray 核心已安装,无需重复操作。${NC}"
return 0
fi
echo "--> 正在使用官方脚本安装 Xray 核心..."
bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install -u root
if [ ! -f /usr/local/bin/xray ]; then
echo -e "${RED}Xray 核心安装失败。${NC}"
return 1
else
echo -e "${GREEN}Xray 核心安装成功。${NC}"
echo "--> 正在清理旧的配置文件..."
systemctl stop xray >/dev/null 2>&1
rm -f "${XRAY_CONFIG_FILE}"
rm -f "${XRAY_KEYS_FILE}"
echo " 旧配置已清理。"
return 0
fi
}
# --- 函数: (包装器) 配置 Reality ---
configure_reality_simple() {
if ! [ -f /usr/local/bin/xray ]; then
echo "--> Xray 核心未安装,正在自动安装..."
install_xray_core || return
fi
if [ -f "${XRAY_CONFIG_FILE}" ]; then
read -p "检测到现有配置,继续将覆盖它。确定吗?[y/N]: " confirm
if [[ ! "$confirm" =~ ^[yY] ]]; then echo "操作已取消。"; return; fi
fi
generate_reality_simple_config
echo "--> 正在测试配置并启动 Xray..."
/usr/local/bin/xray -test -config "${XRAY_CONFIG_FILE}"
if [ $? -ne 0 ]; then
echo -e "${RED}配置文件测试失败,请检查。配置未应用。${NC}"; return; fi
systemctl restart xray
systemctl enable xray > /dev/null 2>&1
echo -e "${GREEN}🎉 Xray Reality 配置成功!${NC}"
view_config_xray
}
# --- 函数: (包装器) 配置 Reality (防偷) ---
configure_reality_dokodemo() {
if ! [ -f /usr/local/bin/xray ]; then
echo "--> Xray 核心未安装,正在自动安装..."
install_xray_core || return
fi
if [ -f "${XRAY_CONFIG_FILE}" ]; then
read -p "检测到现有配置,继续将覆盖它。确定吗?[y/N]: " confirm
if [[ ! "$confirm" =~ ^[yY] ]]; then echo "操作已取消。"; return; fi
fi
generate_reality_dokodemo_config
echo "--> 正在测试配置并启动 Xray..."
/usr/local/bin/xray -test -config "${XRAY_CONFIG_FILE}"
if [ $? -ne 0 ]; then
echo -e "${RED}配置文件测试失败,请检查。配置未应用。${NC}"; return; fi
systemctl restart xray
systemctl enable xray > /dev/null 2>&1
echo -e "${GREEN}🎉 Xray Reality (防偷) 配置成功!${NC}"
view_config_xray
}
# --- 函数: 卸载 Xray ---
uninstall_xray() {
if [ ! -f /usr/local/bin/xray ]; then
echo -e "${RED}Xray 未安装。${NC}"; return; fi
read -p "警告:确定要卸载 Xray 吗?这将删除所有数据。[y/N]: " confirm
if [[ ! "$confirm" =~ ^[yY]([eE][sS])?$ ]]; then
echo "卸载操作已取消。"; return; fi
systemctl stop xray
bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ remove --purge
rm -f "${XRAY_KEYS_FILE}"
echo -e "${GREEN}Xray 已成功卸载。${NC}"
}
# --- 函数: 查看 Xray 配置 ---
view_config_xray() {
if [ ! -f "${XRAY_CONFIG_FILE}" ]; then
echo -e "${RED}Xray 未配置。请先选择一个配置方案。${NC}"; return; fi
ensure_jq || return
if ! jq . "${XRAY_CONFIG_FILE}" >/dev/null 2>&1; then
echo -e "${RED}错误:配置文件 ${XRAY_CONFIG_FILE} 格式无效。${NC}"; return; fi
local ip_address=$(curl -s https://ipv4.icanhazip.com || echo "<您的服务器IP>")
local public_key="<未找到>"
if [ -f "${XRAY_KEYS_FILE}" ]; then
public_key=$(grep 'PublicKey' "${XRAY_KEYS_FILE}" | awk '{print $2}')
fi
echo "------------------------------------------"
echo " Xray (Reality) 当前配置信息"
echo "------------------------------------------"
# 通过 tag 判断配置类型
if jq -e '.inbounds[] | select(.tag=="dokodemo-in")' "${XRAY_CONFIG_FILE}" >/dev/null 2>&1; then
# 防偷配置
local ext_port=$(jq '.inbounds[] | select(.tag=="dokodemo-in") | .port' "${XRAY_CONFIG_FILE}")
local vless_inbound=$(jq '.inbounds[] | select(.protocol=="vless")' "${XRAY_CONFIG_FILE}")
local uuid=$(echo "$vless_inbound" | jq -r '.settings.clients[0].id')
local flow=$(echo "$vless_inbound" | jq -r '.settings.clients[0].flow')
local sni=$(echo "$vless_inbound" | jq -r '.streamSettings.realitySettings.serverNames[0]')
local short_id=$(echo "$vless_inbound" | jq -r '.streamSettings.realitySettings.shortIds[0]')
echo -e "配置类型 : ${GREEN}Reality (防偷)${NC}"
echo -e "监听地址 : ${GREEN}${ip_address}${NC}"
echo -e "外部端口 : ${GREEN}${ext_port}${NC}"
echo -e "UUID : ${GREEN}${uuid}${NC}"
echo -e "Flow : ${GREEN}${flow}${NC}"
echo -e "伪装域名 : ${GREEN}${sni}${NC}"
echo -e "Short ID : ${GREEN}${short_id}${NC}"
echo -e "公钥 (pbk) : ${GREEN}${public_key}${NC}"
echo "------------------------------------------"
echo "VLESS 分享链接:"
local vless_link="vless://${uuid}@${ip_address}:${ext_port}?encryption=none&flow=${flow}&security=reality&sni=${sni}&fp=random&pbk=${public_key}&sid=${short_id}&allowInsecure=1&type=tcp&headerType=none#VPS_防偷"
echo -e "${GREEN}${vless_link}${NC}"
else
# Reality 配置
local vless_inbound=$(jq '.inbounds[] | select(.protocol=="vless")' "${XRAY_CONFIG_FILE}")
local port=$(echo "$vless_inbound" | jq -r '.port')
local uuid=$(echo "$vless_inbound" | jq -r '.settings.clients[0].id')
local flow=$(echo "$vless_inbound" | jq -r '.settings.clients[0].flow')
local sni=$(echo "$vless_inbound" | jq -r '.streamSettings.realitySettings.serverNames[0]')
local short_id=$(echo "$vless_inbound" | jq -r '.streamSettings.realitySettings.shortIds[0]')
echo -e "配置类型 : ${GREEN}Reality 配置${NC}"
echo -e "监听地址 : ${GREEN}${ip_address}${NC}"
echo -e "端口 : ${GREEN}${port}${NC}"
echo -e "UUID : ${GREEN}${uuid}${NC}"
echo -e "Flow : ${GREEN}${flow}${NC}"
echo -e "伪装域名 : ${GREEN}${sni}${NC}"
echo -e "Short ID : ${GREEN}${short_id}${NC}"
echo -e "公钥 (pbk) : ${GREEN}${public_key}${NC}"
echo "------------------------------------------"
echo "VLESS 分享链接:"
local vless_link="vless://${uuid}@${ip_address}:${port}?encryption=none&flow=${flow}&security=reality&sni=${sni}&fp=random&pbk=${public_key}&sid=${short_id}&allowInsecure=1&type=tcp&headerType=none#VPS_Reality"
echo -e "${GREEN}${vless_link}${NC}"
fi
echo "------------------------------------------"
}
# --- 函数: Xray 服务管理 ---
manage_xray_service() {
if ! systemctl list-units --type=service | grep -q "xray.service"; then
echo -e "${RED}Xray 服务未安装。${NC}"; return; fi
case $1 in
start) systemctl start xray && echo -e "${GREEN}服务启动成功。${NC}" || echo -e "${RED}服务启动失败。${NC}" ;;
stop) systemctl stop xray && echo -e "${GREEN}服务已停止。${NC}" || echo -e "${RED}服务停止失败。${NC}" ;;
restart) systemctl restart xray && echo -e "${GREEN}服务重启成功。${NC}" || echo -e "${RED}服务重启失败。${NC}" ;;
status) systemctl status xray ;;
esac
}
# --- 函数: Xray 主菜单 ---
xray_menu() {
while true; do
clear
echo "=================================================="
echo " XTLS-RPRX-VISION Reality 管理脚本"
echo "=================================================="
check_xray_status
echo "--------------------------------------------------"
echo "1. 安装 Xray 核心"
echo "2. 配置 Reality"
echo "3. 配置 Reality (防偷)"
echo "4. 卸载 Xray"
echo "5. 查看 Xray 配置"
echo "6. 启动 Xray"
echo "7. 停止 Xray"
echo "8. 重启 Xray"
echo "9. 查看运行状态"
echo "0. 退出脚本"
echo "=================================================="
read -p "请输入选项 [0-9]: " choice
case $choice in
1) install_xray_core ;;
2) configure_reality_simple ;;
3) configure_reality_dokodemo ;;
4) uninstall_xray ;;
5) view_config_xray ;;
6) manage_xray_service start ;;
7) manage_xray_service stop ;;
8) manage_xray_service restart ;;
9) manage_xray_service status ;;
0) break ;;
*) echo -e "${RED}无效选项,请重试。${NC}" ;;
esac
[ "$choice" != "0" ] && [ "$choice" != "9" ] && read -p "按 Enter 键返回..."
done
}
# --- 脚本入口 ---
check_root
xray_menu
echo "脚本已退出。"

422
scripts/snell-v5.sh Executable file
View File

@@ -0,0 +1,422 @@
#!/bin/bash
# ==============================================================================
# Snell v5 管理脚本
# ==============================================================================
# --- 函数: 检查 Snell 安装和运行状态 ---
check_snell_status() {
# 检查 Snell 是否安装
if [ -f /usr/local/bin/snell-server ] && [ -f /etc/snell/snell-server.conf ]; then
echo -e "\033[32mSnell 状态: 已安装\033[0m"
else
echo -e "\033[31mSnell 状态: 未安装\033[0m"
fi
# 检查 Snell 服务是否运行
if systemctl is-active --quiet snell; then
echo -e "\033[32m服务状态: 运行中\033[0m"
else
echo -e "\033[31m服务状态: 未运行\033[0m"
fi
}
# --- 函数: 显示菜单 ---
show_menu() {
clear
echo "=================================================="
echo " Snell v5 管理脚本"
echo "=================================================="
check_snell_status
echo "--------------------------------------------------"
echo "1. 安装 Snell"
echo "2. 卸载 Snell"
echo "3. 修改 Snell 配置"
echo "4. 查看 Snell 配置"
echo "5. 查看 Snell 运行状态"
echo "6. 启动 Snell 服务"
echo "7. 停止 Snell 服务"
echo "8. 重启 Snell 服务"
echo "0. 退出脚本"
echo "=================================================="
echo -n "请输入选项 [0-8]: "
}
# --- 函数: 检查 root 权限 ---
check_root() {
if [ "$(id -u)" -ne 0 ]; then
echo "错误:此脚本需要以 root 权限运行。" >&2
exit 1
fi
}
# --- 函数: 安装 Snell ---
install_snell() {
# --- 新增:检查 Snell 是否已安装 ---
if [ -f /usr/local/bin/snell-server ] && [ -f /etc/snell/snell-server.conf ]; then
echo -e "\033[32mSnell 似乎已经安装,无需重复安装。\033[0m"
return
fi
# --- 步骤 1: 更新软件包列表并安装必要工具 ---
echo "--> 更新软件包列表并安装必要工具 (wget, unzip, coreutils)..."
if ! apt-get update > /dev/null; then
echo "错误:软件包列表更新失败。请检查网络连接或 apt 源。"
exit 1
fi
# coreutils 包含 shuf 命令
if ! apt-get install -y wget unzip coreutils > /dev/null; then
echo "错误:工具安装失败。请检查 apt 源或网络连接。"
exit 1
fi
echo " 工具安装完成。"
# --- 步骤 2: 下载、解压并部署 Snell ---
echo "--> 正在下载、解压并部署 Snell 服务器程序..."
if ! wget -q --show-progress https://dl.nssurge.com/snell/snell-server-v5.0.1-linux-amd64.zip -O snell.zip; then
echo "错误Snell 下载失败!请检查网络或链接是否有效。"
exit 1
fi
if ! unzip -o snell.zip -d /usr/local/bin/ > /dev/null; then
echo "错误Snell 解压失败!"
rm snell.zip
exit 1
fi
chmod +x /usr/local/bin/snell-server
mkdir -p /etc/snell
rm snell.zip
echo " Snell 程序部署完成。"
# --- 步骤 3: 用户输入端口和密码 ---
read -p "请输入 Snell 的监听端口 (留空则随机生成): " snell_port
if [ -z "${snell_port}" ]; then
while true; do
snell_port=$(shuf -i 30001-65535 -n 1)
if ! ss -lntu | grep -q ":${snell_port} "; then
echo " 端口未输入,使用随机端口: ${snell_port}"
break
fi
done
fi
read -p "请输入 Snell 的密码 (PSK留空则随机生成): " snell_psk
if [ -z "${snell_psk}" ]; then
# --- 新的密码生成逻辑 ---
# 1. 生成14位字母和数字
ALPHANUM=$(< /dev/urandom tr -dc 'A-Za-z0-9' | head -c 14)
# 2. 从 '-/@' 中随机选择两个不同的特殊字符
SPECIAL_CHARS='-/@'
S1_INDEX=$(($RANDOM % 3))
S1=${SPECIAL_CHARS:$S1_INDEX:1}
REMAINING_CHARS=${SPECIAL_CHARS//$S1/} # 移除已选的字符
S2_INDEX=$(($RANDOM % 2))
S2=${REMAINING_CHARS:$S2_INDEX:1}
# 3. 组合所有字符并打乱顺序
COMBINED_CHARS="${ALPHANUM}${S1}${S2}"
snell_psk=$(echo "$COMBINED_CHARS" | grep -o . | shuf | tr -d '\n')
echo " 密码未输入,使用随机密码: ${snell_psk}"
fi
# --- 步骤 4: 配置确认 ---
echo ""
echo "============================================="
echo "端口 (Port): ${snell_port}"
echo "密码 (PSK): ${snell_psk}"
echo "============================================="
echo "安装将在 2 秒后继续,按 Ctrl+C 取消"
sleep 2
# --- 步骤 5: 生成配置文件 ---
echo "--> 正在创建配置文件..."
cat > /etc/snell/snell-server.conf <<EOF
[snell-server]
listen = 0.0.0.0:${snell_port}
psk = ${snell_psk}
EOF
# --- 步骤 6: 创建 systemd 服务并启动 ---
echo "--> 正在创建 systemd 服务并启动..."
cat > /etc/systemd/system/snell.service <<EOF
[Unit]
Description=Snell Proxy Service
After=network.target
[Service]
Type=simple
User=root
Group=nogroup
LimitNOFILE=32768
ExecStart=/usr/local/bin/snell-server -c /etc/snell/snell-server.conf
AmbientCapabilities=CAP_NET_BIND_SERVICE
SyslogIdentifier=snell-server
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable snell > /dev/null 2>&1
systemctl start snell
# --- 步骤 7: 显示结果 ---
echo "--> 正在获取服务器公网 IP 地址..."
ip_address=$(curl -s https://ipv4.icanhazip.com || curl -s https://api.ipify.org)
if [ -z "$ip_address" ]; then
echo "警告:无法获取公网 IP 地址,请手动检查。"
fi
echo ""
echo "=================================================="
echo "🎉 Snell 服务器安装并配置成功!"
echo ""
echo "--------------- 服务状态 ---------------"
systemctl status snell
echo ""
echo "---------- 客户端配置信息 ----------"
echo "在Surge使用以下配置"
echo ""
echo "vps = snell, ${ip_address:-<您的服务器IP>}, ${snell_port}, psk=${snell_psk}, version=5"
echo ""
echo "=================================================="
}
# --- 函数: 卸载 Snell ---
uninstall_snell() {
echo "警告:此操作将彻底卸载 Snell 并删除所有相关文件!"
read -p "确定要继续吗?(y/n): " confirm
if [ "$confirm" != "y" ]; then
echo "卸载操作已取消。"
return
fi
echo "--> 正在停止并禁用 Snell 服务..."
systemctl stop snell > /dev/null 2>&1
systemctl disable snell > /dev/null 2>&1
echo "--> 正在删除 Snell systemd 服务文件..."
rm -f /etc/systemd/system/snell.service
systemctl daemon-reload
echo "--> 正在删除 Snell 可执行文件..."
rm -f /usr/local/bin/snell-server
echo "--> 正在删除 Snell 配置文件..."
rm -rf /etc/snell
echo "--> 正在删除此脚本..."
rm -- "$0"
echo ""
echo "✅ Snell 已被彻底卸载。"
echo "脚本自身也已被删除。退出。"
exit 0
}
# --- 函数: 修改 Snell 配置 ---
modify_config() {
if [ -f /etc/snell/snell-server.conf ]; then
# --- 步骤 1: 用户输入新端口和密码 ---
read -p "请输入新的 Snell 监听端口 (留空则随机生成): " snell_port
if [ -z "${snell_port}" ]; then
while true; do
snell_port=$(shuf -i 30001-65535 -n 1)
if ! ss -lntu | grep -q ":${snell_port} "; then
echo " 端口未输入,使用随机端口: ${snell_port}"
break
fi
done
fi
read -p "请输入新的 Snell 密码 (PSK留空则随机生成): " snell_psk
if [ -z "${snell_psk}" ]; then
# --- 新的密码生成逻辑 ---
# 1. 生成14位字母和数字
ALPHANUM=$(< /dev/urandom tr -dc 'A-Za-z0-9' | head -c 14)
# 2. 从 '-/@' 中随机选择两个不同的特殊字符
SPECIAL_CHARS='-/@'
S1_INDEX=$(($RANDOM % 3))
S1=${SPECIAL_CHARS:$S1_INDEX:1}
REMAINING_CHARS=${SPECIAL_CHARS//$S1/} # 移除已选的字符
S2_INDEX=$(($RANDOM % 2))
S2=${REMAINING_CHARS:$S2_INDEX:1}
# 3. 组合所有字符并打乱顺序
COMBINED_CHARS="${ALPHANUM}${S1}${S2}"
snell_psk=$(echo "$COMBINED_CHARS" | grep -o . | shuf | tr -d '\n')
echo " 密码未输入,使用随机密码: ${snell_psk}"
fi
# --- 步骤 2: 配置确认 ---
echo ""
echo "============================================="
echo "新端口 (Port): ${snell_port}"
echo "新密码 (PSK): ${snell_psk}"
echo "============================================="
echo "配置将在 2 秒后更新,按 Ctrl+C 取消"
sleep 2
# --- 步骤 3: 更新配置文件 ---
echo "--> 正在更新配置文件..."
cat > /etc/snell/snell-server.conf <<EOF
[snell-server]
listen = ::0:${snell_port}
psk = ${snell_psk}
EOF
# --- 步骤 4: 显示客户端配置信息 ---
echo "--> 正在获取服务器公网 IP 地址..."
ip_address=$(curl -s https://ipv4.icanhazip.com || curl -s https://api.ipify.org)
if [ -z "$ip_address" ]; then
echo "警告:无法获取公网 IP 地址,请手动检查。"
fi
echo ""
echo "=================================================="
echo "🎉 Snell 配置已更新!"
echo ""
echo "---------- 客户端配置信息 ----------"
echo "在Surge使用以下配置"
echo ""
echo "vps = snell, ${ip_address:-<您的服务器IP>}, ${snell_port}, psk=${snell_psk}, version=5"
echo ""
echo "=================================================="
# --- 步骤 5: 自动重启服务 ---
restart_snell
else
echo "错误Snell 配置文件不存在,可能尚未安装。"
fi
}
# --- 函数: 查看 Snell 配置 ---
view_config() {
if [ -f /etc/snell/snell-server.conf ]; then
echo "--> Snell 配置文件内容:"
cat /etc/snell/snell-server.conf
echo ""
ip_address=$(curl -s https://ipv4.icanhazip.com || curl -s https://api.ipify.org)
# --- 使用 awk 和 cut 准确提取配置 ---
port=$(grep "listen" /etc/snell/snell-server.conf | awk -F':' '{print $NF}')
psk=$(grep "psk" /etc/snell/snell-server.conf | cut -d'=' -f2 | tr -d ' ')
echo "--> 客户端配置信息:"
echo "vps = snell, ${ip_address:-<您的服务器IP>}, ${port}, psk=${psk}, version=5"
else
echo "错误Snell 配置文件不存在,可能尚未安装。"
fi
}
# --- 函数: 查看 Snell 运行状态 ---
check_snell_running() {
echo "--> Snell 服务运行状态:"
systemctl status snell
}
# --- 函数: 启动 Snell 服务 ---
start_snell() {
if [ -f /etc/systemd/system/snell.service ]; then
echo "--> 正在启动 Snell 服务..."
systemctl daemon-reload
systemctl enable snell > /dev/null 2>&1
if systemctl start snell; then
echo " Snell 服务已启动并启用。"
echo ""
echo "--> Snell 服务运行状态:"
systemctl status snell
else
echo " 错误Snell 服务启动失败,请使用 'journalctl -u snell' 查看日志。"
echo ""
echo "--> Snell 服务运行状态:"
systemctl status snell
fi
else
echo "错误Snell 服务未安装。"
fi
}
# --- 函数: 停止 Snell 服务 ---
stop_snell() {
if systemctl is-active --quiet snell || systemctl is-enabled --quiet snell; then
echo "--> 正在停止 Snell 服务..."
systemctl stop snell
systemctl disable snell > /dev/null 2>&1
echo " Snell 服务已停止并禁用。"
echo ""
echo "--> Snell 服务运行状态:"
systemctl status snell
else
echo "错误Snell 服务未安装或未运行。"
fi
}
# --- 函数: 重启 Snell 服务 ---
restart_snell() {
if [ -f /etc/systemd/system/snell.service ]; then
echo "--> 正在重启 Snell 服务..."
systemctl daemon-reload
systemctl enable snell > /dev/null 2>&1
if systemctl restart snell; then
echo " Snell 服务已重启并启用。"
echo ""
echo "--> Snell 服务运行状态:"
systemctl status snell
else
echo " 错误Snell 服务重启失败,请使用 'journalctl -u snell' 查看日志。"
echo ""
echo "--> Snell 服务运行状态:"
systemctl status snell
fi
else
echo "错误Snell 服务未安装。"
fi
}
# --- 主程序: 检查 root 权限并显示菜单 ---
check_root
while true; do
show_menu
read choice
case $choice in
1)
install_snell
;;
2)
uninstall_snell
;;
3)
modify_config
;;
4)
view_config
;;
5)
check_snell_running
;;
6)
start_snell
;;
7)
stop_snell
;;
8)
restart_snell
;;
0)
echo "退出脚本。"
exit 0
;;
*)
echo "无效选项,请输入 0-8。"
;;
esac
echo ""
echo "按 Enter 键返回菜单..."
read -r
done

518
scripts/ss2022-shadowtls.sh Executable file
View File

@@ -0,0 +1,518 @@
#!/bin/bash
# =================================================================
# shadowsocks-rust & shadowtls 服务器端综合管理脚本
# 描述: 提供一个主菜单,分别进入 ss-rust 和 shadowtls 的管理界面。
# =================================================================
# 定义输出颜色
GREEN='\033[0;32m'
RED='\033[0;31m'
NC='\033[0m' # 无颜色
# --- 通用函数 ---
check_root() {
if [ "$(id -u)" -ne 0 ]; then
echo -e "${RED}错误:此脚本需要以 root 权限运行。${NC}" >&2
exit 1
fi
}
# --- 新增函数: 检查是否所有组件都已卸载,如果是则删除脚本 ---
check_and_delete_script_if_all_uninstalled() {
# 检查 ss-rust 和 shadowtls 的二进制文件是否都不存在
if [ ! -f /usr/local/bin/ss-rust ] && [ ! -f /usr/local/bin/shadowtls ]; then
echo -e "${GREEN}检测到 ss-rust 和 shadowtls 均已卸载。${NC}"
echo "--> 正在删除此脚本..."
rm -- "$0"
echo "脚本自身也已被删除。即将退出。"
exit 0
fi
}
# =================================================================
# S-S-R-U-S-T M-A-N-A-G-E-M-E-N-T
# =================================================================
# --- ss-rust 变量定义 (这里改为了动态获取,不再硬编码版本号) ---
# SS_VERSION, SS_URL, SS_TAR_FILE 将在安装函数中动态生成
# --- 函数: 检查 ss-rust 安装和运行状态 ---
check_ss_rust_status() {
if [ -f /usr/local/bin/ss-rust ] && [ -f /etc/systemd/system/ss-rust.service ]; then
echo -e "${GREEN}ss-rust 状态: 已安装${NC}"
else
echo -e "${RED}ss-rust 状态: 未安装${NC}"
fi
if systemctl is-active --quiet ss-rust; then
echo -e "${GREEN}服务状态 : 运行中${NC}"
else
echo -e "${RED}服务状态 : 未运行${NC}"
fi
}
# --- 函数: 确保 jq 已安装 ---
ensure_jq() {
if ! command -v jq &> /dev/null || ! command -v curl &> /dev/null; then
echo "--> 检测到依赖工具 jq 或 curl 未安装,正在尝试自动安装..."
if command -v apt-get &> /dev/null; then
apt-get update >/dev/null && apt-get install -y jq curl
elif command -v yum &> /dev/null; then
yum install -y jq curl
else
echo -e "${RED}无法自动安装 jq/curl。请手动安装后再试。${NC}"
return 1
fi
fi
return 0
}
# --- 函数: 安装 ss-rust ---
install_ss_rust() {
if [ -f /usr/local/bin/ss-rust ]; then
echo -e "${GREEN}ss-rust 似乎已经安装,无需重复安装。${NC}"
return
fi
# --- 新增: 自动获取最新版本逻辑 ---
ensure_jq || exit 1
echo "--> 正在获取 ss-rust 最新版本号..."
SS_VERSION=$(curl -s "https://api.github.com/repos/shadowsocks/shadowsocks-rust/releases/latest" | jq -r .tag_name)
if [ -z "$SS_VERSION" ] || [ "$SS_VERSION" == "null" ]; then
echo -e "${RED}获取最新版本失败,请检查网络!${NC}"
exit 1
fi
SS_URL="https://github.com/shadowsocks/shadowsocks-rust/releases/download/${SS_VERSION}/shadowsocks-${SS_VERSION}.x86_64-unknown-linux-gnu.tar.xz"
SS_TAR_FILE="shadowsocks-${SS_VERSION}.x86_64-unknown-linux-gnu.tar.xz"
echo -e "${GREEN}检测到最新版本: ${SS_VERSION}${NC}"
# ----------------------------
echo "--> 正在准备安装环境..."
if command -v apt-get &> /dev/null; then
apt-get update && apt-get install -y wget tar xz-utils openssl jq coreutils
elif command -v yum &> /dev/null; then
yum install -y wget tar xz-utils openssl jq coreutils
else
echo -e "${RED}无法确定包管理器,请手动安装 wget, tar, xz-utils, openssl, jq, coreutils。${NC}"
exit 1
fi
echo "--> 正在下载、解压并部署 ss-rust..."
if ! wget -O "${SS_TAR_FILE}" "${SS_URL}"; then
echo -e "${RED}下载 ss-rust 失败!请检查网络或链接是否有效。${NC}"
exit 1
fi
tar -xf "${SS_TAR_FILE}"
mv ssserver /usr/local/bin/ss-rust
chmod +x /usr/local/bin/ss-rust
rm -f sslocal ssmanager ssurl "${SS_TAR_FILE}"
echo " ss-rust 程序部署完成。"
mkdir -p /etc/ss-rust
read -p "请输入 ss-rust 的监听端口 (留空则随机生成): " PORT
[ -z "$PORT" ] && PORT=$((RANDOM % 55536 + 10000))
read -p "请输入 ss-rust 的密码 (留空则随机生成): " PASSWORD
[ -z "$PASSWORD" ] && PASSWORD=$(head -c 16 /dev/urandom | base64 -w 0)
echo "--> 正在创建配置文件..."
cat > /etc/ss-rust/config.json <<EOF
{
"server": "0.0.0.0",
"server_port": ${PORT},
"password": "${PASSWORD}",
"method": "2022-blake3-aes-128-gcm",
"timeout": 300,
"fast_open": false,
"mode": "tcp_and_udp"
}
EOF
echo "--> 正在创建 systemd 服务..."
cat > /etc/systemd/system/ss-rust.service <<EOF
[Unit]
Description=Shadowsocks Rust Server
After=network.target
[Service]
ExecStart=/usr/local/bin/ss-rust -c /etc/ss-rust/config.json
Restart=always
User=root
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable ss-rust > /dev/null 2>&1
systemctl start ss-rust
echo -e "${GREEN}🎉 ss-rust 服务器安装并配置成功!${NC}"
view_config_ss_rust
}
# --- 函数: 卸载 ss-rust ---
uninstall_ss_rust() {
if [ ! -f /usr/local/bin/ss-rust ]; then
echo -e "${RED}ss-rust 未安装,无需卸载。${NC}"
return
fi
read -p "警告:确定要卸载 ss-rust 吗?[y/N]: " confirm
if [[ ! "$confirm" =~ ^[yY]([eE][sS])?$ ]]; then
echo "卸载操作已取消。"
return
fi
systemctl stop ss-rust
systemctl disable ss-rust > /dev/null 2>&1
rm -f /etc/systemd/system/ss-rust.service
rm -f /usr/local/bin/ss-rust
rm -rf /etc/ss-rust
systemctl daemon-reload
echo -e "${GREEN}ss-rust 已成功卸载。${NC}"
# 调用检查函数
check_and_delete_script_if_all_uninstalled
}
# --- 函数: 修改 ss-rust 配置 ---
modify_config_ss_rust() {
if [ ! -f /etc/ss-rust/config.json ]; then
echo -e "${RED}ss-rust 未安装,无法修改配置。${NC}"; return; fi
ensure_jq || return
read -p "请输入新的监听端口 (留空则随机生成): " PORT
[ -z "$PORT" ] && PORT=$((RANDOM % 55536 + 10000))
read -p "请输入新的密码 (留空则随机生成): " PASSWORD
[ -z "$PASSWORD" ] && PASSWORD=$(head -c 16 /dev/urandom | base64 -w 0)
jq ".server_port = ${PORT} | .password = \"${PASSWORD}\"" /etc/ss-rust/config.json > /tmp/ss-config.tmp && mv /tmp/ss-config.tmp /etc/ss-rust/config.json
systemctl restart ss-rust
echo -e "${GREEN}🎉 ss-rust 配置已更新!${NC}"
view_config_ss_rust
}
# --- 函数: 查看 ss-rust 配置 ---
view_config_ss_rust() {
if [ ! -f /etc/ss-rust/config.json ]; then
echo -e "${RED}ss-rust 未安装,无法查看配置。${NC}"; return; fi
ensure_jq || return
local port=$(jq .server_port /etc/ss-rust/config.json)
local password=$(jq -r .password /etc/ss-rust/config.json)
local method=$(jq -r .method /etc/ss-rust/config.json)
local ip_address=$(curl -s https://ipv4.icanhazip.com || echo "<您的服务器IP>")
echo "------------------------------------------"
echo " ss-rust 当前配置信息"
echo "------------------------------------------"
echo -e "端口 (Port) : ${GREEN}${port}${NC}"
echo -e "密码 (Password) : ${GREEN}${password}${NC}"
echo -e "加密 (Method) : ${GREEN}${method}${NC}"
echo "------------------------------------------"
echo "Surge 客户端配置:"
echo -e "${GREEN}VPS = ss, ${ip_address}, ${port}, encrypt-method=${method}, password=${password}, udp-relay=true${NC}"
echo "------------------------------------------"
}
# --- 函数: ss-rust 服务管理 ---
manage_ss_rust_service() {
if [ ! -f /etc/systemd/system/ss-rust.service ]; then
echo -e "${RED}ss-rust 未安装。${NC}"; return; fi
case $1 in
start) systemctl start ss-rust && echo -e "${GREEN}服务启动成功。${NC}" || echo -e "${RED}服务启动失败。${NC}" ;;
stop) systemctl stop ss-rust && echo -e "${GREEN}服务已停止。${NC}" || echo -e "${RED}服务停止失败。${NC}" ;;
restart) systemctl restart ss-rust && echo -e "${GREEN}服务重启成功。${NC}" || echo -e "${RED}服务重启失败。${NC}" ;;
status) systemctl status ss-rust ;;
esac
}
# --- 函数: ss-rust 子菜单 ---
ss_rust_menu() {
while true; do
clear
echo "=================================================="
echo " shadowsocks-rust 管理界面"
echo "=================================================="
check_ss_rust_status
echo "--------------------------------------------------"
echo "1. 安装 ss-rust"
echo "2. 卸载 ss-rust"
echo "3. 修改 ss-rust 配置"
echo "4. 查看 ss-rust 配置"
echo "5. 启动 ss-rust"
echo "6. 停止 ss-rust"
echo "7. 重启 ss-rust"
echo "8. 查看运行状态"
echo "0. 返回主菜单"
echo "=================================================="
read -p "请输入选项 [0-8]: " choice
case $choice in
1) install_ss_rust ;;
2) uninstall_ss_rust ;;
3) modify_config_ss_rust ;;
4) view_config_ss_rust ;;
5) manage_ss_rust_service start ;;
6) manage_ss_rust_service stop ;;
7) manage_ss_rust_service restart ;;
8) manage_ss_rust_service status ;;
0) return ;;
*) echo -e "${RED}无效选项,请重试。${NC}" ;;
esac
[ "$choice" != "0" ] && read -p "按 Enter 键返回..."
done
}
# =================================================================
# S-H-A-D-O-W-T-L-S M-A-N-A-G-E-M-E-N-T
# =================================================================
# --- shadowtls 变量定义 ---
STLS_URL="https://github.com/ihciah/shadow-tls/releases/download/v0.2.25/shadow-tls-x86_64-unknown-linux-musl"
# --- 函数: 检查 shadowtls 安装和运行状态 ---
check_shadowtls_status() {
if [ -f /usr/local/bin/shadowtls ] && [ -f /etc/systemd/system/shadowtls.service ]; then
echo -e "${GREEN}shadowtls 状态: 已安装${NC}"
else
echo -e "${RED}shadowtls 状态: 未安装${NC}"
fi
if systemctl is-active --quiet shadowtls; then
echo -e "${GREEN}服务状态 : 运行中${NC}"
else
echo -e "${RED}服务状态 : 未运行${NC}"
fi
}
# --- 函数: 安装 shadowtls ---
install_shadowtls() {
if [ -f /usr/local/bin/shadowtls ]; then
echo -e "${GREEN}shadowtls 似乎已经安装。${NC}"; return; fi
echo "--> 正在下载 shadowtls..."
curl -L "$STLS_URL" -o /usr/local/bin/shadowtls
chmod +x /usr/local/bin/shadowtls
read -p "请输入 shadowtls 监听端口 (留空默认 8443): " LISTEN_PORT
[ -z "$LISTEN_PORT" ] && LISTEN_PORT=8443
read -p "请输入后端的 ss-rust 端口: " SS_PORT
while [ -z "$SS_PORT" ]; do
read -p "${RED}后端 ss-rust 端口不能为空,请重新输入: ${NC}" SS_PORT
done
read -p "请输入伪装域名 (留空默认 www.muji.com): " SNI_HOST
[ -z "$SNI_HOST" ] && SNI_HOST="www.muji.com"
read -p "请输入 shadowtls 密码 (留空随机生成): " PASSWORD
if [ -z "$PASSWORD" ]; then
ALPHANUM=$(< /dev/urandom tr -dc 'A-Za-z0-9' | head -c 14)
SPECIAL_CHARS='-/@'
S1_INDEX=$(($RANDOM % 3)); S1=${SPECIAL_CHARS:$S1_INDEX:1}
REMAINING_CHARS=${SPECIAL_CHARS//$S1/}; S2_INDEX=$(($RANDOM % 2)); S2=${REMAINING_CHARS:$S2_INDEX:1}
COMBINED_CHARS="${ALPHANUM}${S1}${S2}"
PASSWORD=$(echo "$COMBINED_CHARS" | grep -o . | shuf | tr -d '\n')
fi
echo "--> 正在创建 systemd 服务..."
cat > /etc/systemd/system/shadowtls.service <<EOF
[Unit]
Description=ShadowTLS Server Service
After=network-online.target
Wants=network-online.target systemd-networkd-wait-online.service
[Service]
LimitNOFILE=32767
Type=simple
User=root
Restart=on-failure
RestartSec=5s
ExecStart=/usr/local/bin/shadowtls --v3 --strict server --listen 0.0.0.0:${LISTEN_PORT} --server 127.0.0.1:${SS_PORT} --tls ${SNI_HOST}:443 --password ${PASSWORD}
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable shadowtls > /dev/null 2>&1
systemctl start shadowtls
echo -e "${GREEN}🎉 shadowtls 服务器安装并配置成功!${NC}"
view_config_shadowtls
}
# --- 函数: 卸载 shadowtls ---
uninstall_shadowtls() {
if [ ! -f /usr/local/bin/shadowtls ]; then
echo -e "${RED}shadowtls 未安装。${NC}"; return; fi
read -p "警告:确定要卸载 shadowtls 吗?[y/N]: " confirm
if [[ ! "$confirm" =~ ^[yY]([eE][sS])?$ ]]; then
echo "卸载操作已取消。"; return; fi
systemctl stop shadowtls
systemctl disable shadowtls > /dev/null 2>&1
rm -f /etc/systemd/system/shadowtls.service
rm -f /usr/local/bin/shadowtls
systemctl daemon-reload
echo -e "${GREEN}shadowtls 已成功卸载。${NC}"
# 调用检查函数
check_and_delete_script_if_all_uninstalled
}
# --- 函数: 查看 shadowtls 配置 ---
view_config_shadowtls() {
if [ ! -f /etc/systemd/system/shadowtls.service ]; then
echo -e "${RED}shadowtls 未安装。${NC}"; return; fi
local exec_start=$(grep 'ExecStart=' /etc/systemd/system/shadowtls.service)
# 使用更通用的正则表达式解析端口,以提高兼容性
local listen_port=$(echo "$exec_start" | sed -n 's/.*--listen [^ ]*:\([0-9]*\).*/\1/p')
local server_port=$(echo "$exec_start" | sed -n 's/.*--server [^ ]*:\([0-9]*\).*/\1/p')
local sni_host=$(echo "$exec_start" | sed -n 's/.*--tls \([^:]*\):443.*/\1/p')
local stls_password=$(echo "$exec_start" | sed -n 's/.*--password \([^ ]*\).*/\1/p')
local ip_address=$(curl -s https://ipv4.icanhazip.com || echo "<您的服务器IP>")
local ss_password="<ss密码>"
local ss_method="2022-blake3-aes-128-gcm"
if [ -f /etc/ss-rust/config.json ] && ensure_jq; then
ss_password=$(jq -r .password /etc/ss-rust/config.json)
ss_method=$(jq -r .method /etc/ss-rust/config.json)
fi
echo "------------------------------------------"
echo " shadowtls 当前配置信息"
echo "------------------------------------------"
echo -e "监听端口 : ${GREEN}${listen_port}${NC}"
echo -e "密码 : ${GREEN}${stls_password}${NC}"
echo -e "后端 SS 端口: ${GREEN}${server_port}${NC}"
echo -e "伪装域名 : ${GREEN}${sni_host}${NC}"
echo "------------------------------------------"
echo "Surge 客户端配置:"
echo -e "${GREEN}VPS = ss, ${ip_address}, ${listen_port}, encrypt-method=${ss_method}, password=${ss_password}, shadow-tls-password=${stls_password}, shadow-tls-sni=${sni_host}, shadow-tls-version=3, udp-relay=true${NC}"
echo "------------------------------------------"
}
# --- 函数: 修改 shadowtls 配置 ---
modify_config_shadowtls() {
if [ ! -f /etc/systemd/system/shadowtls.service ]; then
echo -e "${RED}shadowtls 未安装。${NC}"; return; fi
read -p "请输入新的 shadowtls 监听端口 (留空默认 8443): " LISTEN_PORT
[ -z "$LISTEN_PORT" ] && LISTEN_PORT=8443
read -p "请输入新的后端 ss-rust 端口: " SS_PORT
while [ -z "$SS_PORT" ]; do
read -p "${RED}后端 ss-rust 端口不能为空,请重新输入: ${NC}" SS_PORT
done
read -p "请输入新的伪装域名 (留空默认 www.muji.com): " SNI_HOST
[ -z "$SNI_HOST" ] && SNI_HOST="www.muji.com"
read -p "请输入新的 shadowtls 密码 (留空随机): " PASSWORD
if [ -z "$PASSWORD" ]; then
ALPHANUM=$(< /dev/urandom tr -dc 'A-Za-z0-9' | head -c 14)
SPECIAL_CHARS='-/@'
S1_INDEX=$(($RANDOM % 3)); S1=${SPECIAL_CHARS:$S1_INDEX:1}
REMAINING_CHARS=${SPECIAL_CHARS//$S1/}; S2_INDEX=$(($RANDOM % 2)); S2=${REMAINING_CHARS:$S2_INDEX:1}
COMBINED_CHARS="${ALPHANUM}${S1}${S2}"
PASSWORD=$(echo "$COMBINED_CHARS" | grep -o . | shuf | tr -d '\n')
fi
local exec_line="ExecStart=/usr/local/bin/shadowtls --v3 --strict server --listen 0.0.0.0:${LISTEN_PORT} --server 127.0.0.1:${SS_PORT} --tls ${SNI_HOST}:443 --password ${PASSWORD}"
sed -i "s|^ExecStart=.*|$exec_line|" /etc/systemd/system/shadowtls.service
systemctl daemon-reload
systemctl restart shadowtls
echo -e "${GREEN}🎉 shadowtls 配置已更新!${NC}"
view_config_shadowtls
}
# --- 函数: shadowtls 服务管理 ---
manage_shadowtls_service() {
if [ ! -f /etc/systemd/system/shadowtls.service ]; then
echo -e "${RED}shadowtls 未安装。${NC}"; return; fi
case $1 in
start) systemctl start shadowtls && echo -e "${GREEN}服务启动成功。${NC}" || echo -e "${RED}服务启动失败。${NC}" ;;
stop) systemctl stop shadowtls && echo -e "${GREEN}服务已停止。${NC}" || echo -e "${RED}服务停止失败。${NC}" ;;
restart) systemctl restart shadowtls && echo -e "${GREEN}服务重启成功。${NC}" || echo -e "${RED}服务重启失败。${NC}" ;;
status) systemctl status shadowtls ;;
esac
}
# --- 函数: shadowtls 子菜单 ---
shadowtls_menu() {
while true; do
clear
echo "=================================================="
echo " shadowtls 管理界面"
echo "=================================================="
check_shadowtls_status
echo "--------------------------------------------------"
echo "1. 安装 shadowtls"
echo "2. 卸载 shadowtls"
echo "3. 修改 shadowtls 配置"
echo "4. 查看 shadowtls 配置"
echo "5. 启动 shadowtls"
echo "6. 停止 shadowtls"
echo "7. 重启 shadowtls"
echo "8. 查看运行状态"
echo "0. 返回主菜单"
echo "=================================================="
read -p "请输入选项 [0-8]: " choice
case $choice in
1) install_shadowtls ;;
2) uninstall_shadowtls ;;
3) modify_config_shadowtls ;;
4) view_config_shadowtls ;;
5) manage_shadowtls_service start ;;
6) manage_shadowtls_service stop ;;
7) manage_shadowtls_service restart ;;
8) manage_shadowtls_service status ;;
0) return ;;
*) echo -e "${RED}无效选项,请重试。${NC}" ;;
esac
[ "$choice" != "0" ] && read -p "按 Enter 键返回..."
done
}
# =================================================================
# M-A-I-N M-E-N-U
# =================================================================
main_menu() {
while true; do
clear
echo "=================================================="
echo " SS-Rust & ShadowTLS 综合管理脚本"
echo "=================================================="
echo "1. shadowsocks-rust 管理"
echo "2. shadowtls 管理"
echo "0. 退出脚本"
echo "=================================================="
read -p "请输入选项 [0-2]: " choice
case $choice in
1) ss_rust_menu ;;
2) shadowtls_menu ;;
0) break ;;
*) echo -e "${RED}无效选项,请重试。${NC}"; sleep 1 ;;
esac
done
}
# --- 脚本入口 ---
check_root
main_menu
echo "脚本已退出。"