fix: 完整重写,用python3生成JSON避免变量污染,端口密码可自定义
This commit is contained in:
451
ss-rust.sh
451
ss-rust.sh
@@ -15,6 +15,16 @@ info() { echo -e "${GREEN}[INFO]${NC} $1"; }
|
|||||||
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||||||
error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; }
|
error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; }
|
||||||
|
|
||||||
|
# ============ 全局变量 ============
|
||||||
|
SERVER_IP=""
|
||||||
|
PORT_2022=""
|
||||||
|
KEY_2022=""
|
||||||
|
METHOD_2022=""
|
||||||
|
PORT_RAW=""
|
||||||
|
KEY_RAW=""
|
||||||
|
METHOD_RAW=""
|
||||||
|
NODE_MODE=""
|
||||||
|
|
||||||
# ============ 基础检测 ============
|
# ============ 基础检测 ============
|
||||||
check_root() {
|
check_root() {
|
||||||
[[ $EUID -ne 0 ]] && error "请使用 root 用户运行"
|
[[ $EUID -ne 0 ]] && error "请使用 root 用户运行"
|
||||||
@@ -35,9 +45,9 @@ get_pkg_manager() {
|
|||||||
install_deps() {
|
install_deps() {
|
||||||
info "安装依赖..."
|
info "安装依赖..."
|
||||||
case $PKG in
|
case $PKG in
|
||||||
apt) apt update -qq &>/dev/null; apt install -y -qq curl openssl xz-utils tar chrony &>/dev/null ;;
|
apt) apt update -qq &>/dev/null; apt install -y -qq curl openssl xz-utils tar chrony python3 &>/dev/null ;;
|
||||||
yum) yum install -y -q curl openssl xz tar chrony &>/dev/null ;;
|
yum) yum install -y -q curl openssl xz tar chrony python3 &>/dev/null ;;
|
||||||
apk) apk add --quiet curl openssl xz tar chrony &>/dev/null ;;
|
apk) apk add --quiet curl openssl xz tar chrony python3 &>/dev/null ;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,9 +61,10 @@ get_arch() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get_ip() {
|
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)
|
local ip
|
||||||
[[ -z "$IP" ]] && error "无法获取公网IP"
|
ip=$(curl -s4m5 ip.sb 2>/dev/null || curl -s4m5 ifconfig.me 2>/dev/null || curl -s4m5 ipinfo.io/ip 2>/dev/null)
|
||||||
echo "$IP"
|
[[ -z "$ip" ]] && error "无法获取公网IP"
|
||||||
|
echo "$ip"
|
||||||
}
|
}
|
||||||
|
|
||||||
# ============ 时间同步 ============
|
# ============ 时间同步 ============
|
||||||
@@ -72,65 +83,47 @@ sync_time() {
|
|||||||
# ============ 安装 ss-rust ============
|
# ============ 安装 ss-rust ============
|
||||||
install_ssrust() {
|
install_ssrust() {
|
||||||
info "安装 shadowsocks-rust..."
|
info "安装 shadowsocks-rust..."
|
||||||
ARCH_NAME=$(get_arch)
|
local arch_name
|
||||||
|
arch_name=$(get_arch)
|
||||||
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"
|
local latest
|
||||||
info "版本: $LATEST"
|
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"
|
||||||
URL="https://github.com/shadowsocks/shadowsocks-rust/releases/download/${LATEST}/shadowsocks-${LATEST}.${ARCH_NAME}.tar.xz"
|
info "版本: $latest"
|
||||||
|
|
||||||
|
local url="https://github.com/shadowsocks/shadowsocks-rust/releases/download/${latest}/shadowsocks-${latest}.${arch_name}.tar.xz"
|
||||||
|
|
||||||
cd /tmp
|
cd /tmp
|
||||||
rm -f ss-rust-dl.tar.xz
|
rm -f ss-rust-dl.tar.xz ssserver sslocal ssurl ssmanager ssservice
|
||||||
curl -sL "$URL" -o ss-rust-dl.tar.xz
|
curl -sL "$url" -o ss-rust-dl.tar.xz
|
||||||
|
|
||||||
# 验证下载
|
local fsize
|
||||||
FILE_SIZE=$(stat -c%s ss-rust-dl.tar.xz 2>/dev/null || stat -f%z ss-rust-dl.tar.xz 2>/dev/null)
|
fsize=$(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),可能是网络问题"
|
[[ "$fsize" -lt 100000 ]] && error "下载失败 (${fsize} bytes)"
|
||||||
|
|
||||||
file ss-rust-dl.tar.xz | grep -q "XZ" || error "下载的文件不是有效的 XZ 压缩包"
|
file ss-rust-dl.tar.xz | grep -q "XZ" || error "下载的文件不是有效的 XZ 压缩包"
|
||||||
|
|
||||||
tar xf ss-rust-dl.tar.xz || error "解压失败"
|
tar xf ss-rust-dl.tar.xz || error "解压失败"
|
||||||
|
[[ ! -f ssserver ]] && error "找不到 ssserver"
|
||||||
[[ ! -f ssserver ]] && error "解压后找不到 ssserver 二进制文件"
|
|
||||||
|
|
||||||
cp -f ssserver /usr/local/bin/
|
cp -f ssserver /usr/local/bin/
|
||||||
cp -f sslocal /usr/local/bin/ 2>/dev/null || true
|
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/ssserver /usr/local/bin/sslocal 2>/dev/null
|
||||||
chmod +x /usr/local/bin/ss*
|
|
||||||
|
|
||||||
# 清理
|
|
||||||
rm -f ss-rust-dl.tar.xz ssserver sslocal ssurl ssmanager ssservice
|
rm -f ss-rust-dl.tar.xz ssserver sslocal ssurl ssmanager ssservice
|
||||||
|
|
||||||
/usr/local/bin/ssserver --version && info "shadowsocks-rust 安装完成" || error "安装验证失败"
|
/usr/local/bin/ssserver --version && info "shadowsocks-rust 安装完成" || error "安装验证失败"
|
||||||
}
|
}
|
||||||
|
|
||||||
# ============ 询问端口和密码 ============
|
# ============ 节点选择 + 端口密码 + 写配置 ============
|
||||||
ask_port_key() {
|
|
||||||
local label="$1"
|
|
||||||
local default_port="$2"
|
|
||||||
local default_key="$3"
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo -e "${GREEN}【${label}】${NC}"
|
|
||||||
read -p " 端口 (回车随机=${default_port}): " input_port
|
|
||||||
[[ -z "$input_port" ]] && input_port="$default_port"
|
|
||||||
read -p " 密码 (回车随机=${default_key}): " input_key
|
|
||||||
[[ -z "$input_key" ]] && input_key="$default_key"
|
|
||||||
|
|
||||||
echo "$input_port $input_key"
|
|
||||||
}
|
|
||||||
|
|
||||||
# ============ 节点选择 + 配置生成 ============
|
|
||||||
select_and_configure() {
|
select_and_configure() {
|
||||||
SERVER_IP=$(get_ip)
|
SERVER_IP=$(get_ip)
|
||||||
mkdir -p /etc/shadowsocks-rust
|
mkdir -p /etc/shadowsocks-rust
|
||||||
|
|
||||||
# 清空所有变量
|
# 清空
|
||||||
PORT_2022="" ; KEY_2022="" ; METHOD_2022=""
|
PORT_2022="" ; KEY_2022="" ; METHOD_2022=""
|
||||||
PORT_RAW="" ; KEY_RAW="" ; METHOD_RAW=""
|
PORT_RAW="" ; KEY_RAW="" ; METHOD_RAW=""
|
||||||
NODE_MODE=""
|
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${CYAN}════════════════════════════════════════${NC}"
|
echo -e "${CYAN}════════════════════════════════════════${NC}"
|
||||||
echo -e "${CYAN} 🔐 选择节点类型${NC}"
|
echo -e "${CYAN} 🔐 选择节点类型${NC}"
|
||||||
@@ -140,100 +133,60 @@ select_and_configure() {
|
|||||||
echo -e " ${GREEN}2.${NC} SS-AES-128 (aes-128-gcm) — 传统协议,兼容性好"
|
echo -e " ${GREEN}2.${NC} SS-AES-128 (aes-128-gcm) — 传统协议,兼容性好"
|
||||||
echo -e " ${GREEN}3.${NC} 双节点全装 (SS2022 + SS128)"
|
echo -e " ${GREEN}3.${NC} 双节点全装 (SS2022 + SS128)"
|
||||||
echo ""
|
echo ""
|
||||||
read -p "请选择 [1-3] (默认3): " node_choice
|
read -rp "请选择 [1-3] (默认3): " node_choice
|
||||||
node_choice=${node_choice:-3}
|
node_choice=${node_choice:-3}
|
||||||
|
|
||||||
METHOD_2022="2022-blake3-aes-128-gcm"
|
if [[ "$node_choice" == "1" || "$node_choice" == "3" ]]; then
|
||||||
METHOD_RAW="aes-128-gcm"
|
local dp=$((RANDOM % 10000 + 20000))
|
||||||
|
local dk=$(openssl rand -base64 16)
|
||||||
case "${node_choice}" in
|
echo ""
|
||||||
1)
|
echo -e " ${GREEN}SS2022-128 配置:${NC}"
|
||||||
local dp=$((RANDOM % 10000 + 20000))
|
read -rp " 端口 [回车=${dp}]: " PORT_2022
|
||||||
local dk=$(openssl rand -base64 16)
|
PORT_2022=${PORT_2022:-$dp}
|
||||||
local result=$(ask_port_key "SS2022-128" "$dp" "$dk")
|
read -rp " 密码 [回车=${dk}]: " KEY_2022
|
||||||
PORT_2022=$(echo "$result" | awk '{print $1}')
|
KEY_2022=${KEY_2022:-$dk}
|
||||||
KEY_2022=$(echo "$result" | awk '{print $2}')
|
METHOD_2022="2022-blake3-aes-128-gcm"
|
||||||
NODE_MODE="ss2022"
|
fi
|
||||||
|
|
||||||
cat > /etc/shadowsocks-rust/config.json << EOF
|
if [[ "$node_choice" == "2" || "$node_choice" == "3" ]]; then
|
||||||
{
|
local dp2=$((RANDOM % 10000 + 30000))
|
||||||
"servers": [
|
local dk2=$(openssl rand -base64 16)
|
||||||
{
|
echo ""
|
||||||
"server": "0.0.0.0",
|
echo -e " ${GREEN}SS-AES-128 配置:${NC}"
|
||||||
"server_port": ${PORT_2022},
|
read -rp " 端口 [回车=${dp2}]: " PORT_RAW
|
||||||
"method": "${METHOD_2022}",
|
PORT_RAW=${PORT_RAW:-$dp2}
|
||||||
"password": "${KEY_2022}",
|
read -rp " 密码 [回车=${dk2}]: " KEY_RAW
|
||||||
"timeout": 300,
|
KEY_RAW=${KEY_RAW:-$dk2}
|
||||||
"fast_open": true
|
METHOD_RAW="aes-128-gcm"
|
||||||
}
|
fi
|
||||||
]
|
|
||||||
}
|
# 写 JSON 配置
|
||||||
EOF
|
python3 -c "
|
||||||
METHOD_RAW=""
|
import json
|
||||||
;;
|
servers = []
|
||||||
2)
|
if '${PORT_2022}':
|
||||||
local dp=$((RANDOM % 10000 + 30000))
|
servers.append({
|
||||||
local dk=$(openssl rand -base64 16)
|
'server': '0.0.0.0',
|
||||||
local result=$(ask_port_key "SS-AES-128" "$dp" "$dk")
|
'server_port': int('${PORT_2022}'),
|
||||||
PORT_RAW=$(echo "$result" | awk '{print $1}')
|
'method': '${METHOD_2022}',
|
||||||
KEY_RAW=$(echo "$result" | awk '{print $2}')
|
'password': '${KEY_2022}',
|
||||||
NODE_MODE="ss128"
|
'timeout': 300,
|
||||||
|
'fast_open': True
|
||||||
cat > /etc/shadowsocks-rust/config.json << EOF
|
})
|
||||||
{
|
if '${PORT_RAW}':
|
||||||
"servers": [
|
servers.append({
|
||||||
{
|
'server': '0.0.0.0',
|
||||||
"server": "0.0.0.0",
|
'server_port': int('${PORT_RAW}'),
|
||||||
"server_port": ${PORT_RAW},
|
'method': '${METHOD_RAW}',
|
||||||
"method": "${METHOD_RAW}",
|
'password': '${KEY_RAW}',
|
||||||
"password": "${KEY_RAW}",
|
'timeout': 300,
|
||||||
"timeout": 300,
|
'fast_open': True
|
||||||
"fast_open": true
|
})
|
||||||
}
|
with open('/etc/shadowsocks-rust/config.json', 'w') as f:
|
||||||
]
|
json.dump({'servers': servers}, f, indent=4)
|
||||||
}
|
print('OK')
|
||||||
EOF
|
" || error "生成配置失败"
|
||||||
METHOD_2022=""
|
|
||||||
;;
|
|
||||||
3|*)
|
|
||||||
local dp1=$((RANDOM % 10000 + 20000))
|
|
||||||
local dk1=$(openssl rand -base64 16)
|
|
||||||
local result1=$(ask_port_key "SS2022-128" "$dp1" "$dk1")
|
|
||||||
PORT_2022=$(echo "$result1" | awk '{print $1}')
|
|
||||||
KEY_2022=$(echo "$result1" | awk '{print $2}')
|
|
||||||
|
|
||||||
local dp2=$((RANDOM % 10000 + 30000))
|
|
||||||
local dk2=$(openssl rand -base64 16)
|
|
||||||
local result2=$(ask_port_key "SS-AES-128" "$dp2" "$dk2")
|
|
||||||
PORT_RAW=$(echo "$result2" | awk '{print $1}')
|
|
||||||
KEY_RAW=$(echo "$result2" | awk '{print $2}')
|
|
||||||
NODE_MODE="both"
|
|
||||||
|
|
||||||
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
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"server": "0.0.0.0",
|
|
||||||
"server_port": ${PORT_RAW},
|
|
||||||
"method": "${METHOD_RAW}",
|
|
||||||
"password": "${KEY_RAW}",
|
|
||||||
"timeout": 300,
|
|
||||||
"fast_open": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
info "配置文件: /etc/shadowsocks-rust/config.json"
|
info "配置文件: /etc/shadowsocks-rust/config.json"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,15 +207,14 @@ LimitNOFILE=65535
|
|||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
systemctl enable --now ss-rust
|
systemctl enable --now ss-rust
|
||||||
sleep 2
|
sleep 2
|
||||||
|
|
||||||
if systemctl is-active --quiet ss-rust; then
|
if systemctl is-active --quiet ss-rust; then
|
||||||
info "ss-rust 服务启动成功"
|
info "ss-rust 服务启动成功"
|
||||||
else
|
else
|
||||||
echo ""
|
|
||||||
journalctl -u ss-rust -n 5 --no-pager
|
journalctl -u ss-rust -n 5 --no-pager
|
||||||
error "ss-rust 服务启动失败"
|
error "ss-rust 服务启动失败"
|
||||||
fi
|
fi
|
||||||
@@ -270,18 +222,16 @@ EOF
|
|||||||
|
|
||||||
# ============ 读取现有配置 ============
|
# ============ 读取现有配置 ============
|
||||||
load_config() {
|
load_config() {
|
||||||
if [[ ! -f /etc/shadowsocks-rust/config.json ]]; then
|
[[ ! -f /etc/shadowsocks-rust/config.json ]] && return 1
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
SERVER_IP=$(get_ip)
|
SERVER_IP=$(get_ip)
|
||||||
|
PORT_2022="" ; KEY_2022="" ; METHOD_2022=""
|
||||||
# 用 python3 或 grep 解析
|
PORT_RAW="" ; KEY_RAW="" ; METHOD_RAW=""
|
||||||
if command -v python3 &>/dev/null; then
|
|
||||||
eval $(python3 -c "
|
eval $(python3 -c "
|
||||||
import json
|
import json
|
||||||
with open('/etc/shadowsocks-rust/config.json') as f:
|
with open('/etc/shadowsocks-rust/config.json') as f:
|
||||||
c = json.load(f)
|
c = json.load(f)
|
||||||
for i,s in enumerate(c['servers']):
|
for s in c['servers']:
|
||||||
m = s['method']
|
m = s['method']
|
||||||
if '2022' in m:
|
if '2022' in m:
|
||||||
print(f'PORT_2022={s[\"server_port\"]}')
|
print(f'PORT_2022={s[\"server_port\"]}')
|
||||||
@@ -291,80 +241,41 @@ for i,s in enumerate(c['servers']):
|
|||||||
print(f'PORT_RAW={s[\"server_port\"]}')
|
print(f'PORT_RAW={s[\"server_port\"]}')
|
||||||
print(f'KEY_RAW={s[\"password\"]}')
|
print(f'KEY_RAW={s[\"password\"]}')
|
||||||
print(f'METHOD_RAW={m}')
|
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)
|
" 2>/dev/null)
|
||||||
fi
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
# ============ 生成订阅 ============
|
# ============ 生成订阅 ============
|
||||||
gen_subscribe() {
|
gen_subscribe() {
|
||||||
load_config || return
|
load_config || return
|
||||||
SUB_DIR="/etc/shadowsocks-rust/subscribe"
|
local sub_dir="/etc/shadowsocks-rust/subscribe"
|
||||||
mkdir -p "$SUB_DIR"
|
mkdir -p "$sub_dir"
|
||||||
|
|
||||||
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 "${SS_URIS}" | base64 -w0 > "$SUB_DIR/subscribe.txt"
|
|
||||||
|
|
||||||
# Surge
|
|
||||||
cat > "$SUB_DIR/surge.conf" << EOF
|
|
||||||
# Surge SS 配置 | $(date '+%Y-%m-%d %H:%M:%S') | ${SERVER_IP}
|
|
||||||
[Proxy]
|
|
||||||
$(echo -e "${SURGE_PROXIES}")
|
|
||||||
[Proxy Group]
|
|
||||||
Proxy = select, $(echo "${SURGE_NAMES}DIRECT" | sed 's/, DIRECT$/, DIRECT/')
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# Clash
|
|
||||||
cat > "$SUB_DIR/clash.yaml" << EOF
|
|
||||||
# Clash SS 配置 | $(date '+%Y-%m-%d %H:%M:%S')
|
|
||||||
proxies:
|
|
||||||
$(echo -e "${CLASH_PROXIES}")
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# Info
|
|
||||||
cat > "$SUB_DIR/info.txt" << EOF
|
|
||||||
════════════════════════════════════════
|
|
||||||
Shadowsocks-Rust 节点信息
|
|
||||||
$(date '+%Y-%m-%d %H:%M:%S') | ${SERVER_IP}
|
|
||||||
════════════════════════════════════════
|
|
||||||
|
|
||||||
$(echo -e "${INFO_NODES}")
|
local uris="" surge="" clash="" info_txt=""
|
||||||
【SS 链接】
|
|
||||||
$(echo -e "${SS_URIS}")
|
if [[ -n "$PORT_2022" ]]; then
|
||||||
════════════════════════════════════════
|
local uri="ss://$(echo -n "${METHOD_2022}:${KEY_2022}" | base64 -w0)@${SERVER_IP}:${PORT_2022}#SS2022-128"
|
||||||
EOF
|
URI_2022="$uri"
|
||||||
|
uris="${uris}${uri}\n"
|
||||||
|
surge="${surge}SS2022-128 = ss, ${SERVER_IP}, ${PORT_2022}, encrypt-method=${METHOD_2022}, password=${KEY_2022}\n"
|
||||||
|
clash="${clash} - 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_txt="${info_txt}【SS2022-AES-128】新协议\n 地址: ${SERVER_IP}\n 端口: ${PORT_2022}\n 加密: ${METHOD_2022}\n 密码: ${KEY_2022}\n\n"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "$PORT_RAW" ]]; then
|
||||||
|
local uri="ss://$(echo -n "${METHOD_RAW}:${KEY_RAW}" | base64 -w0)@${SERVER_IP}:${PORT_RAW}#SS-AES-128"
|
||||||
|
URI_RAW="$uri"
|
||||||
|
uris="${uris}${uri}\n"
|
||||||
|
surge="${surge}SS-AES-128 = ss, ${SERVER_IP}, ${PORT_RAW}, encrypt-method=${METHOD_RAW}, password=${KEY_RAW}\n"
|
||||||
|
clash="${clash} - 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_txt="${info_txt}【SS-AES-128】传统协议\n 地址: ${SERVER_IP}\n 端口: ${PORT_RAW}\n 加密: ${METHOD_RAW}\n 密码: ${KEY_RAW}\n\n"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "$uris" | base64 -w0 > "$sub_dir/subscribe.txt"
|
||||||
|
|
||||||
|
echo -e "# Surge SS | $(date '+%Y-%m-%d %H:%M:%S') | ${SERVER_IP}\n[Proxy]\n${surge}" > "$sub_dir/surge.conf"
|
||||||
|
echo -e "# Clash SS | $(date '+%Y-%m-%d %H:%M:%S')\nproxies:\n${clash}" > "$sub_dir/clash.yaml"
|
||||||
|
echo -e "═══ SS-Rust 节点 | $(date '+%Y-%m-%d %H:%M:%S') | ${SERVER_IP} ═══\n\n${info_txt}\n【SS 链接】\n${uris}" > "$sub_dir/info.txt"
|
||||||
}
|
}
|
||||||
|
|
||||||
# ============ 显示结果 ============
|
# ============ 显示结果 ============
|
||||||
@@ -375,57 +286,51 @@ show_result() {
|
|||||||
echo -e "${CYAN} 🚀 Shadowsocks-Rust 安装完成${NC}"
|
echo -e "${CYAN} 🚀 Shadowsocks-Rust 安装完成${NC}"
|
||||||
echo -e "${CYAN}════════════════════════════════════════${NC}"
|
echo -e "${CYAN}════════════════════════════════════════${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
if [[ -n "${PORT_2022:-}" ]]; then
|
if [[ -n "$PORT_2022" ]]; then
|
||||||
echo -e "${GREEN}【节点1】SS2022-AES-128 (新协议)${NC}"
|
echo -e "${GREEN}【SS2022-AES-128】新协议${NC}"
|
||||||
echo -e " 地址: ${SERVER_IP}"
|
echo -e " 地址: ${SERVER_IP}"
|
||||||
echo -e " 端口: ${YELLOW}${PORT_2022}${NC}"
|
echo -e " 端口: ${YELLOW}${PORT_2022}${NC}"
|
||||||
echo -e " 加密: ${METHOD_2022}"
|
echo -e " 加密: ${METHOD_2022}"
|
||||||
echo -e " 密码: ${YELLOW}${KEY_2022}${NC}"
|
echo -e " 密码: ${YELLOW}${KEY_2022}${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -n "${PORT_RAW:-}" ]]; then
|
if [[ -n "$PORT_RAW" ]]; then
|
||||||
echo -e "${GREEN}【节点2】SS-AES-128 (传统协议)${NC}"
|
echo -e "${GREEN}【SS-AES-128】传统协议${NC}"
|
||||||
echo -e " 地址: ${SERVER_IP}"
|
echo -e " 地址: ${SERVER_IP}"
|
||||||
echo -e " 端口: ${YELLOW}${PORT_RAW}${NC}"
|
echo -e " 端口: ${YELLOW}${PORT_RAW}${NC}"
|
||||||
echo -e " 加密: ${METHOD_RAW}"
|
echo -e " 加密: ${METHOD_RAW}"
|
||||||
echo -e " 密码: ${YELLOW}${KEY_RAW}${NC}"
|
echo -e " 密码: ${YELLOW}${KEY_RAW}${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -e "${CYAN}────────────────────────────────────────${NC}"
|
echo -e "${CYAN}────────────────────────────────────────${NC}"
|
||||||
echo -e "${GREEN}【Surge 格式】${NC}"
|
echo -e "${GREEN}【Surge 格式】${NC}"
|
||||||
[[ -n "${PORT_2022:-}" ]] && echo -e " SS2022-128 = ss, ${SERVER_IP}, ${PORT_2022}, encrypt-method=${METHOD_2022}, password=${KEY_2022}"
|
[[ -n "$PORT_2022" ]] && echo " 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}"
|
[[ -n "$PORT_RAW" ]] && echo " SS-AES-128 = ss, ${SERVER_IP}, ${PORT_RAW}, encrypt-method=${METHOD_RAW}, password=${KEY_RAW}"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
echo -e "${CYAN}────────────────────────────────────────${NC}"
|
echo -e "${CYAN}────────────────────────────────────────${NC}"
|
||||||
echo -e "${GREEN}【SS 链接】${NC}"
|
echo -e "${GREEN}【SS 链接】${NC}"
|
||||||
[[ -n "${URI_2022:-}" ]] && echo -e " ${URI_2022}"
|
[[ -n "${URI_2022:-}" ]] && echo " ${URI_2022}"
|
||||||
[[ -n "${URI_RAW:-}" ]] && echo -e " ${URI_RAW}"
|
[[ -n "${URI_RAW:-}" ]] && echo " ${URI_RAW}"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
echo -e "${CYAN}────────────────────────────────────────${NC}"
|
echo -e "${CYAN}────────────────────────────────────────${NC}"
|
||||||
echo -e "${GREEN}【文件位置】${NC}"
|
echo -e "${GREEN}【文件】${NC}"
|
||||||
echo -e " 配置: /etc/shadowsocks-rust/config.json"
|
echo " 配置: /etc/shadowsocks-rust/config.json"
|
||||||
echo -e " 订阅: /etc/shadowsocks-rust/subscribe/subscribe.txt"
|
echo " 订阅: /etc/shadowsocks-rust/subscribe/"
|
||||||
echo -e " Surge: /etc/shadowsocks-rust/subscribe/surge.conf"
|
|
||||||
echo -e " Clash: /etc/shadowsocks-rust/subscribe/clash.yaml"
|
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${CYAN}【管理】${NC} 再次运行本脚本即可进入管理菜单"
|
echo -e "${CYAN}【管理】${NC} 再次运行脚本进入管理菜单"
|
||||||
echo -e "${CYAN}════════════════════════════════════════${NC}"
|
echo -e "${CYAN}════════════════════════════════════════${NC}"
|
||||||
}
|
}
|
||||||
|
|
||||||
# ============ 查看配置 ============
|
# ============ 查看配置 ============
|
||||||
show_config() {
|
show_config() {
|
||||||
load_config || error "未安装 shadowsocks-rust"
|
load_config || error "未安装"
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${CYAN}════════════════════════════════════════${NC}"
|
echo -e "${CYAN} 📋 当前配置 | 状态: $(systemctl is-active ss-rust 2>/dev/null)${NC}"
|
||||||
echo -e "${CYAN} 📋 当前配置${NC}"
|
|
||||||
echo -e "${CYAN}════════════════════════════════════════${NC}"
|
|
||||||
echo ""
|
|
||||||
echo -e "${GREEN}服务状态:${NC} $(systemctl is-active ss-rust 2>/dev/null || echo '未运行')"
|
|
||||||
echo ""
|
echo ""
|
||||||
cat /etc/shadowsocks-rust/config.json
|
cat /etc/shadowsocks-rust/config.json
|
||||||
echo ""
|
echo ""
|
||||||
@@ -434,15 +339,14 @@ show_config() {
|
|||||||
|
|
||||||
# ============ 修改端口 ============
|
# ============ 修改端口 ============
|
||||||
change_port() {
|
change_port() {
|
||||||
load_config || error "未安装 shadowsocks-rust"
|
load_config || error "未安装"
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${GREEN}当前节点:${NC}"
|
[[ -n "$PORT_2022" ]] && echo -e " 1) SS2022-128 | 端口 ${PORT_2022}"
|
||||||
[[ -n "${PORT_2022:-}" ]] && echo -e " 1) SS2022-128 | 端口 ${PORT_2022}"
|
[[ -n "$PORT_RAW" ]] && echo -e " 2) SS-AES-128 | 端口 ${PORT_RAW}"
|
||||||
[[ -n "${PORT_RAW:-}" ]] && echo -e " 2) SS-AES-128 | 端口 ${PORT_RAW}"
|
|
||||||
echo ""
|
echo ""
|
||||||
read -p "输入节点编号: " pn
|
read -rp "节点编号: " pn
|
||||||
read -p "输入新端口: " new_port
|
read -rp "新端口: " new_port
|
||||||
|
|
||||||
python3 -c "
|
python3 -c "
|
||||||
import json
|
import json
|
||||||
with open('/etc/shadowsocks-rust/config.json') as f:
|
with open('/etc/shadowsocks-rust/config.json') as f:
|
||||||
@@ -452,27 +356,24 @@ if 0 <= idx < len(c['servers']):
|
|||||||
c['servers'][idx]['server_port'] = int('${new_port}')
|
c['servers'][idx]['server_port'] = int('${new_port}')
|
||||||
with open('/etc/shadowsocks-rust/config.json','w') as f:
|
with open('/etc/shadowsocks-rust/config.json','w') as f:
|
||||||
json.dump(c, f, indent=4)
|
json.dump(c, f, indent=4)
|
||||||
" 2>/dev/null
|
"
|
||||||
|
|
||||||
systemctl restart ss-rust
|
systemctl restart ss-rust
|
||||||
gen_subscribe
|
gen_subscribe
|
||||||
info "端口已修改为 ${new_port},订阅已更新"
|
info "端口已改为 ${new_port}"
|
||||||
}
|
}
|
||||||
|
|
||||||
# ============ 重置密钥 ============
|
# ============ 重置密钥 ============
|
||||||
reset_keys() {
|
reset_keys() {
|
||||||
load_config || error "未安装 shadowsocks-rust"
|
load_config || error "未安装"
|
||||||
|
|
||||||
python3 -c "
|
python3 -c "
|
||||||
import json, subprocess, base64, os
|
import json,base64,os
|
||||||
with open('/etc/shadowsocks-rust/config.json') as f:
|
with open('/etc/shadowsocks-rust/config.json') as f:
|
||||||
c = json.load(f)
|
c = json.load(f)
|
||||||
for s in c['servers']:
|
for s in c['servers']:
|
||||||
s['password'] = base64.b64encode(os.urandom(16)).decode()
|
s['password'] = base64.b64encode(os.urandom(16)).decode()
|
||||||
with open('/etc/shadowsocks-rust/config.json','w') as f:
|
with open('/etc/shadowsocks-rust/config.json','w') as f:
|
||||||
json.dump(c, f, indent=4)
|
json.dump(c, f, indent=4)
|
||||||
" 2>/dev/null
|
"
|
||||||
|
|
||||||
systemctl restart ss-rust
|
systemctl restart ss-rust
|
||||||
gen_subscribe
|
gen_subscribe
|
||||||
info "密钥已重置"
|
info "密钥已重置"
|
||||||
@@ -491,7 +392,7 @@ uninstall() {
|
|||||||
info "卸载完成"
|
info "卸载完成"
|
||||||
}
|
}
|
||||||
|
|
||||||
# ============ 完整安装流程 ============
|
# ============ 安装流程 ============
|
||||||
do_install() {
|
do_install() {
|
||||||
get_pkg_manager
|
get_pkg_manager
|
||||||
install_deps
|
install_deps
|
||||||
@@ -521,16 +422,16 @@ show_menu() {
|
|||||||
echo -e " ${RED}9.${NC} 卸载"
|
echo -e " ${RED}9.${NC} 卸载"
|
||||||
echo -e " ${YELLOW}0.${NC} 退出"
|
echo -e " ${YELLOW}0.${NC} 退出"
|
||||||
echo ""
|
echo ""
|
||||||
read -p "请选择 [0-9]: " choice
|
read -rp "请选择 [0-9]: " choice
|
||||||
|
|
||||||
case "$choice" in
|
case "$choice" in
|
||||||
1) do_install ;;
|
1) do_install ;;
|
||||||
2) show_config ;;
|
2) show_config ;;
|
||||||
3) change_port ;;
|
3) change_port ;;
|
||||||
4) reset_keys ;;
|
4) reset_keys ;;
|
||||||
5) systemctl start ss-rust && info "服务已启动" ;;
|
5) systemctl start ss-rust && info "已启动" ;;
|
||||||
6) systemctl stop ss-rust && info "服务已停止" ;;
|
6) systemctl stop ss-rust && info "已停止" ;;
|
||||||
7) systemctl restart ss-rust && info "服务已重启" ;;
|
7) systemctl restart ss-rust && info "已重启" ;;
|
||||||
8) journalctl -u ss-rust --no-pager -n 30 ;;
|
8) journalctl -u ss-rust --no-pager -n 30 ;;
|
||||||
9) uninstall ;;
|
9) uninstall ;;
|
||||||
0) exit 0 ;;
|
0) exit 0 ;;
|
||||||
@@ -542,14 +443,14 @@ show_menu() {
|
|||||||
main() {
|
main() {
|
||||||
check_root
|
check_root
|
||||||
case "${1:-}" in
|
case "${1:-}" in
|
||||||
install) do_install ;;
|
install) do_install ;;
|
||||||
uninstall|remove) uninstall ;;
|
uninstall|remove) uninstall ;;
|
||||||
show|config|info) show_config ;;
|
show|config|info) show_config ;;
|
||||||
restart) systemctl restart ss-rust && info "服务已重启" ;;
|
restart) systemctl restart ss-rust && info "已重启" ;;
|
||||||
start) systemctl start ss-rust && info "服务已启动" ;;
|
start) systemctl start ss-rust && info "已启动" ;;
|
||||||
stop) systemctl stop ss-rust && info "服务已停止" ;;
|
stop) systemctl stop ss-rust && info "已停止" ;;
|
||||||
log|logs) journalctl -u ss-rust --no-pager -n 30 ;;
|
log|logs) journalctl -u ss-rust --no-pager -n 30 ;;
|
||||||
reset) reset_keys ;;
|
reset) reset_keys ;;
|
||||||
*)
|
*)
|
||||||
if [[ -f /etc/shadowsocks-rust/config.json ]]; then
|
if [[ -f /etc/shadowsocks-rust/config.json ]]; then
|
||||||
show_menu
|
show_menu
|
||||||
|
|||||||
Reference in New Issue
Block a user