feat: 完整重写 - 节点选择菜单 + 依赖自动安装 + 管理面板

This commit is contained in:
mango
2026-02-14 21:04:25 +08:00
parent e44d172e24
commit a11c93794a

View File

@@ -1,9 +1,8 @@
#!/bin/bash
# SS-Rust 一键安装脚本 (ss2022 + aes-128-gcm)
# 自动生成订阅链接 + Surge 配置
# Usage: curl -sL <url> | 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