diff --git a/ss-rust.sh b/ss-rust.sh index 54e475e..2ad2d0b 100644 --- a/ss-rust.sh +++ b/ss-rust.sh @@ -1,9 +1,8 @@ #!/bin/bash -# SS-Rust 一键安装脚本 (ss2022 + aes-128-gcm) -# 自动生成订阅链接 + Surge 配置 -# Usage: curl -sL | bash - -# 不用 set -e,手动处理错误 +# SS-Rust 一键安装脚本 +# 支持: ss2022 (2022-blake3-aes-128-gcm) / ss128 (aes-128-gcm) / 双节点 +# 自动生成 SS订阅 + Surge + Clash 配置 +# GitHub: https://github.com/mango082888-bit/ss-rust # ============ 颜色 ============ RED='\033[0;31m' @@ -16,33 +15,54 @@ info() { echo -e "${GREEN}[INFO]${NC} $1"; } warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; } -# ============ 检测系统 ============ +# ============ 基础检测 ============ check_root() { [[ $EUID -ne 0 ]] && error "请使用 root 用户运行" } -check_os() { - if [[ -f /etc/debian_version ]]; then +get_pkg_manager() { + if command -v apt &>/dev/null; then PKG="apt" - elif [[ -f /etc/redhat-release ]]; then + elif command -v yum &>/dev/null; then PKG="yum" + elif command -v apk &>/dev/null; then + PKG="apk" else - error "不支持的系统" + error "不支持的包管理器" fi } +install_deps() { + info "安装依赖..." + case $PKG in + apt) apt update -qq &>/dev/null; apt install -y -qq curl openssl xz-utils tar chrony &>/dev/null ;; + yum) yum install -y -q curl openssl xz tar chrony &>/dev/null ;; + apk) apk add --quiet curl openssl xz tar chrony &>/dev/null ;; + esac +} + +get_arch() { + case $(uname -m) in + x86_64) echo "x86_64-unknown-linux-gnu" ;; + aarch64) echo "aarch64-unknown-linux-gnu" ;; + armv7l) echo "armv7-unknown-linux-gnueabihf" ;; + *) error "不支持的架构: $(uname -m)" ;; + esac +} + +get_ip() { + IP=$(curl -s4m5 ip.sb 2>/dev/null || curl -s4m5 ifconfig.me 2>/dev/null || curl -s4m5 ipinfo.io/ip 2>/dev/null) + [[ -z "$IP" ]] && error "无法获取公网IP" + echo "$IP" +} + # ============ 时间同步 ============ sync_time() { info "同步系统时间..." if command -v timedatectl &>/dev/null; then timedatectl set-ntp true 2>/dev/null || true fi - if command -v ntpdate &>/dev/null; then - ntpdate -u pool.ntp.org 2>/dev/null || true - elif command -v chronyd &>/dev/null; then - chronyc makestep 2>/dev/null || true - else - $PKG install -y chrony &>/dev/null + if command -v chronyd &>/dev/null; then systemctl enable --now chronyd 2>/dev/null || true chronyc makestep 2>/dev/null || true fi @@ -52,64 +72,103 @@ sync_time() { # ============ 安装 ss-rust ============ install_ssrust() { info "安装 shadowsocks-rust..." + ARCH_NAME=$(get_arch) - ARCH=$(uname -m) - case $ARCH in - x86_64) ARCH_NAME="x86_64-unknown-linux-gnu" ;; - aarch64) ARCH_NAME="aarch64-unknown-linux-gnu" ;; - *) error "不支持的架构: $ARCH" ;; - esac - - # 获取最新版本 - LATEST=$(curl -sL https://api.github.com/repos/shadowsocks/shadowsocks-rust/releases/latest | grep tag_name | head -1 | grep -oP 'v[\d.]+') - [[ -z "$LATEST" ]] && LATEST="v1.21.2" + LATEST=$(curl -sLm10 https://api.github.com/repos/shadowsocks/shadowsocks-rust/releases/latest | grep tag_name | head -1 | grep -oP 'v[\d.]+') + [[ -z "$LATEST" ]] && LATEST="v1.24.0" info "版本: $LATEST" URL="https://github.com/shadowsocks/shadowsocks-rust/releases/download/${LATEST}/shadowsocks-${LATEST}.${ARCH_NAME}.tar.xz" cd /tmp - curl -sL "$URL" -o ss-rust.tar.xz || error "下载失败" - tar xf ss-rust.tar.xz - cp -f ssserver sslocal ssurl /usr/local/bin/ 2>/dev/null || cp -f ss* /usr/local/bin/ - chmod +x /usr/local/bin/ss* - rm -f ss-rust.tar.xz + rm -f ss-rust-dl.tar.xz + curl -sL "$URL" -o ss-rust-dl.tar.xz - info "shadowsocks-rust 安装完成" + # 验证下载 + FILE_SIZE=$(stat -c%s ss-rust-dl.tar.xz 2>/dev/null || stat -f%z ss-rust-dl.tar.xz 2>/dev/null) + [[ "$FILE_SIZE" -lt 100000 ]] && error "下载失败,文件太小 (${FILE_SIZE} bytes),可能是网络问题" + + file ss-rust-dl.tar.xz | grep -q "XZ" || error "下载的文件不是有效的 XZ 压缩包" + + tar xf ss-rust-dl.tar.xz || error "解压失败" + + [[ ! -f ssserver ]] && error "解压后找不到 ssserver 二进制文件" + + cp -f ssserver /usr/local/bin/ + cp -f sslocal /usr/local/bin/ 2>/dev/null || true + cp -f ssurl /usr/local/bin/ 2>/dev/null || true + chmod +x /usr/local/bin/ss* + + # 清理 + rm -f ss-rust-dl.tar.xz ssserver sslocal ssurl ssmanager ssservice + + /usr/local/bin/ssserver --version && info "shadowsocks-rust 安装完成" || error "安装验证失败" } -# ============ 生成密钥 ============ -gen_key_128() { - openssl rand -base64 16 -} - -gen_key_256() { - openssl rand -base64 32 -} - -# ============ 获取公网IP ============ -get_ip() { - IP=$(curl -s4 ip.sb 2>/dev/null || curl -s4 ifconfig.me 2>/dev/null || curl -s4 ipinfo.io/ip 2>/dev/null) - [[ -z "$IP" ]] && error "无法获取公网IP" - echo "$IP" +# ============ 节点选择菜单 ============ +select_node_type() { + echo "" + echo -e "${CYAN}════════════════════════════════════════${NC}" + echo -e "${CYAN} 🔐 选择节点类型${NC}" + echo -e "${CYAN}════════════════════════════════════════${NC}" + echo "" + echo -e " ${GREEN}1.${NC} SS2022-128 (2022-blake3-aes-128-gcm) — 新协议,推荐" + echo -e " ${GREEN}2.${NC} SS-AES-128 (aes-128-gcm) — 传统协议,兼容性好" + echo -e " ${GREEN}3.${NC} 双节点全装 (SS2022 + SS128)" + echo "" + read -p "请选择 [1-3] (默认3): " node_choice + node_choice=${node_choice:-3} } # ============ 生成配置 ============ gen_config() { SERVER_IP=$(get_ip) + mkdir -p /etc/shadowsocks-rust - # ss2022-128 + ss裸128 端口和密钥 PORT_2022=$((RANDOM % 10000 + 20000)) PORT_RAW=$((RANDOM % 10000 + 30000)) - KEY_2022=$(gen_key_128) + KEY_2022=$(openssl rand -base64 16) KEY_RAW=$(openssl rand -base64 16) - METHOD_2022="2022-blake3-aes-128-gcm" METHOD_RAW="aes-128-gcm" - mkdir -p /etc/shadowsocks-rust - - # 多端口配置 - cat > /etc/shadowsocks-rust/config.json << EOF + case "${node_choice}" in + 1) + cat > /etc/shadowsocks-rust/config.json << EOF +{ + "servers": [ + { + "server": "0.0.0.0", + "server_port": ${PORT_2022}, + "method": "${METHOD_2022}", + "password": "${KEY_2022}", + "timeout": 300, + "fast_open": true + } + ] +} +EOF + NODE_MODE="ss2022" + ;; + 2) + cat > /etc/shadowsocks-rust/config.json << EOF +{ + "servers": [ + { + "server": "0.0.0.0", + "server_port": ${PORT_RAW}, + "method": "${METHOD_RAW}", + "password": "${KEY_RAW}", + "timeout": 300, + "fast_open": true + } + ] +} +EOF + NODE_MODE="ss128" + ;; + 3|*) + cat > /etc/shadowsocks-rust/config.json << EOF { "servers": [ { @@ -131,6 +190,9 @@ gen_config() { ] } EOF + NODE_MODE="both" + ;; + esac info "配置文件: /etc/shadowsocks-rust/config.json" } @@ -155,269 +217,262 @@ EOF systemctl daemon-reload systemctl enable --now ss-rust - sleep 1 + sleep 2 if systemctl is-active --quiet ss-rust; then info "ss-rust 服务启动成功" else - error "ss-rust 服务启动失败,请检查日志: journalctl -u ss-rust" + echo "" + journalctl -u ss-rust -n 5 --no-pager + error "ss-rust 服务启动失败" fi } +# ============ 读取现有配置 ============ +load_config() { + if [[ ! -f /etc/shadowsocks-rust/config.json ]]; then + return 1 + fi + SERVER_IP=$(get_ip) + + # 用 python3 或 grep 解析 + if command -v python3 &>/dev/null; then + eval $(python3 -c " +import json +with open('/etc/shadowsocks-rust/config.json') as f: + c = json.load(f) +for i,s in enumerate(c['servers']): + m = s['method'] + if '2022' in m: + print(f'PORT_2022={s[\"server_port\"]}') + print(f'KEY_2022={s[\"password\"]}') + print(f'METHOD_2022={m}') + else: + print(f'PORT_RAW={s[\"server_port\"]}') + print(f'KEY_RAW={s[\"password\"]}') + print(f'METHOD_RAW={m}') +n = len(c['servers']) +if n == 1: + if '2022' in c['servers'][0]['method']: + print('NODE_MODE=ss2022') + else: + print('NODE_MODE=ss128') +else: + print('NODE_MODE=both') +" 2>/dev/null) + fi + return 0 +} + # ============ 生成订阅 ============ gen_subscribe() { - SERVER_IP=$(get_ip) + load_config || return SUB_DIR="/etc/shadowsocks-rust/subscribe" mkdir -p "$SUB_DIR" - # SS URI 格式: ss://method:password@host:port#name - URI_2022="ss://$(echo -n "${METHOD_2022}:${KEY_2022}" | base64 -w0)@${SERVER_IP}:${PORT_2022}#SS2022-128" - URI_RAW="ss://$(echo -n "${METHOD_RAW}:${KEY_RAW}" | base64 -w0)@${SERVER_IP}:${PORT_RAW}#SS-AES-128" + SS_URIS="" + SURGE_PROXIES="" + CLASH_PROXIES="" + INFO_NODES="" + SURGE_NAMES="" + + if [[ -n "${PORT_2022:-}" ]]; then + URI_2022="ss://$(echo -n "${METHOD_2022}:${KEY_2022}" | base64 -w0)@${SERVER_IP}:${PORT_2022}#SS2022-128" + SS_URIS="${SS_URIS}${URI_2022}\n" + SURGE_PROXIES="${SURGE_PROXIES}SS2022-128 = ss, ${SERVER_IP}, ${PORT_2022}, encrypt-method=${METHOD_2022}, password=${KEY_2022}\n" + SURGE_NAMES="${SURGE_NAMES}SS2022-128, " + CLASH_PROXIES="${CLASH_PROXIES} - name: SS2022-128\n type: ss\n server: ${SERVER_IP}\n port: ${PORT_2022}\n cipher: ${METHOD_2022}\n password: \"${KEY_2022}\"\n\n" + INFO_NODES="${INFO_NODES}【SS2022-AES-128】新协议\n 地址: ${SERVER_IP}\n 端口: ${PORT_2022}\n 加密: ${METHOD_2022}\n 密码: ${KEY_2022}\n\n" + fi + + if [[ -n "${PORT_RAW:-}" ]]; then + URI_RAW="ss://$(echo -n "${METHOD_RAW}:${KEY_RAW}" | base64 -w0)@${SERVER_IP}:${PORT_RAW}#SS-AES-128" + SS_URIS="${SS_URIS}${URI_RAW}\n" + SURGE_PROXIES="${SURGE_PROXIES}SS-AES-128 = ss, ${SERVER_IP}, ${PORT_RAW}, encrypt-method=${METHOD_RAW}, password=${KEY_RAW}\n" + SURGE_NAMES="${SURGE_NAMES}SS-AES-128, " + CLASH_PROXIES="${CLASH_PROXIES} - name: SS-AES-128\n type: ss\n server: ${SERVER_IP}\n port: ${PORT_RAW}\n cipher: ${METHOD_RAW}\n password: \"${KEY_RAW}\"\n\n" + INFO_NODES="${INFO_NODES}【SS-AES-128】传统协议\n 地址: ${SERVER_IP}\n 端口: ${PORT_RAW}\n 加密: ${METHOD_RAW}\n 密码: ${KEY_RAW}\n\n" + fi # Base64 订阅 - echo -e "${URI_2022}\n${URI_RAW}" | base64 -w0 > "$SUB_DIR/subscribe.txt" + echo -e "${SS_URIS}" | base64 -w0 > "$SUB_DIR/subscribe.txt" - # Surge 配置 + # Surge cat > "$SUB_DIR/surge.conf" << EOF -# Surge SS 配置 -# 生成时间: $(date '+%Y-%m-%d %H:%M:%S') -# 服务器: ${SERVER_IP} - +# Surge SS 配置 | $(date '+%Y-%m-%d %H:%M:%S') | ${SERVER_IP} [Proxy] -SS2022-128 = ss, ${SERVER_IP}, ${PORT_2022}, encrypt-method=${METHOD_2022}, password=${KEY_2022} -SS-AES-128 = ss, ${SERVER_IP}, ${PORT_RAW}, encrypt-method=${METHOD_RAW}, password=${KEY_RAW} - +$(echo -e "${SURGE_PROXIES}") [Proxy Group] -Proxy = select, SS2022-128, SS-AES-128, DIRECT +Proxy = select, $(echo "${SURGE_NAMES}DIRECT" | sed 's/, DIRECT$/, DIRECT/') EOF - # Clash 配置 + # Clash cat > "$SUB_DIR/clash.yaml" << EOF -# Clash SS 配置 -# 生成时间: $(date '+%Y-%m-%d %H:%M:%S') - +# Clash SS 配置 | $(date '+%Y-%m-%d %H:%M:%S') proxies: - - name: SS2022-128 - type: ss - server: ${SERVER_IP} - port: ${PORT_2022} - cipher: ${METHOD_2022} - password: "${KEY_2022}" - - - name: SS-AES-128 - type: ss - server: ${SERVER_IP} - port: ${PORT_RAW} - cipher: ${METHOD_RAW} - password: "${KEY_RAW}" +$(echo -e "${CLASH_PROXIES}") EOF - # 纯文本信息 + # Info cat > "$SUB_DIR/info.txt" << EOF -======================================== +════════════════════════════════════════ Shadowsocks-Rust 节点信息 - 生成时间: $(date '+%Y-%m-%d %H:%M:%S') - 服务器IP: ${SERVER_IP} -======================================== + $(date '+%Y-%m-%d %H:%M:%S') | ${SERVER_IP} +════════════════════════════════════════ -【节点1】SS2022-AES-128 (新协议) - 地址: ${SERVER_IP} - 端口: ${PORT_2022} - 加密: ${METHOD_2022} - 密码: ${KEY_2022} - -【节点2】SS-AES-128 (传统协议) - 地址: ${SERVER_IP} - 端口: ${PORT_RAW} - 加密: ${METHOD_RAW} - 密码: ${KEY_RAW} - -【SS 订阅链接】 - ${URI_2022} - ${URI_RAW} - -【Surge 配置】 - SS2022-128 = ss, ${SERVER_IP}, ${PORT_2022}, encrypt-method=${METHOD_2022}, password=${KEY_2022} - SS-AES-128 = ss, ${SERVER_IP}, ${PORT_RAW}, encrypt-method=${METHOD_RAW}, password=${KEY_RAW} - -======================================== +$(echo -e "${INFO_NODES}") +【SS 链接】 +$(echo -e "${SS_URIS}") +════════════════════════════════════════ EOF } -# ============ 输出结果 ============ +# ============ 显示结果 ============ show_result() { + load_config || return echo "" echo -e "${CYAN}════════════════════════════════════════${NC}" echo -e "${CYAN} 🚀 Shadowsocks-Rust 安装完成${NC}" echo -e "${CYAN}════════════════════════════════════════${NC}" echo "" - echo -e "${GREEN}【节点1】SS2022-AES-128 (新协议)${NC}" - echo -e " 地址: ${SERVER_IP}" - echo -e " 端口: ${YELLOW}${PORT_2022}${NC}" - echo -e " 加密: ${METHOD_2022}" - echo -e " 密码: ${YELLOW}${KEY_2022}${NC}" - echo "" - echo -e "${GREEN}【节点2】SS-AES-128 (传统协议)${NC}" - echo -e " 地址: ${SERVER_IP}" - echo -e " 端口: ${YELLOW}${PORT_RAW}${NC}" - echo -e " 加密: ${METHOD_RAW}" - echo -e " 密码: ${YELLOW}${KEY_RAW}${NC}" - echo "" + + if [[ -n "${PORT_2022:-}" ]]; then + echo -e "${GREEN}【节点1】SS2022-AES-128 (新协议)${NC}" + echo -e " 地址: ${SERVER_IP}" + echo -e " 端口: ${YELLOW}${PORT_2022}${NC}" + echo -e " 加密: ${METHOD_2022}" + echo -e " 密码: ${YELLOW}${KEY_2022}${NC}" + echo "" + fi + + if [[ -n "${PORT_RAW:-}" ]]; then + echo -e "${GREEN}【节点2】SS-AES-128 (传统协议)${NC}" + echo -e " 地址: ${SERVER_IP}" + echo -e " 端口: ${YELLOW}${PORT_RAW}${NC}" + echo -e " 加密: ${METHOD_RAW}" + echo -e " 密码: ${YELLOW}${KEY_RAW}${NC}" + echo "" + fi + echo -e "${CYAN}────────────────────────────────────────${NC}" echo -e "${GREEN}【Surge 格式】${NC}" - echo -e " SS2022-128 = ss, ${SERVER_IP}, ${PORT_2022}, encrypt-method=${METHOD_2022}, password=${KEY_2022}" - echo -e " SS-AES-128 = ss, ${SERVER_IP}, ${PORT_RAW}, encrypt-method=${METHOD_RAW}, password=${KEY_RAW}" + [[ -n "${PORT_2022:-}" ]] && echo -e " SS2022-128 = ss, ${SERVER_IP}, ${PORT_2022}, encrypt-method=${METHOD_2022}, password=${KEY_2022}" + [[ -n "${PORT_RAW:-}" ]] && echo -e " SS-AES-128 = ss, ${SERVER_IP}, ${PORT_RAW}, encrypt-method=${METHOD_RAW}, password=${KEY_RAW}" echo "" + echo -e "${CYAN}────────────────────────────────────────${NC}" echo -e "${GREEN}【SS 链接】${NC}" - echo -e " ${URI_2022}" - echo -e " ${URI_RAW}" + [[ -n "${URI_2022:-}" ]] && echo -e " ${URI_2022}" + [[ -n "${URI_RAW:-}" ]] && echo -e " ${URI_RAW}" echo "" + echo -e "${CYAN}────────────────────────────────────────${NC}" echo -e "${GREEN}【文件位置】${NC}" echo -e " 配置: /etc/shadowsocks-rust/config.json" echo -e " 订阅: /etc/shadowsocks-rust/subscribe/subscribe.txt" echo -e " Surge: /etc/shadowsocks-rust/subscribe/surge.conf" echo -e " Clash: /etc/shadowsocks-rust/subscribe/clash.yaml" - echo -e " 信息: /etc/shadowsocks-rust/subscribe/info.txt" echo "" - echo -e "${CYAN}【管理命令】${NC}" - echo -e " 启动: systemctl start ss-rust" - echo -e " 停止: systemctl stop ss-rust" - echo -e " 状态: systemctl status ss-rust" - echo -e " 日志: journalctl -u ss-rust -f" + echo -e "${CYAN}【管理】${NC} 再次运行本脚本即可进入管理菜单" echo -e "${CYAN}════════════════════════════════════════${NC}" } +# ============ 查看配置 ============ +show_config() { + load_config || error "未安装 shadowsocks-rust" + echo "" + echo -e "${CYAN}════════════════════════════════════════${NC}" + echo -e "${CYAN} 📋 当前配置${NC}" + echo -e "${CYAN}════════════════════════════════════════${NC}" + echo "" + echo -e "${GREEN}服务状态:${NC} $(systemctl is-active ss-rust 2>/dev/null || echo '未运行')" + echo "" + cat /etc/shadowsocks-rust/config.json + echo "" + [[ -f /etc/shadowsocks-rust/subscribe/info.txt ]] && cat /etc/shadowsocks-rust/subscribe/info.txt +} + +# ============ 修改端口 ============ +change_port() { + load_config || error "未安装 shadowsocks-rust" + echo "" + echo -e "${GREEN}当前节点:${NC}" + [[ -n "${PORT_2022:-}" ]] && echo -e " 1) SS2022-128 | 端口 ${PORT_2022}" + [[ -n "${PORT_RAW:-}" ]] && echo -e " 2) SS-AES-128 | 端口 ${PORT_RAW}" + echo "" + read -p "输入节点编号: " pn + read -p "输入新端口: " new_port + + python3 -c " +import json +with open('/etc/shadowsocks-rust/config.json') as f: + c = json.load(f) +idx = int('${pn}') - 1 +if 0 <= idx < len(c['servers']): + c['servers'][idx]['server_port'] = int('${new_port}') + with open('/etc/shadowsocks-rust/config.json','w') as f: + json.dump(c, f, indent=4) +" 2>/dev/null + + systemctl restart ss-rust + gen_subscribe + info "端口已修改为 ${new_port},订阅已更新" +} + +# ============ 重置密钥 ============ +reset_keys() { + load_config || error "未安装 shadowsocks-rust" + + python3 -c " +import json, subprocess, base64, os +with open('/etc/shadowsocks-rust/config.json') as f: + c = json.load(f) +for s in c['servers']: + s['password'] = base64.b64encode(os.urandom(16)).decode() +with open('/etc/shadowsocks-rust/config.json','w') as f: + json.dump(c, f, indent=4) +" 2>/dev/null + + systemctl restart ss-rust + gen_subscribe + info "密钥已重置" + show_result +} + # ============ 卸载 ============ uninstall() { warn "卸载 shadowsocks-rust..." systemctl stop ss-rust 2>/dev/null systemctl disable ss-rust 2>/dev/null rm -f /etc/systemd/system/ss-rust.service - rm -f /usr/local/bin/ss{server,local,url} + rm -f /usr/local/bin/ssserver /usr/local/bin/sslocal /usr/local/bin/ssurl rm -rf /etc/shadowsocks-rust systemctl daemon-reload info "卸载完成" - exit 0 } -# ============ 查看配置 ============ -show_config() { - if [[ ! -f /etc/shadowsocks-rust/config.json ]]; then - error "未安装 shadowsocks-rust" - fi - echo "" - echo -e "${CYAN}════════════════════════════════════════${NC}" - echo -e "${CYAN} 📋 当前配置${NC}" - echo -e "${CYAN}════════════════════════════════════════${NC}" - echo "" - cat /etc/shadowsocks-rust/config.json - echo "" - echo -e "${CYAN}────────────────────────────────────────${NC}" - echo -e "${GREEN}服务状态:${NC}" - systemctl status ss-rust --no-pager 2>/dev/null | head -5 - echo "" - if [[ -f /etc/shadowsocks-rust/subscribe/info.txt ]]; then - cat /etc/shadowsocks-rust/subscribe/info.txt - fi -} - -# ============ 修改端口 ============ -change_port() { - if [[ ! -f /etc/shadowsocks-rust/config.json ]]; then - error "未安装 shadowsocks-rust" - fi - echo "" - echo -e "${GREEN}当前配置:${NC}" - python3 -c " -import json -with open('/etc/shadowsocks-rust/config.json') as f: - c = json.load(f) -for i,s in enumerate(c['servers']): - print(f\" 节点{i+1}: {s['method']} | 端口 {s['server_port']}\") -" 2>/dev/null || cat /etc/shadowsocks-rust/config.json - echo "" - read -p "输入节点编号 (1/2): " node_num - read -p "输入新端口: " new_port - - python3 -c " -import json,sys -with open('/etc/shadowsocks-rust/config.json') as f: - c = json.load(f) -idx = int('${node_num}') - 1 -if 0 <= idx < len(c['servers']): - c['servers'][idx]['server_port'] = int('${new_port}') - with open('/etc/shadowsocks-rust/config.json','w') as f: - json.dump(c, f, indent=4) - print('端口已修改') -else: - print('无效节点编号') - sys.exit(1) -" 2>/dev/null - - systemctl restart ss-rust - info "服务已重启,新端口: ${new_port}" - # 重新生成订阅 - SERVER_IP=$(get_ip) - source_config +# ============ 完整安装流程 ============ +do_install() { + get_pkg_manager + install_deps + sync_time + select_node_type + install_ssrust + gen_config + setup_service gen_subscribe - info "订阅配置已更新" -} - -# ============ 读取现有配置 ============ -source_config() { - if [[ -f /etc/shadowsocks-rust/config.json ]]; then - eval $(python3 -c " -import json -with open('/etc/shadowsocks-rust/config.json') as f: - c = json.load(f) -s = c['servers'] -print(f'PORT_2022={s[0][\"server_port\"]}') -print(f'KEY_2022={s[0][\"password\"]}') -print(f'METHOD_2022={s[0][\"method\"]}') -print(f'PORT_RAW={s[1][\"server_port\"]}') -print(f'KEY_RAW={s[1][\"password\"]}') -print(f'METHOD_RAW={s[1][\"method\"]}') -" 2>/dev/null) - fi -} - -# ============ 重置密钥 ============ -reset_keys() { - if [[ ! -f /etc/shadowsocks-rust/config.json ]]; then - error "未安装 shadowsocks-rust" - fi - SERVER_IP=$(get_ip) - KEY_2022=$(gen_key_128) - KEY_RAW=$(openssl rand -base64 16) - - python3 -c " -import json -with open('/etc/shadowsocks-rust/config.json') as f: - c = json.load(f) -c['servers'][0]['password'] = '${KEY_2022}' -c['servers'][1]['password'] = '${KEY_RAW}' -with open('/etc/shadowsocks-rust/config.json','w') as f: - json.dump(c, f, indent=4) -" 2>/dev/null - - systemctl restart ss-rust - source_config - gen_subscribe - info "密钥已重置,服务已重启" show_result } -# ============ 交互菜单 ============ +# ============ 管理菜单 ============ show_menu() { echo "" echo -e "${CYAN}════════════════════════════════════════${NC}" echo -e "${CYAN} 🚀 SS-Rust 管理面板${NC}" echo -e "${CYAN}════════════════════════════════════════${NC}" echo "" - echo -e " ${GREEN}1.${NC} 安装 SS-Rust" - echo -e " ${GREEN}2.${NC} 查看配置" + echo -e " ${GREEN}1.${NC} 重新安装 (选择节点类型)" + echo -e " ${GREEN}2.${NC} 查看配置 + 节点信息" echo -e " ${GREEN}3.${NC} 修改端口" echo -e " ${GREEN}4.${NC} 重置密钥" echo -e " ${GREEN}5.${NC} 启动服务" @@ -430,15 +485,7 @@ show_menu() { read -p "请选择 [0-9]: " choice case "$choice" in - 1) - check_os - sync_time - install_ssrust - gen_config - setup_service - gen_subscribe - show_result - ;; + 1) do_install ;; 2) show_config ;; 3) change_port ;; 4) reset_keys ;; @@ -452,40 +499,23 @@ show_menu() { esac } -# ============ 主流程 ============ +# ============ 主入口 ============ main() { check_root case "${1:-}" in - install) - check_os; sync_time; install_ssrust; gen_config; setup_service; gen_subscribe; show_result - ;; - uninstall|remove) - uninstall - ;; - show|config|info) - show_config - ;; - restart) - systemctl restart ss-rust && info "服务已重启" - ;; - start) - systemctl start ss-rust && info "服务已启动" - ;; - stop) - systemctl stop ss-rust && info "服务已停止" - ;; - log|logs) - journalctl -u ss-rust --no-pager -n 30 - ;; - reset) - reset_keys - ;; + install) do_install ;; + uninstall|remove) uninstall ;; + show|config|info) show_config ;; + restart) systemctl restart ss-rust && info "服务已重启" ;; + start) systemctl start ss-rust && info "服务已启动" ;; + stop) systemctl stop ss-rust && info "服务已停止" ;; + log|logs) journalctl -u ss-rust --no-pager -n 30 ;; + reset) reset_keys ;; *) - # 无参数时:已安装显示菜单,未安装直接安装 if [[ -f /etc/shadowsocks-rust/config.json ]]; then show_menu else - check_os; sync_time; install_ssrust; gen_config; setup_service; gen_subscribe; show_result + do_install fi ;; esac