|
|
@@ -0,0 +1,1867 @@
|
|
|
+#!/usr/bin/env bash
|
|
|
+PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
|
|
|
+export PATH
|
|
|
+
|
|
|
+#=================================================
|
|
|
+# System Required: CentOS/Debian/Ubuntu
|
|
|
+# Description: Shadowsocks Rust 管理脚本
|
|
|
+# Author: 翠花
|
|
|
+# WebSite: https://about.nange.cn
|
|
|
+#=================================================
|
|
|
+
|
|
|
+# 当前脚本版本号
|
|
|
+sh_ver="1.5.3"
|
|
|
+
|
|
|
+# Shadowsocks Rust 相关路径
|
|
|
+SS_Folder="/etc/ss-rust"
|
|
|
+SS_File="/usr/local/bin/ss-rust"
|
|
|
+SS_Conf="/etc/ss-rust/config.json"
|
|
|
+SS_Now_ver_File="/etc/ss-rust/ver.txt"
|
|
|
+
|
|
|
+# BBR 配置文件
|
|
|
+BBR_Local="/etc/sysctl.d/local.conf"
|
|
|
+
|
|
|
+# Shadow TLS 相关路径
|
|
|
+STLS_Folder="/etc/shadowtls"
|
|
|
+STLS_File="/usr/local/bin/shadow-tls"
|
|
|
+STLS_Conf="/etc/shadowtls/config.json"
|
|
|
+STLS_Now_ver_File="/etc/shadowtls/ver.txt"
|
|
|
+
|
|
|
+Green_font_prefix="\033[32m" && Red_font_prefix="\033[31m" && Green_background_prefix="\033[42;37m" && Red_background_prefix="\033[41;37m" && Font_color_suffix="\033[0m" && Yellow_font_prefix="\033[0;33m"
|
|
|
+Info="${Green_font_prefix}[信息]${Font_color_suffix}"
|
|
|
+Error="${Red_font_prefix}[错误]${Font_color_suffix}"
|
|
|
+Tip="${Yellow_font_prefix}[注意]${Font_color_suffix}"
|
|
|
+
|
|
|
+check_root(){
|
|
|
+ if [[ $EUID != 0 ]]; then
|
|
|
+ echo -e "${Error} 当前非ROOT账号(或没有ROOT权限),无法继续操作,请更换ROOT账号或使用 ${Green_background_prefix}sudo su${Font_color_suffix} 命令获取临时ROOT权限(执行后可能会提示输入当前账号的密码)。"
|
|
|
+ exit 1
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+check_sys(){
|
|
|
+ if [[ -f /etc/redhat-release ]]; then
|
|
|
+ release="centos"
|
|
|
+ elif cat /etc/issue | grep -q -E -i "debian"; then
|
|
|
+ release="debian"
|
|
|
+ elif cat /etc/issue | grep -q -E -i "ubuntu"; then
|
|
|
+ release="ubuntu"
|
|
|
+ elif cat /etc/issue | grep -q -E -i "centos|red hat|redhat"; then
|
|
|
+ release="centos"
|
|
|
+ elif cat /proc/version | grep -q -E -i "debian"; then
|
|
|
+ release="debian"
|
|
|
+ elif cat /proc/version | grep -q -E -i "ubuntu"; then
|
|
|
+ release="ubuntu"
|
|
|
+ elif cat /proc/version | grep -q -E -i "centos|red hat|redhat"; then
|
|
|
+ release="centos"
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+sys_arch() {
|
|
|
+ uname=$(uname -m)
|
|
|
+ if [[ "$uname" == "i686" ]] || [[ "$uname" == "i386" ]]; then
|
|
|
+ arch="i686"
|
|
|
+ elif [[ "$uname" == *"armv7"* ]] || [[ "$uname" == "armv6l" ]]; then
|
|
|
+ arch="arm"
|
|
|
+ elif [[ "$uname" == *"armv8"* ]] || [[ "$uname" == "aarch64" ]]; then
|
|
|
+ arch="aarch64"
|
|
|
+ else
|
|
|
+ arch="x86_64"
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+#开启系统 TCP Fast Open
|
|
|
+enable_systfo() {
|
|
|
+ kernel=$(uname -r | awk -F . '{print $1}')
|
|
|
+ if [ "$kernel" -ge 3 ]; then
|
|
|
+ echo 3 >/proc/sys/net/ipv4/tcp_fastopen
|
|
|
+ [[ ! -e $BBR_Local ]] && echo "fs.file-max = 51200
|
|
|
+net.core.rmem_max = 67108864
|
|
|
+net.core.wmem_max = 67108864
|
|
|
+net.core.rmem_default = 65536
|
|
|
+net.core.wmem_default = 65536
|
|
|
+net.core.netdev_max_backlog = 4096
|
|
|
+net.core.somaxconn = 4096
|
|
|
+net.ipv4.tcp_syncookies = 1
|
|
|
+net.ipv4.tcp_tw_reuse = 1
|
|
|
+net.ipv4.tcp_tw_recycle = 0
|
|
|
+net.ipv4.tcp_fin_timeout = 30
|
|
|
+net.ipv4.tcp_keepalive_time = 1200
|
|
|
+net.ipv4.ip_local_port_range = 10000 65000
|
|
|
+net.ipv4.tcp_max_syn_backlog = 4096
|
|
|
+net.ipv4.tcp_max_tw_buckets = 5000
|
|
|
+net.ipv4.tcp_fastopen = 3
|
|
|
+net.ipv4.tcp_rmem = 4096 87380 67108864
|
|
|
+net.ipv4.tcp_wmem = 4096 65536 67108864
|
|
|
+net.ipv4.tcp_mtu_probing = 1
|
|
|
+net.ipv4.tcp_ecn=1
|
|
|
+net.core.default_qdisc=fq
|
|
|
+net.ipv4.tcp_congestion_control = bbr" >>/etc/sysctl.d/local.conf && sysctl --system >/dev/null 2>&1
|
|
|
+ else
|
|
|
+ echo -e "$Error系统内核版本过低,无法支持 TCP Fast Open !"
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+check_installed_status(){
|
|
|
+ [[ ! -e ${SS_File} ]] && echo -e "${Error} Shadowsocks Rust 没有安装,请检查!" && exit 1
|
|
|
+}
|
|
|
+
|
|
|
+check_status(){
|
|
|
+ status=`systemctl status ss-rust | grep Active | awk '{print $3}' | cut -d "(" -f2 | cut -d ")" -f1`
|
|
|
+}
|
|
|
+
|
|
|
+check_new_ver(){
|
|
|
+ new_ver=$(wget -qO- https://api.github.com/repos/shadowsocks/shadowsocks-rust/releases| jq -r '[.[] | select(.prerelease == false) | select(.draft == false) | .tag_name] | .[0]')
|
|
|
+ [[ -z ${new_ver} ]] && echo -e "${Error} Shadowsocks Rust 最新版本获取失败!" && exit 1
|
|
|
+ echo -e "${Info} 检测到 Shadowsocks Rust 最新版本为 [ ${new_ver} ]"
|
|
|
+}
|
|
|
+
|
|
|
+check_ver_comparison(){
|
|
|
+ now_ver=$(cat ${SS_Now_ver_File})
|
|
|
+ if [[ "${now_ver}" != "${new_ver}" ]]; then
|
|
|
+ echo -e "${Info} 发现 Shadowsocks Rust 已有新版本 [ ${new_ver} ],旧版本 [ ${now_ver} ]"
|
|
|
+ read -e -p "是否更新 ? [Y/n]:" yn
|
|
|
+ [[ -z "${yn}" ]] && yn="y"
|
|
|
+ if [[ $yn == [Yy] ]]; then
|
|
|
+ check_status
|
|
|
+ # [[ "$status" == "running" ]] && systemctl stop ss-rust
|
|
|
+ \cp "${SS_Conf}" "/tmp/config.json"
|
|
|
+ # rm -rf ${SS_Folder}
|
|
|
+ download
|
|
|
+ mv -f "/tmp/config.json" "${SS_Conf}"
|
|
|
+ restart
|
|
|
+ fi
|
|
|
+ else
|
|
|
+ echo -e "${Info} 当前 Shadowsocks Rust 已是最新版本 [ ${new_ver} ] !" && exit 1
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+# 官方源
|
|
|
+stable_download() {
|
|
|
+ echo -e "${Info} 默认开始下载官方源 Shadowsocks Rust ……"
|
|
|
+ wget --no-check-certificate -N "https://github.com/shadowsocks/shadowsocks-rust/releases/download/${new_ver}/shadowsocks-${new_ver}.${arch}-unknown-linux-gnu.tar.xz"
|
|
|
+ if [[ ! -e "shadowsocks-${new_ver}.${arch}-unknown-linux-gnu.tar.xz" ]]; then
|
|
|
+ echo -e "${Error} Shadowsocks Rust 官方源下载失败!"
|
|
|
+ return 1 && exit 1
|
|
|
+ else
|
|
|
+ tar -xvf "shadowsocks-${new_ver}.${arch}-unknown-linux-gnu.tar.xz"
|
|
|
+ fi
|
|
|
+ if [[ ! -e "ssserver" ]]; then
|
|
|
+ echo -e "${Error} Shadowsocks Rust 解压失败!"
|
|
|
+ echo -e "${Error} Shadowsocks Rust 安装失败 !"
|
|
|
+ return 1 && exit 1
|
|
|
+ else
|
|
|
+ rm -rf "shadowsocks-${new_ver}.${arch}-unknown-linux-gnu.tar.xz"
|
|
|
+ chmod +x ssserver
|
|
|
+ mv -f ssserver "${SS_File}"
|
|
|
+ rm sslocal ssmanager ssservice ssurl
|
|
|
+ echo "${new_ver}" > ${SS_Now_ver_File}
|
|
|
+
|
|
|
+ echo -e "${Info} Shadowsocks Rust 主程序下载安装完毕!"
|
|
|
+ return 0
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+# 备用源
|
|
|
+backup_download() {
|
|
|
+ echo -e "${Info} 试图请求 备份源(旧版本) Shadowsocks Rust ……"
|
|
|
+ wget --no-check-certificate -N "https://raw.githubusercontent.com/xOS/Others/master/shadowsocks-rust/v1.14.1/shadowsocks-v1.14.1.${arch}-unknown-linux-gnu.tar.xz"
|
|
|
+ if [[ ! -e "shadowsocks-v1.14.1.${arch}-unknown-linux-gnu.tar.xz" ]]; then
|
|
|
+ echo -e "${Error} Shadowsocks Rust 备份源(旧版本) 下载失败!"
|
|
|
+ return 1 && exit 1
|
|
|
+ else
|
|
|
+ tar -xvf "shadowsocks-v1.14.1.${arch}-unknown-linux-gnu.tar.xz"
|
|
|
+ fi
|
|
|
+ if [[ ! -e "ssserver" ]]; then
|
|
|
+ echo -e "${Error} Shadowsocks Rust 备份源(旧版本) 解压失败 !"
|
|
|
+ echo -e "${Error} Shadowsocks Rust 备份源(旧版本) 安装失败 !"
|
|
|
+ return 1 && exit 1
|
|
|
+ else
|
|
|
+ rm -rf "shadowsocks-v1.14.1.${arch}-unknown-linux-gnu.tar.xz"
|
|
|
+ chmod +x ssserver
|
|
|
+ mv -f ssserver "${SS_File}"
|
|
|
+ rm sslocal ssmanager ssservice ssurl
|
|
|
+ echo "v1.14.1" > ${SS_Now_ver_File}
|
|
|
+ echo -e "${Info} Shadowsocks Rust 备份源(旧版本) 主程序下载安装完毕!"
|
|
|
+ return 0
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+download() {
|
|
|
+ if [[ ! -e "${SS_Folder}" ]]; then
|
|
|
+ mkdir "${SS_Folder}"
|
|
|
+ # else
|
|
|
+ # [[ -e "${SS_File}" ]] && rm -rf "${SS_File}"
|
|
|
+ fi
|
|
|
+ stable_download
|
|
|
+ if [[ $? != 0 ]]; then
|
|
|
+ backup_download
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+# Shadow TLS 官方源下载
|
|
|
+stable_download_stls() {
|
|
|
+ echo -e "${Info} 默认开始下载官方源 Shadow TLS ……"
|
|
|
+ wget --no-check-certificate -N "https://github.com/ihciah/shadow-tls/releases/download/${stls_new_ver}/shadow-tls-${arch}-unknown-linux-musl"
|
|
|
+ if [[ ! -e "shadow-tls-${arch}-unknown-linux-musl" ]]; then
|
|
|
+ echo -e "${Error} Shadow TLS 官方源下载失败!"
|
|
|
+ return 1 && exit 1
|
|
|
+ else
|
|
|
+ chmod +x "shadow-tls-${arch}-unknown-linux-musl"
|
|
|
+ mv -f "shadow-tls-${arch}-unknown-linux-musl" "${STLS_File}"
|
|
|
+ echo "${stls_new_ver}" > ${STLS_Now_ver_File}
|
|
|
+ echo -e "${Info} Shadow TLS 主程序下载安装完毕!"
|
|
|
+ return 0
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+download_stls() {
|
|
|
+ if [[ ! -e "${STLS_Folder}" ]]; then
|
|
|
+ mkdir "${STLS_Folder}"
|
|
|
+ fi
|
|
|
+ stable_download_stls
|
|
|
+}
|
|
|
+
|
|
|
+# Shadow TLS 配置相关函数
|
|
|
+set_stls_port(){
|
|
|
+ while true
|
|
|
+ do
|
|
|
+ echo -e "${Tip} Shadow TLS 端口需与防火墙端口一致!"
|
|
|
+ echo -e "请输入 Shadow TLS 端口 [1-65535]"
|
|
|
+ read -e -p "(默认:8443):" stls_port
|
|
|
+ [[ -z "${stls_port}" ]] && stls_port="8443"
|
|
|
+ echo $((${stls_port}+0)) &>/dev/null
|
|
|
+ if [[ $? -eq 0 ]]; then
|
|
|
+ if [[ ${stls_port} -ge 1 ]] && [[ ${stls_port} -le 65535 ]]; then
|
|
|
+ echo && echo "========================================"
|
|
|
+ echo -e "Shadow TLS 端口:${Red_background_prefix} ${stls_port} ${Font_color_suffix}"
|
|
|
+ echo "========================================" && echo
|
|
|
+ break
|
|
|
+ else
|
|
|
+ echo "输入错误, 请输入正确的端口。"
|
|
|
+ fi
|
|
|
+ else
|
|
|
+ echo "输入错误, 请输入正确的端口。"
|
|
|
+ fi
|
|
|
+ done
|
|
|
+}
|
|
|
+
|
|
|
+set_stls_password(){
|
|
|
+ echo "请输入 Shadow TLS 密码 [0-9][a-z][A-Z]"
|
|
|
+ read -e -p "(默认:随机生成):" stls_password
|
|
|
+ [[ -z "${stls_password}" ]] && stls_password=$(< /dev/urandom tr -dc 'a-zA-Z0-9' | head -c 16)
|
|
|
+ echo && echo "========================================"
|
|
|
+ echo -e "Shadow TLS 密码:${Red_background_prefix} ${stls_password} ${Font_color_suffix}"
|
|
|
+ echo "========================================" && echo
|
|
|
+}
|
|
|
+
|
|
|
+set_stls_sni(){
|
|
|
+ echo "请输入 Shadow TLS SNI 域名"
|
|
|
+ read -e -p "(默认:cloudflare.com):" stls_sni
|
|
|
+ [[ -z "${stls_sni}" ]] && stls_sni="cloudflare.com"
|
|
|
+ echo && echo "========================================"
|
|
|
+ echo -e "Shadow TLS SNI:${Red_background_prefix} ${stls_sni} ${Font_color_suffix}"
|
|
|
+ echo "========================================" && echo
|
|
|
+}
|
|
|
+
|
|
|
+set_stls_fastopen(){
|
|
|
+ echo -e "是否开启 Shadow TLS TCP Fast Open ?
|
|
|
+========================================
|
|
|
+${Green_font_prefix} 1.${Font_color_suffix} 开启 ${Green_font_prefix} 2.${Font_color_suffix} 关闭
|
|
|
+========================================"
|
|
|
+ read -e -p "(默认:1.开启):" stls_fastopen_choice
|
|
|
+ [[ -z "${stls_fastopen_choice}" ]] && stls_fastopen_choice="1"
|
|
|
+ if [[ ${stls_fastopen_choice} == "1" ]]; then
|
|
|
+ stls_fastopen="true"
|
|
|
+ else
|
|
|
+ stls_fastopen="false"
|
|
|
+ fi
|
|
|
+ echo && echo "========================================"
|
|
|
+ echo -e "Shadow TLS FastOpen:${Red_background_prefix} ${stls_fastopen} ${Font_color_suffix}"
|
|
|
+ echo "========================================" && echo
|
|
|
+}
|
|
|
+
|
|
|
+set_stls_strict(){
|
|
|
+ echo -e "是否开启 Shadow TLS Strict 模式 ?
|
|
|
+========================================
|
|
|
+${Green_font_prefix} 1.${Font_color_suffix} 开启 ${Green_font_prefix} 2.${Font_color_suffix} 关闭
|
|
|
+========================================"
|
|
|
+ read -e -p "(默认:1.开启):" stls_strict_choice
|
|
|
+ [[ -z "${stls_strict_choice}" ]] && stls_strict_choice="1"
|
|
|
+ if [[ ${stls_strict_choice} == "1" ]]; then
|
|
|
+ stls_strict="true"
|
|
|
+ else
|
|
|
+ stls_strict="false"
|
|
|
+ fi
|
|
|
+ echo && echo "========================================"
|
|
|
+ echo -e "Shadow TLS Strict:${Red_background_prefix} ${stls_strict} ${Font_color_suffix}"
|
|
|
+ echo "========================================" && echo
|
|
|
+}
|
|
|
+
|
|
|
+set_stls_tls_wildcard_sni(){
|
|
|
+ echo -e "请选择 Shadow TLS Wildcard SNI 模式:
|
|
|
+========================================
|
|
|
+${Green_font_prefix} 1.${Font_color_suffix} authed (默认)
|
|
|
+${Green_font_prefix} 2.${Font_color_suffix} off
|
|
|
+${Green_font_prefix} 3.${Font_color_suffix} all
|
|
|
+========================================"
|
|
|
+ read -e -p "(默认:1.authed):" stls_tls_wildcard_sni_choice
|
|
|
+ [[ -z "${stls_tls_wildcard_sni_choice}" ]] && stls_tls_wildcard_sni_choice="1"
|
|
|
+ case "${stls_tls_wildcard_sni_choice}" in
|
|
|
+ 1) stls_tls_wildcard_sni="authed" ;;
|
|
|
+ 2) stls_tls_wildcard_sni="off" ;;
|
|
|
+ 3) stls_tls_wildcard_sni="all" ;;
|
|
|
+ *) stls_tls_wildcard_sni="authed" ;;
|
|
|
+ esac
|
|
|
+ echo && echo "========================================"
|
|
|
+ echo -e "TLS Wildcard SNI:${Red_background_prefix} ${stls_tls_wildcard_sni} ${Font_color_suffix}"
|
|
|
+ echo "========================================" && echo
|
|
|
+}
|
|
|
+
|
|
|
+set_stls_fallback(){
|
|
|
+ echo "请输入 Shadow TLS 回退域名"
|
|
|
+ read -e -p "(默认:cloud.tencent.com:443):" stls_fallback
|
|
|
+ [[ -z "${stls_fallback}" ]] && stls_fallback="cloud.tencent.com:443"
|
|
|
+ echo && echo "========================================"
|
|
|
+ echo -e "Shadow TLS 回退域名:${Red_background_prefix} ${stls_fallback} ${Font_color_suffix}"
|
|
|
+ echo "========================================" && echo
|
|
|
+}
|
|
|
+
|
|
|
+service(){
|
|
|
+ echo "
|
|
|
+[Unit]
|
|
|
+Description= Shadowsocks Rust Service
|
|
|
+After=network-online.target
|
|
|
+Wants=network-online.target systemd-networkd-wait-online.service
|
|
|
+[Service]
|
|
|
+LimitNOFILE=32767
|
|
|
+Type=simple
|
|
|
+User=root
|
|
|
+Restart=on-failure
|
|
|
+RestartSec=5s
|
|
|
+DynamicUser=true
|
|
|
+ExecStartPre=/bin/sh -c 'ulimit -n 51200'
|
|
|
+ExecStart=${SS_File} -c ${SS_Conf}
|
|
|
+[Install]
|
|
|
+WantedBy=multi-user.target" > /etc/systemd/system/ss-rust.service
|
|
|
+systemctl enable --now ss-rust
|
|
|
+ echo -e "${Info} Shadowsocks Rust 服务配置完成!"
|
|
|
+}
|
|
|
+
|
|
|
+service_stls(){
|
|
|
+ cat > /etc/systemd/system/shadowtls.service<<-EOF
|
|
|
+[Unit]
|
|
|
+Description=Shadow TLS Service
|
|
|
+After=network-online.target
|
|
|
+Wants=network-online.target systemd-networkd-wait-online.service
|
|
|
+
|
|
|
+[Service]
|
|
|
+LimitNOFILE=32767
|
|
|
+Type=simple
|
|
|
+User=root
|
|
|
+Restart=on-failure
|
|
|
+RestartSec=5s
|
|
|
+Environment=MONOIO_FORCE_LEGACY_DRIVER=1
|
|
|
+ExecStartPre=/bin/sh -c 'ulimit -n 51200'
|
|
|
+ExecStart=${STLS_File} config --config ${STLS_Conf}
|
|
|
+
|
|
|
+[Install]
|
|
|
+WantedBy=multi-user.target
|
|
|
+EOF
|
|
|
+ systemctl enable --now shadowtls
|
|
|
+ echo -e "${Info} Shadow TLS 服务配置完成!"
|
|
|
+}
|
|
|
+
|
|
|
+installation_dependency(){
|
|
|
+ if [[ ${release} == "centos" ]]; then
|
|
|
+ yum update
|
|
|
+ yum install jq gzip wget curl unzip xz openssl -y
|
|
|
+ else
|
|
|
+ apt-get update
|
|
|
+ apt-get install jq gzip wget curl unzip xz-utils openssl -y
|
|
|
+ fi
|
|
|
+ \cp -f /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
|
|
|
+}
|
|
|
+
|
|
|
+write_config(){
|
|
|
+ cat > ${SS_Conf}<<-EOF
|
|
|
+{
|
|
|
+ "server": "::",
|
|
|
+ "server_port": ${port},
|
|
|
+ "password": "${password}",
|
|
|
+ "method": "${cipher}",
|
|
|
+ "fast_open": ${tfo},
|
|
|
+ "mode": "tcp_and_udp",
|
|
|
+ "user":"nobody",
|
|
|
+ "timeout":300,
|
|
|
+ "nameserver":"1.1.1.1"
|
|
|
+}
|
|
|
+EOF
|
|
|
+}
|
|
|
+
|
|
|
+write_stls_config(){
|
|
|
+ # 设置默认值
|
|
|
+ [[ -z "${stls_fastopen}" ]] && stls_fastopen="true"
|
|
|
+ [[ -z "${stls_strict}" ]] && stls_strict="true"
|
|
|
+ [[ -z "${stls_tls_wildcard_sni}" ]] && stls_tls_wildcard_sni="authed"
|
|
|
+ [[ -z "${stls_fallback}" ]] && stls_fallback="cloud.tencent.com:443"
|
|
|
+
|
|
|
+ # 构建 dispatch 配置
|
|
|
+ if [[ -z "${stls_dispatch}" ]]; then
|
|
|
+ # 没有现有配置,使用默认配置
|
|
|
+ # SNI 域名对应的目标地址也使用相同的域名:443
|
|
|
+ stls_dispatch_config="\"${stls_sni}\": \"${stls_sni}:443\",
|
|
|
+ \"captive.apple.com\": \"captive.apple.com:443\""
|
|
|
+ else
|
|
|
+ # 有现有配置,需要智能更新 SNI
|
|
|
+ if [[ ! -z "${stls_sni}" && -e ${STLS_Conf} ]]; then
|
|
|
+ # 查找需要更新的 SNI(排除 captive.apple.com)
|
|
|
+ old_sni=$(cat ${STLS_Conf}|jq -r '.server.tls_addr.dispatch | keys[] | select(. != "captive.apple.com")' 2>/dev/null | head -1)
|
|
|
+ if [[ ! -z "${old_sni}" && "${old_sni}" != "null" && "${old_sni}" != "${stls_sni}" ]]; then
|
|
|
+ # 需要替换旧的 SNI 为新的 SNI,同时更新键和值
|
|
|
+ echo -e "${Info} 更新主要 SNI 从 ${old_sni} 到 ${stls_sni}"
|
|
|
+
|
|
|
+ # 使用 jq 来精确替换键和值
|
|
|
+ stls_dispatch_config=$(cat ${STLS_Conf} | jq -r --arg old_sni "${old_sni}" --arg new_sni "${stls_sni}" '
|
|
|
+ .server.tls_addr.dispatch |
|
|
|
+ to_entries |
|
|
|
+ map(if .key == $old_sni then (.key = $new_sni | .value = ($new_sni + ":443")) else . end) |
|
|
|
+ map("\"\(.key)\": \"\(.value)\"") |
|
|
|
+ join(",\n ")
|
|
|
+ ' 2>/dev/null)
|
|
|
+
|
|
|
+ # 如果 jq 处理失败,回退到字符串替换
|
|
|
+ if [[ -z "${stls_dispatch_config}" || "${stls_dispatch_config}" == "null" ]]; then
|
|
|
+ echo -e "${Info} jq 处理失败,使用字符串替换"
|
|
|
+ # 先替换键,再替换对应的值
|
|
|
+ stls_dispatch_config=$(echo "${stls_dispatch}" | sed "s/\"${old_sni}\": \"[^\"]*\"/\"${stls_sni}\": \"${stls_sni}:443\"/g")
|
|
|
+ fi
|
|
|
+ else
|
|
|
+ # 如果没有找到需要更新的 SNI,或者 SNI 已经是正确的,直接使用现有配置
|
|
|
+ stls_dispatch_config="${stls_dispatch}"
|
|
|
+ fi
|
|
|
+ else
|
|
|
+ stls_dispatch_config="${stls_dispatch}"
|
|
|
+ fi
|
|
|
+ fi
|
|
|
+
|
|
|
+ # 调试信息(可选,用于排查问题)
|
|
|
+ # echo -e "${Info} 调试信息:"
|
|
|
+ # echo -e " stls_sni: ${stls_sni}"
|
|
|
+ # echo -e " stls_dispatch_config: ${stls_dispatch_config}"
|
|
|
+
|
|
|
+ cat > ${STLS_Conf}<<-EOF
|
|
|
+{
|
|
|
+ "disable_nodelay": false,
|
|
|
+ "fastopen": ${stls_fastopen},
|
|
|
+ "v3": true,
|
|
|
+ "strict": ${stls_strict},
|
|
|
+ "server": {
|
|
|
+ "listen": "0.0.0.0:${stls_port}",
|
|
|
+ "server_addr": "127.0.0.1:${port}",
|
|
|
+ "tls_addr": {
|
|
|
+ "wildcard_sni": "${stls_tls_wildcard_sni}",
|
|
|
+ "dispatch": {
|
|
|
+ ${stls_dispatch_config}
|
|
|
+ },
|
|
|
+ "fallback": "${stls_fallback}"
|
|
|
+ },
|
|
|
+ "password": "${stls_password}",
|
|
|
+ "wildcard_sni": "authed"
|
|
|
+ }
|
|
|
+}
|
|
|
+EOF
|
|
|
+
|
|
|
+ # 验证配置文件是否正确生成
|
|
|
+ if [[ -e ${STLS_Conf} ]]; then
|
|
|
+ # 检查配置文件是否为有效的 JSON
|
|
|
+ if ! jq . ${STLS_Conf} >/dev/null 2>&1; then
|
|
|
+ echo -e "${Error} Shadow TLS 配置文件格式错误!"
|
|
|
+ return 1
|
|
|
+ fi
|
|
|
+ echo -e "${Info} Shadow TLS 配置文件写入成功"
|
|
|
+
|
|
|
+ # 显示当前配置的 SNI
|
|
|
+ current_sni=$(cat ${STLS_Conf}|jq -r '.server.tls_addr.dispatch | keys[0]' 2>/dev/null)
|
|
|
+ if [[ ! -z "${current_sni}" && "${current_sni}" != "null" ]]; then
|
|
|
+ echo -e "${Info} 当前配置的 SNI: ${Green_font_prefix}${current_sni}${Font_color_suffix}"
|
|
|
+ fi
|
|
|
+ else
|
|
|
+ echo -e "${Error} Shadow TLS 配置文件写入失败!"
|
|
|
+ return 1
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+read_config(){
|
|
|
+ [[ ! -e ${SS_Conf} ]] && echo -e "${Error} Shadowsocks Rust 配置文件不存在!" && exit 1
|
|
|
+ port=$(cat ${SS_Conf}|jq -r '.server_port')
|
|
|
+ password=$(cat ${SS_Conf}|jq -r '.password')
|
|
|
+ cipher=$(cat ${SS_Conf}|jq -r '.method')
|
|
|
+ tfo=$(cat ${SS_Conf}|jq -r '.fast_open')
|
|
|
+}
|
|
|
+
|
|
|
+read_stls_config(){
|
|
|
+ [[ ! -e ${STLS_Conf} ]] && echo -e "${Error} Shadow TLS 配置文件不存在!" && exit 1
|
|
|
+ stls_port=$(cat ${STLS_Conf}|jq -r '.server.listen' | grep -oE '[0-9]+$')
|
|
|
+ stls_password=$(cat ${STLS_Conf}|jq -r '.server.password')
|
|
|
+ stls_sni=$(cat ${STLS_Conf}|jq -r '.server.tls_addr.dispatch | keys[0]')
|
|
|
+ stls_fastopen=$(cat ${STLS_Conf}|jq -r '.fastopen')
|
|
|
+ stls_strict=$(cat ${STLS_Conf}|jq -r '.strict')
|
|
|
+ stls_tls_wildcard_sni=$(cat ${STLS_Conf}|jq -r '.server.tls_addr.wildcard_sni')
|
|
|
+ stls_fallback=$(cat ${STLS_Conf}|jq -r '.server.tls_addr.fallback')
|
|
|
+ # 读取完整的 dispatch 配置
|
|
|
+ stls_dispatch=$(cat ${STLS_Conf}|jq -r '.server.tls_addr.dispatch | to_entries | map("\"\(.key)\": \"\(.value)\"") | join(",\n ")')
|
|
|
+}
|
|
|
+
|
|
|
+set_port(){
|
|
|
+ while true
|
|
|
+ do
|
|
|
+ echo -e "${Tip} 本步骤不涉及系统防火墙端口操作,请手动放行相应端口!"
|
|
|
+ echo -e "请输入 Shadowsocks Rust 端口 [1-65535]"
|
|
|
+ read -e -p "(默认:2525):" port
|
|
|
+ [[ -z "${port}" ]] && port="2525"
|
|
|
+ echo $((${port}+0)) &>/dev/null
|
|
|
+ if [[ $? -eq 0 ]]; then
|
|
|
+ if [[ ${port} -ge 1 ]] && [[ ${port} -le 65535 ]]; then
|
|
|
+ echo && echo "========================================"
|
|
|
+ echo -e "端口:${Red_background_prefix} ${port} ${Font_color_suffix}"
|
|
|
+ echo "========================================" && echo
|
|
|
+ break
|
|
|
+ else
|
|
|
+ echo "输入错误, 请输入正确的端口。"
|
|
|
+ fi
|
|
|
+ else
|
|
|
+ echo "输入错误, 请输入正确的端口。"
|
|
|
+ fi
|
|
|
+ done
|
|
|
+}
|
|
|
+
|
|
|
+set_tfo(){
|
|
|
+ echo -e "是否开启 TCP Fast Open ?
|
|
|
+========================================
|
|
|
+${Green_font_prefix} 1.${Font_color_suffix} 开启 ${Green_font_prefix} 2.${Font_color_suffix} 关闭
|
|
|
+========================================"
|
|
|
+ read -e -p "(默认:1.开启):" tfo
|
|
|
+ [[ -z "${tfo}" ]] && tfo="1"
|
|
|
+ if [[ ${tfo} == "1" ]]; then
|
|
|
+ tfo=true
|
|
|
+ enable_systfo
|
|
|
+ else
|
|
|
+ tfo=false
|
|
|
+ fi
|
|
|
+ echo && echo "=================================="
|
|
|
+ echo -e "TCP Fast Open 开启状态:${Red_background_prefix} ${tfo} ${Font_color_suffix}"
|
|
|
+ echo "==================================" && echo
|
|
|
+}
|
|
|
+
|
|
|
+set_password(){
|
|
|
+ echo "请输入 Shadowsocks Rust 密码 [0-9][a-z][A-Z]"
|
|
|
+ read -e -p "(默认:随机生成):" password
|
|
|
+ # 当用户未输入密码时,执行默认生成逻辑
|
|
|
+ if [[ -z "${password}" ]]; then
|
|
|
+ # 判断是否为2022系列加密
|
|
|
+ if [[ ${cipher} == "2022-blake3-aes-256-gcm" || ${cipher} == "2022-blake3-chacha20-poly1305" ]]; then
|
|
|
+ # 2022系列必须使用指定长度的Base64密钥
|
|
|
+ echo -e "${Tip} 为 ${cipher} 生成 32 字节 Base64 密钥..."
|
|
|
+ password=$(openssl rand -base64 32)
|
|
|
+ elif [[ ${cipher} == "2022-blake3-aes-128-gcm" ]]; then
|
|
|
+ # 2022系列必须使用指定长度的Base64密钥
|
|
|
+ echo -e "${Tip} 为 ${cipher} 生成 16 字节 Base64 密钥..."
|
|
|
+ password=$(openssl rand -base64 16)
|
|
|
+ else
|
|
|
+ # 其他加密方式,生成一个普通的16位字母和数字的随机密码
|
|
|
+ echo -e "${Tip} 为 ${cipher} 生成 16 位随机密码 (非Base64)..."
|
|
|
+ password=$(< /dev/urandom tr -dc 'a-zA-Z0-9' | head -c 16)
|
|
|
+ fi
|
|
|
+ fi
|
|
|
+ echo && echo "========================================"
|
|
|
+ echo -e "密码:${Red_font_prefix} ${password} ${Font_color_suffix}"
|
|
|
+ echo "========================================" && echo
|
|
|
+}
|
|
|
+
|
|
|
+set_cipher(){
|
|
|
+ echo -e "请选择 Shadowsocks Rust 加密方式
|
|
|
+========================================
|
|
|
+ ${Green_font_prefix} 1.${Font_color_suffix} aes-128-gcm ${Green_font_prefix}(默认)${Font_color_suffix}
|
|
|
+ ${Green_font_prefix} 2.${Font_color_suffix} aes-256-gcm ${Green_font_prefix}(推荐)${Font_color_suffix}
|
|
|
+ ${Green_font_prefix} 3.${Font_color_suffix} chacha20-ietf-poly1305 ${Green_font_prefix}${Font_color_suffix}
|
|
|
+ ${Green_font_prefix} 4.${Font_color_suffix} plain ${Red_font_prefix}(不推荐)${Font_color_suffix}
|
|
|
+ ${Green_font_prefix} 5.${Font_color_suffix} none ${Red_font_prefix}(不推荐)${Font_color_suffix}
|
|
|
+ ${Green_font_prefix} 6.${Font_color_suffix} table
|
|
|
+ ${Green_font_prefix} 7.${Font_color_suffix} aes-128-cfb
|
|
|
+ ${Green_font_prefix} 8.${Font_color_suffix} aes-256-cfb
|
|
|
+ ${Green_font_prefix} 9.${Font_color_suffix} aes-256-ctr
|
|
|
+ ${Green_font_prefix}10.${Font_color_suffix} camellia-256-cfb
|
|
|
+ ${Green_font_prefix}11.${Font_color_suffix} rc4-md5
|
|
|
+ ${Green_font_prefix}12.${Font_color_suffix} chacha20-ietf
|
|
|
+========================================
|
|
|
+ ${Tip} AEAD 2022 加密(须v1.15.0及以上版本且密码须经过Base64加密)
|
|
|
+========================================
|
|
|
+ ${Green_font_prefix}13.${Font_color_suffix} 2022-blake3-aes-128-gcm ${Green_font_prefix}(推荐)${Font_color_suffix}
|
|
|
+ ${Green_font_prefix}14.${Font_color_suffix} 2022-blake3-aes-256-gcm ${Green_font_prefix}(推荐)${Font_color_suffix}
|
|
|
+ ${Green_font_prefix}15.${Font_color_suffix} 2022-blake3-chacha20-poly1305
|
|
|
+ ========================================
|
|
|
+ ${Tip} 如需其它加密方式请手动修改配置文件 !" && echo
|
|
|
+ read -e -p "(默认: 1. aes-128-gcm):" cipher
|
|
|
+ [[ -z "${cipher}" ]] && cipher="1"
|
|
|
+ if [[ ${cipher} == "1" ]]; then
|
|
|
+ cipher="aes-128-gcm"
|
|
|
+ elif [[ ${cipher} == "2" ]]; then
|
|
|
+ cipher="aes-256-gcm"
|
|
|
+ elif [[ ${cipher} == "3" ]]; then
|
|
|
+ cipher="chacha20-ietf-poly1305"
|
|
|
+ elif [[ ${cipher} == "4" ]]; then
|
|
|
+ cipher="plain"
|
|
|
+ elif [[ ${cipher} == "5" ]]; then
|
|
|
+ cipher="none"
|
|
|
+ elif [[ ${cipher} == "6" ]]; then
|
|
|
+ cipher="table"
|
|
|
+ elif [[ ${cipher} == "7" ]]; then
|
|
|
+ cipher="aes-128-cfb"
|
|
|
+ elif [[ ${cipher} == "8" ]]; then
|
|
|
+ cipher="aes-256-cfb"
|
|
|
+ elif [[ ${cipher} == "9" ]]; then
|
|
|
+ cipher="aes-256-ctr"
|
|
|
+ elif [[ ${cipher} == "10" ]]; then
|
|
|
+ cipher="camellia-256-cfb"
|
|
|
+ elif [[ ${cipher} == "11" ]]; then
|
|
|
+ cipher="arc4-md5"
|
|
|
+ elif [[ ${cipher} == "12" ]]; then
|
|
|
+ cipher="chacha20-ietf"
|
|
|
+ elif [[ ${cipher} == "13" ]]; then
|
|
|
+ cipher="2022-blake3-aes-128-gcm"
|
|
|
+ elif [[ ${cipher} == "14" ]]; then
|
|
|
+ cipher="2022-blake3-aes-256-gcm"
|
|
|
+ elif [[ ${cipher} == "15" ]]; then
|
|
|
+ cipher="2022-blake3-chacha20-poly1305"
|
|
|
+ else
|
|
|
+ cipher="aes-128-gcm"
|
|
|
+ fi
|
|
|
+ echo && echo "========================================"
|
|
|
+ echo -e "加密:${Red_background_prefix} ${cipher} ${Font_color_suffix}"
|
|
|
+ echo "========================================" && echo
|
|
|
+}
|
|
|
+
|
|
|
+set_config(){
|
|
|
+ check_installed_status
|
|
|
+ echo && echo -e "你要做什么?
|
|
|
+========================================
|
|
|
+ ${Green_font_prefix}1.${Font_color_suffix} 修改 端口配置
|
|
|
+ ${Green_font_prefix}2.${Font_color_suffix} 修改 加密配置
|
|
|
+ ${Green_font_prefix}3.${Font_color_suffix} 修改 密码配置
|
|
|
+ ${Green_font_prefix}4.${Font_color_suffix} 修改 TFO 配置
|
|
|
+========================================
|
|
|
+ ${Green_font_prefix}5.${Font_color_suffix} 修改 全部配置" && echo
|
|
|
+ read -e -p "(默认:取消):" modify
|
|
|
+ [[ -z "${modify}" ]] && echo "已取消..." && exit 1
|
|
|
+ if [[ "${modify}" == "1" ]]; then
|
|
|
+ read_config
|
|
|
+ set_port
|
|
|
+ cipher=${cipher}
|
|
|
+ password=${password}
|
|
|
+ tfo=${tfo}
|
|
|
+ write_config
|
|
|
+ restart
|
|
|
+ elif [[ "${modify}" == "2" ]]; then
|
|
|
+ read_config
|
|
|
+ set_cipher
|
|
|
+ port=${port}
|
|
|
+ password=${password}
|
|
|
+ tfo=${tfo}
|
|
|
+ write_config
|
|
|
+ restart
|
|
|
+ elif [[ "${modify}" == "3" ]]; then
|
|
|
+ read_config
|
|
|
+ cipher=${cipher}
|
|
|
+ set_password
|
|
|
+ port=${port}
|
|
|
+ tfo=${tfo}
|
|
|
+ write_config
|
|
|
+ restart
|
|
|
+ elif [[ "${modify}" == "4" ]]; then
|
|
|
+ read_config
|
|
|
+ set_tfo
|
|
|
+ cipher=${cipher}
|
|
|
+ port=${port}
|
|
|
+ password=${password}
|
|
|
+ write_config
|
|
|
+ restart
|
|
|
+ elif [[ "${modify}" == "5" ]]; then
|
|
|
+ read_config
|
|
|
+ set_port
|
|
|
+ set_cipher
|
|
|
+ set_password
|
|
|
+ set_tfo
|
|
|
+ write_config
|
|
|
+ restart
|
|
|
+ else
|
|
|
+ echo -e "${Error} 请输入正确的数字(1-5)" && exit 1
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+install(){
|
|
|
+ [[ -e ${SS_File} ]] && echo -e "${Error} 检测到 Shadowsocks Rust 已安装!" && exit 1
|
|
|
+ echo -e "${Info} 开始设置 配置..."
|
|
|
+ set_port
|
|
|
+ set_cipher
|
|
|
+ set_password
|
|
|
+ set_tfo
|
|
|
+ echo -e "${Info} 开始安装/配置 依赖..."
|
|
|
+ installation_dependency
|
|
|
+ echo -e "${Info} 开始下载/安装..."
|
|
|
+ check_new_ver
|
|
|
+ download
|
|
|
+ echo -e "${Info} 开始安装系统服务脚本..."
|
|
|
+ service
|
|
|
+ echo -e "${Info} 开始写入 配置文件..."
|
|
|
+ write_config
|
|
|
+ echo -e "${Info} 所有步骤 安装完毕,开始启动..."
|
|
|
+ start
|
|
|
+ echo -e "${Info} Shadowsocks Rust 安装完成!"
|
|
|
+
|
|
|
+ # 询问是否继续安装 Shadow TLS
|
|
|
+ echo && echo -e "${Tip} 是否继续安装 Shadow TLS 流量伪装?"
|
|
|
+ read -e -p "(默认: N 不安装) [y/N]: " install_stls_choice
|
|
|
+ [[ -z "${install_stls_choice}" ]] && install_stls_choice="n"
|
|
|
+
|
|
|
+ if [[ ${install_stls_choice} == [Yy] ]]; then
|
|
|
+ echo -e "${Info} 开始安装 Shadow TLS..."
|
|
|
+ install_stls_after_ss
|
|
|
+ else
|
|
|
+ echo -e "${Info} 跳过 Shadow TLS 安装,显示 Shadowsocks Rust 配置..."
|
|
|
+ view_ss_only
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+install_stls(){
|
|
|
+ [[ -e ${STLS_File} ]] && echo -e "${Error} 检测到 Shadow TLS 已安装!" && exit 1
|
|
|
+
|
|
|
+ # 检查 Shadowsocks Rust 是否已安装
|
|
|
+ if [[ ! -e ${SS_File} ]]; then
|
|
|
+ echo -e "${Error} 检测到 Shadowsocks Rust 尚未安装!"
|
|
|
+ echo -e "${Info} Shadow TLS 需要配合 Shadowsocks Rust 使用。"
|
|
|
+ echo -e "${Info} 建议先安装 Shadowsocks Rust,再安装 Shadow TLS。"
|
|
|
+ echo && read -e -p "是否现在安装 Shadowsocks Rust?[Y/n]:" install_ss_choice
|
|
|
+ [[ -z "${install_ss_choice}" ]] && install_ss_choice="Y"
|
|
|
+ if [[ ${install_ss_choice} == [Yy] ]]; then
|
|
|
+ echo -e "${Info} 开始安装 Shadowsocks Rust..."
|
|
|
+ install
|
|
|
+ echo -e "${Info} Shadowsocks Rust 安装完成,现在开始安装 Shadow TLS..."
|
|
|
+ else
|
|
|
+ echo -e "${Info} 已取消安装,返回上级菜单..."
|
|
|
+ shadowtls_menu
|
|
|
+ return
|
|
|
+ fi
|
|
|
+ fi
|
|
|
+
|
|
|
+ echo -e "${Info} 开始设置 Shadow TLS 配置..."
|
|
|
+ read_config # 读取现有 SS 配置
|
|
|
+
|
|
|
+ # 使用交互式配置,每项都有默认值
|
|
|
+ echo -e "${Info} 请配置 Shadow TLS 参数(可直接回车使用默认值):"
|
|
|
+
|
|
|
+ set_stls_port
|
|
|
+ set_stls_password
|
|
|
+ set_stls_sni
|
|
|
+ set_stls_fastopen
|
|
|
+ set_stls_strict
|
|
|
+ set_stls_tls_wildcard_sni
|
|
|
+ set_stls_fallback
|
|
|
+ manage_stls_dispatch
|
|
|
+
|
|
|
+ echo -e "${Info} 开始下载/安装 Shadow TLS..."
|
|
|
+ check_stls_new_ver
|
|
|
+ download_stls
|
|
|
+ echo -e "${Info} 开始安装 Shadow TLS 服务脚本..."
|
|
|
+ service_stls
|
|
|
+ echo -e "${Info} 开始写入 Shadow TLS 配置文件..."
|
|
|
+ write_stls_config
|
|
|
+ echo -e "${Info} Shadow TLS 安装完毕,开始启动..."
|
|
|
+ start_stls
|
|
|
+ echo -e "${Info} Shadow TLS 安装完成!显示完整配置信息..."
|
|
|
+ view_combined_config_with_return
|
|
|
+}
|
|
|
+
|
|
|
+install_stls_after_ss(){
|
|
|
+ echo -e "${Info} 开始设置 Shadow TLS 配置..."
|
|
|
+ read_config # 读取现有 SS 配置
|
|
|
+
|
|
|
+ # 使用交互式配置,每项都有默认值
|
|
|
+ echo -e "${Info} 请配置 Shadow TLS 参数(可直接回车使用默认值):"
|
|
|
+
|
|
|
+ set_stls_port
|
|
|
+ set_stls_password
|
|
|
+ set_stls_sni
|
|
|
+ set_stls_fastopen
|
|
|
+ set_stls_strict
|
|
|
+ set_stls_tls_wildcard_sni
|
|
|
+ set_stls_fallback
|
|
|
+ manage_stls_dispatch
|
|
|
+
|
|
|
+ echo -e "${Info} 开始下载/安装 Shadow TLS..."
|
|
|
+ check_stls_new_ver
|
|
|
+ download_stls
|
|
|
+ echo -e "${Info} 开始安装 Shadow TLS 服务脚本..."
|
|
|
+ service_stls
|
|
|
+ echo -e "${Info} 开始写入 Shadow TLS 配置文件..."
|
|
|
+ write_stls_config
|
|
|
+ echo -e "${Info} Shadow TLS 安装完毕,开始启动..."
|
|
|
+ start_stls
|
|
|
+ echo -e "${Info} Shadow TLS 安装完成!显示完整配置信息..."
|
|
|
+ view_combined_config_with_return
|
|
|
+}
|
|
|
+
|
|
|
+view(){
|
|
|
+ check_installed_status
|
|
|
+ read_config
|
|
|
+ getipv4
|
|
|
+ getipv6
|
|
|
+ link_qr
|
|
|
+ clear && echo
|
|
|
+ echo -e "Shadowsocks Rust 配置:"
|
|
|
+ echo -e "————————————————————————————————————————"
|
|
|
+ [[ "${ipv4}" != "IPv4_Error" ]] && echo -e " 地址:${Green_font_prefix}${ipv4}${Font_color_suffix}"
|
|
|
+ [[ "${ipv6}" != "IPv6_Error" ]] && echo -e " 地址:${Green_font_prefix}${ipv6}${Font_color_suffix}"
|
|
|
+ echo -e " 端口:${Green_font_prefix}${port}${Font_color_suffix}"
|
|
|
+ echo -e " 密码:${Green_font_prefix}${password}${Font_color_suffix}"
|
|
|
+ echo -e " 加密:${Green_font_prefix}${cipher}${Font_color_suffix}"
|
|
|
+ echo -e " TFO :${Green_font_prefix}${tfo}${Font_color_suffix}"
|
|
|
+ echo -e "————————————————————————————————————————"
|
|
|
+ [[ ! -z "${link_ipv4}" ]] && echo -e "${link_ipv4}"
|
|
|
+ [[ ! -z "${link_ipv6}" ]] && echo -e "${link_ipv6}"
|
|
|
+ echo -e "—————————————————————————"
|
|
|
+ echo -e "${Info} Surge 配置:"
|
|
|
+ if [[ "${ipv4}" != "IPv4_Error" ]]; then
|
|
|
+ echo -e "$(uname -n) = ss, ${ipv4},${port}, encrypt-method=${cipher}, password=${password}, tfo=${tfo}, udp-relay=true, ecn=true"
|
|
|
+ else
|
|
|
+ echo -e "$(uname -n) = ss, ${ipv6},${port}, encrypt-method=${cipher}, password=${password}, tfo=${tfo}, udp-relay=true, ecn=true"
|
|
|
+ fi
|
|
|
+ echo -e "—————————————————————————"
|
|
|
+ echo && echo -n " 按回车键返回主菜单..." && read
|
|
|
+ start_menu
|
|
|
+}
|
|
|
+
|
|
|
+view_ss_only(){
|
|
|
+ check_installed_status
|
|
|
+ read_config
|
|
|
+ getipv4
|
|
|
+ getipv6
|
|
|
+ link_qr
|
|
|
+ clear && echo
|
|
|
+ echo -e "Shadowsocks Rust 配置:"
|
|
|
+ echo -e "————————————————————————————————————————"
|
|
|
+ [[ "${ipv4}" != "IPv4_Error" ]] && echo -e " 地址:${Green_font_prefix}${ipv4}${Font_color_suffix}"
|
|
|
+ [[ "${ipv6}" != "IPv6_Error" ]] && echo -e " 地址:${Green_font_prefix}${ipv6}${Font_color_suffix}"
|
|
|
+ echo -e " 端口:${Green_font_prefix}${port}${Font_color_suffix}"
|
|
|
+ echo -e " 密码:${Green_font_prefix}${password}${Font_color_suffix}"
|
|
|
+ echo -e " 加密:${Green_font_prefix}${cipher}${Font_color_suffix}"
|
|
|
+ echo -e " TFO :${Green_font_prefix}${tfo}${Font_color_suffix}"
|
|
|
+ echo -e "————————————————————————————————————————"
|
|
|
+ [[ ! -z "${link_ipv4}" ]] && echo -e "${link_ipv4}"
|
|
|
+ [[ ! -z "${link_ipv6}" ]] && echo -e "${link_ipv6}"
|
|
|
+ echo -e "—————————————————————————"
|
|
|
+ echo -e "${Info} Surge 配置:"
|
|
|
+ if [[ "${ipv4}" != "IPv4_Error" ]]; then
|
|
|
+ echo -e "$(uname -n) = ss, ${ipv4},${port}, encrypt-method=${cipher}, password=${password}, tfo=${tfo}, udp-relay=true, ecn=true"
|
|
|
+ else
|
|
|
+ echo -e "$(uname -n) = ss, ${ipv6},${port}, encrypt-method=${cipher}, password=${password}, tfo=${tfo}, udp-relay=true, ecn=true"
|
|
|
+ fi
|
|
|
+ echo -e "—————————————————————————"
|
|
|
+ echo && echo -n " 按回车键返回主菜单..." && read
|
|
|
+ start_menu
|
|
|
+}
|
|
|
+
|
|
|
+view_combined_config(){
|
|
|
+ local menu_source="$1" # 接收调用来源参数
|
|
|
+ check_installed_status
|
|
|
+ read_config
|
|
|
+ getipv4
|
|
|
+ getipv6
|
|
|
+ link_qr
|
|
|
+ clear && echo
|
|
|
+
|
|
|
+ echo -e "完整配置信息:"
|
|
|
+ echo -e "========================================"
|
|
|
+
|
|
|
+ # 显示 Shadow TLS + SS 配置
|
|
|
+ if [[ -e ${STLS_File} ]]; then
|
|
|
+ read_stls_config
|
|
|
+ echo -e "${Info} Shadow TLS + Shadowsocks Rust 配置:"
|
|
|
+ echo -e "————————————————————————————————————————"
|
|
|
+ [[ "${ipv4}" != "IPv4_Error" ]] && echo -e " 服务器:${Green_font_prefix}${ipv4}${Font_color_suffix}"
|
|
|
+ [[ "${ipv6}" != "IPv6_Error" ]] && echo -e " 服务器:${Green_font_prefix}${ipv6}${Font_color_suffix}"
|
|
|
+ echo -e " Shadow TLS 端口:${Green_font_prefix}${stls_port}${Font_color_suffix}"
|
|
|
+ echo -e " Shadow TLS 密码:${Green_font_prefix}${stls_password}${Font_color_suffix}"
|
|
|
+ echo -e " Shadow TLS SNI:${Green_font_prefix}${stls_sni}${Font_color_suffix}"
|
|
|
+ echo -e " SS 本地端口:${Green_font_prefix}${port}${Font_color_suffix}"
|
|
|
+ echo -e " SS 密码:${Green_font_prefix}${password}${Font_color_suffix}"
|
|
|
+ echo -e " SS 加密:${Green_font_prefix}${cipher}${Font_color_suffix}"
|
|
|
+ echo -e "————————————————————————————————————————"
|
|
|
+ echo -e "${Info} Shadow TLS + SS Surge 配置:"
|
|
|
+ if [[ "${ipv4}" != "IPv4_Error" ]]; then
|
|
|
+ echo -e "$(uname -n) = ss, ${ipv4}, ${stls_port}, encrypt-method=${cipher}, password=${password}, shadow-tls-password=${stls_password}, shadow-tls-sni=${stls_sni}, shadow-tls-version=3, tfo=${tfo}, udp-relay=true, ecn=true, udp-port=${port}"
|
|
|
+ else
|
|
|
+ echo -e "$(uname -n) = ss, ${ipv6}, ${stls_port}, encrypt-method=${cipher}, password=${password}, shadow-tls-password=${stls_password}, shadow-tls-sni=${stls_sni}, shadow-tls-version=3, tfo=${tfo}, udp-relay=true, ecn=true, udp-port=${port}"
|
|
|
+ fi
|
|
|
+ echo && echo -e "========================================"
|
|
|
+ fi
|
|
|
+
|
|
|
+ # 显示纯 SS 配置
|
|
|
+ echo -e "${Info} 原始 Shadowsocks Rust 配置:"
|
|
|
+ echo -e "————————————————————————————————————————"
|
|
|
+ [[ "${ipv4}" != "IPv4_Error" ]] && echo -e " 地址:${Green_font_prefix}${ipv4}${Font_color_suffix}"
|
|
|
+ [[ "${ipv6}" != "IPv6_Error" ]] && echo -e " 地址:${Green_font_prefix}${ipv6}${Font_color_suffix}"
|
|
|
+ echo -e " 端口:${Green_font_prefix}${port}${Font_color_suffix}"
|
|
|
+ echo -e " 密码:${Green_font_prefix}${password}${Font_color_suffix}"
|
|
|
+ echo -e " 加密:${Green_font_prefix}${cipher}${Font_color_suffix}"
|
|
|
+ echo -e "————————————————————————————————————————"
|
|
|
+ [[ ! -z "${link_ipv4}" ]] && echo -e "${link_ipv4}"
|
|
|
+ [[ ! -z "${link_ipv6}" ]] && echo -e "${link_ipv6}"
|
|
|
+ echo -e "—————————————————————————"
|
|
|
+ echo -e "${Info} 原始 SS Surge 配置:"
|
|
|
+ if [[ "${ipv4}" != "IPv4_Error" ]]; then
|
|
|
+ echo -e "$(uname -n) = ss, ${ipv4}, ${port}, encrypt-method=${cipher}, password=${password}, tfo=${tfo}, udp-relay=true, ecn=true"
|
|
|
+ fi
|
|
|
+ echo -e "========================================"
|
|
|
+
|
|
|
+ # 根据调用来源返回到相应菜单
|
|
|
+ if [[ "$menu_source" == "shadowtls" ]]; then
|
|
|
+ echo && echo -n " 按回车键返回 Shadow TLS 菜单..." && read
|
|
|
+ shadowtls_menu
|
|
|
+ else
|
|
|
+ echo && echo -n " 按回车键返回主菜单..." && read
|
|
|
+ start_menu
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+view_combined_config_with_return(){
|
|
|
+ check_installed_status
|
|
|
+ read_config
|
|
|
+ getipv4
|
|
|
+ getipv6
|
|
|
+ link_qr
|
|
|
+ clear && echo
|
|
|
+
|
|
|
+ echo -e "完整配置信息:"
|
|
|
+ echo -e "========================================"
|
|
|
+
|
|
|
+ # 显示 Shadow TLS + SS 配置
|
|
|
+ if [[ -e ${STLS_File} ]]; then
|
|
|
+ read_stls_config
|
|
|
+ echo -e "${Info} Shadow TLS + Shadowsocks Rust 配置:"
|
|
|
+ echo -e "————————————————————————————————————————"
|
|
|
+ [[ "${ipv4}" != "IPv4_Error" ]] && echo -e " 服务器:${Green_font_prefix}${ipv4}${Font_color_suffix}"
|
|
|
+ [[ "${ipv6}" != "IPv6_Error" ]] && echo -e " 服务器:${Green_font_prefix}${ipv6}${Font_color_suffix}"
|
|
|
+ echo -e " Shadow TLS 端口:${Green_font_prefix}${stls_port}${Font_color_suffix}"
|
|
|
+ echo -e " Shadow TLS 密码:${Green_font_prefix}${stls_password}${Font_color_suffix}"
|
|
|
+ echo -e " Shadow TLS SNI:${Green_font_prefix}${stls_sni}${Font_color_suffix}"
|
|
|
+ echo -e " SS 本地端口:${Green_font_prefix}${port}${Font_color_suffix}"
|
|
|
+ echo -e " SS 密码:${Green_font_prefix}${password}${Font_color_suffix}"
|
|
|
+ echo -e " SS 加密:${Green_font_prefix}${cipher}${Font_color_suffix}"
|
|
|
+ echo -e "————————————————————————————————————————"
|
|
|
+ echo -e "${Info} Shadow TLS + SS Surge 配置:"
|
|
|
+ if [[ "${ipv4}" != "IPv4_Error" ]]; then
|
|
|
+ echo -e "$(uname -n) = ss, ${ipv4}, ${stls_port}, encrypt-method=${cipher}, password=${password}, shadow-tls-password=${stls_password}, shadow-tls-sni=${stls_sni}, shadow-tls-version=3, tfo=${tfo}, ecn=true, udp-relay=true, udp-port=${port}"
|
|
|
+ else
|
|
|
+ echo -e "$(uname -n) = ss, ${ipv6}, ${stls_port}, encrypt-method=${cipher}, password=${password}, shadow-tls-password=${stls_password}, shadow-tls-sni=${stls_sni}, shadow-tls-version=3, tfo=${tfo}, ecn=true, udp-relay=true, udp-port=${port}"
|
|
|
+ fi
|
|
|
+ echo && echo -e "========================================"
|
|
|
+ fi
|
|
|
+
|
|
|
+ # 显示纯 SS 配置
|
|
|
+ echo -e "${Info} 原始 Shadowsocks Rust 配置:"
|
|
|
+ echo -e "————————————————————————————————————————"
|
|
|
+ [[ "${ipv4}" != "IPv4_Error" ]] && echo -e " 地址:${Green_font_prefix}${ipv4}${Font_color_suffix}"
|
|
|
+ [[ "${ipv6}" != "IPv6_Error" ]] && echo -e " 地址:${Green_font_prefix}${ipv6}${Font_color_suffix}"
|
|
|
+ echo -e " 端口:${Green_font_prefix}${port}${Font_color_suffix}"
|
|
|
+ echo -e " 密码:${Green_font_prefix}${password}${Font_color_suffix}"
|
|
|
+ echo -e " 加密:${Green_font_prefix}${cipher}${Font_color_suffix}"
|
|
|
+ echo -e "————————————————————————————————————————"
|
|
|
+ [[ ! -z "${link_ipv4}" ]] && echo -e "${link_ipv4}"
|
|
|
+ [[ ! -z "${link_ipv6}" ]] && echo -e "${link_ipv6}"
|
|
|
+ echo -e "—————————————————————————"
|
|
|
+ echo -e "${Info} SS Surge 配置:"
|
|
|
+ if [[ "${ipv4}" != "IPv4_Error" ]]; then
|
|
|
+ echo -e "$(uname -n) = ss, ${ipv4}, ${port}, encrypt-method=${cipher}, password=${password}, tfo=${tfo}, udp-relay=true, ecn=true"
|
|
|
+ fi
|
|
|
+ echo -e "========================================"
|
|
|
+ echo && echo -n " 按回车键继续..." && read
|
|
|
+}
|
|
|
+
|
|
|
+# 综合 Shadow TLS 配置函数
|
|
|
+set_stls_config(){
|
|
|
+ check_stls_installed_status
|
|
|
+ read_config
|
|
|
+ read_stls_config
|
|
|
+
|
|
|
+ echo && echo -e "你要修改哪项 Shadow TLS 配置?
|
|
|
+========================================
|
|
|
+ ${Green_font_prefix}1.${Font_color_suffix} 修改 端口配置
|
|
|
+ ${Green_font_prefix}2.${Font_color_suffix} 修改 密码配置
|
|
|
+ ${Green_font_prefix}3.${Font_color_suffix} 修改 Shadow TLS SNI 域名
|
|
|
+ ${Green_font_prefix}4.${Font_color_suffix} 修改 FastOpen 配置
|
|
|
+ ${Green_font_prefix}5.${Font_color_suffix} 修改 Strict 模式配置
|
|
|
+ ${Green_font_prefix}6.${Font_color_suffix} 修改 TLS Wildcard SNI 配置
|
|
|
+ ${Green_font_prefix}7.${Font_color_suffix} 修改 回退域名配置
|
|
|
+ ${Green_font_prefix}8.${Font_color_suffix} 管理 Dispatch 分发配置
|
|
|
+========================================
|
|
|
+ ${Green_font_prefix}9.${Font_color_suffix} 修改 全部配置" && echo
|
|
|
+ read -e -p "(默认:取消):" modify
|
|
|
+ [[ -z "${modify}" ]] && echo "已取消..." && return
|
|
|
+
|
|
|
+ case "${modify}" in
|
|
|
+ 1)
|
|
|
+ set_stls_port
|
|
|
+ write_stls_config
|
|
|
+ restart_stls
|
|
|
+ ;;
|
|
|
+ 2)
|
|
|
+ set_stls_password
|
|
|
+ write_stls_config
|
|
|
+ restart_stls
|
|
|
+ ;;
|
|
|
+ 3)
|
|
|
+ set_stls_sni
|
|
|
+ write_stls_config
|
|
|
+ restart_stls
|
|
|
+ ;;
|
|
|
+ 4)
|
|
|
+ set_stls_fastopen
|
|
|
+ write_stls_config
|
|
|
+ restart_stls
|
|
|
+ ;;
|
|
|
+ 5)
|
|
|
+ set_stls_strict
|
|
|
+ write_stls_config
|
|
|
+ restart_stls
|
|
|
+ ;;
|
|
|
+ 6)
|
|
|
+ set_stls_tls_wildcard_sni
|
|
|
+ write_stls_config
|
|
|
+ restart_stls
|
|
|
+ ;;
|
|
|
+ 7)
|
|
|
+ set_stls_fallback
|
|
|
+ write_stls_config
|
|
|
+ restart_stls
|
|
|
+ ;;
|
|
|
+ 8)
|
|
|
+ manage_stls_dispatch
|
|
|
+ if [[ ! -z "${stls_dispatch}" ]]; then
|
|
|
+ write_stls_config
|
|
|
+ restart_stls
|
|
|
+ fi
|
|
|
+ ;;
|
|
|
+ 9)
|
|
|
+ set_stls_port
|
|
|
+ set_stls_password
|
|
|
+ set_stls_sni
|
|
|
+ set_stls_fastopen
|
|
|
+ set_stls_strict
|
|
|
+ set_stls_tls_wildcard_sni
|
|
|
+ set_stls_fallback
|
|
|
+ manage_stls_dispatch
|
|
|
+ write_stls_config
|
|
|
+ restart_stls
|
|
|
+ ;;
|
|
|
+ *)
|
|
|
+ echo -e "${Error} 请输入正确的数字(1-9)"
|
|
|
+ set_stls_config
|
|
|
+ ;;
|
|
|
+ esac
|
|
|
+}
|
|
|
+
|
|
|
+# Dispatch 管理的简化版本
|
|
|
+manage_stls_dispatch(){
|
|
|
+ echo -e "${Info} 当前 dispatch 配置:"
|
|
|
+ if [[ -e ${STLS_Conf} ]]; then
|
|
|
+ echo -e "${Green_font_prefix}$(cat ${STLS_Conf}|jq -r '.server.tls_addr.dispatch | to_entries | map(" \(.key) -> \(.value)") | join("\n")')${Font_color_suffix}"
|
|
|
+ else
|
|
|
+ echo -e " ${stls_sni} -> 1.1.1.1:443"
|
|
|
+ echo -e " captive.apple.com -> captive.apple.com:443"
|
|
|
+ fi
|
|
|
+
|
|
|
+ echo && echo -e "是否需要修改 dispatch 配置?
|
|
|
+========================================
|
|
|
+${Green_font_prefix} 1.${Font_color_suffix} 使用默认配置(推荐)
|
|
|
+${Green_font_prefix} 2.${Font_color_suffix} 自定义配置所有条目
|
|
|
+========================================"
|
|
|
+ read -e -p "(默认:1.使用默认):" dispatch_choice
|
|
|
+ [[ -z "${dispatch_choice}" ]] && dispatch_choice="1"
|
|
|
+
|
|
|
+ if [[ "${dispatch_choice}" == "1" ]]; then
|
|
|
+ # 使用默认配置,确保使用当前设置的 SNI
|
|
|
+ echo -e "${Info} 使用默认 dispatch 配置,SNI: ${stls_sni}"
|
|
|
+ # 不设置 stls_dispatch,让 write_stls_config 使用默认逻辑
|
|
|
+ stls_dispatch=""
|
|
|
+ elif [[ "${dispatch_choice}" == "2" ]]; then
|
|
|
+ echo -e "${Info} 重新配置 dispatch 条目"
|
|
|
+ echo "请输入 dispatch 配置 (每行格式: 域名:目标地址,回车结束):"
|
|
|
+ echo "示例: cloudflare.com:1.1.1.1:443"
|
|
|
+
|
|
|
+ local dispatch_entries=""
|
|
|
+ local line_count=0
|
|
|
+ while true; do
|
|
|
+ read -e -p "条目 $((line_count+1)) (直接回车结束):" dispatch_entry
|
|
|
+ if [[ -z "${dispatch_entry}" ]]; then
|
|
|
+ break
|
|
|
+ fi
|
|
|
+
|
|
|
+ if [[ "${dispatch_entry}" =~ ^([^:]+):(.+)$ ]]; then
|
|
|
+ local sni="${BASH_REMATCH[1]}"
|
|
|
+ local target="${BASH_REMATCH[2]}"
|
|
|
+
|
|
|
+ if [[ ${line_count} -gt 0 ]]; then
|
|
|
+ dispatch_entries="${dispatch_entries},
|
|
|
+ "
|
|
|
+ fi
|
|
|
+ dispatch_entries="${dispatch_entries}\"${sni}\": \"${target}\""
|
|
|
+ line_count=$((line_count+1))
|
|
|
+ else
|
|
|
+ echo -e "${Error} 格式错误,请使用格式: 域名:目标地址"
|
|
|
+ fi
|
|
|
+ done
|
|
|
+
|
|
|
+ if [[ ${line_count} -gt 0 ]]; then
|
|
|
+ stls_dispatch="${dispatch_entries}"
|
|
|
+ echo -e "${Info} 已配置 ${line_count} 个 dispatch 条目"
|
|
|
+ else
|
|
|
+ echo -e "${Info} 没有输入条目,使用默认 dispatch 配置"
|
|
|
+ # 不设置 stls_dispatch,让 write_stls_config 使用默认逻辑
|
|
|
+ stls_dispatch=""
|
|
|
+ fi
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+# 增强版 Dispatch 管理(支持单条增删改)
|
|
|
+manage_stls_dispatch_advanced(){
|
|
|
+ echo -e "${Info} 当前 dispatch 配置:"
|
|
|
+ if [[ -e ${STLS_Conf} ]]; then
|
|
|
+ echo -e "${Green_font_prefix}$(cat ${STLS_Conf}|jq -r '.server.tls_addr.dispatch | to_entries | map(" \(.key) -> \(.value)") | join("\n")')${Font_color_suffix}"
|
|
|
+ else
|
|
|
+ echo -e " ${stls_sni} -> 1.1.1.1:443"
|
|
|
+ echo -e " captive.apple.com -> captive.apple.com:443"
|
|
|
+ fi
|
|
|
+
|
|
|
+ echo && echo -e "请选择 dispatch 管理操作:
|
|
|
+========================================
|
|
|
+${Green_font_prefix} 1.${Font_color_suffix} 保持当前配置
|
|
|
+${Green_font_prefix} 2.${Font_color_suffix} 添加新条目
|
|
|
+${Green_font_prefix} 3.${Font_color_suffix} 删除指定条目
|
|
|
+${Green_font_prefix} 4.${Font_color_suffix} 修改指定条目
|
|
|
+${Green_font_prefix} 5.${Font_color_suffix} 重新配置所有条目
|
|
|
+========================================"
|
|
|
+ read -e -p "(默认:1.保持当前):" dispatch_choice
|
|
|
+ [[ -z "${dispatch_choice}" ]] && dispatch_choice="1"
|
|
|
+
|
|
|
+ case "${dispatch_choice}" in
|
|
|
+ 1)
|
|
|
+ echo -e "${Info} 保持当前配置"
|
|
|
+ ;;
|
|
|
+ 2)
|
|
|
+ add_dispatch_entry
|
|
|
+ ;;
|
|
|
+ 3)
|
|
|
+ delete_dispatch_entry
|
|
|
+ ;;
|
|
|
+ 4)
|
|
|
+ modify_dispatch_entry
|
|
|
+ ;;
|
|
|
+ 5)
|
|
|
+ reconfigure_all_dispatch
|
|
|
+ ;;
|
|
|
+ *)
|
|
|
+ echo -e "${Error} 输入错误,保持当前配置"
|
|
|
+ ;;
|
|
|
+ esac
|
|
|
+}
|
|
|
+
|
|
|
+# 添加 dispatch 条目
|
|
|
+add_dispatch_entry(){
|
|
|
+ echo -e "${Info} 添加新的 dispatch 条目"
|
|
|
+ read -e -p "请输入域名 (如: example.com):" new_sni
|
|
|
+ if [[ -z "${new_sni}" ]]; then
|
|
|
+ echo -e "${Error} 域名不能为空"
|
|
|
+ return
|
|
|
+ fi
|
|
|
+
|
|
|
+ read -e -p "请输入目标地址 (如: 1.1.1.1:443):" new_target
|
|
|
+ if [[ -z "${new_target}" ]]; then
|
|
|
+ echo -e "${Error} 目标地址不能为空"
|
|
|
+ return
|
|
|
+ fi
|
|
|
+
|
|
|
+ # 获取当前 dispatch 配置
|
|
|
+ if [[ -e ${STLS_Conf} ]]; then
|
|
|
+ current_dispatch=$(cat ${STLS_Conf}|jq -r '.server.tls_addr.dispatch | to_entries | map("\"\(.key)\": \"\(.value)\"") | join(",\n ")')
|
|
|
+ stls_dispatch="${current_dispatch},
|
|
|
+ \"${new_sni}\": \"${new_target}\""
|
|
|
+ else
|
|
|
+ stls_dispatch="\"${stls_sni}\": \"1.1.1.1:443\",
|
|
|
+ \"captive.apple.com\": \"captive.apple.com:443\",
|
|
|
+ \"${new_sni}\": \"${new_target}\""
|
|
|
+ fi
|
|
|
+
|
|
|
+ echo -e "${Info} 已添加条目: ${new_sni} -> ${new_target}"
|
|
|
+}
|
|
|
+
|
|
|
+# 删除 dispatch 条目
|
|
|
+delete_dispatch_entry(){
|
|
|
+ if [[ ! -e ${STLS_Conf} ]]; then
|
|
|
+ echo -e "${Error} 配置文件不存在"
|
|
|
+ return
|
|
|
+ fi
|
|
|
+
|
|
|
+ echo -e "${Info} 当前 dispatch 条目:"
|
|
|
+ # 显示带编号的列表
|
|
|
+ local domains=($(cat ${STLS_Conf}|jq -r '.server.tls_addr.dispatch | keys[]'))
|
|
|
+ local targets=($(cat ${STLS_Conf}|jq -r '.server.tls_addr.dispatch | to_entries | map(.value) | .[]'))
|
|
|
+
|
|
|
+ if [[ ${#domains[@]} -eq 0 ]]; then
|
|
|
+ echo -e "${Error} 没有可删除的条目"
|
|
|
+ return
|
|
|
+ fi
|
|
|
+
|
|
|
+ for i in "${!domains[@]}"; do
|
|
|
+ echo -e " ${Green_font_prefix}$((i+1)).${Font_color_suffix} ${domains[i]} -> ${targets[i]}"
|
|
|
+ done
|
|
|
+
|
|
|
+ read -e -p "请输入要删除的条目编号 (1-${#domains[@]}):" del_num
|
|
|
+ if [[ -z "${del_num}" ]] || [[ ${del_num} -lt 1 ]] || [[ ${del_num} -gt ${#domains[@]} ]]; then
|
|
|
+ echo -e "${Error} 输入的编号无效"
|
|
|
+ return
|
|
|
+ fi
|
|
|
+
|
|
|
+ # 重新构建 dispatch 配置,排除删除的条目
|
|
|
+ local del_domain="${domains[$((del_num-1))]}"
|
|
|
+ local new_entries=""
|
|
|
+ local count=0
|
|
|
+
|
|
|
+ for i in "${!domains[@]}"; do
|
|
|
+ if [[ "${domains[i]}" != "${del_domain}" ]]; then
|
|
|
+ if [[ ${count} -gt 0 ]]; then
|
|
|
+ new_entries="${new_entries},
|
|
|
+ "
|
|
|
+ fi
|
|
|
+ new_entries="${new_entries}\"${domains[i]}\": \"${targets[i]}\""
|
|
|
+ count=$((count+1))
|
|
|
+ fi
|
|
|
+ done
|
|
|
+
|
|
|
+ if [[ ${count} -eq 0 ]]; then
|
|
|
+ # 如果删除后没有条目,使用默认配置
|
|
|
+ stls_dispatch="\"${stls_sni}\": \"1.1.1.1:443\",
|
|
|
+ \"captive.apple.com\": \"captive.apple.com:443\""
|
|
|
+ else
|
|
|
+ stls_dispatch="${new_entries}"
|
|
|
+ fi
|
|
|
+
|
|
|
+ echo -e "${Info} 已删除条目: ${del_domain}"
|
|
|
+}
|
|
|
+
|
|
|
+# 修改 dispatch 条目
|
|
|
+modify_dispatch_entry(){
|
|
|
+ if [[ ! -e ${STLS_Conf} ]]; then
|
|
|
+ echo -e "${Error} 配置文件不存在"
|
|
|
+ return
|
|
|
+ fi
|
|
|
+
|
|
|
+ echo -e "${Info} 当前 dispatch 条目:"
|
|
|
+ # 显示带编号的列表
|
|
|
+ local domains=($(cat ${STLS_Conf}|jq -r '.server.tls_addr.dispatch | keys[]'))
|
|
|
+ local targets=($(cat ${STLS_Conf}|jq -r '.server.tls_addr.dispatch | to_entries | map(.value) | .[]'))
|
|
|
+
|
|
|
+ if [[ ${#domains[@]} -eq 0 ]]; then
|
|
|
+ echo -e "${Error} 没有可修改的条目"
|
|
|
+ return
|
|
|
+ fi
|
|
|
+
|
|
|
+ for i in "${!domains[@]}"; do
|
|
|
+ echo -e " ${Green_font_prefix}$((i+1)).${Font_color_suffix} ${domains[i]} -> ${targets[i]}"
|
|
|
+ done
|
|
|
+
|
|
|
+ read -e -p "请输入要修改的条目编号 (1-${#domains[@]}):" mod_num
|
|
|
+ if [[ -z "${mod_num}" ]] || [[ ${mod_num} -lt 1 ]] || [[ ${mod_num} -gt ${#domains[@]} ]]; then
|
|
|
+ echo -e "${Error} 输入的编号无效"
|
|
|
+ return
|
|
|
+ fi
|
|
|
+
|
|
|
+ local mod_domain="${domains[$((mod_num-1))]}"
|
|
|
+ local mod_target="${targets[$((mod_num-1))]}"
|
|
|
+
|
|
|
+ echo -e "${Info} 当前条目: ${mod_domain} -> ${mod_target}"
|
|
|
+ read -e -p "请输入新的域名 (直接回车保持不变):" new_domain
|
|
|
+ read -e -p "请输入新的目标地址 (直接回车保持不变):" new_target
|
|
|
+
|
|
|
+ [[ -z "${new_domain}" ]] && new_domain="${mod_domain}"
|
|
|
+ [[ -z "${new_target}" ]] && new_target="${mod_target}"
|
|
|
+
|
|
|
+ # 重新构建 dispatch 配置
|
|
|
+ local new_entries=""
|
|
|
+ for i in "${!domains[@]}"; do
|
|
|
+ if [[ ${i} -gt 0 ]]; then
|
|
|
+ new_entries="${new_entries},
|
|
|
+ "
|
|
|
+ fi
|
|
|
+
|
|
|
+ if [[ ${i} -eq $((mod_num-1)) ]]; then
|
|
|
+ new_entries="${new_entries}\"${new_domain}\": \"${new_target}\""
|
|
|
+ else
|
|
|
+ new_entries="${new_entries}\"${domains[i]}\": \"${targets[i]}\""
|
|
|
+ fi
|
|
|
+ done
|
|
|
+
|
|
|
+ stls_dispatch="${new_entries}"
|
|
|
+ echo -e "${Info} 已修改条目: ${mod_domain} -> ${mod_target} => ${new_domain} -> ${new_target}"
|
|
|
+}
|
|
|
+
|
|
|
+# 重新配置所有 dispatch 条目
|
|
|
+reconfigure_all_dispatch(){
|
|
|
+ echo -e "${Info} 重新配置所有 dispatch 条目"
|
|
|
+ echo "请输入 dispatch 配置 (每行格式: 域名:目标地址,回车结束):"
|
|
|
+ echo "示例: cloudflare.com:1.1.1.1:443"
|
|
|
+
|
|
|
+ local dispatch_entries=""
|
|
|
+ local line_count=0
|
|
|
+ while true; do
|
|
|
+ read -e -p "条目 $((line_count+1)) (直接回车结束):" dispatch_entry
|
|
|
+ if [[ -z "${dispatch_entry}" ]]; then
|
|
|
+ break
|
|
|
+ fi
|
|
|
+
|
|
|
+ if [[ "${dispatch_entry}" =~ ^([^:]+):(.+)$ ]]; then
|
|
|
+ local sni="${BASH_REMATCH[1]}"
|
|
|
+ local target="${BASH_REMATCH[2]}"
|
|
|
+
|
|
|
+ if [[ ${line_count} -gt 0 ]]; then
|
|
|
+ dispatch_entries="${dispatch_entries},
|
|
|
+ "
|
|
|
+ fi
|
|
|
+ dispatch_entries="${dispatch_entries}\"${sni}\": \"${target}\""
|
|
|
+ line_count=$((line_count+1))
|
|
|
+ else
|
|
|
+ echo -e "${Error} 格式错误,请使用格式: 域名:目标地址"
|
|
|
+ fi
|
|
|
+ done
|
|
|
+
|
|
|
+ if [[ ${line_count} -gt 0 ]]; then
|
|
|
+ stls_dispatch="${dispatch_entries}"
|
|
|
+ echo -e "${Info} 已配置 ${line_count} 个 dispatch 条目"
|
|
|
+ else
|
|
|
+ echo -e "${Info} 使用默认 dispatch 配置"
|
|
|
+ stls_dispatch="\"${stls_sni}\": \"1.1.1.1:443\",
|
|
|
+ \"captive.apple.com\": \"captive.apple.com:443\""
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+start(){
|
|
|
+ check_installed_status
|
|
|
+ check_status
|
|
|
+ if [[ "$status" == "running" ]]; then
|
|
|
+ echo -e "${Info} Shadowsocks Rust 已在运行!"
|
|
|
+ else
|
|
|
+ systemctl start ss-rust
|
|
|
+ check_status
|
|
|
+ if [[ "$status" == "running" ]]; then
|
|
|
+ echo -e "${Info} Shadowsocks Rust 启动成功!"
|
|
|
+ else
|
|
|
+ echo -e "${Error} Shadowsocks Rust 启动失败!"
|
|
|
+ exit 1
|
|
|
+ fi
|
|
|
+ fi
|
|
|
+ sleep 3s
|
|
|
+}
|
|
|
+
|
|
|
+start_stls(){
|
|
|
+ check_stls_installed_status
|
|
|
+ check_stls_status
|
|
|
+ if [[ "$stls_status" == "running" ]]; then
|
|
|
+ echo -e "${Info} Shadow TLS 已在运行!"
|
|
|
+ else
|
|
|
+ systemctl start shadowtls
|
|
|
+ check_stls_status
|
|
|
+ if [[ "$stls_status" == "running" ]]; then
|
|
|
+ echo -e "${Info} Shadow TLS 启动成功!"
|
|
|
+ else
|
|
|
+ echo -e "${Error} Shadow TLS 启动失败!"
|
|
|
+ exit 1
|
|
|
+ fi
|
|
|
+ fi
|
|
|
+ sleep 3s
|
|
|
+}
|
|
|
+
|
|
|
+stop(){
|
|
|
+ check_installed_status
|
|
|
+ check_status
|
|
|
+ [[ !"$status" == "running" ]] && echo -e "${Error} Shadowsocks Rust 没有运行,请检查!" && exit 1
|
|
|
+ systemctl stop ss-rust
|
|
|
+ sleep 3s
|
|
|
+ start_menu
|
|
|
+}
|
|
|
+
|
|
|
+stop_stls(){
|
|
|
+ check_stls_installed_status
|
|
|
+ check_stls_status
|
|
|
+ [[ !"$stls_status" == "running" ]] && echo -e "${Error} Shadow TLS 没有运行,请检查!" && exit 1
|
|
|
+ systemctl stop shadowtls
|
|
|
+ sleep 3s
|
|
|
+}
|
|
|
+
|
|
|
+restart(){
|
|
|
+ check_installed_status
|
|
|
+ systemctl restart ss-rust
|
|
|
+ echo -e "${Info} Shadowsocks Rust 重启完毕 !"
|
|
|
+ sleep 3s
|
|
|
+ start_menu
|
|
|
+}
|
|
|
+
|
|
|
+restart_stls(){
|
|
|
+ check_stls_installed_status
|
|
|
+ systemctl restart shadowtls
|
|
|
+ echo -e "${Info} Shadow TLS 重启完毕 !"
|
|
|
+ sleep 3s
|
|
|
+}
|
|
|
+
|
|
|
+update(){
|
|
|
+ check_installed_status
|
|
|
+ check_new_ver
|
|
|
+ check_ver_comparison
|
|
|
+ echo -e "${Info} Shadowsocks Rust 更新完毕!"
|
|
|
+ sleep 3s
|
|
|
+ start_menu
|
|
|
+}
|
|
|
+
|
|
|
+update_stls(){
|
|
|
+ check_stls_installed_status
|
|
|
+ check_stls_new_ver
|
|
|
+ check_stls_ver_comparison
|
|
|
+ echo -e "${Info} Shadow TLS 更新完毕!"
|
|
|
+ sleep 3s
|
|
|
+}
|
|
|
+
|
|
|
+# 脚本更新函数
|
|
|
+update_sh(){
|
|
|
+ echo -e "当前版本为 [ ${sh_ver} ],开始检测最新版本..."
|
|
|
+ sh_new_ver=$(wget --no-check-certificate -qO- "https://raw.githubusercontent.com/xOS/Shadowsocks-Rust/master/ss-rust.sh"|grep 'sh_ver="'|awk -F "=" '{print $NF}'|sed 's/\"//g'|head -1)
|
|
|
+ [[ -z ${sh_new_ver} ]] && echo -e "${Error} 检测最新版本失败 !" && start_menu
|
|
|
+ if [[ ${sh_new_ver} != ${sh_ver} ]]; then
|
|
|
+ echo -e "发现新版本[ ${sh_new_ver} ],是否更新?[Y/n]"
|
|
|
+ read -p "(默认:y):" yn
|
|
|
+ [[ -z "${yn}" ]] && yn="y"
|
|
|
+ if [[ ${yn} == [Yy] ]]; then
|
|
|
+ wget -O ss-rust.sh --no-check-certificate https://raw.githubusercontent.com/xOS/Shadowsocks-Rust/master/ss-rust.sh && chmod +x ss-rust.sh
|
|
|
+ echo -e "脚本已更新为最新版本[ ${sh_new_ver} ]!"
|
|
|
+ echo -e "3s后执行新脚本"
|
|
|
+ sleep 3s
|
|
|
+ bash ss-rust.sh
|
|
|
+ else
|
|
|
+ echo && echo " 已取消..." && echo
|
|
|
+ sleep 3s
|
|
|
+ start_menu
|
|
|
+ fi
|
|
|
+ else
|
|
|
+ echo -e "当前已是最新版本[ ${sh_new_ver} ] !"
|
|
|
+ sleep 3s
|
|
|
+ start_menu
|
|
|
+ fi
|
|
|
+ sleep 3s
|
|
|
+ bash ss-rust.sh
|
|
|
+}
|
|
|
+
|
|
|
+uninstall(){
|
|
|
+ check_installed_status
|
|
|
+ echo "确定要卸载 Shadowsocks Rust ? (y/N)"
|
|
|
+ echo
|
|
|
+ read -e -p "(默认:n):" unyn
|
|
|
+ [[ -z ${unyn} ]] && unyn="n"
|
|
|
+ if [[ ${unyn} == [Yy] ]]; then
|
|
|
+ check_status
|
|
|
+ [[ "$status" == "running" ]] && systemctl stop ss-rust
|
|
|
+ systemctl disable ss-rust
|
|
|
+ rm -rf "${SS_Folder}"
|
|
|
+ rm -rf "${SS_File}"
|
|
|
+ echo && echo "Shadowsocks Rust 卸载完成!" && echo
|
|
|
+ else
|
|
|
+ echo && echo "卸载已取消..." && echo
|
|
|
+ fi
|
|
|
+ sleep 3s
|
|
|
+ start_menu
|
|
|
+}
|
|
|
+
|
|
|
+uninstall_stls(){
|
|
|
+ check_stls_installed_status
|
|
|
+ echo "确定要卸载 Shadow TLS ? (y/N)"
|
|
|
+ echo
|
|
|
+ read -e -p "(默认:n):" unyn
|
|
|
+ [[ -z ${unyn} ]] && unyn="n"
|
|
|
+ if [[ ${unyn} == [Yy] ]]; then
|
|
|
+ check_stls_status
|
|
|
+ [[ "$stls_status" == "running" ]] && systemctl stop shadowtls
|
|
|
+ systemctl disable shadowtls
|
|
|
+ rm -rf "${STLS_Folder}"
|
|
|
+ rm -rf "${STLS_File}"
|
|
|
+ rm -f "/etc/systemd/system/shadowtls.service"
|
|
|
+ systemctl daemon-reload
|
|
|
+ echo && echo "Shadow TLS 卸载完成!" && echo
|
|
|
+ else
|
|
|
+ echo && echo "卸载已取消..." && echo
|
|
|
+ fi
|
|
|
+ sleep 3s
|
|
|
+}
|
|
|
+
|
|
|
+getipv4(){
|
|
|
+ ipv4=$(wget -qO- -4 -t1 -T2 ipinfo.io/ip)
|
|
|
+ if [[ -z "${ipv4}" ]]; then
|
|
|
+ ipv4=$(wget -qO- -4 -t1 -T2 api.ip.sb/ip)
|
|
|
+ if [[ -z "${ipv4}" ]]; then
|
|
|
+ ipv4=$(wget -qO- -4 -t1 -T2 members.3322.org/dyndns/getip)
|
|
|
+ if [[ -z "${ipv4}" ]]; then
|
|
|
+ ipv4="IPv4_Error"
|
|
|
+ fi
|
|
|
+ fi
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+getipv6(){
|
|
|
+ ipv6=$(wget -qO- -6 -t1 -T2 ifconfig.co)
|
|
|
+ if [[ -z "${ipv6}" ]]; then
|
|
|
+ ipv6="IPv6_Error"
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+urlsafe_base64(){
|
|
|
+ date=$(echo -n "$1"|base64|sed ':a;N;s/\n/ /g;ta'|sed 's/ //g;s/=//g;s/+/-/g;s/\//_/g')
|
|
|
+ echo -e "${date}"
|
|
|
+}
|
|
|
+
|
|
|
+link_qr(){
|
|
|
+ if [[ "${ipv4}" != "IPv4_Error" ]]; then
|
|
|
+ SSbase64=$(urlsafe_base64 "${cipher}:${password}@${ipv4}:${port}")
|
|
|
+ SSurl="ss://${SSbase64}"
|
|
|
+ SSQRcode="https://cli.im/api/qrcode/code?text=${SSurl}"
|
|
|
+ link_ipv4=" 链接 [IPv4]:${Red_font_prefix}${SSurl}${Font_color_suffix} \n 二维码[IPv4]:${Red_font_prefix}${SSQRcode}${Font_color_suffix}"
|
|
|
+ fi
|
|
|
+ if [[ "${ipv6}" != "IPv6_Error" ]]; then
|
|
|
+ SSbase64=$(urlsafe_base64 "${cipher}:${password}@${ipv6}:${port}")
|
|
|
+ SSurl="ss://${SSbase64}"
|
|
|
+ SSQRcode="https://cli.im/api/qrcode/code?text=${SSurl}"
|
|
|
+ link_ipv6=" 链接 [IPv6]:${Red_font_prefix}${SSurl}${Font_color_suffix} \n 二维码[IPv6]:${Red_font_prefix}${SSQRcode}${Font_color_suffix}"
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+before_start_menu(){
|
|
|
+ echo && echo -n " 任意键继续..." && read
|
|
|
+ start_menu
|
|
|
+}
|
|
|
+
|
|
|
+before_shadowtls_menu(){
|
|
|
+ echo && echo -n " 任意键继续..." && read
|
|
|
+ shadowtls_menu
|
|
|
+}
|
|
|
+
|
|
|
+# Shadow TLS 状态和版本检查函数
|
|
|
+check_stls_installed_status(){
|
|
|
+ [[ ! -e ${STLS_File} ]] && echo -e "${Error} Shadow TLS 没有安装,请检查!" && exit 1
|
|
|
+}
|
|
|
+
|
|
|
+check_stls_status(){
|
|
|
+ stls_status=`systemctl status shadowtls | grep Active | awk '{print $3}' | cut -d "(" -f2 | cut -d ")" -f1`
|
|
|
+}
|
|
|
+
|
|
|
+check_stls_new_ver(){
|
|
|
+ stls_new_ver=$(wget -qO- https://api.github.com/repos/ihciah/shadow-tls/releases| jq -r '[.[] | select(.prerelease == false) | select(.draft == false) | .tag_name] | .[0]')
|
|
|
+ [[ -z ${stls_new_ver} ]] && echo -e "${Error} Shadow TLS 最新版本获取失败!" && exit 1
|
|
|
+ echo -e "${Info} 检测到 Shadow TLS 最新版本为 [ ${stls_new_ver} ]"
|
|
|
+}
|
|
|
+
|
|
|
+check_stls_ver_comparison(){
|
|
|
+ stls_now_ver=$(cat ${STLS_Now_ver_File})
|
|
|
+ if [[ "${stls_now_ver}" != "${stls_new_ver}" ]]; then
|
|
|
+ echo -e "${Info} 发现 Shadow TLS 已有新版本 [ ${stls_new_ver} ],旧版本 [ ${stls_now_ver} ]"
|
|
|
+ read -e -p "是否更新 ? [Y/n]:" yn
|
|
|
+ [[ -z "${yn}" ]] && yn="y"
|
|
|
+ if [[ $yn == [Yy] ]]; then
|
|
|
+ check_stls_status
|
|
|
+ \cp "${STLS_Conf}" "/tmp/stls_config.json"
|
|
|
+ download_stls
|
|
|
+ mv -f "/tmp/stls_config.json" "${STLS_Conf}"
|
|
|
+ restart_stls
|
|
|
+ fi
|
|
|
+ else
|
|
|
+ echo -e "${Info} 当前 Shadow TLS 已是最新版本 [ ${stls_new_ver} ] !" && exit 1
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
+# Shadow TLS 专用菜单
|
|
|
+shadowtls_menu(){
|
|
|
+ check_root
|
|
|
+ check_sys
|
|
|
+ sys_arch
|
|
|
+
|
|
|
+ # 检查 Shadow TLS 安装状态
|
|
|
+ if [[ -e ${STLS_File} ]]; then
|
|
|
+ check_stls_status
|
|
|
+ if [[ "$stls_status" == "running" ]]; then
|
|
|
+ stls_status_show="${Green_font_prefix}已安装${Font_color_suffix} 且 ${Green_font_prefix}运行中${Font_color_suffix}"
|
|
|
+ else
|
|
|
+ stls_status_show="${Green_font_prefix}已安装${Font_color_suffix} 但 ${Yellow_font_prefix}未运行${Font_color_suffix}"
|
|
|
+ fi
|
|
|
+ else
|
|
|
+ stls_status_show="${Red_font_prefix}未安装${Font_color_suffix}"
|
|
|
+ fi
|
|
|
+
|
|
|
+ clear
|
|
|
+ echo -e "Shadow TLS 管理菜单 ${Red_font_prefix}[v${sh_ver}]${Font_color_suffix}
|
|
|
+
|
|
|
+==================状态==================
|
|
|
+ Shadow TLS : [${stls_status_show}]
|
|
|
+========================================
|
|
|
+ ${Green_font_prefix}0.${Font_color_suffix} 更新脚本
|
|
|
+==================菜单==================
|
|
|
+ ${Green_font_prefix}1.${Font_color_suffix} 安装 Shadow TLS
|
|
|
+ ${Green_font_prefix}2.${Font_color_suffix} 更新 Shadow TLS
|
|
|
+ ${Green_font_prefix}3.${Font_color_suffix} 卸载 Shadow TLS
|
|
|
+————————————————————————————————————————
|
|
|
+ ${Green_font_prefix}4.${Font_color_suffix} 启动 Shadow TLS
|
|
|
+ ${Green_font_prefix}5.${Font_color_suffix} 停止 Shadow TLS
|
|
|
+ ${Green_font_prefix}6.${Font_color_suffix} 重启 Shadow TLS
|
|
|
+————————————————————————————————————————
|
|
|
+ ${Green_font_prefix}7.${Font_color_suffix} 修改 Shadow TLS 配置
|
|
|
+ ${Green_font_prefix}8.${Font_color_suffix} 查看 Shadow TLS 配置
|
|
|
+ ${Green_font_prefix}9.${Font_color_suffix} 查看 Shadow TLS 状态
|
|
|
+————————————————————————————————————————
|
|
|
+ ${Green_font_prefix}10.${Font_color_suffix} 查看完整配置信息
|
|
|
+ ${Green_font_prefix}11.${Font_color_suffix} 返回主菜单
|
|
|
+————————————————————————————————————————
|
|
|
+ ${Green_font_prefix}00.${Font_color_suffix} 退出脚本
|
|
|
+========================================" && echo
|
|
|
+
|
|
|
+ read -e -p " 请输入数字 [0-11]:" stls_num
|
|
|
+ case "$stls_num" in
|
|
|
+ 1)
|
|
|
+ install_stls
|
|
|
+ shadowtls_menu
|
|
|
+ ;;
|
|
|
+ 2)
|
|
|
+ update_stls
|
|
|
+ shadowtls_menu
|
|
|
+ ;;
|
|
|
+ 3)
|
|
|
+ uninstall_stls
|
|
|
+ shadowtls_menu
|
|
|
+ ;;
|
|
|
+ 4)
|
|
|
+ start_stls
|
|
|
+ shadowtls_menu
|
|
|
+ ;;
|
|
|
+ 5)
|
|
|
+ stop_stls
|
|
|
+ shadowtls_menu
|
|
|
+ ;;
|
|
|
+ 6)
|
|
|
+ restart_stls
|
|
|
+ shadowtls_menu
|
|
|
+ ;;
|
|
|
+ 7)
|
|
|
+ set_stls_config
|
|
|
+ shadowtls_menu
|
|
|
+ ;;
|
|
|
+ 8)
|
|
|
+ view_stls_only
|
|
|
+ ;;
|
|
|
+ 9)
|
|
|
+ view_stls_status
|
|
|
+ ;;
|
|
|
+ 10)
|
|
|
+ view_combined_config shadowtls
|
|
|
+ ;;
|
|
|
+ 11)
|
|
|
+ start_menu
|
|
|
+ ;;
|
|
|
+ 0)
|
|
|
+ update_sh
|
|
|
+ ;;
|
|
|
+ 00)
|
|
|
+ exit 1
|
|
|
+ ;;
|
|
|
+ *)
|
|
|
+ echo -e "${Error} 请输入正确数字 [0-11] (退出输入00)"
|
|
|
+ sleep 5s
|
|
|
+ shadowtls_menu
|
|
|
+ ;;
|
|
|
+ esac
|
|
|
+}
|
|
|
+
|
|
|
+# 查看 Shadowsocks Rust 状态函数
|
|
|
+view_ss_status(){
|
|
|
+ check_installed_status
|
|
|
+
|
|
|
+ echo -e "${Info} 正在获取 Shadowsocks Rust 状态信息..."
|
|
|
+ echo
|
|
|
+ echo "=================================="
|
|
|
+ echo -e " Shadowsocks Rust 服务状态"
|
|
|
+ echo "=================================="
|
|
|
+
|
|
|
+ systemctl status ss-rust
|
|
|
+
|
|
|
+ echo "=================================="
|
|
|
+ echo
|
|
|
+ read -e -p "按回车键返回主菜单..."
|
|
|
+ start_menu
|
|
|
+}
|
|
|
+
|
|
|
+# 查看 Shadow TLS 状态函数
|
|
|
+view_stls_status(){
|
|
|
+ check_stls_installed_status
|
|
|
+
|
|
|
+ echo -e "${Info} 正在获取 Shadow TLS 状态信息..."
|
|
|
+ echo
|
|
|
+ echo "=================================="
|
|
|
+ echo -e " Shadow TLS 服务状态"
|
|
|
+ echo "=================================="
|
|
|
+
|
|
|
+ systemctl status shadowtls
|
|
|
+
|
|
|
+ echo "=================================="
|
|
|
+ echo
|
|
|
+ read -e -p "按回车键返回 Shadow TLS 菜单..."
|
|
|
+ shadowtls_menu
|
|
|
+}
|
|
|
+
|
|
|
+# 查看 Shadow TLS 配置函数
|
|
|
+view_stls_only(){
|
|
|
+ check_stls_installed_status
|
|
|
+ echo -e "${Info} 正在获取 Shadow TLS 配置信息..."
|
|
|
+ echo
|
|
|
+ echo "=================================="
|
|
|
+ echo -e " Shadow TLS 配置信息"
|
|
|
+ echo "=================================="
|
|
|
+
|
|
|
+ if [[ -f "$STLS_Conf" ]]; then
|
|
|
+ cat "$STLS_Conf"
|
|
|
+ else
|
|
|
+ echo -e "${Error} Shadow TLS 配置文件不存在!"
|
|
|
+ fi
|
|
|
+
|
|
|
+ echo "=================================="
|
|
|
+ echo
|
|
|
+ read -e -p "按回车键返回 Shadow TLS 菜单..."
|
|
|
+ shadowtls_menu
|
|
|
+}
|
|
|
+
|
|
|
+# 主菜单函数
|
|
|
+start_menu(){
|
|
|
+ echo -e "${Info} 正在启动 Shadowsocks Rust 管理脚本..."
|
|
|
+ check_root
|
|
|
+ echo -e "${Info} 权限检查完成,正在检测系统..."
|
|
|
+ check_sys
|
|
|
+ echo -e "${Info} 系统检测完成,正在检测架构..."
|
|
|
+ sys_arch
|
|
|
+ echo -e "${Info} 架构检测完成,正在检查服务状态..."
|
|
|
+
|
|
|
+ # 检查安装状态
|
|
|
+ if [[ -e ${SS_File} ]]; then
|
|
|
+ check_status
|
|
|
+ if [[ "$status" == "running" ]]; then
|
|
|
+ ss_status_show="${Green_font_prefix}已安装${Font_color_suffix} 且 ${Green_font_prefix}运行中${Font_color_suffix}"
|
|
|
+ else
|
|
|
+ ss_status_show="${Green_font_prefix}已安装${Font_color_suffix} 但 ${Yellow_font_prefix}未运行${Font_color_suffix}"
|
|
|
+ fi
|
|
|
+ else
|
|
|
+ ss_status_show="${Red_font_prefix}未安装${Font_color_suffix}"
|
|
|
+ fi
|
|
|
+
|
|
|
+ # 检查 Shadow TLS 安装状态
|
|
|
+ if [[ -e ${STLS_File} ]]; then
|
|
|
+ check_stls_status
|
|
|
+ if [[ "$stls_status" == "running" ]]; then
|
|
|
+ stls_status_show="${Green_font_prefix}已安装${Font_color_suffix} 且 ${Green_font_prefix}运行中${Font_color_suffix}"
|
|
|
+ else
|
|
|
+ stls_status_show="${Green_font_prefix}已安装${Font_color_suffix} 但 ${Yellow_font_prefix}未运行${Font_color_suffix}"
|
|
|
+ fi
|
|
|
+ else
|
|
|
+ stls_status_show="${Red_font_prefix}未安装${Font_color_suffix}"
|
|
|
+ fi
|
|
|
+
|
|
|
+ clear
|
|
|
+ echo -e "Shadowsocks Rust 管理脚本 ${Red_font_prefix}[v${sh_ver}]${Font_color_suffix}
|
|
|
+
|
|
|
+==================状态==================
|
|
|
+ Shadowsocks Rust : [${ss_status_show}]
|
|
|
+ Shadow TLS : [${stls_status_show}]
|
|
|
+========================================
|
|
|
+ ${Green_font_prefix}0.${Font_color_suffix} 更新脚本
|
|
|
+==================菜单==================
|
|
|
+ ${Green_font_prefix}1.${Font_color_suffix} 安装 Shadowsocks Rust
|
|
|
+ ${Green_font_prefix}2.${Font_color_suffix} 更新 Shadowsocks Rust
|
|
|
+ ${Green_font_prefix}3.${Font_color_suffix} 卸载 Shadowsocks Rust
|
|
|
+————————————————————————————————————————
|
|
|
+ ${Green_font_prefix}4.${Font_color_suffix} 启动 Shadowsocks Rust
|
|
|
+ ${Green_font_prefix}5.${Font_color_suffix} 停止 Shadowsocks Rust
|
|
|
+ ${Green_font_prefix}6.${Font_color_suffix} 重启 Shadowsocks Rust
|
|
|
+————————————————————————————————————————
|
|
|
+ ${Green_font_prefix}7.${Font_color_suffix} 配置 Shadowsocks Rust 相关
|
|
|
+ ${Green_font_prefix}8.${Font_color_suffix} 查看 Shadowsocks Rust 配置
|
|
|
+ ${Green_font_prefix}9.${Font_color_suffix} 查看 Shadowsocks Rust 状态
|
|
|
+========================================
|
|
|
+ ${Green_font_prefix}10.${Font_color_suffix} 配置 Shadow TLS 相关
|
|
|
+ ${Green_font_prefix}11.${Font_color_suffix} 查看完整配置信息
|
|
|
+————————————————————————————————————————
|
|
|
+ ${Green_font_prefix}00.${Font_color_suffix} 退出脚本
|
|
|
+========================================" && echo
|
|
|
+ read -e -p " 请输入数字 [0-11]:" num
|
|
|
+ case "$num" in
|
|
|
+ 1)
|
|
|
+ install
|
|
|
+ ;;
|
|
|
+ 2)
|
|
|
+ update
|
|
|
+ start_menu
|
|
|
+ ;;
|
|
|
+ 3)
|
|
|
+ uninstall
|
|
|
+ start_menu
|
|
|
+ ;;
|
|
|
+ 4)
|
|
|
+ start
|
|
|
+ start_menu
|
|
|
+ ;;
|
|
|
+ 5)
|
|
|
+ stop
|
|
|
+ start_menu
|
|
|
+ ;;
|
|
|
+ 6)
|
|
|
+ restart
|
|
|
+ start_menu
|
|
|
+ ;;
|
|
|
+ 7)
|
|
|
+ set_config
|
|
|
+ ;;
|
|
|
+ 8)
|
|
|
+ view
|
|
|
+ ;;
|
|
|
+ 9)
|
|
|
+ view_ss_status
|
|
|
+ ;;
|
|
|
+ 10)
|
|
|
+ shadowtls_menu
|
|
|
+ ;;
|
|
|
+ 11)
|
|
|
+ view_combined_config
|
|
|
+ ;;
|
|
|
+ 0)
|
|
|
+ update_sh
|
|
|
+ ;;
|
|
|
+ 00)
|
|
|
+ exit 1
|
|
|
+ ;;
|
|
|
+ *)
|
|
|
+ echo -e "${Error} 请输入正确数字 [0-11] (退出输入00)"
|
|
|
+ sleep 5s
|
|
|
+ start_menu
|
|
|
+ ;;
|
|
|
+ esac
|
|
|
+}
|
|
|
+
|
|
|
+# 脚本执行入口
|
|
|
+start_menu
|