Gogs 1 month ago
parent
commit
214ac4f4aa
8 changed files with 6202 additions and 0 deletions
  1. 232 0
      MHSanaei_3x-ui.sh
  2. 594 0
      hysteria.sh
  3. 203 0
      install_CN.sh
  4. 417 0
      mt_setup.sh
  5. 417 0
      mt_setup.sh.1
  6. 2472 0
      singbox.sh
  7. 0 0
      snell.sh
  8. 1867 0
      ss-rust.sh

+ 232 - 0
MHSanaei_3x-ui.sh

@@ -0,0 +1,232 @@
+#!/bin/bash
+
+red='\033[0;31m'
+green='\033[0;32m'
+blue='\033[0;34m'
+yellow='\033[0;33m'
+plain='\033[0m'
+
+cur_dir=$(pwd)
+
+# check root
+[[ $EUID -ne 0 ]] && echo -e "${red}Fatal error: ${plain} Please run this script with root privilege \n " && exit 1
+
+# Check OS and set release variable
+if [[ -f /etc/os-release ]]; then
+    source /etc/os-release
+    release=$ID
+elif [[ -f /usr/lib/os-release ]]; then
+    source /usr/lib/os-release
+    release=$ID
+else
+    echo "Failed to check the system OS, please contact the author!" >&2
+    exit 1
+fi
+echo "The OS release is: $release"
+
+arch() {
+    case "$(uname -m)" in
+    x86_64 | x64 | amd64) echo 'amd64' ;;
+    i*86 | x86) echo '386' ;;
+    armv8* | armv8 | arm64 | aarch64) echo 'arm64' ;;
+    armv7* | armv7 | arm) echo 'armv7' ;;
+    armv6* | armv6) echo 'armv6' ;;
+    armv5* | armv5) echo 'armv5' ;;
+    s390x) echo 's390x' ;;
+    *) echo -e "${green}Unsupported CPU architecture! ${plain}" && rm -f install.sh && exit 1 ;;
+    esac
+}
+
+echo "Arch: $(arch)"
+
+install_base() {
+    case "${release}" in
+    ubuntu | debian | armbian)
+        apt-get update && apt-get install -y -q wget curl tar tzdata
+        ;;
+    centos | rhel | almalinux | rocky | ol)
+        yum -y update && yum install -y -q wget curl tar tzdata
+        ;;
+    fedora | amzn | virtuozzo)
+        dnf -y update && dnf install -y -q wget curl tar tzdata
+        ;;
+    arch | manjaro | parch)
+        pacman -Syu && pacman -Syu --noconfirm wget curl tar tzdata
+        ;;
+    opensuse-tumbleweed)
+        zypper refresh && zypper -q install -y wget curl tar timezone
+        ;;
+    *)
+        apt-get update && apt-get install -y -q wget curl tar tzdata
+        ;;
+    esac
+}
+
+gen_random_string() {
+    local length="$1"
+    local random_string=$(LC_ALL=C tr -dc 'a-zA-Z0-9' </dev/urandom | fold -w "$length" | head -n 1)
+    echo "$random_string"
+}
+
+config_after_install() {
+    local existing_hasDefaultCredential=$(/usr/local/x-ui/x-ui setting -show true | grep -Eo 'hasDefaultCredential: .+' | awk '{print $2}')
+    local existing_webBasePath=$(/usr/local/x-ui/x-ui setting -show true | grep -Eo 'webBasePath: .+' | awk '{print $2}')
+    local existing_port=$(/usr/local/x-ui/x-ui setting -show true | grep -Eo 'port: .+' | awk '{print $2}')
+    local URL_lists=(
+        "https://api4.ipify.org"
+		"https://ipv4.icanhazip.com"
+		"https://v4.api.ipinfo.io/ip"
+		"https://ipv4.myexternalip.com/raw"
+		"https://4.ident.me"
+		"https://check-host.net/ip"
+    )
+    local server_ip=""
+    for ip_address in "${URL_lists[@]}"; do
+        server_ip=$(curl -s --max-time 3 "${ip_address}" 2>/dev/null | tr -d '[:space:]')
+        if [[ -n "${server_ip}" ]]; then
+            break
+        fi
+    done
+
+    if [[ ${#existing_webBasePath} -lt 4 ]]; then
+        if [[ "$existing_hasDefaultCredential" == "true" ]]; then
+            local config_webBasePath=$(gen_random_string 18)
+            local config_username=$(gen_random_string 10)
+            local config_password=$(gen_random_string 10)
+
+            read -rp "Would you like to customize the Panel Port settings? (If not, a random port will be applied) [y/n]: " config_confirm
+            if [[ "${config_confirm}" == "y" || "${config_confirm}" == "Y" ]]; then
+                read -rp "Please set up the panel port: " config_port
+                echo -e "${yellow}Your Panel Port is: ${config_port}${plain}"
+            else
+                local config_port=$(shuf -i 1024-62000 -n 1)
+                echo -e "${yellow}Generated random port: ${config_port}${plain}"
+            fi
+
+            /usr/local/x-ui/x-ui setting -username "${config_username}" -password "${config_password}" -port "${config_port}" -webBasePath "${config_webBasePath}"
+            echo -e "This is a fresh installation, generating random login info for security concerns:"
+            echo -e "###############################################"
+            echo -e "${green}Username: ${config_username}${plain}"
+            echo -e "${green}Password: ${config_password}${plain}"
+            echo -e "${green}Port: ${config_port}${plain}"
+            echo -e "${green}WebBasePath: ${config_webBasePath}${plain}"
+            echo -e "${green}Access URL: http://${server_ip}:${config_port}/${config_webBasePath}${plain}"
+            echo -e "###############################################"
+        else
+            local config_webBasePath=$(gen_random_string 18)
+            echo -e "${yellow}WebBasePath is missing or too short. Generating a new one...${plain}"
+            /usr/local/x-ui/x-ui setting -webBasePath "${config_webBasePath}"
+            echo -e "${green}New WebBasePath: ${config_webBasePath}${plain}"
+            echo -e "${green}Access URL: http://${server_ip}:${existing_port}/${config_webBasePath}${plain}"
+        fi
+    else
+        if [[ "$existing_hasDefaultCredential" == "true" ]]; then
+            local config_username=$(gen_random_string 10)
+            local config_password=$(gen_random_string 10)
+
+            echo -e "${yellow}Default credentials detected. Security update required...${plain}"
+            /usr/local/x-ui/x-ui setting -username "${config_username}" -password "${config_password}"
+            echo -e "Generated new random login credentials:"
+            echo -e "###############################################"
+            echo -e "${green}Username: ${config_username}${plain}"
+            echo -e "${green}Password: ${config_password}${plain}"
+            echo -e "###############################################"
+        else
+            echo -e "${green}Username, Password, and WebBasePath are properly set. Exiting...${plain}"
+        fi
+    fi
+
+    /usr/local/x-ui/x-ui migrate
+}
+
+install_x-ui() {
+    cd /usr/local/
+
+    # Download resources
+    if [ $# == 0 ]; then
+        tag_version=$(curl -Ls "https://api.github.com/repos/MHSanaei/3x-ui/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
+        if [[ ! -n "$tag_version" ]]; then
+            echo -e "${red}Failed to fetch x-ui version, it may be due to GitHub API restrictions, please try it later${plain}"
+            exit 1
+        fi
+        echo -e "Got x-ui latest version: ${tag_version}, beginning the installation..."
+        wget -N -O /usr/local/x-ui-linux-$(arch).tar.gz https://github.com/MHSanaei/3x-ui/releases/download/${tag_version}/x-ui-linux-$(arch).tar.gz
+        if [[ $? -ne 0 ]]; then
+            echo -e "${red}Downloading x-ui failed, please be sure that your server can access GitHub ${plain}"
+            exit 1
+        fi
+    else
+        tag_version=$1
+        tag_version_numeric=${tag_version#v}
+        min_version="2.3.5"
+
+        if [[ "$(printf '%s\n' "$min_version" "$tag_version_numeric" | sort -V | head -n1)" != "$min_version" ]]; then
+            echo -e "${red}Please use a newer version (at least v2.3.5). Exiting installation.${plain}"
+            exit 1
+        fi
+
+        url="https://github.com/MHSanaei/3x-ui/releases/download/${tag_version}/x-ui-linux-$(arch).tar.gz"
+        echo -e "Beginning to install x-ui $1"
+        wget -N -O /usr/local/x-ui-linux-$(arch).tar.gz ${url}
+        if [[ $? -ne 0 ]]; then
+            echo -e "${red}Download x-ui $1 failed, please check if the version exists ${plain}"
+            exit 1
+        fi
+    fi
+    wget -O /usr/bin/x-ui-temp https://raw.githubusercontent.com/MHSanaei/3x-ui/main/x-ui.sh
+
+    # Stop x-ui service and remove old resources
+    if [[ -e /usr/local/x-ui/ ]]; then
+        systemctl stop x-ui
+        rm /usr/local/x-ui/ -rf
+    fi
+
+    # Extract resources and set permissions
+    tar zxvf x-ui-linux-$(arch).tar.gz
+    rm x-ui-linux-$(arch).tar.gz -f
+    
+    cd x-ui
+    chmod +x x-ui
+    chmod +x x-ui.sh
+
+    # Check the system's architecture and rename the file accordingly
+    if [[ $(arch) == "armv5" || $(arch) == "armv6" || $(arch) == "armv7" ]]; then
+        mv bin/xray-linux-$(arch) bin/xray-linux-arm
+        chmod +x bin/xray-linux-arm
+    fi
+    chmod +x x-ui bin/xray-linux-$(arch)
+
+    # Update x-ui cli and se set permission
+    mv -f /usr/bin/x-ui-temp /usr/bin/x-ui
+    chmod +x /usr/bin/x-ui
+    config_after_install
+
+    cp -f x-ui.service /etc/systemd/system/
+    systemctl daemon-reload
+    systemctl enable x-ui
+    systemctl start x-ui
+    echo -e "${green}x-ui ${tag_version}${plain} installation finished, it is running now..."
+    echo -e ""
+    echo -e "┌───────────────────────────────────────────────────────┐
+│  ${blue}x-ui control menu usages (subcommands):${plain}              │
+│                                                       │
+│  ${blue}x-ui${plain}              - Admin Management Script          │
+│  ${blue}x-ui start${plain}        - Start                            │
+│  ${blue}x-ui stop${plain}         - Stop                             │
+│  ${blue}x-ui restart${plain}      - Restart                          │
+│  ${blue}x-ui status${plain}       - Current Status                   │
+│  ${blue}x-ui settings${plain}     - Current Settings                 │
+│  ${blue}x-ui enable${plain}       - Enable Autostart on OS Startup   │
+│  ${blue}x-ui disable${plain}      - Disable Autostart on OS Startup  │
+│  ${blue}x-ui log${plain}          - Check logs                       │
+│  ${blue}x-ui banlog${plain}       - Check Fail2ban ban logs          │
+│  ${blue}x-ui update${plain}       - Update                           │
+│  ${blue}x-ui legacy${plain}       - legacy version                   │
+│  ${blue}x-ui install${plain}      - Install                          │
+│  ${blue}x-ui uninstall${plain}    - Uninstall                        │
+└───────────────────────────────────────────────────────┘"
+}
+
+echo -e "${green}Running...${plain}"
+install_base
+install_x-ui $1

+ 594 - 0
hysteria.sh

@@ -0,0 +1,594 @@
+#!/bin/bash
+
+export LANG=en_US.UTF-8
+
+RED="\033[31m"
+GREEN="\033[32m"
+YELLOW="\033[33m"
+PLAIN="\033[0m"
+
+red(){
+    echo -e "\033[31m\033[01m$1\033[0m"
+}
+
+green(){
+    echo -e "\033[32m\033[01m$1\033[0m"
+}
+
+yellow(){
+    echo -e "\033[33m\033[01m$1\033[0m"
+}
+
+# 判断系统及定义系统安装依赖方式
+REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'" "fedora")
+RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS" "Fedora")
+PACKAGE_UPDATE=("apt-get update" "apt-get update" "yum -y update" "yum -y update" "yum -y update")
+PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install" "yum -y install")
+PACKAGE_REMOVE=("apt -y remove" "apt -y remove" "yum -y remove" "yum -y remove" "yum -y remove")
+PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove" "yum -y autoremove")
+
+[[ $EUID -ne 0 ]] && red "注意: 请在root用户下运行脚本" && exit 1
+
+CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')")
+
+for i in "${CMD[@]}"; do
+    SYS="$i" && [[ -n $SYS ]] && break
+done
+
+for ((int = 0; int < ${#REGEX[@]}; int++)); do
+    [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]] && SYSTEM="${RELEASE[int]}" && [[ -n $SYSTEM ]] && break
+done
+
+[[ -z $SYSTEM ]] && red "目前暂不支持你的VPS的操作系统!" && exit 1
+
+if [[ -z $(type -P curl) ]]; then
+    if [[ ! $SYSTEM == "CentOS" ]]; then
+        ${PACKAGE_UPDATE[int]}
+    fi
+    ${PACKAGE_INSTALL[int]} curl
+fi
+
+realip(){
+    ip=$(curl -s4m8 ip.gs -k) || ip=$(curl -s6m8 ip.gs -k)
+}
+
+inst_cert(){
+    green "Hysteria 2 协议证书申请方式如下:"
+    echo ""
+    echo -e " ${GREEN}1.${PLAIN} 必应自签证书 ${YELLOW}(默认)${PLAIN}"
+    echo -e " ${GREEN}2.${PLAIN} Acme 脚本自动申请"
+    echo -e " ${GREEN}3.${PLAIN} 自定义证书路径"
+    echo ""
+    read -rp "请输入选项 [1-3]: " certInput
+    if [[ $certInput == 2 ]]; then
+        cert_path="/root/cert.crt"
+        key_path="/root/private.key"
+
+        chmod -R 777 /root
+        
+        chmod +rw /root/cert.crt
+        chmod +rw /root/private.key
+
+        if [[ -f /root/cert.crt && -f /root/private.key ]] && [[ -s /root/cert.crt && -s /root/private.key ]] && [[ -f /root/ca.log ]]; then
+            domain=$(cat /root/ca.log)
+            green "检测到原有域名:$domain 的证书,正在应用"
+            hy_domain=$domain
+        else
+            WARPv4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2)
+            WARPv6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2)
+            if [[ $WARPv4Status =~ on|plus ]] || [[ $WARPv6Status =~ on|plus ]]; then
+                wg-quick down wgcf >/dev/null 2>&1
+                systemctl stop warp-go >/dev/null 2>&1
+                realip
+                wg-quick up wgcf >/dev/null 2>&1
+                systemctl start warp-go >/dev/null 2>&1
+            else
+                realip
+            fi
+            
+            read -p "请输入需要申请证书的域名:" domain
+            [[ -z $domain ]] && red "未输入域名,无法执行操作!" && exit 1
+            green "已输入的域名:$domain" && sleep 1
+            domainIP=$(dig @8.8.8.8 +time=2 +short "$domain" 2>/dev/null)
+            if echo $domainIP | grep -q "network unreachable\|timed out" || [[ -z $domainIP ]]; then
+                domainIP=$(dig @2001:4860:4860::8888 +time=2 aaaa +short "$domain" 2>/dev/null)
+            fi
+            if echo $domainIP | grep -q "network unreachable\|timed out" || [[ -z $domainIP ]] ; then
+                red "未解析出 IP,请检查域名是否输入有误" 
+                yellow "是否尝试强行匹配?"
+                green "1. 是,将使用强行匹配"
+                green "2. 否,退出脚本"
+                read -p "请输入选项 [1-2]:" ipChoice
+                if [[ $ipChoice == 1 ]]; then
+                    yellow "将尝试强行匹配以申请域名证书"
+                else
+                    red "将退出脚本"
+                    exit 1
+                fi
+            fi
+            if [[ $domainIP == $ip ]]; then
+                ${PACKAGE_INSTALL[int]} curl wget sudo socat openssl
+                if [[ $SYSTEM == "CentOS" ]]; then
+                    ${PACKAGE_INSTALL[int]} cronie
+                    systemctl start crond
+                    systemctl enable crond
+                else
+                    ${PACKAGE_INSTALL[int]} cron
+                    systemctl start cron
+                    systemctl enable cron
+                fi
+                curl https://get.acme.sh | sh -s email=$(date +%s%N | md5sum | cut -c 1-16)@gmail.com
+                source ~/.bashrc
+                bash ~/.acme.sh/acme.sh --upgrade --auto-upgrade
+                bash ~/.acme.sh/acme.sh --set-default-ca --server letsencrypt
+                if [[ -n $(echo $ip | grep ":") ]]; then
+                    bash ~/.acme.sh/acme.sh --issue -d ${domain} --standalone -k ec-256 --listen-v6 --insecure
+                else
+                    bash ~/.acme.sh/acme.sh --issue -d ${domain} --standalone -k ec-256 --insecure
+                fi
+                bash ~/.acme.sh/acme.sh --install-cert -d ${domain} --key-file /root/private.key --fullchain-file /root/cert.crt --ecc
+                if [[ -f /root/cert.crt && -f /root/private.key ]] && [[ -s /root/cert.crt && -s /root/private.key ]]; then
+                    echo $domain > /root/ca.log
+                    sed -i '/--cron/d' /etc/crontab >/dev/null 2>&1
+                    echo "0 0 * * * root bash /root/.acme.sh/acme.sh --cron -f >/dev/null 2>&1" >> /etc/crontab
+                    green "证书申请成功! 脚本申请到的证书 (cert.crt) 和私钥 (private.key) 文件已保存到 /root 文件夹下"
+                    yellow "证书crt文件路径如下: /root/cert.crt"
+                    yellow "私钥key文件路径如下: /root/private.key"
+                    hy_domain=$domain
+                fi
+            else
+                red "当前域名解析的IP与当前VPS使用的真实IP不匹配"
+                green "建议如下:"
+                yellow "1. 请确保CloudFlare小云朵为关闭状态(仅限DNS), 其他域名解析或CDN网站设置同理"
+                yellow "2. 请检查DNS解析设置的IP是否为VPS的真实IP"
+                yellow "3. 脚本可能跟不上时代, 建议截图发布到GitHub Issues、GitLab Issues、论坛或TG群询问"
+                exit 1
+            fi
+        fi
+    elif [[ $certInput == 3 ]]; then
+        read -p "请输入公钥文件 crt 的路径:" cert_path
+        yellow "公钥文件 crt 的路径:$cert_path "
+        read -p "请输入密钥文件 key 的路径:" key_path
+        yellow "密钥文件 key 的路径:$key_path "
+        read -p "请输入证书的域名:" domain
+        yellow "证书域名:$domain"
+        hy_domain=$domain
+
+        chmod +rw $cert_path
+        chmod +rw $key_path
+    else
+        green "将使用必应自签证书作为 Hysteria 2 的节点证书"
+
+        cert_path="/etc/hysteria/cert.crt"
+        key_path="/etc/hysteria/private.key"
+        openssl ecparam -genkey -name prime256v1 -out /etc/hysteria/private.key
+        openssl req -new -x509 -days 36500 -key /etc/hysteria/private.key -out /etc/hysteria/cert.crt -subj "/CN=www.bing.com"
+        chmod 777 /etc/hysteria/cert.crt
+        chmod 777 /etc/hysteria/private.key
+        hy_domain="www.bing.com"
+        domain="www.bing.com"
+    fi
+}
+
+inst_port(){
+    iptables -t nat -F PREROUTING >/dev/null 2>&1
+
+    read -p "设置 Hysteria 2 端口 [1-65535](回车则随机分配端口):" port
+    [[ -z $port ]] && port=$(shuf -i 2000-65535 -n 1)
+    until [[ -z $(ss -tunlp | grep -w udp | awk '{print $5}' | sed 's/.*://g' | grep -w "$port") ]]; do
+        if [[ -n $(ss -tunlp | grep -w udp | awk '{print $5}' | sed 's/.*://g' | grep -w "$port") ]]; then
+            echo -e "${RED} $port ${PLAIN} 端口已经被其他程序占用,请更换端口重试!"
+            read -p "设置 Hysteria 2 端口 [1-65535](回车则随机分配端口):" port
+            [[ -z $port ]] && port=$(shuf -i 2000-65535 -n 1)
+        fi
+    done
+
+    yellow "将在 Hysteria 2 节点使用的端口是:$port"
+    inst_jump
+}
+
+inst_jump(){
+    green "Hysteria 2 端口使用模式如下:"
+    echo ""
+    echo -e " ${GREEN}1.${PLAIN} 单端口 ${YELLOW}(默认)${PLAIN}"
+    echo -e " ${GREEN}2.${PLAIN} 端口跳跃"
+    echo ""
+    read -rp "请输入选项 [1-2]: " jumpInput
+    if [[ $jumpInput == 2 ]]; then
+        read -p "设置范围端口的起始端口 (建议10000-65535之间):" firstport
+        read -p "设置一个范围端口的末尾端口 (建议10000-65535之间,一定要比上面起始端口大):" endport
+        if [[ $firstport -ge $endport ]]; then
+            until [[ $firstport -le $endport ]]; do
+                if [[ $firstport -ge $endport ]]; then
+                    red "你设置的起始端口小于末尾端口,请重新输入起始和末尾端口"
+                    read -p "设置范围端口的起始端口 (建议10000-65535之间):" firstport
+                    read -p "设置一个范围端口的末尾端口 (建议10000-65535之间,一定要比上面起始端口大):" endport
+                fi
+            done
+        fi
+        iptables -t nat -A PREROUTING -p udp --dport $firstport:$endport  -j DNAT --to-destination :$port
+        ip6tables -t nat -A PREROUTING -p udp --dport $firstport:$endport  -j DNAT --to-destination :$port
+        netfilter-persistent save >/dev/null 2>&1
+    else
+        red "将继续使用单端口模式"
+    fi
+}
+
+inst_pwd(){
+    read -p "设置 Hysteria 2 密码(回车跳过为随机字符):" auth_pwd
+    [[ -z $auth_pwd ]] && auth_pwd=$(date +%s%N | md5sum | cut -c 1-8)
+    yellow "使用在 Hysteria 2 节点的密码为:$auth_pwd"
+}
+
+inst_site(){
+    read -rp "请输入 Hysteria 2 的伪装网站地址 (去除https://) [回车世嘉maimai日本网站]:" proxysite
+    [[ -z $proxysite ]] && proxysite="maimai.sega.jp"
+    yellow "使用在 Hysteria 2 节点的伪装网站为:$proxysite"
+}
+
+insthysteria(){
+    warpv6=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2)
+    warpv4=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2)
+    if [[ $warpv4 =~ on|plus || $warpv6 =~ on|plus ]]; then
+        wg-quick down wgcf >/dev/null 2>&1
+        systemctl stop warp-go >/dev/null 2>&1
+        realip
+        systemctl start warp-go >/dev/null 2>&1
+        wg-quick up wgcf >/dev/null 2>&1
+    else
+        realip
+    fi
+
+    if [[ ! ${SYSTEM} == "CentOS" ]]; then
+        ${PACKAGE_UPDATE}
+    fi
+    ${PACKAGE_INSTALL} curl wget sudo qrencode procps iptables-persistent netfilter-persistent
+
+    wget -N https://raw.githubusercontent.com/Misaka-blog/hysteria-install/main/hy2/install_server.sh
+    bash install_server.sh
+    rm -f install_server.sh
+
+    if [[ -f "/usr/local/bin/hysteria" ]]; then
+        green "Hysteria 2 安装成功!"
+    else
+        red "Hysteria 2 安装失败!"
+        exit 1
+    fi
+
+    # 询问用户 Hysteria 配置
+    inst_cert
+    inst_port
+    inst_pwd
+    inst_site
+
+    # 设置 Hysteria 配置文件
+    cat << EOF > /etc/hysteria/config.yaml
+listen: :$port
+
+tls:
+  cert: $cert_path
+  key: $key_path
+
+quic:
+  initStreamReceiveWindow: 16777216
+  maxStreamReceiveWindow: 16777216
+  initConnReceiveWindow: 33554432
+  maxConnReceiveWindow: 33554432
+
+auth:
+  type: password
+  password: $auth_pwd
+
+masquerade:
+  type: proxy
+  proxy:
+    url: https://$proxysite
+    rewriteHost: true
+EOF
+
+    # 确定最终入站端口范围
+    if [[ -n $firstport ]]; then
+        last_port="$port,$firstport-$endport"
+    else
+        last_port=$port
+    fi
+
+    # 给 IPv6 地址加中括号
+    if [[ -n $(echo $ip | grep ":") ]]; then
+        last_ip="[$ip]"
+    else
+        last_ip=$ip
+    fi
+
+    mkdir /root/hy
+    cat << EOF > /root/hy/hy-client.yaml
+server: $last_ip:$last_port
+
+auth: $auth_pwd
+
+tls:
+  sni: $hy_domain
+  insecure: true
+
+quic:
+  initStreamReceiveWindow: 16777216
+  maxStreamReceiveWindow: 16777216
+  initConnReceiveWindow: 33554432
+  maxConnReceiveWindow: 33554432
+
+fastOpen: true
+
+socks5:
+  listen: 127.0.0.1:5080
+
+transport:
+  udp:
+    hopInterval: 30s 
+EOF
+    cat << EOF > /root/hy/hy-client.json
+{
+  "server": "$last_ip:$last_port",
+  "auth": "$auth_pwd",
+  "tls": {
+    "sni": "$hy_domain",
+    "insecure": true
+  },
+  "quic": {
+    "initStreamReceiveWindow": 16777216,
+    "maxStreamReceiveWindow": 16777216,
+    "initConnReceiveWindow": 33554432,
+    "maxConnReceiveWindow": 33554432
+  },
+  "fastOpen": true,
+  "socks5": {
+    "listen": "127.0.0.1:5080"
+  },
+  "transport": {
+    "udp": {
+      "hopInterval": "30s"
+    }
+  }
+}
+EOF
+    cat <<EOF > /root/hy/clash-meta.yaml
+mixed-port: 7890
+external-controller: 127.0.0.1:9090
+allow-lan: false
+mode: rule
+log-level: debug
+ipv6: true
+dns:
+  enable: true
+  listen: 0.0.0.0:53
+  enhanced-mode: fake-ip
+  nameserver:
+    - 8.8.8.8
+    - 1.1.1.1
+    - 114.114.114.114
+proxies:
+  - name: Misaka-Hysteria2
+    type: hysteria2
+    server: $last_ip
+    port: $port
+    password: $auth_pwd
+    sni: $hy_domain
+    skip-cert-verify: true
+proxy-groups:
+  - name: Proxy
+    type: select
+    proxies:
+      - Misaka-Hysteria2
+      
+rules:
+  - GEOIP,CN,DIRECT
+  - MATCH,Proxy
+EOF
+    url="hysteria2://$auth_pwd@$last_ip:$last_port/?insecure=1&sni=$hy_domain#Misaka-Hysteria2"
+    echo $url > /root/hy/url.txt
+    nohopurl="hysteria2://$auth_pwd@$last_ip:$port/?insecure=1&sni=$hy_domain#Misaka-Hysteria2"
+    echo $nohopurl > /root/hy/url-nohop.txt
+
+    systemctl daemon-reload
+    systemctl enable hysteria-server
+    systemctl start hysteria-server
+    if [[ -n $(systemctl status hysteria-server 2>/dev/null | grep -w active) && -f '/etc/hysteria/config.yaml' ]]; then
+        green "Hysteria 2 服务启动成功"
+    else
+        red "Hysteria 2 服务启动失败,请运行 systemctl status hysteria-server 查看服务状态并反馈,脚本退出" && exit 1
+    fi
+    red "======================================================================================"
+    green "Hysteria 2 代理服务安装完成"
+    yellow "Hysteria 2 客户端 YAML 配置文件 hy-client.yaml 内容如下,并保存到 /root/hy/hy-client.yaml"
+    red "$(cat /root/hy/hy-client.yaml)"
+    yellow "Hysteria 2 客户端 JSON 配置文件 hy-client.json 内容如下,并保存到 /root/hy/hy-client.json"
+    red "$(cat /root/hy/hy-client.json)"
+    yellow "Clash Meta 客户端配置文件已保存到 /root/hy/clash-meta.yaml"
+    yellow "Hysteria 2 节点分享链接如下,并保存到 /root/hy/url.txt"
+    red "$(cat /root/hy/url.txt)"
+    yellow "Hysteria 2 节点单端口的分享链接如下,并保存到 /root/hy/url.txt"
+    red "$(cat /root/hy/url-nohop.txt)"
+}
+
+unsthysteria(){
+    systemctl stop hysteria-server.service >/dev/null 2>&1
+    systemctl disable hysteria-server.service >/dev/null 2>&1
+    rm -f /lib/systemd/system/hysteria-server.service /lib/systemd/system/hysteria-server@.service
+    rm -rf /usr/local/bin/hysteria /etc/hysteria /root/hy /root/hysteria.sh
+    iptables -t nat -F PREROUTING >/dev/null 2>&1
+    netfilter-persistent save >/dev/null 2>&1
+
+    green "Hysteria 2 已彻底卸载完成!"
+}
+
+starthysteria(){
+    systemctl start hysteria-server
+    systemctl enable hysteria-server >/dev/null 2>&1
+}
+
+stophysteria(){
+    systemctl stop hysteria-server
+    systemctl disable hysteria-server >/dev/null 2>&1
+}
+
+hysteriaswitch(){
+    yellow "请选择你需要的操作:"
+    echo ""
+    echo -e " ${GREEN}1.${PLAIN} 启动 Hysteria 2"
+    echo -e " ${GREEN}2.${PLAIN} 关闭 Hysteria 2"
+    echo -e " ${GREEN}3.${PLAIN} 重启 Hysteria 2"
+    echo ""
+    read -rp "请输入选项 [0-3]: " switchInput
+    case $switchInput in
+        1 ) starthysteria ;;
+        2 ) stophysteria ;;
+        3 ) stophysteria && starthysteria ;;
+        * ) exit 1 ;;
+    esac
+}
+
+changeport(){
+    oldport=$(cat /etc/hysteria/config.yaml 2>/dev/null | sed -n 1p | awk '{print $2}' | awk -F ":" '{print $2}')
+    
+    read -p "设置 Hysteria 2 端口[1-65535](回车则随机分配端口):" port
+    [[ -z $port ]] && port=$(shuf -i 2000-65535 -n 1)
+
+    until [[ -z $(ss -tunlp | grep -w udp | awk '{print $5}' | sed 's/.*://g' | grep -w "$port") ]]; do
+        if [[ -n $(ss -tunlp | grep -w udp | awk '{print $5}' | sed 's/.*://g' | grep -w "$port") ]]; then
+            echo -e "${RED} $port ${PLAIN} 端口已经被其他程序占用,请更换端口重试!"
+            read -p "设置 Hysteria 2 端口 [1-65535](回车则随机分配端口):" port
+            [[ -z $port ]] && port=$(shuf -i 2000-65535 -n 1)
+        fi
+    done
+
+    sed -i "1s#$oldport#$port#g" /etc/hysteria/config.yaml
+    sed -i "1s#$oldport#$port#g" /root/hy/hy-client.yaml
+    sed -i "2s#$oldport#$port#g" /root/hy/hy-client.json
+
+    stophysteria && starthysteria
+
+    green "Hysteria 2 端口已成功修改为:$port"
+    yellow "请手动更新客户端配置文件以使用节点"
+    showconf
+}
+
+changepasswd(){
+    oldpasswd=$(cat /etc/hysteria/config.yaml 2>/dev/null | sed -n 15p | awk '{print $2}')
+
+    read -p "设置 Hysteria 2 密码(回车跳过为随机字符):" passwd
+    [[ -z $passwd ]] && passwd=$(date +%s%N | md5sum | cut -c 1-8)
+
+    sed -i "1s#$oldpasswd#$passwd#g" /etc/hysteria/config.yaml
+    sed -i "1s#$oldpasswd#$passwd#g" /root/hy/hy-client.yaml
+    sed -i "3s#$oldpasswd#$passwd#g" /root/hy/hy-client.json
+
+    stophysteria && starthysteria
+
+    green "Hysteria 2 节点密码已成功修改为:$passwd"
+    yellow "请手动更新客户端配置文件以使用节点"
+    showconf
+}
+
+change_cert(){
+    old_cert=$(cat /etc/hysteria/config.yaml | grep cert | awk -F " " '{print $2}')
+    old_key=$(cat /etc/hysteria/config.yaml | grep key | awk -F " " '{print $2}')
+    old_hydomain=$(cat /root/hy/hy-client.yaml | grep sni | awk '{print $2}')
+
+    inst_cert
+
+    sed -i "s!$old_cert!$cert_path!g" /etc/hysteria/config.yaml
+    sed -i "s!$old_key!$key_path!g" /etc/hysteria/config.yaml
+    sed -i "6s/$old_hydomain/$hy_domain/g" /root/hy/hy-client.yaml
+    sed -i "5s/$old_hydomain/$hy_domain/g" /root/hy/hy-client.json
+
+    stophysteria && starthysteria
+
+    green "Hysteria 2 节点证书类型已成功修改"
+    yellow "请手动更新客户端配置文件以使用节点"
+    showconf
+}
+
+changeproxysite(){
+    oldproxysite=$(cat /etc/hysteria/config.yaml | grep url | awk -F " " '{print $2}' | awk -F "https://" '{print $2}')
+    
+    inst_site
+
+    sed -i "s#$oldproxysite#$proxysite#g" /etc/caddy/Caddyfile
+
+    stophysteria && starthysteria
+
+    green "Hysteria 2 节点伪装网站已成功修改为:$proxysite"
+}
+
+changeconf(){
+    green "Hysteria 2 配置变更选择如下:"
+    echo -e " ${GREEN}1.${PLAIN} 修改端口"
+    echo -e " ${GREEN}2.${PLAIN} 修改密码"
+    echo -e " ${GREEN}3.${PLAIN} 修改证书类型"
+    echo -e " ${GREEN}4.${PLAIN} 修改伪装网站"
+    echo ""
+    read -p " 请选择操作 [1-4]:" confAnswer
+    case $confAnswer in
+        1 ) changeport ;;
+        2 ) changepasswd ;;
+        3 ) change_cert ;;
+        4 ) changeproxysite ;;
+        * ) exit 1 ;;
+    esac
+}
+
+showconf(){
+    yellow "Hysteria 2 客户端 YAML 配置文件 hy-client.yaml 内容如下,并保存到 /root/hy/hy-client.yaml"
+    red "$(cat /root/hy/hy-client.yaml)"
+    yellow "Hysteria 2 客户端 JSON 配置文件 hy-client.json 内容如下,并保存到 /root/hy/hy-client.json"
+    red "$(cat /root/hy/hy-client.json)"
+    yellow "Clash Meta 客户端配置文件已保存到 /root/hy/clash-meta.yaml"
+    yellow "Hysteria 2 节点分享链接如下,并保存到 /root/hy/url.txt"
+    red "$(cat /root/hy/url.txt)"
+    yellow "Hysteria 2 节点单端口的分享链接如下,并保存到 /root/hy/url.txt"
+    red "$(cat /root/hy/url-nohop.txt)"
+}
+
+update_core(){
+    wget -N https://raw.githubusercontent.com/Misaka-blog/hysteria-install/main/hy2/install_server.sh
+    bash install_server.sh
+    
+    rm -f install_server.sh
+}
+
+menu() {
+    clear
+    echo "#############################################################"
+    echo -e "#                  ${RED}Hysteria 2 一键安装脚本${PLAIN}                  #"
+    echo -e "# ${GREEN}作者${PLAIN}: MisakaNo の 小破站                                  #"
+    echo -e "# ${GREEN}博客${PLAIN}: https://blog.misaka.cyou                            #"
+    echo -e "# ${GREEN}GitHub 项目${PLAIN}: https://github.com/Misaka-blog               #"
+    echo -e "# ${GREEN}GitLab 项目${PLAIN}: https://gitlab.com/Misaka-blog               #"
+    echo -e "# ${GREEN}Telegram 频道${PLAIN}: https://t.me/misakanocchannel              #"
+    echo -e "# ${GREEN}Telegram 群组${PLAIN}: https://t.me/misakanoc                     #"
+    echo -e "# ${GREEN}YouTube 频道${PLAIN}: https://www.youtube.com/@misaka-blog        #"
+    echo "#############################################################"
+    echo ""
+    echo -e " ${GREEN}1.${PLAIN} 安装 Hysteria 2"
+    echo -e " ${GREEN}2.${PLAIN} ${RED}卸载 Hysteria 2${PLAIN}"
+    echo " -------------"
+    echo -e " ${GREEN}3.${PLAIN} 关闭、开启、重启 Hysteria 2"
+    echo -e " ${GREEN}4.${PLAIN} 修改 Hysteria 2 配置"
+    echo -e " ${GREEN}5.${PLAIN} 显示 Hysteria 2 配置文件"
+    echo " -------------"
+    echo -e " ${GREEN}6.${PLAIN} 更新 Hysteria 2 内核"
+    echo " -------------"
+    echo -e " ${GREEN}0.${PLAIN} 退出脚本"
+    echo ""
+    read -rp "请输入选项 [0-5]: " menuInput
+    case $menuInput in
+        1 ) insthysteria ;;
+        2 ) unsthysteria ;;
+        3 ) hysteriaswitch ;;
+        4 ) changeconf ;;
+        5 ) showconf ;;
+        6 ) update_core ;;
+        * ) exit 1 ;;
+    esac
+}
+
+menu

+ 203 - 0
install_CN.sh

@@ -0,0 +1,203 @@
+#!/bin/bash
+
+red='\033[0;31m'
+green='\033[0;32m'
+yellow='\033[0;33m'
+plain='\033[0m'
+
+cur_dir=$(pwd)
+
+# check root
+[[ $EUID -ne 0 ]] && echo -e "${red}错误:${plain} 必须使用root用户运行此脚本!\n" && exit 1
+
+# check os
+if [[ -f /etc/redhat-release ]]; then
+    release="centos"
+elif cat /etc/issue | grep -Eqi "debian"; then
+    release="debian"
+elif cat /etc/issue | grep -Eqi "ubuntu"; then
+    release="ubuntu"
+elif cat /etc/issue | grep -Eqi "centos|red hat|redhat"; then
+    release="centos"
+elif cat /proc/version | grep -Eqi "debian"; then
+    release="debian"
+elif cat /proc/version | grep -Eqi "ubuntu"; then
+    release="ubuntu"
+elif cat /proc/version | grep -Eqi "centos|red hat|redhat"; then
+    release="centos"
+else
+    echo -e "${red}未检测到系统版本,请联系脚本作者!${plain}\n" && exit 1
+fi
+
+arch=$(arch)
+
+if [[ $arch == "i386" || $arch == "i686" ]]; then
+    arch="386"
+elif [[ $arch == "x86_64" || $arch == "x64" || $arch == "amd64" ]]; then
+    arch="amd64"
+elif [[ $arch == "aarch64" || $arch == "arm64" ]]; then
+    arch="arm64"
+elif [[ $arch == "s390x" ]]; then
+    arch="s390x"
+else
+    arch="amd64"
+    echo -e "${red}检测架构失败,使用默认架构: ${arch}${plain}"
+fi
+
+echo "架构: ${arch}"
+
+if [ $(getconf WORD_BIT) != '32' ] && [ $(getconf LONG_BIT) != '64' ]; then
+    echo "本软件不支持 32 位系统(x86),请使用 64 位系统(x86_64),如果检测有误,请联系作者"
+    exit -1
+fi
+
+os_version=""
+
+# os version
+if [[ -f /etc/os-release ]]; then
+    os_version=$(awk -F'[= ."]' '/VERSION_ID/{print $3}' /etc/os-release)
+fi
+if [[ -z "$os_version" && -f /etc/lsb-release ]]; then
+    os_version=$(awk -F'[= ."]+' '/DISTRIB_RELEASE/{print $2}' /etc/lsb-release)
+fi
+
+if [[ x"${release}" == x"centos" ]]; then
+    if [[ ${os_version} -le 6 ]]; then
+        echo -e "${red}请使用 CentOS 7 或更高版本的系统!${plain}\n" && exit 1
+    fi
+elif [[ x"${release}" == x"ubuntu" ]]; then
+    if [[ ${os_version} -lt 16 ]]; then
+        echo -e "${red}请使用 Ubuntu 16 或更高版本的系统!${plain}\n" && exit 1
+    fi
+elif [[ x"${release}" == x"debian" ]]; then
+    if [[ ${os_version} -lt 8 ]]; then
+        echo -e "${red}请使用 Debian 8 或更高版本的系统!${plain}\n" && exit 1
+    fi
+fi
+
+install_base() {
+    if [[ x"${release}" == x"centos" ]]; then
+        yum install wget curl tar -y
+    else
+        apt-get update
+        apt install wget curl tar -y
+    fi
+}
+
+#This function will be called when user installed x-ui out of sercurity
+config_after_install() {
+    echo -e "${yellow}出于安全考虑,安装/更新完成后需要强制修改端口与账户密码${plain}"
+    read -p "确认是否继续? [y/n]: " config_confirm
+    if [[ x"${config_confirm}" == x"y" || x"${config_confirm}" == x"Y" ]]; then
+        read -p "请设置您的账户名(如未填写则随机8位字符): " config_account
+        [[ -z $config_account ]] && config_account=$(date +%s%N | md5sum | cut -c 1-8)
+        echo -e "${yellow}您的账户名将设定为:${config_account}${plain}"
+        read -p "请设置您的账户密码(如未填写则随机8位字符): " config_password
+        [[ -z $config_password ]] && config_password=$(date +%s%N | md5sum | cut -c 1-8)
+        echo -e "${yellow}您的账户密码将设定为:${config_password}${plain}"
+        read -p "请设置面板访问端口(如未填写则随机端口号): " config_port
+        [[ -z $config_port ]] && config_port=$(shuf -i 2000-65535 -n 1)
+        until [[ -z $(ss -ntlp | awk '{print $4}' | sed 's/.*://g' | grep -w "$port") ]]; do
+            if [[ -n $(ss -ntlp | awk '{print $4}' | sed 's/.*://g' | grep -w "$port") ]]; then
+                echo -e "${red} $config_port ${plain} 端口已经其他程序占用,请更换面板端口号"
+                read -p "请设置面板访问端口(如未填写则随机端口号): " config_port
+                [[ -z $config_port ]] && config_port=$(shuf -i 2000-65535 -n 1)
+            fi
+        done
+        echo -e "${yellow}您的面板访问端口将设定为:${config_port}${plain}"
+        echo -e "${yellow}确认设定,设定中${plain}"
+        /usr/local/x-ui/x-ui setting -username ${config_account} -password ${config_password}
+        echo -e "${yellow}账户密码设定完成${plain}"
+        /usr/local/x-ui/x-ui setting -port ${config_port}
+        echo -e "${yellow}面板端口设定完成${plain}"
+    else
+        config_port=$(/usr/local/x-ui/x-ui setting -show | sed -n 4p | awk -F ": " '{print $2}')
+        echo -e "${red}已取消, 所有设置项均为默认设置, 请及时修改${plain}"
+    fi
+}
+
+install_x-ui() {
+    systemctl stop x-ui
+    cd /usr/local/
+
+    if [ $# == 0 ]; then
+        last_version=$(curl -Ls "https://api.github.com/repos/sing-web/x-ui/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
+        if [[ ! -n "$last_version" ]]; then
+            echo -e "${red}检测 x-ui 版本失败,可能是超出 Github API 限制,请稍后再试,或手动指定 x-ui 版本安装${plain}"
+            exit 1
+        fi
+        echo -e "检测到 x-ui 最新版本:${last_version},开始安装"
+        wget -N --no-check-certificate -O /usr/local/x-ui-linux-${arch}.tar.gz https://github.com/sing-web/x-ui/releases/download/${last_version}/x-ui-linux-${arch}.tar.gz
+        if [[ $? -ne 0 ]]; then
+            echo -e "${red}下载 x-ui 失败,请确保你的服务器能够下载 Github 的文件${plain}"
+            exit 1
+        fi
+    else
+        last_version=$1
+        url="https://github.com/sing-web/x-ui/releases/download/${last_version}/x-ui-linux-${arch}.tar.gz"
+        echo -e "开始安装 x-ui $1"
+        wget -N --no-check-certificate -O /usr/local/x-ui-linux-${arch}.tar.gz ${url}
+        if [[ $? -ne 0 ]]; then
+            echo -e "${red}下载 x-ui $1 失败,请确保此版本存在${plain}"
+            exit 1
+        fi
+    fi
+
+    if [[ -e /usr/local/x-ui/ ]]; then
+        rm /usr/local/x-ui/ -rf
+    fi
+
+    tar zxvf x-ui-linux-${arch}.tar.gz
+    rm x-ui-linux-${arch}.tar.gz -f
+    cd x-ui
+    chmod +x x-ui bin/xray-linux-${arch}
+    cp -f x-ui.service /etc/systemd/system/
+    wget --no-check-certificate -O /usr/bin/x-ui https://raw.githubusercontent.com/sing-web/x-ui/main/x-ui_CN.sh
+    chmod +x /usr/local/x-ui/x-ui.sh
+    chmod +x /usr/bin/x-ui
+    config_after_install
+    #echo -e "如果是全新安装,默认网页端口为 ${green}54321${plain},用户名和密码默认都是 ${green}admin${plain}"
+    #echo -e "请自行确保此端口没有被其他程序占用,${yellow}并且确保 54321 端口已放行${plain}"
+    #    echo -e "若想将 54321 修改为其它端口,输入 x-ui 命令进行修改,同样也要确保你修改的端口也是放行的"
+    #echo -e ""
+    #echo -e "如果是更新面板,则按你之前的方式访问面板"
+    #echo -e ""
+    systemctl daemon-reload
+    systemctl enable x-ui
+    systemctl start x-ui
+    
+    systemctl stop warp-go >/dev/null 2>&1
+    wg-quick down wgcf >/dev/null 2>&1
+    ipv4=$(curl -s4m8 ip.p3terx.com -k | sed -n 1p)
+    ipv6=$(curl -s6m8 ip.p3terx.com -k | sed -n 1p)
+    systemctl start warp-go >/dev/null 2>&1
+    wg-quick up wgcf >/dev/null 2>&1
+    echo -e "${green}x-ui ${last_version}${plain} 安装完成,面板已启动"
+    echo -e ""
+    echo -e "x-ui 管理脚本使用方法: "
+    echo -e "----------------------------------------------"
+    echo -e "x-ui              - 显示管理菜单 (功能更多)"
+    echo -e "x-ui start        - 启动 x-ui 面板"
+    echo -e "x-ui stop         - 停止 x-ui 面板"
+    echo -e "x-ui restart      - 重启 x-ui 面板"
+    echo -e "x-ui status       - 查看 x-ui 状态"
+    echo -e "x-ui enable       - 设置 x-ui 开机自启"
+    echo -e "x-ui disable      - 取消 x-ui 开机自启"
+    echo -e "x-ui log          - 查看 x-ui 日志"
+    echo -e "x-ui update       - 更新 x-ui 面板"
+    echo -e "x-ui install      - 安装 x-ui 面板"
+    echo -e "x-ui uninstall    - 卸载 x-ui 面板"
+    echo -e "----------------------------------------------"
+    echo ""
+    if [[ -n $ipv4 ]]; then
+        echo -e "${yellow}面板IPv4访问地址为:${plain} ${green}http://$ipv4:$config_port ${plain}"
+    fi
+    if [[ -n $ipv6 ]]; then
+        echo -e "${yellow}面板IPv6访问地址为:${plain} ${green}http://[$ipv6]:$config_port ${plain}"
+    fi
+    echo -e "请自行确保此端口没有被其他程序占用,${yellow}并且确保${plain} ${red} $config_port ${plain} ${yellow}端口已放行${plain}"
+}
+
+echo -e "${green}开始安装${plain}"
+install_base
+install_x-ui $1

+ 417 - 0
mt_setup.sh

@@ -0,0 +1,417 @@
+#!/bin/bash
+# MTProto一键安装脚本
+# Author: palm<https://tizi.blog>
+
+RED="\033[31m"      # Error message
+GREEN="\033[32m"    # Success message
+YELLOW="\033[33m"   # Warning message
+BLUE="\033[36m"     # Info message
+PLAIN='\033[0m'
+
+export MTG_CONFIG="${MTG_CONFIG:-$HOME/.config/mtg}"
+export MTG_ENV="$MTG_CONFIG/env"
+export MTG_SECRET="$MTG_CONFIG/secret"
+export MTG_CONTAINER="${MTG_CONTAINER:-mtg}"
+export MTG_IMAGENAME="${MTG_IMAGENAME:-nineseconds/mtg:1}"
+
+DOCKER_CMD="$(command -v docker)"
+OSNAME=`hostnamectl | grep -i system | cut -d: -f2`
+
+IP=`curl -sL -4 ip.sb`
+
+colorEcho() {
+    echo -e "${1}${@:2}${PLAIN}"
+}
+
+checkSystem() {
+    result=$(id | awk '{print $1}')
+    if [[ $result != "uid=0(root)" ]]; then
+        colorEcho $RED " 请以root身份执行该脚本"
+        exit 1
+    fi
+
+    res=`which yum`
+    if [[ "$?" != "0" ]]; then
+        res=`which apt`
+        if [ "$?" != "0" ]; then
+            colorEcho $RED " 不受支持的Linux系统"
+            exit 1
+        fi
+        res=`hostnamectl | grep -i ubuntu`
+        if [[ "${res}" != "" ]]; then
+            OS="ubuntu"
+        else
+            OS="debian"
+        fi
+        PMT="apt"
+        CMD_INSTALL="apt install -y "
+        CMD_REMOVE="apt remove -y "
+    else
+        OS="centos"
+        PMT="yum"
+        CMD_INSTALL="yum install -y "
+        CMD_REMOVE="yum remove -y "
+    fi
+    res=`which systemctl`
+    if [[ "$?" != "0" ]]; then
+        colorEcho $RED " 系统版本过低,请升级到最新版本"
+        exit 1
+    fi
+}
+
+status() {
+    if [[ "$DOCKER_CMD" = "" ]]; then
+        echo 0
+        return
+    elif [[ ! -f $MTG_ENV ]]; then
+        echo 1
+        return
+    fi
+    port=`grep MTG_PORT $MTG_ENV|cut -d= -f2`
+    if [[ -z "$port" ]]; then
+        echo 2
+        return
+    fi
+    res=`ss -ntlp| grep ${port} | grep docker`
+    if [[ -z "$res" ]]; then
+        echo 3
+    else
+        echo 4
+    fi
+}
+
+statusText() {
+    res=`status`
+    case $res in
+        3)
+            echo -e ${GREEN}已安装${PLAIN} ${RED}未运行${PLAIN}
+            ;;
+        4)
+            echo -e ${GREEN}已安装${PLAIN} ${GREEN}正在运行${PLAIN}
+            ;;
+        *)
+            echo -e ${RED}未安装${PLAIN}
+            ;;
+    esac
+}
+
+getData() {
+    read -p " 请输入MTProto端口[100-65535的一个数字]:" PORT
+    [[ -z "${PORT}" ]] && {
+        echo -e " ${RED}请输入MTProto端口!${PLAIN}"
+        exit 1
+    }
+    if [[ "${PORT:0:1}" = "0" ]]; then
+        echo -e " ${RED}端口不能以0开头${PLAIN}"
+        exit 1
+    fi
+    MTG_PORT=$PORT
+    mkdir -p $MTG_CONFIG
+    echo "MTG_IMAGENAME=$MTG_IMAGENAME" > "$MTG_ENV"
+    echo "MTG_PORT=$MTG_PORT" >> "$MTG_ENV"
+    echo "MTG_CONTAINER=$MTG_CONTAINER" >> "$MTG_ENV"
+}
+
+installDocker() {
+    if [[ "$DOCKER_CMD" != "" ]]; then
+        systemctl enable docker
+        systemctl start docker
+        selinux
+        return
+    fi
+
+    #$CMD_REMOVE docker docker-engine docker.io containerd runc
+    $PMT clean all
+    $CMD_INSTALL wget curl
+    if [[ $PMT = "apt" ]]; then
+        apt clean all
+		apt-get -y install \
+			apt-transport-https \
+			ca-certificates \
+			curl \
+			gnupg-agent \
+			software-properties-common
+        curl -fsSL https://download.docker.com/linux/$OS/gpg | apt-key add -
+        add-apt-repository \
+            "deb [arch=amd64] https://download.docker.com/linux/$OS \
+            $(lsb_release -cs) \
+            stable"
+        apt update
+    else
+        wget -O /etc/yum.repos.d/docker-ce.repo https://download.docker.com/linux/centos/docker-ce.repo
+        yum clean all
+    fi
+    $CMD_INSTALL docker-ce docker-ce-cli containerd.io
+
+    DOCKER_CMD="$(command -v docker)"
+    if [[ "$DOCKER_CMD" = "" ]]; then
+        echo -e " ${RED}$OSNAME docker安装失败,请到https://tizi.blog反馈${PLAIN}"
+        exit 1
+    fi
+    systemctl enable docker
+    systemctl start docker
+
+    selinux
+}
+
+pullImage() {
+    if [[ "$DOCKER_CMD" = "" ]]; then
+        echo -e " ${RED}MTProto未安装,请先安装!${PLAIN}"
+        exit 1
+    fi
+
+    set -a
+    source "$MTG_ENV"
+    set +a
+
+    $DOCKER_CMD pull "$MTG_IMAGENAME" > /dev/null
+}
+
+selinux() {
+    if [[ -s /etc/selinux/config ]] && grep 'SELINUX=enforcing' /etc/selinux/config; then
+        sed -i 's/SELINUX=enforcing/SELINUX=permissive/g' /etc/selinux/config
+        setenforce 0
+    fi
+}
+
+firewall() {
+    port=$1
+    systemctl status firewalld > /dev/null 2>&1
+    if [[ $? -eq 0 ]];then
+        firewall-cmd --permanent --add-port=$port/tcp
+        firewall-cmd --reload
+    else
+        nl=`iptables -nL | nl | grep FORWARD | awk '{print $1}'`
+        if [ "$nl" != "3" ]; then
+            iptables -I INPUT -p tcp --dport=$port -j ACCEPT
+        else
+            res=`ufw status | grep -i inactive`
+            if [ "$res" = "" ]; then
+                ufw allow $port/tcp
+            fi
+        fi
+    fi
+}
+
+start() {
+    res=`status`
+    if [[ $res -lt 3 ]]; then
+        echo -e " ${RED}MTProto未安装,请先安装!${PLAIN}"
+        return
+    fi
+
+    set -a
+    source "$MTG_ENV"
+    set +a
+
+    if [[ ! -f "$MTG_SECRET" ]]; then
+        $DOCKER_CMD run \
+                --rm \
+                "$MTG_IMAGENAME" \
+            generate-secret tls -c "$(openssl rand -hex 16).com" \
+        > "$MTG_SECRET"
+    fi
+
+    $DOCKER_CMD ps --filter "Name=$MTG_CONTAINER" -aq | xargs -r $DOCKER_CMD rm -fv > /dev/null
+    $DOCKER_CMD run \
+            -d \
+            --restart=unless-stopped \
+            --name "$MTG_CONTAINER" \
+            --ulimit nofile=51200:51200 \
+            -p "$MTG_PORT:3128" \
+        "$MTG_IMAGENAME" run "$(cat "$MTG_SECRET")" > /dev/null
+
+    sleep 3
+    res=`ss -ntlp| grep ${MTG_PORT} | grep docker`
+    if [[ "$res" = "" ]]; then
+        docker logs $MTG_CONTAINER | tail
+        echo -e " ${RED}$OSNAME 启动docker镜像失败,请到 https://tizi.blog 反馈${PLAIN}"
+        exit 1
+    else
+        colorEcho $BLUE " MTProto启动成功!"
+    fi
+}
+
+stop() {
+    res=`status`
+    if [[ $res -lt 3 ]]; then
+        echo -e " ${RED}MTProto未安装,请先安装!${PLAIN}"
+        return
+    fi
+
+    set -a
+    source "$MTG_ENV"
+    set +a
+
+    $DOCKER_CMD stop $MTG_CONTAINER >> /dev/null
+    colorEcho $BLUE " MTProto停止成功!"
+}
+
+showInfo() {
+    res=`status`
+    if [[ $res -lt 3 ]]; then
+        echo -e " ${RED}MTProto未安装,请先安装!${PLAIN}"
+        return
+    fi
+
+    SECRET=$(cat "$MTG_SECRET")
+    set -a
+    source "$MTG_ENV"
+    set +a
+
+    echo 
+    echo -e " ${RED}MTProto代理信息:${PLAIN}"
+    echo 
+    echo -n -e "  ${BLUE}当前状态:${PLAIN}"
+    statusText
+    echo -e "  ${BLUE}IP:${PLAIN}${RED}$IP${PLAIN}"
+    echo -e "  ${BLUE}端口:${PLAIN}${RED}$MTG_PORT${PLAIN}"
+    echo -e "  ${BLUE}密钥:${PLAIN}${RED}$SECRET${PLAIN}"
+    echo ""
+    echo -e "  如需获取tg://proxy形式的链接,请打开telegrame关注${GREEN}@MTProxybot${PLAIN}生成"
+    echo ""
+}
+
+install() {
+    getData
+    installDocker
+    pullImage
+    start
+    firewall $MTG_PORT
+    showInfo
+}
+
+update() {
+    res=`status`
+    if [[ $res -lt 2 ]]; then
+        echo -e " ${RED}MTProto未安装,请先安装!${PLAIN}"
+        return
+    fi
+
+    pullImage
+    stop
+    start
+    showInfo
+}
+
+uninstall() {
+    echo ""
+    read -p " 确定卸载MTProto?[y/n]:" answer
+    if [[ "$answer" = "y" ]] || [[ "$answer" = "Y" ]]; then
+        stop
+        rm -rf $MTG_CONFIG
+        docker system prune -af
+        systemctl stop docker
+        systemctl disable docker
+        $CMD_REMOVE docker-ce docker-ce-cli containerd.io
+        colorEcho $GREEN " 卸载成功"
+    fi
+}
+
+restart() {
+    res=`status`
+    if [[ $res -lt 3 ]]; then
+        echo -e " ${RED}MTProto未安装,请先安装!${PLAIN}"
+        return
+    fi
+
+    stop
+    start
+}
+
+reconfig()
+{
+    res=`status`
+    if [[ $res -lt 2 ]]; then
+        echo -e " ${RED}MTProto未安装,请先安装!${PLAIN}"
+        return
+    fi
+
+    getData
+    stop
+    start
+    firewall $MTG_PORT
+    showInfo
+}
+
+showLog() {
+    res=`status`
+    if [[ $res -lt 3 ]]; then
+        echo -e " ${RED}MTProto未安装,请先安装!${PLAIN}"
+        return
+    fi
+
+    set -a
+    source "$MTG_ENV"
+    set +a
+
+    $DOCKER_CMD logs $MTG_CONTAINER | tail
+}
+
+menu() {
+    clear
+    echo "#############################################################"
+    echo -e "#                    ${RED}MTProto一键安装脚本${PLAIN}                    #"
+    echo "#############################################################"
+    echo ""
+
+    echo -e "  ${GREEN}1.${PLAIN} 安装MTProto代理"
+    echo -e "  ${GREEN}2.${PLAIN} 更新MTProto代理"
+    echo -e "  ${GREEN}3.${PLAIN} 卸载MTProto代理"
+    echo " -------------"
+    echo -e "  ${GREEN}4.${PLAIN} 启动MTProto代理"
+    echo -e "  ${GREEN}5.${PLAIN} 重启MTProto代理"
+    echo -e "  ${GREEN}6.${PLAIN} 停止MTProto代理"
+    echo " -------------"
+    echo -e "  ${GREEN}7.${PLAIN} 查看MTProto信息"
+    echo -e "  ${GREEN}8.${PLAIN} 修改MTProto配置"
+    echo -e "  ${GREEN}9.${PLAIN} 查看MTProto日志"
+    echo " -------------"
+    echo -e "  ${GREEN}0.${PLAIN} 退出"
+    echo 
+    echo -n " 当前状态:"
+    statusText
+    echo 
+
+    read -p " 请选择操作[0-9]:" answer
+    case $answer in
+        0)
+            exit 0
+            ;;
+        1)
+            install
+            ;;
+        2)
+            update
+            ;;
+        3)
+            uninstall
+            ;;
+        4)
+            start
+            ;;
+        5)
+            restart
+            ;;
+        6)
+            stop
+            ;;
+        7)
+            showInfo
+            ;;
+        8)
+            reconfig
+            ;;
+        9)
+            showLog
+            ;;
+        *)
+            echo -e " ${RED}请选择正确的操作!${PLAIN}"
+            exit 1
+            ;;
+    esac
+}
+
+checkSystem
+
+menu

+ 417 - 0
mt_setup.sh.1

@@ -0,0 +1,417 @@
+#!/bin/bash
+# MTProto一键安装脚本
+# Author: palm<https://tizi.blog>
+
+RED="\033[31m"      # Error message
+GREEN="\033[32m"    # Success message
+YELLOW="\033[33m"   # Warning message
+BLUE="\033[36m"     # Info message
+PLAIN='\033[0m'
+
+export MTG_CONFIG="${MTG_CONFIG:-$HOME/.config/mtg}"
+export MTG_ENV="$MTG_CONFIG/env"
+export MTG_SECRET="$MTG_CONFIG/secret"
+export MTG_CONTAINER="${MTG_CONTAINER:-mtg}"
+export MTG_IMAGENAME="${MTG_IMAGENAME:-nineseconds/mtg:1}"
+
+DOCKER_CMD="$(command -v docker)"
+OSNAME=`hostnamectl | grep -i system | cut -d: -f2`
+
+IP=`curl -sL -4 ip.sb`
+
+colorEcho() {
+    echo -e "${1}${@:2}${PLAIN}"
+}
+
+checkSystem() {
+    result=$(id | awk '{print $1}')
+    if [[ $result != "uid=0(root)" ]]; then
+        colorEcho $RED " 请以root身份执行该脚本"
+        exit 1
+    fi
+
+    res=`which yum`
+    if [[ "$?" != "0" ]]; then
+        res=`which apt`
+        if [ "$?" != "0" ]; then
+            colorEcho $RED " 不受支持的Linux系统"
+            exit 1
+        fi
+        res=`hostnamectl | grep -i ubuntu`
+        if [[ "${res}" != "" ]]; then
+            OS="ubuntu"
+        else
+            OS="debian"
+        fi
+        PMT="apt"
+        CMD_INSTALL="apt install -y "
+        CMD_REMOVE="apt remove -y "
+    else
+        OS="centos"
+        PMT="yum"
+        CMD_INSTALL="yum install -y "
+        CMD_REMOVE="yum remove -y "
+    fi
+    res=`which systemctl`
+    if [[ "$?" != "0" ]]; then
+        colorEcho $RED " 系统版本过低,请升级到最新版本"
+        exit 1
+    fi
+}
+
+status() {
+    if [[ "$DOCKER_CMD" = "" ]]; then
+        echo 0
+        return
+    elif [[ ! -f $MTG_ENV ]]; then
+        echo 1
+        return
+    fi
+    port=`grep MTG_PORT $MTG_ENV|cut -d= -f2`
+    if [[ -z "$port" ]]; then
+        echo 2
+        return
+    fi
+    res=`ss -ntlp| grep ${port} | grep docker`
+    if [[ -z "$res" ]]; then
+        echo 3
+    else
+        echo 4
+    fi
+}
+
+statusText() {
+    res=`status`
+    case $res in
+        3)
+            echo -e ${GREEN}已安装${PLAIN} ${RED}未运行${PLAIN}
+            ;;
+        4)
+            echo -e ${GREEN}已安装${PLAIN} ${GREEN}正在运行${PLAIN}
+            ;;
+        *)
+            echo -e ${RED}未安装${PLAIN}
+            ;;
+    esac
+}
+
+getData() {
+    read -p " 请输入MTProto端口[100-65535的一个数字]:" PORT
+    [[ -z "${PORT}" ]] && {
+        echo -e " ${RED}请输入MTProto端口!${PLAIN}"
+        exit 1
+    }
+    if [[ "${PORT:0:1}" = "0" ]]; then
+        echo -e " ${RED}端口不能以0开头${PLAIN}"
+        exit 1
+    fi
+    MTG_PORT=$PORT
+    mkdir -p $MTG_CONFIG
+    echo "MTG_IMAGENAME=$MTG_IMAGENAME" > "$MTG_ENV"
+    echo "MTG_PORT=$MTG_PORT" >> "$MTG_ENV"
+    echo "MTG_CONTAINER=$MTG_CONTAINER" >> "$MTG_ENV"
+}
+
+installDocker() {
+    if [[ "$DOCKER_CMD" != "" ]]; then
+        systemctl enable docker
+        systemctl start docker
+        selinux
+        return
+    fi
+
+    #$CMD_REMOVE docker docker-engine docker.io containerd runc
+    $PMT clean all
+    $CMD_INSTALL wget curl
+    if [[ $PMT = "apt" ]]; then
+        apt clean all
+		apt-get -y install \
+			apt-transport-https \
+			ca-certificates \
+			curl \
+			gnupg-agent \
+			software-properties-common
+        curl -fsSL https://download.docker.com/linux/$OS/gpg | apt-key add -
+        add-apt-repository \
+            "deb [arch=amd64] https://download.docker.com/linux/$OS \
+            $(lsb_release -cs) \
+            stable"
+        apt update
+    else
+        wget -O /etc/yum.repos.d/docker-ce.repo https://download.docker.com/linux/centos/docker-ce.repo
+        yum clean all
+    fi
+    $CMD_INSTALL docker-ce docker-ce-cli containerd.io
+
+    DOCKER_CMD="$(command -v docker)"
+    if [[ "$DOCKER_CMD" = "" ]]; then
+        echo -e " ${RED}$OSNAME docker安装失败,请到https://tizi.blog反馈${PLAIN}"
+        exit 1
+    fi
+    systemctl enable docker
+    systemctl start docker
+
+    selinux
+}
+
+pullImage() {
+    if [[ "$DOCKER_CMD" = "" ]]; then
+        echo -e " ${RED}MTProto未安装,请先安装!${PLAIN}"
+        exit 1
+    fi
+
+    set -a
+    source "$MTG_ENV"
+    set +a
+
+    $DOCKER_CMD pull "$MTG_IMAGENAME" > /dev/null
+}
+
+selinux() {
+    if [[ -s /etc/selinux/config ]] && grep 'SELINUX=enforcing' /etc/selinux/config; then
+        sed -i 's/SELINUX=enforcing/SELINUX=permissive/g' /etc/selinux/config
+        setenforce 0
+    fi
+}
+
+firewall() {
+    port=$1
+    systemctl status firewalld > /dev/null 2>&1
+    if [[ $? -eq 0 ]];then
+        firewall-cmd --permanent --add-port=$port/tcp
+        firewall-cmd --reload
+    else
+        nl=`iptables -nL | nl | grep FORWARD | awk '{print $1}'`
+        if [ "$nl" != "3" ]; then
+            iptables -I INPUT -p tcp --dport=$port -j ACCEPT
+        else
+            res=`ufw status | grep -i inactive`
+            if [ "$res" = "" ]; then
+                ufw allow $port/tcp
+            fi
+        fi
+    fi
+}
+
+start() {
+    res=`status`
+    if [[ $res -lt 3 ]]; then
+        echo -e " ${RED}MTProto未安装,请先安装!${PLAIN}"
+        return
+    fi
+
+    set -a
+    source "$MTG_ENV"
+    set +a
+
+    if [[ ! -f "$MTG_SECRET" ]]; then
+        $DOCKER_CMD run \
+                --rm \
+                "$MTG_IMAGENAME" \
+            generate-secret tls -c "$(openssl rand -hex 16).com" \
+        > "$MTG_SECRET"
+    fi
+
+    $DOCKER_CMD ps --filter "Name=$MTG_CONTAINER" -aq | xargs -r $DOCKER_CMD rm -fv > /dev/null
+    $DOCKER_CMD run \
+            -d \
+            --restart=unless-stopped \
+            --name "$MTG_CONTAINER" \
+            --ulimit nofile=51200:51200 \
+            -p "$MTG_PORT:3128" \
+        "$MTG_IMAGENAME" run "$(cat "$MTG_SECRET")" > /dev/null
+
+    sleep 3
+    res=`ss -ntlp| grep ${MTG_PORT} | grep docker`
+    if [[ "$res" = "" ]]; then
+        docker logs $MTG_CONTAINER | tail
+        echo -e " ${RED}$OSNAME 启动docker镜像失败,请到 https://tizi.blog 反馈${PLAIN}"
+        exit 1
+    else
+        colorEcho $BLUE " MTProto启动成功!"
+    fi
+}
+
+stop() {
+    res=`status`
+    if [[ $res -lt 3 ]]; then
+        echo -e " ${RED}MTProto未安装,请先安装!${PLAIN}"
+        return
+    fi
+
+    set -a
+    source "$MTG_ENV"
+    set +a
+
+    $DOCKER_CMD stop $MTG_CONTAINER >> /dev/null
+    colorEcho $BLUE " MTProto停止成功!"
+}
+
+showInfo() {
+    res=`status`
+    if [[ $res -lt 3 ]]; then
+        echo -e " ${RED}MTProto未安装,请先安装!${PLAIN}"
+        return
+    fi
+
+    SECRET=$(cat "$MTG_SECRET")
+    set -a
+    source "$MTG_ENV"
+    set +a
+
+    echo 
+    echo -e " ${RED}MTProto代理信息:${PLAIN}"
+    echo 
+    echo -n -e "  ${BLUE}当前状态:${PLAIN}"
+    statusText
+    echo -e "  ${BLUE}IP:${PLAIN}${RED}$IP${PLAIN}"
+    echo -e "  ${BLUE}端口:${PLAIN}${RED}$MTG_PORT${PLAIN}"
+    echo -e "  ${BLUE}密钥:${PLAIN}${RED}$SECRET${PLAIN}"
+    echo ""
+    echo -e "  如需获取tg://proxy形式的链接,请打开telegrame关注${GREEN}@MTProxybot${PLAIN}生成"
+    echo ""
+}
+
+install() {
+    getData
+    installDocker
+    pullImage
+    start
+    firewall $MTG_PORT
+    showInfo
+}
+
+update() {
+    res=`status`
+    if [[ $res -lt 2 ]]; then
+        echo -e " ${RED}MTProto未安装,请先安装!${PLAIN}"
+        return
+    fi
+
+    pullImage
+    stop
+    start
+    showInfo
+}
+
+uninstall() {
+    echo ""
+    read -p " 确定卸载MTProto?[y/n]:" answer
+    if [[ "$answer" = "y" ]] || [[ "$answer" = "Y" ]]; then
+        stop
+        rm -rf $MTG_CONFIG
+        docker system prune -af
+        systemctl stop docker
+        systemctl disable docker
+        $CMD_REMOVE docker-ce docker-ce-cli containerd.io
+        colorEcho $GREEN " 卸载成功"
+    fi
+}
+
+restart() {
+    res=`status`
+    if [[ $res -lt 3 ]]; then
+        echo -e " ${RED}MTProto未安装,请先安装!${PLAIN}"
+        return
+    fi
+
+    stop
+    start
+}
+
+reconfig()
+{
+    res=`status`
+    if [[ $res -lt 2 ]]; then
+        echo -e " ${RED}MTProto未安装,请先安装!${PLAIN}"
+        return
+    fi
+
+    getData
+    stop
+    start
+    firewall $MTG_PORT
+    showInfo
+}
+
+showLog() {
+    res=`status`
+    if [[ $res -lt 3 ]]; then
+        echo -e " ${RED}MTProto未安装,请先安装!${PLAIN}"
+        return
+    fi
+
+    set -a
+    source "$MTG_ENV"
+    set +a
+
+    $DOCKER_CMD logs $MTG_CONTAINER | tail
+}
+
+menu() {
+    clear
+    echo "#############################################################"
+    echo -e "#                    ${RED}MTProto一键安装脚本${PLAIN}                    #"
+    echo "#############################################################"
+    echo ""
+
+    echo -e "  ${GREEN}1.${PLAIN} 安装MTProto代理"
+    echo -e "  ${GREEN}2.${PLAIN} 更新MTProto代理"
+    echo -e "  ${GREEN}3.${PLAIN} 卸载MTProto代理"
+    echo " -------------"
+    echo -e "  ${GREEN}4.${PLAIN} 启动MTProto代理"
+    echo -e "  ${GREEN}5.${PLAIN} 重启MTProto代理"
+    echo -e "  ${GREEN}6.${PLAIN} 停止MTProto代理"
+    echo " -------------"
+    echo -e "  ${GREEN}7.${PLAIN} 查看MTProto信息"
+    echo -e "  ${GREEN}8.${PLAIN} 修改MTProto配置"
+    echo -e "  ${GREEN}9.${PLAIN} 查看MTProto日志"
+    echo " -------------"
+    echo -e "  ${GREEN}0.${PLAIN} 退出"
+    echo 
+    echo -n " 当前状态:"
+    statusText
+    echo 
+
+    read -p " 请选择操作[0-9]:" answer
+    case $answer in
+        0)
+            exit 0
+            ;;
+        1)
+            install
+            ;;
+        2)
+            update
+            ;;
+        3)
+            uninstall
+            ;;
+        4)
+            start
+            ;;
+        5)
+            restart
+            ;;
+        6)
+            stop
+            ;;
+        7)
+            showInfo
+            ;;
+        8)
+            reconfig
+            ;;
+        9)
+            showLog
+            ;;
+        *)
+            echo -e " ${RED}请选择正确的操作!${PLAIN}"
+            exit 1
+            ;;
+    esac
+}
+
+checkSystem
+
+menu

File diff suppressed because it is too large
+ 2472 - 0
singbox.sh


+ 0 - 0
snell.sh


+ 1867 - 0
ss-rust.sh

@@ -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

Some files were not shown because too many files changed in this diff