1400 lines
41 KiB
Bash
1400 lines
41 KiB
Bash
#!/bin/bash
|
||
# Shadowsocks 管理脚本 - 集成安装、卸载和管理功能
|
||
# 专门支持 shadowsocks-libev 协议
|
||
# 使用方法: chmod +x shadowsocks-manager.sh && ./shadowsocks-manager.sh
|
||
# 使用方法: chmod +x ss2022-manager.sh && ./ss2022-manager.sh
|
||
|
||
|
||
# 全局变量
|
||
SS_PATH="/usr/local/bin"
|
||
CONFIG_PATH="/etc/shadowsocks-libev"
|
||
SS_PORT="" # Shadowsocks 端口
|
||
LOG_PATH="/var/log/shadowsocks"
|
||
LOG_FILE="/var/log/shadowsocks-manager.log"
|
||
SCRIPT_VERSION="1.0.0"
|
||
SS_PASSWORD=""
|
||
SS_METHOD="aes-128-gcm" # 默认使用 AEAD 加密方法
|
||
CONFIG_BACKUP=""
|
||
SERVER_IP=""
|
||
|
||
# 颜色定义
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[0;33m'
|
||
BLUE='\033[0;34m'
|
||
CYAN='\033[0;36m'
|
||
NC='\033[0m' # No Color
|
||
|
||
# 进度条函数
|
||
show_progress() {
|
||
local pid=$1
|
||
local delay=0.1
|
||
local spinstr='|/-\'
|
||
local temp
|
||
local count=0
|
||
local start_time=$(date +%s)
|
||
echo -n " "
|
||
|
||
while ps -p $pid > /dev/null; do
|
||
temp=${spinstr#?}
|
||
printf "\r[%c] %s 已进行 %ds" "$spinstr" "$2" "$(($(date +%s) - start_time))"
|
||
spinstr=$temp${spinstr%"$temp"}
|
||
sleep $delay
|
||
count=$((count + 1))
|
||
done
|
||
printf "\r\033[K"
|
||
}
|
||
|
||
# 进度条显示函数 - 适用于apt操作
|
||
apt_progress() {
|
||
local cmd="$1"
|
||
local msg="$2"
|
||
local logfile="$LOG_FILE.tmp"
|
||
|
||
echo -e "${CYAN}开始 $msg...${NC}"
|
||
touch "$logfile"
|
||
($cmd 2>&1 | tee -a "$LOG_FILE" > "$logfile") &
|
||
local pid=$!
|
||
|
||
# 显示进度条
|
||
local start_time=$(date +%s)
|
||
local dots=""
|
||
local status=""
|
||
local progress=0
|
||
local last_line=""
|
||
local delay=0.2
|
||
|
||
while ps -p $pid > /dev/null; do
|
||
# 读取最后一行日志
|
||
if [[ -f "$logfile" ]]; then
|
||
last_line=$(tail -n 1 "$logfile")
|
||
|
||
# 尝试从输出中提取进度信息
|
||
if [[ $last_line == *%* ]]; then
|
||
status="${last_line%%(*}"
|
||
progress="${last_line#*(}"
|
||
progress="${progress%%)*}"
|
||
printf "\r\033[K${CYAN}[$msg]${NC} %s %s " "$status" "$progress"
|
||
else
|
||
dots="${dots}."
|
||
if [[ ${#dots} -gt 5 ]]; then dots="."; fi
|
||
elapsed=$(($(date +%s) - start_time))
|
||
printf "\r\033[K${CYAN}[$msg]${NC} 进行中%s (%ds)" "$dots" "$elapsed"
|
||
fi
|
||
fi
|
||
sleep $delay
|
||
done
|
||
|
||
if wait $pid; then
|
||
printf "\r\033[K${GREEN}[$msg]${NC} 完成! 用时: %ds\n" "$(($(date +%s) - start_time))"
|
||
rm -f "$logfile"
|
||
return 0
|
||
else
|
||
printf "\r\033[K${RED}[$msg]${NC} 失败! 查看日志: $LOG_FILE\n"
|
||
rm -f "$logfile"
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
# 日志函数
|
||
log_info() {
|
||
echo -e "${GREEN}[INFO]${NC} $1" | tee -a "$LOG_FILE"
|
||
}
|
||
|
||
log_warn() {
|
||
echo -e "${YELLOW}[WARN]${NC} $1" | tee -a "$LOG_FILE"
|
||
}
|
||
|
||
log_error() {
|
||
echo -e "${RED}[ERROR]${NC} $1" >&2 | tee -a "$LOG_FILE"
|
||
}
|
||
|
||
log_debug() {
|
||
echo -e "${BLUE}[DEBUG]${NC} $1" | tee -a "$LOG_FILE"
|
||
}
|
||
|
||
# 检查是否有 root 权限
|
||
check_root() {
|
||
if [[ $EUID -ne 0 ]]; then
|
||
log_error "此脚本需要 root 权限运行"
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
# 检查系统环境
|
||
check_system() {
|
||
# 显示系统信息
|
||
echo "系统信息:"
|
||
echo "------------------------"
|
||
if [ -f /etc/os-release ]; then
|
||
cat /etc/os-release | grep "PRETTY_NAME" | cut -d= -f2- | tr -d '"'
|
||
fi
|
||
echo "内核版本: $(uname -r)"
|
||
echo "架构: $(uname -m)"
|
||
echo "------------------------"
|
||
|
||
# 检查是否为 Debian/Ubuntu 系统
|
||
if [[ ! -f /etc/debian_version && ! -f /etc/lsb-release ]]; then
|
||
log_warn "未检测到 Debian/Ubuntu 系统,脚本可能无法正常工作"
|
||
read -rp "是否继续? [y/N] " response
|
||
if [[ ! "$response" =~ ^[yY]$ ]]; then
|
||
exit 1
|
||
fi
|
||
fi
|
||
|
||
# 检查网络连接
|
||
echo -n "检查网络连接... "
|
||
if ping -c 1 -W 2 github.com &>/dev/null; then
|
||
echo -e "${GREEN}连接正常${NC}"
|
||
else
|
||
echo -e "${YELLOW}无法连接到 GitHub${NC}"
|
||
log_warn "无法连接到 GitHub,请检查网络连接"
|
||
read -rp "是否继续? [y/N] " response
|
||
if [[ ! "$response" =~ ^[yY]$ ]]; then
|
||
exit 1
|
||
fi
|
||
fi
|
||
}
|
||
|
||
# 备份函数
|
||
backup_config() {
|
||
if [[ -d "$CONFIG_PATH" ]]; then
|
||
CONFIG_BACKUP="${CONFIG_PATH}_backup_$(date +%Y%m%d%H%M%S)"
|
||
log_info "备份现有配置到 $CONFIG_BACKUP"
|
||
cp -r "$CONFIG_PATH" "$CONFIG_BACKUP" || log_warn "配置备份失败"
|
||
|
||
# 备份 Shadowsocks 信息文件
|
||
if [[ -f "/root/shadowsocks_info.txt" ]]; then
|
||
cp "/root/shadowsocks_info.txt" "${CONFIG_BACKUP}/shadowsocks_info.txt.bak" || log_warn "Shadowsocks 信息文件备份失败"
|
||
fi
|
||
else
|
||
log_warn "找不到配置目录,跳过备份"
|
||
fi
|
||
}
|
||
|
||
# 显示帮助信息
|
||
show_help() {
|
||
echo "Shadowsocks 管理脚本 v${SCRIPT_VERSION}"
|
||
echo "用法: $0 [选项]"
|
||
echo ""
|
||
echo "选项:"
|
||
echo " -h, --help 显示此帮助信息"
|
||
echo " -i, --install 直接运行安装"
|
||
echo " -u, --uninstall 直接运行卸载"
|
||
echo " -s, --status 查看 Shadowsocks 状态"
|
||
echo " -up, --update 更新 Shadowsocks"
|
||
echo ""
|
||
echo "无参数运行脚本将显示交互式菜单"
|
||
}
|
||
|
||
# 菜单函数
|
||
show_menu() {
|
||
clear
|
||
echo "=================================================="
|
||
echo -e "${CYAN}Shadowsocks 管理脚本 v${SCRIPT_VERSION}${NC}"
|
||
echo -e "${CYAN}(shadowsocks-libev)${NC}"
|
||
echo "=================================================="
|
||
echo -e "1) ${GREEN}安装 Shadowsocks${NC}"
|
||
echo -e "2) ${RED}卸载 Shadowsocks${NC}"
|
||
echo -e "3) ${YELLOW}更新 Shadowsocks${NC}"
|
||
echo -e "4) ${BLUE}查看 Shadowsocks 状态${NC}"
|
||
echo -e "5) ${CYAN}查看 Shadowsocks 配置信息${NC}"
|
||
echo -e "6) ${GREEN}重启 Shadowsocks 服务${NC}"
|
||
echo -e "7) ${YELLOW}修改服务器配置${NC}"
|
||
echo -e "0) ${RED}退出${NC}"
|
||
echo "=================================================="
|
||
echo ""
|
||
read -rp "请输入选项 [0-7]: " choice
|
||
|
||
case $choice in
|
||
1) install_shadowsocks ;;
|
||
2) uninstall_shadowsocks ;;
|
||
3) update_shadowsocks ;;
|
||
4) check_status ;;
|
||
5) show_config ;;
|
||
6) restart_service ;;
|
||
7) modify_config ;;
|
||
0) exit 0 ;;
|
||
*) log_error "无效选项" && sleep 2 && show_menu ;;
|
||
esac
|
||
}
|
||
|
||
# 安装依赖
|
||
install_dependencies() {
|
||
log_info "安装必要依赖"
|
||
|
||
# 更新软件包列表
|
||
apt_progress "apt-get update" "更新软件包列表" || {
|
||
log_error "更新软件包列表失败"
|
||
return 1
|
||
}
|
||
|
||
# 安装必要工具
|
||
local deps=(curl wget jq)
|
||
for dep in "${deps[@]}"; do
|
||
if ! command -v "$dep" &>/dev/null; then
|
||
apt_progress "apt-get install -y $dep" "安装 $dep" || {
|
||
log_error "安装 $dep 失败"
|
||
return 1
|
||
}
|
||
else
|
||
log_info "$dep 已安装,跳过"
|
||
fi
|
||
done
|
||
|
||
# 检查安装结果
|
||
local all_installed=true
|
||
for dep in "${deps[@]}"; do
|
||
if ! command -v "$dep" &>/dev/null; then
|
||
log_error "$dep 安装失败"
|
||
all_installed=false
|
||
fi
|
||
done
|
||
|
||
if [ "$all_installed" = true ]; then
|
||
log_info "所有依赖安装完成"
|
||
return 0
|
||
else
|
||
log_error "部分依赖安装失败"
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
# 安装 shadowsocks-libev
|
||
install_shadowsocks_libev() {
|
||
log_info "开始安装 shadowsocks-libev"
|
||
|
||
# 检查是否已安装
|
||
if command -v ss-server &>/dev/null; then
|
||
log_info "检测到已安装的 shadowsocks-libev,将进行更新"
|
||
|
||
# 停止服务
|
||
if systemctl is-active shadowsocks-libev &>/dev/null; then
|
||
echo -n "停止 Shadowsocks 服务... "
|
||
if systemctl stop shadowsocks-libev &>/dev/null; then
|
||
echo -e "${GREEN}成功${NC}"
|
||
else
|
||
echo -e "${RED}失败${NC}"
|
||
log_warn "无法停止 Shadowsocks 服务"
|
||
fi
|
||
fi
|
||
fi
|
||
|
||
# 添加 shadowsocks-libev 官方仓库(如果是 Ubuntu)
|
||
if command -v lsb_release &>/dev/null && [[ $(lsb_release -si) == "Ubuntu" ]]; then
|
||
local ubuntu_version=$(lsb_release -sr)
|
||
if [[ $(echo "$ubuntu_version >= 16.04" | bc) -eq 1 ]]; then
|
||
log_info "添加 shadowsocks-libev 官方 PPA"
|
||
apt_progress "add-apt-repository -y ppa:max-c-lv/shadowsocks-libev" "添加 PPA 仓库"
|
||
apt_progress "apt-get update" "更新软件包列表"
|
||
fi
|
||
fi
|
||
|
||
# 安装 shadowsocks-libev
|
||
apt_progress "apt-get install -y shadowsocks-libev" "安装 shadowsocks-libev" || {
|
||
log_error "安装 shadowsocks-libev 失败"
|
||
return 1
|
||
}
|
||
|
||
# 验证安装
|
||
if command -v ss-server &>/dev/null; then
|
||
log_info "shadowsocks-libev 安装成功"
|
||
return 0
|
||
else
|
||
log_error "shadowsocks-libev 安装失败"
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
# 生成随机配置值
|
||
generate_random_values() {
|
||
log_info "生成随机配置值"
|
||
|
||
# 询问用户是否指定端口
|
||
if [[ -z "$SS_PORT" ]]; then
|
||
read -rp "是否指定端口? [y/N] " specify_port
|
||
if [[ "$specify_port" =~ ^[yY]$ ]]; then
|
||
# 用户选择指定端口
|
||
while true; do
|
||
read -rp "请输入端口号 (1-65535): " SS_PORT
|
||
# 验证端口是否为有效数字
|
||
if ! [[ "$SS_PORT" =~ ^[0-9]+$ ]] || [ "$SS_PORT" -lt 1 ] || [ "$SS_PORT" -gt 65535 ]; then
|
||
log_error "无效的端口号,请输入1-65535之间的数字"
|
||
continue
|
||
fi
|
||
|
||
# 检查端口是否被占用
|
||
if ss -tuln | grep -q ":$SS_PORT "; then
|
||
log_warn "端口 $SS_PORT 已被占用,请选择其他端口"
|
||
continue
|
||
fi
|
||
|
||
log_info "将使用指定端口: $SS_PORT"
|
||
break
|
||
done
|
||
else
|
||
# 用户选择随机端口
|
||
local attempts=0
|
||
while [[ "$attempts" -lt 10 ]]; do
|
||
SS_PORT=$(shuf -i 10000-60000 -n 1)
|
||
# 检查端口是否被占用
|
||
if ! ss -tuln | grep -q ":$SS_PORT "; then
|
||
log_info "生成随机端口: $SS_PORT"
|
||
break
|
||
fi
|
||
attempts=$((attempts + 1))
|
||
done
|
||
if [[ "$attempts" -eq 10 ]]; then
|
||
log_warn "无法找到未占用的端口,使用随机端口: $SS_PORT"
|
||
fi
|
||
fi
|
||
fi
|
||
|
||
# 生成密码
|
||
if [[ -z "$SS_PASSWORD" ]]; then
|
||
read -rp "是否指定密码? [y/N] " specify_password
|
||
if [[ "$specify_password" =~ ^[yY]$ ]]; then
|
||
while true; do
|
||
read -rp "请输入密码 (至少8位): " SS_PASSWORD
|
||
if [[ ${#SS_PASSWORD} -lt 8 ]]; then
|
||
log_error "密码至少需要8位"
|
||
continue
|
||
fi
|
||
log_info "将使用指定密码"
|
||
break
|
||
done
|
||
else
|
||
# 生成随机密码
|
||
SS_PASSWORD=$(openssl rand -base64 16)
|
||
log_info "生成随机密码: $SS_PASSWORD"
|
||
fi
|
||
fi
|
||
|
||
# 选择加密方法
|
||
echo "选择加密方法:"
|
||
echo "1) chacha20-ietf-poly1305"
|
||
echo "2) aes-256-gcm"
|
||
echo "3) aes-192-gcm"
|
||
echo "4) aes-128-gcm (默认)"
|
||
read -rp "请选择加密方法 [1-4, 默认4]: " method_choice
|
||
|
||
case $method_choice in
|
||
1) SS_METHOD="chacha20-ietf-poly1305" ;;
|
||
2) SS_METHOD="aes-256-gcm" ;;
|
||
3) SS_METHOD="aes-192-gcm" ;;
|
||
*) SS_METHOD="aes-128-gcm" ;;
|
||
esac
|
||
|
||
log_info "选择的加密方法: $SS_METHOD"
|
||
|
||
# 获取服务器IP
|
||
get_server_ip
|
||
}
|
||
|
||
# 获取服务器IP
|
||
get_server_ip() {
|
||
log_info "获取服务器IP地址"
|
||
|
||
if [[ -n "$SERVER_IP" ]]; then
|
||
log_info "使用已设置的IP: $SERVER_IP"
|
||
return 0
|
||
fi
|
||
|
||
# 尝试首选方法获取公网IP
|
||
SERVER_IP=$(curl -s -m 5 https://api.ipify.org 2>/dev/null)
|
||
|
||
# 验证获取到的IP是否为有效IPv4地址
|
||
if [[ -n "$SERVER_IP" && "$SERVER_IP" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
|
||
log_info "成功获取公网IP: $SERVER_IP"
|
||
return 0
|
||
fi
|
||
|
||
# 如果第一个方法失败,尝试备用方法
|
||
local backup_services=("https://ifconfig.me" "https://ip.sb" "https://ipinfo.io/ip")
|
||
|
||
for service in "${backup_services[@]}"; do
|
||
SERVER_IP=$(curl -s -m 3 "$service" 2>/dev/null)
|
||
if [[ -n "$SERVER_IP" && "$SERVER_IP" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
|
||
log_info "成功从 $service 获取公网IP: $SERVER_IP"
|
||
return 0
|
||
fi
|
||
done
|
||
|
||
# 如果所有公网IP获取方式都失败,则使用本地IP
|
||
if command -v hostname &>/dev/null; then
|
||
SERVER_IP=$(hostname -I 2>/dev/null | awk '{print $1}')
|
||
fi
|
||
|
||
# 如果hostname命令失败,尝试使用ip命令
|
||
if [[ -z "$SERVER_IP" && -x "$(command -v ip)" ]]; then
|
||
SERVER_IP=$(ip -4 addr show scope global | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | head -n 1)
|
||
fi
|
||
|
||
if [[ -n "$SERVER_IP" ]]; then
|
||
log_warn "无法获取公网IP,使用本地IP: $SERVER_IP"
|
||
return 0
|
||
else
|
||
log_error "无法获取任何有效IP地址,将使用127.0.0.1作为占位符"
|
||
SERVER_IP="127.0.0.1"
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
# 配置 Shadowsocks
|
||
configure_shadowsocks() {
|
||
log_info "配置 Shadowsocks"
|
||
|
||
# 生成随机值
|
||
generate_random_values
|
||
|
||
# 创建配置目录
|
||
mkdir -p "$CONFIG_PATH"
|
||
mkdir -p "$LOG_PATH"
|
||
|
||
log_info "创建 Shadowsocks 配置文件"
|
||
|
||
# 创建主配置文件
|
||
cat > "$CONFIG_PATH/config.json" << EOF
|
||
{
|
||
"server": "0.0.0.0",
|
||
"server_port": $SS_PORT,
|
||
"password": "$SS_PASSWORD",
|
||
"method": "$SS_METHOD",
|
||
"timeout": 300,
|
||
"fast_open": true,
|
||
"workers": 1,
|
||
"prefer_ipv6": false,
|
||
"no_delay": true,
|
||
"reuse_port": true
|
||
}
|
||
EOF
|
||
|
||
# 创建客户端配置示例
|
||
cat > "$CONFIG_PATH/client_config.json" << EOF
|
||
{
|
||
"server": "$SERVER_IP",
|
||
"server_port": $SS_PORT,
|
||
"local_address": "127.0.0.1",
|
||
"local_port": 1080,
|
||
"password": "$SS_PASSWORD",
|
||
"method": "$SS_METHOD",
|
||
"timeout": 300,
|
||
"fast_open": true
|
||
}
|
||
EOF
|
||
|
||
if [[ -f "$CONFIG_PATH/config.json" ]]; then
|
||
log_info "配置文件创建成功"
|
||
else
|
||
log_error "配置文件创建失败"
|
||
return 1
|
||
fi
|
||
|
||
return 0
|
||
}
|
||
|
||
# 配置防火墙
|
||
configure_firewall() {
|
||
log_info "配置防火墙"
|
||
|
||
# 检测和关闭旧端口
|
||
local old_ports=()
|
||
|
||
# 从备份中查找旧端口
|
||
if [[ -n "$CONFIG_BACKUP" && -f "$CONFIG_BACKUP/config.json" ]]; then
|
||
log_info "检测旧配置中的端口"
|
||
if command -v jq &>/dev/null; then
|
||
local detected_port=$(jq '.server_port' "$CONFIG_BACKUP/config.json" 2>/dev/null)
|
||
if [[ "$detected_port" != "null" && -n "$detected_port" ]]; then
|
||
old_ports+=("$detected_port")
|
||
log_info "检测到旧端口: $detected_port"
|
||
fi
|
||
else
|
||
local detected_port=$(grep -o '"server_port": [0-9]*' "$CONFIG_BACKUP/config.json" | awk '{print $2}')
|
||
if [[ -n "$detected_port" ]]; then
|
||
old_ports+=("$detected_port")
|
||
log_info "检测到旧端口: $detected_port"
|
||
fi
|
||
fi
|
||
fi
|
||
|
||
# 检查是否安装了 ufw
|
||
if command -v ufw &>/dev/null; then
|
||
# 检查ufw是否启用
|
||
local ufw_status=$(ufw status | grep -o "Status: active" 2>/dev/null)
|
||
|
||
if [[ -z "$ufw_status" ]]; then
|
||
log_warn "UFW 防火墙未启用,可能需要手动配置防火墙规则"
|
||
log_info "您可以运行 'sudo ufw enable' 启用 UFW 防火墙"
|
||
return 0
|
||
fi
|
||
|
||
# 关闭旧端口
|
||
if [[ ${#old_ports[@]} -gt 0 ]]; then
|
||
log_info "开始关闭旧端口"
|
||
for port in "${old_ports[@]}"; do
|
||
if [[ "$port" -eq "$SS_PORT" ]]; then
|
||
continue # 跳过当前端口
|
||
fi
|
||
|
||
echo -n "关闭 UFW 防火墙端口 $port... "
|
||
if ufw delete allow "$port" &>/dev/null; then
|
||
echo -e "${GREEN}完成${NC}"
|
||
else
|
||
echo -e "${RED}失败${NC}"
|
||
fi
|
||
done
|
||
fi
|
||
|
||
# 开放新端口
|
||
echo -n "配置 UFW 防火墙开放端口 $SS_PORT... "
|
||
if ufw allow "$SS_PORT" &>/dev/null; then
|
||
echo -e "${GREEN}完成${NC}"
|
||
log_info "已在 UFW 防火墙开放端口: $SS_PORT"
|
||
else
|
||
echo -e "${RED}失败${NC}"
|
||
log_warn "无法开放端口 $SS_PORT"
|
||
fi
|
||
else
|
||
log_warn "未检测到 UFW 防火墙,跳过防火墙配置"
|
||
fi
|
||
|
||
return 0
|
||
}
|
||
|
||
# 生成客户端信息
|
||
generate_client_info() {
|
||
log_info "生成客户端信息"
|
||
|
||
# 确保IP地址已获取
|
||
if [[ -z "$SERVER_IP" ]]; then
|
||
get_server_ip
|
||
fi
|
||
|
||
# 生成 Shadowsocks URI
|
||
local userinfo="${SS_METHOD}:${SS_PASSWORD}"
|
||
local userinfo_encoded=$(echo -n "$userinfo" | base64 -w 0)
|
||
local share_uri="ss://${userinfo_encoded}@${SERVER_IP}:${SS_PORT}#Shadowsocks-Server"
|
||
|
||
# 保存客户端信息
|
||
cat > /root/shadowsocks_info.txt << EOF
|
||
========================= Shadowsocks 配置信息 =========================
|
||
服务器地址: ${SERVER_IP}
|
||
端口: ${SS_PORT}
|
||
密码: ${SS_PASSWORD}
|
||
加密方法: ${SS_METHOD}
|
||
==================================================================
|
||
|
||
分享链接 (SIP002 格式):
|
||
${share_uri}
|
||
|
||
二维码链接:
|
||
https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=${share_uri}
|
||
|
||
==================================================================
|
||
|
||
客户端配置文件: ${CONFIG_PATH}/client_config.json
|
||
|
||
支持的客户端:
|
||
- Android: shadowsocks-android
|
||
- Windows: shadowsocks-windows
|
||
- macOS: ShadowsocksX-NG
|
||
- iOS: Shadowrocket, Quantumult
|
||
- Linux: shadowsocks-libev
|
||
|
||
==================================================================
|
||
|
||
服务控制:
|
||
启动: systemctl start shadowsocks-libev
|
||
停止: systemctl stop shadowsocks-libev
|
||
重启: systemctl restart shadowsocks-libev
|
||
状态: systemctl status shadowsocks-libev
|
||
|
||
配置文件: ${CONFIG_PATH}/config.json
|
||
日志文件: /var/log/shadowsocks/shadowsocks.log
|
||
==================================================================
|
||
EOF
|
||
|
||
log_info "客户端信息已保存到 /root/shadowsocks_info.txt"
|
||
|
||
# 打印信息
|
||
cat /root/shadowsocks_info.txt
|
||
|
||
return 0
|
||
}
|
||
|
||
# 创建系统服务
|
||
create_service() {
|
||
log_info "创建 Shadowsocks 系统服务"
|
||
|
||
# 检查并清理现有服务
|
||
if [[ -f /etc/systemd/system/shadowsocks-libev.service ]]; then
|
||
log_info "检测到现有服务文件,清理现有服务"
|
||
systemctl stop shadowsocks-libev &>/dev/null
|
||
systemctl disable shadowsocks-libev &>/dev/null
|
||
|
||
# 确保进程完全停止
|
||
pkill -f ss-server &>/dev/null
|
||
sleep 2
|
||
|
||
# 删除旧服务文件
|
||
rm -f /etc/systemd/system/shadowsocks-libev.service
|
||
systemctl daemon-reload
|
||
log_info "现有服务已清理"
|
||
fi
|
||
|
||
# 创建服务文件
|
||
cat > /etc/systemd/system/shadowsocks-libev.service << EOF
|
||
[Unit]
|
||
Description=Shadowsocks-libev Default Server Service
|
||
Documentation=man:shadowsocks-libev(8)
|
||
After=network-online.target
|
||
|
||
[Service]
|
||
Type=simple
|
||
User=root
|
||
LimitNOFILE=32768
|
||
ExecStart=/usr/bin/ss-server -c $CONFIG_PATH/config.json -u -v
|
||
ExecReload=/bin/kill -s HUP \$MAINPID
|
||
ExecStop=/bin/kill -s TERM \$MAINPID
|
||
TimeoutStopSec=10
|
||
KillMode=mixed
|
||
Restart=on-failure
|
||
RestartSec=5s
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
EOF
|
||
|
||
# 重新加载 systemd 配置并启用服务
|
||
systemctl daemon-reload
|
||
|
||
echo -n "启用 Shadowsocks 服务... "
|
||
if systemctl enable shadowsocks-libev &>/dev/null; then
|
||
echo -e "${GREEN}成功${NC}"
|
||
else
|
||
echo -e "${RED}失败${NC}"
|
||
log_error "无法启用 Shadowsocks 服务"
|
||
return 1
|
||
fi
|
||
|
||
echo -n "启动 Shadowsocks 服务... "
|
||
if systemctl start shadowsocks-libev; then
|
||
echo -e "${GREEN}成功${NC}"
|
||
else
|
||
echo -e "${RED}失败${NC}"
|
||
log_error "无法启动 Shadowsocks 服务"
|
||
return 1
|
||
fi
|
||
|
||
# 等待服务启动并验证配置
|
||
echo -n "验证服务配置... "
|
||
sleep 3
|
||
|
||
# 检查服务是否真正运行
|
||
if systemctl is-active shadowsocks-libev &>/dev/null; then
|
||
echo -e "${GREEN}服务运行正常${NC}"
|
||
|
||
# 验证端口监听
|
||
local config_port=""
|
||
if command -v jq &>/dev/null; then
|
||
config_port=$(jq -r '.server_port' "$CONFIG_PATH/config.json" 2>/dev/null)
|
||
else
|
||
config_port=$(grep -o '"server_port": [0-9]*' "$CONFIG_PATH/config.json" | awk '{print $2}' 2>/dev/null)
|
||
fi
|
||
|
||
if [[ -n "$config_port" ]]; then
|
||
local retry_count=0
|
||
while [[ $retry_count -lt 10 ]]; do
|
||
if command -v netstat &>/dev/null; then
|
||
if netstat -tuln | grep -q ":$config_port "; then
|
||
log_info "端口 $config_port 监听正常"
|
||
break
|
||
fi
|
||
elif command -v ss &>/dev/null; then
|
||
if ss -tuln | grep -q ":$config_port "; then
|
||
log_info "端口 $config_port 监听正常"
|
||
break
|
||
fi
|
||
fi
|
||
sleep 1
|
||
retry_count=$((retry_count + 1))
|
||
done
|
||
|
||
if [[ $retry_count -eq 10 ]]; then
|
||
log_warn "警告: 端口 $config_port 可能未正确监听,请检查配置"
|
||
fi
|
||
fi
|
||
else
|
||
echo -e "${RED}服务启动异常${NC}"
|
||
log_error "服务启动后状态异常,请检查日志"
|
||
systemctl status shadowsocks-libev --no-pager -l
|
||
return 1
|
||
fi
|
||
|
||
return 0
|
||
}
|
||
|
||
# 安装完整流程
|
||
install_shadowsocks() {
|
||
clear
|
||
echo "=================================================="
|
||
echo -e "${GREEN}开始安装 Shadowsocks${NC}"
|
||
echo "=================================================="
|
||
|
||
# 检查是否为 root
|
||
check_root
|
||
|
||
# 检查系统环境
|
||
check_system
|
||
|
||
# 备份现有配置
|
||
backup_config
|
||
|
||
# 安装依赖
|
||
install_dependencies || {
|
||
log_error "安装依赖失败,退出安装"
|
||
return 1
|
||
}
|
||
|
||
# 安装 shadowsocks-libev
|
||
install_shadowsocks_libev || {
|
||
log_error "安装 shadowsocks-libev 失败,退出安装"
|
||
return 1
|
||
}
|
||
|
||
# 配置 Shadowsocks
|
||
configure_shadowsocks || {
|
||
log_error "配置 Shadowsocks 失败,退出安装"
|
||
return 1
|
||
}
|
||
|
||
# 创建系统服务
|
||
create_service || {
|
||
log_error "创建系统服务失败,但会继续安装过程"
|
||
}
|
||
|
||
# 配置防火墙
|
||
configure_firewall
|
||
|
||
# 生成客户端信息
|
||
generate_client_info
|
||
|
||
echo ""
|
||
echo "=================================================="
|
||
echo -e "${GREEN}Shadowsocks 安装完成!${NC}"
|
||
echo "=================================================="
|
||
|
||
# 最终验证
|
||
echo -e "\n${BLUE}最终验证结果:${NC}"
|
||
|
||
# 检查服务状态
|
||
if systemctl is-active shadowsocks-libev &>/dev/null; then
|
||
echo -e "服务状态: ${GREEN}运行中${NC}"
|
||
else
|
||
echo -e "服务状态: ${RED}未运行${NC}"
|
||
fi
|
||
|
||
# 检查端口监听
|
||
if [[ -f "$CONFIG_PATH/config.json" ]]; then
|
||
local current_port=""
|
||
if command -v jq &>/dev/null; then
|
||
current_port=$(jq -r '.server_port' "$CONFIG_PATH/config.json" 2>/dev/null)
|
||
else
|
||
current_port=$(grep -o '"server_port": [0-9]*' "$CONFIG_PATH/config.json" | awk '{print $2}' 2>/dev/null)
|
||
fi
|
||
|
||
if [[ -n "$current_port" ]]; then
|
||
if command -v netstat &>/dev/null; then
|
||
if netstat -tuln | grep -q ":$current_port "; then
|
||
echo -e "端口状态: ${GREEN}$current_port 正常监听${NC}"
|
||
else
|
||
echo -e "端口状态: ${RED}$current_port 未监听${NC}"
|
||
fi
|
||
elif command -v ss &>/dev/null; then
|
||
if ss -tuln | grep -q ":$current_port "; then
|
||
echo -e "端口状态: ${GREEN}$current_port 正常监听${NC}"
|
||
else
|
||
echo -e "端口状态: ${RED}$current_port 未监听${NC}"
|
||
fi
|
||
fi
|
||
fi
|
||
fi
|
||
|
||
echo -e "\n${YELLOW}重要提醒:${NC}"
|
||
echo "1. 客户端信息已保存到 /root/shadowsocks_info.txt"
|
||
echo "2. 如果使用云服务器,请在控制台开放对应端口"
|
||
echo "3. 可以运行脚本选择'4'查看详细状态"
|
||
|
||
read -rp "按回车键返回主菜单..." temp
|
||
show_menu
|
||
}
|
||
|
||
# 停止 Shadowsocks 服务
|
||
stop_shadowsocks_service() {
|
||
log_info "停止 Shadowsocks 服务"
|
||
|
||
if systemctl is-active shadowsocks-libev &>/dev/null; then
|
||
echo -n "正在停止 Shadowsocks 服务... "
|
||
if systemctl stop shadowsocks-libev &>/dev/null; then
|
||
echo -e "${GREEN}成功${NC}"
|
||
else
|
||
echo -e "${RED}失败${NC}"
|
||
log_warn "无法停止 Shadowsocks 服务,将尝试继续卸载"
|
||
fi
|
||
else
|
||
log_info "Shadowsocks 服务未运行"
|
||
fi
|
||
|
||
echo -n "禁用 Shadowsocks 服务自启动... "
|
||
if systemctl disable shadowsocks-libev &>/dev/null; then
|
||
echo -e "${GREEN}成功${NC}"
|
||
else
|
||
echo -e "${YELLOW}失败${NC}"
|
||
log_warn "无法禁用 Shadowsocks 服务自启动"
|
||
fi
|
||
}
|
||
|
||
# 关闭防火墙端口
|
||
close_firewall_port() {
|
||
log_info "尝试关闭之前开放的防火墙端口"
|
||
|
||
# 检查是否安装了 ufw
|
||
if ! command -v ufw &>/dev/null; then
|
||
log_warn "未检测到 UFW 防火墙,跳过防火墙配置关闭"
|
||
return 0
|
||
fi
|
||
|
||
# 尝试从配置文件中读取端口
|
||
local ports=()
|
||
|
||
if [[ -f "$CONFIG_PATH/config.json" ]]; then
|
||
if command -v jq &>/dev/null; then
|
||
local port=$(jq '.server_port' "$CONFIG_PATH/config.json" 2>/dev/null)
|
||
if [[ "$port" != "null" && -n "$port" ]]; then
|
||
ports+=("$port")
|
||
fi
|
||
else
|
||
local port=$(grep -o '"server_port": [0-9]*' "$CONFIG_PATH/config.json" | awk '{print $2}')
|
||
if [[ -n "$port" ]]; then
|
||
ports+=("$port")
|
||
fi
|
||
fi
|
||
fi
|
||
|
||
# 如果找到了端口,关闭防火墙规则
|
||
if [[ ${#ports[@]} -gt 0 ]]; then
|
||
for port in "${ports[@]}"; do
|
||
echo -n "关闭 UFW 防火墙端口 $port... "
|
||
if ufw delete allow "$port" &>/dev/null; then
|
||
echo -e "${GREEN}完成${NC}"
|
||
else
|
||
echo -e "${RED}失败${NC}"
|
||
fi
|
||
done
|
||
fi
|
||
}
|
||
|
||
# 删除 Shadowsocks 文件
|
||
remove_shadowsocks_files() {
|
||
log_info "删除 Shadowsocks 文件"
|
||
|
||
# 删除配置目录
|
||
echo -n "删除配置目录... "
|
||
if [[ -d "$CONFIG_PATH" ]]; then
|
||
if rm -rf "$CONFIG_PATH"; then
|
||
echo -e "${GREEN}成功${NC}"
|
||
else
|
||
echo -e "${RED}失败${NC}"
|
||
fi
|
||
else
|
||
echo -e "${YELLOW}配置目录不存在${NC}"
|
||
fi
|
||
|
||
# 删除日志目录
|
||
echo -n "删除日志目录... "
|
||
if [[ -d "$LOG_PATH" ]]; then
|
||
if rm -rf "$LOG_PATH"; then
|
||
echo -e "${GREEN}成功${NC}"
|
||
else
|
||
echo -e "${RED}失败${NC}"
|
||
fi
|
||
else
|
||
echo -e "${YELLOW}日志目录不存在${NC}"
|
||
fi
|
||
|
||
# 删除服务文件
|
||
echo -n "删除服务文件... "
|
||
if rm -f /etc/systemd/system/shadowsocks-libev.service; then
|
||
echo -e "${GREEN}成功${NC}"
|
||
systemctl daemon-reload
|
||
else
|
||
echo -e "${YELLOW}服务文件不存在${NC}"
|
||
fi
|
||
|
||
# 卸载 shadowsocks-libev 软件包
|
||
echo -n "卸载 shadowsocks-libev... "
|
||
if apt-get remove -y shadowsocks-libev &>/dev/null; then
|
||
echo -e "${GREEN}成功${NC}"
|
||
else
|
||
echo -e "${YELLOW}卸载失败或软件包未安装${NC}"
|
||
fi
|
||
|
||
return 0
|
||
}
|
||
|
||
# 完整卸载流程
|
||
uninstall_shadowsocks() {
|
||
clear
|
||
echo "=================================================="
|
||
echo -e "${RED}开始卸载 Shadowsocks${NC}"
|
||
echo "=================================================="
|
||
|
||
# 确认卸载
|
||
echo -e "${YELLOW}警告: 这将卸载 Shadowsocks 并删除相关文件${NC}"
|
||
read -rp "是否继续? [y/N] " confirm
|
||
if [[ ! "$confirm" =~ ^[yY]$ ]]; then
|
||
log_info "卸载已取消"
|
||
read -rp "按回车键返回主菜单..." temp
|
||
show_menu
|
||
return 0
|
||
fi
|
||
|
||
# 检查 root 权限
|
||
check_root
|
||
|
||
# 备份配置
|
||
backup_config
|
||
|
||
# 停止服务
|
||
stop_shadowsocks_service
|
||
|
||
# 关闭防火墙端口
|
||
close_firewall_port
|
||
|
||
# 删除文件
|
||
remove_shadowsocks_files
|
||
|
||
echo ""
|
||
log_info "Shadowsocks 卸载完成"
|
||
|
||
read -rp "按回车键返回主菜单..." temp
|
||
show_menu
|
||
}
|
||
|
||
# 检查 Shadowsocks 状态
|
||
check_status() {
|
||
clear
|
||
echo "=================================================="
|
||
echo -e "${BLUE}Shadowsocks 状态检查${NC}"
|
||
echo "=================================================="
|
||
|
||
# 检查是否安装
|
||
if ! command -v ss-server &>/dev/null; then
|
||
echo -e "${RED}Shadowsocks 未安装${NC}"
|
||
read -rp "按回车键返回主菜单..." temp
|
||
show_menu
|
||
return 0
|
||
fi
|
||
|
||
# 检查版本
|
||
echo -n "Shadowsocks 版本: "
|
||
ss-server -h 2>&1 | grep -o 'shadowsocks-libev [0-9]\+\.[0-9]\+\.[0-9]\+' || echo "shadowsocks-libev $(dpkg -l shadowsocks-libev 2>/dev/null | grep '^ii' | awk '{print $3}' || echo '未知版本')"
|
||
|
||
# 检查服务状态
|
||
echo -n "服务状态: "
|
||
if systemctl is-active shadowsocks-libev &>/dev/null; then
|
||
echo -e "${GREEN}运行中${NC}"
|
||
else
|
||
echo -e "${RED}未运行${NC}"
|
||
fi
|
||
|
||
echo -n "自启动状态: "
|
||
if systemctl is-enabled shadowsocks-libev &>/dev/null; then
|
||
echo -e "${GREEN}已启用${NC}"
|
||
else
|
||
echo -e "${RED}未启用${NC}"
|
||
fi
|
||
|
||
# 检查端口
|
||
if [[ -f "$CONFIG_PATH/config.json" ]]; then
|
||
local current_port=""
|
||
if command -v jq &>/dev/null; then
|
||
current_port=$(jq '.server_port' "$CONFIG_PATH/config.json" 2>/dev/null)
|
||
else
|
||
current_port=$(grep -o '"server_port": [0-9]*' "$CONFIG_PATH/config.json" | awk '{print $2}')
|
||
fi
|
||
|
||
if [[ -n "$current_port" && "$current_port" != "null" ]]; then
|
||
echo -n "端口 $current_port 状态: "
|
||
if command -v netstat &>/dev/null; then
|
||
if netstat -tuln | grep -q ":$current_port "; then
|
||
echo -e "${GREEN}已开放${NC}"
|
||
else
|
||
echo -e "${RED}未开放${NC}"
|
||
fi
|
||
elif command -v ss &>/dev/null; then
|
||
if ss -tuln | grep -q ":$current_port "; then
|
||
echo -e "${GREEN}已开放${NC}"
|
||
else
|
||
echo -e "${RED}未开放${NC}"
|
||
fi
|
||
else
|
||
echo -e "${YELLOW}无法检查${NC}"
|
||
fi
|
||
fi
|
||
fi
|
||
|
||
echo -e "\n最近的日志:"
|
||
if systemctl status shadowsocks-libev &>/dev/null; then
|
||
systemctl status shadowsocks-libev --no-pager -l
|
||
else
|
||
echo "无法获取服务日志"
|
||
fi
|
||
|
||
read -rp "按回车键返回主菜单..." temp
|
||
show_menu
|
||
}
|
||
|
||
# 显示配置信息
|
||
show_config() {
|
||
clear
|
||
echo "=================================================="
|
||
echo -e "${CYAN}Shadowsocks 配置信息${NC}"
|
||
echo "=================================================="
|
||
|
||
# 检查是否已安装
|
||
if ! command -v ss-server &>/dev/null; then
|
||
echo -e "${RED}Shadowsocks 未安装${NC}"
|
||
read -rp "按回车键返回主菜单..." temp
|
||
show_menu
|
||
return 0
|
||
fi
|
||
|
||
# 显示配置文件内容
|
||
if [[ -f "$CONFIG_PATH/config.json" ]]; then
|
||
echo "服务器配置:"
|
||
if command -v jq &>/dev/null; then
|
||
jq . "$CONFIG_PATH/config.json"
|
||
else
|
||
cat "$CONFIG_PATH/config.json"
|
||
fi
|
||
else
|
||
echo -e "${RED}找不到服务器配置文件${NC}"
|
||
fi
|
||
|
||
echo -e "\n"
|
||
|
||
# 显示客户端信息
|
||
if [[ -f "/root/shadowsocks_info.txt" ]]; then
|
||
echo "客户端信息:"
|
||
cat /root/shadowsocks_info.txt
|
||
else
|
||
echo -e "${RED}找不到客户端信息文件${NC}"
|
||
fi
|
||
|
||
read -rp "按回车键返回主菜单..." temp
|
||
show_menu
|
||
}
|
||
|
||
# 重启 Shadowsocks 服务
|
||
restart_service() {
|
||
clear
|
||
echo "=================================================="
|
||
echo -e "${GREEN}重启 Shadowsocks 服务${NC}"
|
||
echo "=================================================="
|
||
|
||
# 检查是否已安装
|
||
if ! command -v ss-server &>/dev/null; then
|
||
echo -e "${RED}Shadowsocks 未安装${NC}"
|
||
read -rp "按回车键返回主菜单..." temp
|
||
show_menu
|
||
return 0
|
||
fi
|
||
|
||
echo -n "重启 Shadowsocks 服务... "
|
||
if systemctl restart shadowsocks-libev; then
|
||
echo -e "${GREEN}成功${NC}"
|
||
log_info "Shadowsocks 服务已重启"
|
||
else
|
||
echo -e "${RED}失败${NC}"
|
||
log_error "无法重启 Shadowsocks 服务"
|
||
fi
|
||
|
||
# 等待服务启动
|
||
echo -n "等待服务启动... "
|
||
sleep 3
|
||
echo -e "${GREEN}完成${NC}"
|
||
|
||
# 检查服务状态
|
||
echo -n "Shadowsocks 服务状态: "
|
||
if systemctl is-active shadowsocks-libev &>/dev/null; then
|
||
echo -e "${GREEN}运行中${NC}"
|
||
else
|
||
echo -e "${RED}未运行${NC}"
|
||
fi
|
||
|
||
# 验证端口监听
|
||
if [[ -f "$CONFIG_PATH/config.json" ]]; then
|
||
local current_port=""
|
||
if command -v jq &>/dev/null; then
|
||
current_port=$(jq -r '.server_port' "$CONFIG_PATH/config.json" 2>/dev/null)
|
||
else
|
||
current_port=$(grep -o '"server_port": [0-9]*' "$CONFIG_PATH/config.json" | awk '{print $2}' 2>/dev/null)
|
||
fi
|
||
|
||
if [[ -n "$current_port" ]]; then
|
||
echo -n "端口 $current_port 监听状态: "
|
||
if command -v netstat &>/dev/null; then
|
||
if netstat -tuln | grep -q ":$current_port "; then
|
||
echo -e "${GREEN}正常${NC}"
|
||
else
|
||
echo -e "${RED}未监听${NC}"
|
||
fi
|
||
elif command -v ss &>/dev/null; then
|
||
if ss -tuln | grep -q ":$current_port "; then
|
||
echo -e "${GREEN}正常${NC}"
|
||
else
|
||
echo -e "${RED}未监听${NC}"
|
||
fi
|
||
fi
|
||
fi
|
||
fi
|
||
|
||
read -rp "按回车键返回主菜单..." temp
|
||
show_menu
|
||
}
|
||
|
||
# 修改配置
|
||
modify_config() {
|
||
clear
|
||
echo "=================================================="
|
||
echo -e "${YELLOW}修改 Shadowsocks 配置${NC}"
|
||
echo "=================================================="
|
||
|
||
# 检查是否已安装
|
||
if ! command -v ss-server &>/dev/null; then
|
||
echo -e "${RED}Shadowsocks 未安装${NC}"
|
||
read -rp "按回车键返回主菜单..." temp
|
||
show_menu
|
||
return 0
|
||
fi
|
||
|
||
# 读取当前配置
|
||
if [[ -f "$CONFIG_PATH/config.json" ]]; then
|
||
if command -v jq &>/dev/null; then
|
||
SS_PORT=$(jq -r '.server_port' "$CONFIG_PATH/config.json")
|
||
SS_PASSWORD=$(jq -r '.password' "$CONFIG_PATH/config.json")
|
||
SS_METHOD=$(jq -r '.method' "$CONFIG_PATH/config.json")
|
||
else
|
||
SS_PORT=$(grep -o '"server_port": [0-9]*' "$CONFIG_PATH/config.json" | awk '{print $2}')
|
||
SS_PASSWORD=$(grep -o '"password": "[^"]*"' "$CONFIG_PATH/config.json" | cut -d'"' -f4)
|
||
SS_METHOD=$(grep -o '"method": "[^"]*"' "$CONFIG_PATH/config.json" | cut -d'"' -f4)
|
||
fi
|
||
fi
|
||
|
||
echo "当前配置:"
|
||
echo "端口: $SS_PORT"
|
||
echo "密码: $SS_PASSWORD"
|
||
echo "加密方法: $SS_METHOD"
|
||
echo ""
|
||
|
||
echo "1) 修改端口"
|
||
echo "2) 修改密码"
|
||
echo "3) 修改加密方法"
|
||
echo "4) 重新生成所有配置"
|
||
echo "0) 返回主菜单"
|
||
echo ""
|
||
|
||
read -rp "请选择 [0-4]: " modify_choice
|
||
|
||
local config_changed=false
|
||
|
||
case $modify_choice in
|
||
1)
|
||
read -rp "请输入新端口 (当前: $SS_PORT): " new_port
|
||
if [[ "$new_port" =~ ^[0-9]+$ ]] && [[ "$new_port" -ge 1 ]] && [[ "$new_port" -le 65535 ]]; then
|
||
SS_PORT="$new_port"
|
||
config_changed=true
|
||
else
|
||
log_error "无效端口"
|
||
fi
|
||
;;
|
||
2)
|
||
read -rp "请输入新密码 (当前: $SS_PASSWORD): " new_password
|
||
if [[ ${#new_password} -ge 8 ]]; then
|
||
SS_PASSWORD="$new_password"
|
||
config_changed=true
|
||
else
|
||
log_error "密码至少需要8位"
|
||
fi
|
||
;;
|
||
3)
|
||
echo "选择新的加密方法:"
|
||
echo "1) chacha20-ietf-poly1305"
|
||
echo "2) aes-256-gcm"
|
||
echo "3) aes-192-gcm"
|
||
echo "4) aes-128-gcm (默认)"
|
||
read -rp "请选择 [1-4, 默认4]: " method_choice
|
||
|
||
case $method_choice in
|
||
1) SS_METHOD="chacha20-ietf-poly1305"; config_changed=true ;;
|
||
2) SS_METHOD="aes-256-gcm"; config_changed=true ;;
|
||
3) SS_METHOD="aes-192-gcm"; config_changed=true ;;
|
||
4) SS_METHOD="aes-128-gcm"; config_changed=true ;;
|
||
"") SS_METHOD="aes-128-gcm"; config_changed=true ;; # 默认选择
|
||
*) log_error "无效选择" ;;
|
||
esac
|
||
;;
|
||
4)
|
||
SS_PORT=""
|
||
SS_PASSWORD=""
|
||
configure_shadowsocks
|
||
create_service
|
||
configure_firewall
|
||
generate_client_info
|
||
log_info "配置已重新生成"
|
||
read -rp "按回车键返回主菜单..." temp
|
||
show_menu
|
||
return 0
|
||
;;
|
||
0)
|
||
show_menu
|
||
return 0
|
||
;;
|
||
*)
|
||
log_error "无效选择"
|
||
read -rp "按回车键重试..." temp
|
||
modify_config
|
||
return 0
|
||
;;
|
||
esac
|
||
|
||
if [[ "$config_changed" == true ]]; then
|
||
# 更新配置文件
|
||
cat > "$CONFIG_PATH/config.json" << EOF
|
||
{
|
||
"server": "0.0.0.0",
|
||
"server_port": $SS_PORT,
|
||
"password": "$SS_PASSWORD",
|
||
"method": "$SS_METHOD",
|
||
"timeout": 300,
|
||
"fast_open": true,
|
||
"workers": 1,
|
||
"prefer_ipv6": false,
|
||
"no_delay": true,
|
||
"reuse_port": true
|
||
}
|
||
EOF
|
||
|
||
# 重启服务
|
||
systemctl restart shadowsocks-libev
|
||
|
||
# 重新配置防火墙
|
||
configure_firewall
|
||
|
||
# 重新生成客户端信息
|
||
generate_client_info
|
||
|
||
log_info "配置已更新并重启服务"
|
||
fi
|
||
|
||
read -rp "按回车键返回主菜单..." temp
|
||
show_menu
|
||
}
|
||
|
||
|
||
# 更新 Shadowsocks
|
||
update_shadowsocks() {
|
||
clear
|
||
echo "=================================================="
|
||
echo -e "${YELLOW}更新 Shadowsocks${NC}"
|
||
echo "=================================================="
|
||
|
||
# 检查是否已安装
|
||
if ! command -v ss-server &>/dev/null; then
|
||
echo -e "${RED}Shadowsocks 未安装,请先安装${NC}"
|
||
read -rp "按回车键返回主菜单..." temp
|
||
show_menu
|
||
return 0
|
||
fi
|
||
|
||
# 备份配置
|
||
backup_config
|
||
|
||
# 停止服务
|
||
echo -n "停止 Shadowsocks 服务... "
|
||
if systemctl stop shadowsocks-libev &>/dev/null; then
|
||
echo -e "${GREEN}成功${NC}"
|
||
else
|
||
echo -e "${RED}失败${NC}"
|
||
log_warn "无法停止 Shadowsocks 服务"
|
||
fi
|
||
|
||
# 更新软件包
|
||
apt_progress "apt-get update" "更新软件包列表"
|
||
apt_progress "apt-get upgrade -y shadowsocks-libev" "更新 shadowsocks-libev"
|
||
|
||
# 启动服务
|
||
echo -n "启动 Shadowsocks 服务... "
|
||
if systemctl start shadowsocks-libev; then
|
||
echo -e "${GREEN}成功${NC}"
|
||
else
|
||
echo -e "${RED}失败${NC}"
|
||
log_error "启动 Shadowsocks 服务失败"
|
||
fi
|
||
|
||
log_info "Shadowsocks 更新完成"
|
||
|
||
read -rp "按回车键返回主菜单..." temp
|
||
show_menu
|
||
}
|
||
|
||
# 主函数
|
||
main() {
|
||
# 创建日志目录
|
||
mkdir -p "$(dirname "$LOG_FILE")"
|
||
|
||
# 处理命令行参数
|
||
if [[ $# -gt 0 ]]; then
|
||
case "$1" in
|
||
-h|--help)
|
||
show_help
|
||
exit 0
|
||
;;
|
||
-i|--install)
|
||
check_root
|
||
install_shadowsocks
|
||
exit 0
|
||
;;
|
||
-u|--uninstall)
|
||
check_root
|
||
uninstall_shadowsocks
|
||
exit 0
|
||
;;
|
||
-s|--status)
|
||
check_root
|
||
check_status
|
||
exit 0
|
||
;;
|
||
-up|--update)
|
||
check_root
|
||
update_shadowsocks
|
||
exit 0
|
||
;;
|
||
*)
|
||
log_error "未知参数: $1"
|
||
show_help
|
||
exit 1
|
||
;;
|
||
esac
|
||
fi
|
||
|
||
# 无参数则显示菜单
|
||
check_root
|
||
show_menu
|
||
}
|
||
|
||
# 执行主函数
|
||
main "$@"
|