├── .github └── workflows │ └── work.yml ├── LICENSE ├── README.md ├── arm64.config ├── bbr_manage.sh ├── config └── v2ray.json ├── github └── workflows │ └── auto-fix-bbr.yml ├── install.sh ├── lvhy.sh ├── modify_node_params.sh ├── scripts └── enable_bbr.sh └── x86-64.config /.github/workflows/work.yml: -------------------------------------------------------------------------------- 1 | name: 自动修复BBR管理与主脚本适配 2 | on: 3 | workflow_dispatch: 4 | 5 | jobs: 6 | fix-bbr: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: 拉取仓库代码 10 | uses: actions/checkout@v4 11 | 12 | - name: 修正 lvhy.sh BBR 管理菜单路径 13 | run: | 14 | sed -i '/5)/,/\.\.\./c\ 15 | 5)\ 16 | BBR_MANAGE_PATH="$(dirname "\$0")/bbr_manage.sh"\ 17 | if [ -f "\$BBR_MANAGE_PATH" ]; then\ 18 | source "\$BBR_MANAGE_PATH"\ 19 | else\ 20 | echo "未找到 bbr_manage.sh,请检查文件是否存在。";\ 21 | read -n 1 -s -r -p "按任意键返回工具箱...";\ 22 | fi\ 23 | ;;' lvhy.sh 24 | 25 | - name: 修正 bbr_manage.sh 结尾 26 | run: | 27 | echo -e '\necho -e "\\n已返回主菜单"\nread -n 1 -s -r -p "按任意键返回工具箱..."\nreturn 2>/dev/null' >> bbr_manage.sh 28 | 29 | - name: 提交更改 30 | run: | 31 | git config user.name "github-actions[bot]" 32 | git config user.email "41898282+github-actions[bot]@users.noreply.github.com" 33 | git add lvhy.sh bbr_manage.sh 34 | git commit -m "fix: 自动修复BBR菜单与主脚本交互" 35 | git push 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 shangguancaiyun 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # One-Click-Proxy-Installer 一键安装脚本 5 | 6 | ## 🌟 简介 7 | 8 | > 真正适合小白折腾的脚本!当然,大白也可以按需服用哦! 9 | > 快捷启动命令:`box` 10 | 11 | 本脚本用于在 Linux 服务器上快速安装、配置和管理 [Sing-Box](https://github.com/SagerNet/sing-box),特别针对 Hysteria2 和 VLESS Reality 协议优化。 12 | 13 | --- 14 | 15 | ## ✨ 使用方法 16 | 17 | **更新系统(可选):** 18 | 19 | ```bash 20 | apt-get update && apt-get install -y curl 21 | ``` 22 | **命令1. 下载脚本并启动:(报错则更新系统或下载curl)(安装命令不要去做一个保存后面会优化启动命令)** 23 | 24 | ```bash 25 | curl -fsSL "https://github.com/shangguancaiyun/One-Click-Proxy-Installer/raw/main/lvhy.sh" -o lvhy.sh && 26 | curl -fsSL "https://github.com/shangguancaiyun/One-Click-Proxy-Installer/raw/main/modify_node_params.sh" -o modify_node_params.sh && 27 | curl -fsSL "https://github.com/shangguancaiyun/One-Click-Proxy-Installer/raw/main/bbr_manage.sh" -o bbr_manage.sh && 28 | curl -fsSL "https://github.com/shangguancaiyun/One-Click-Proxy-Installer/raw/main/install.sh" -o install.sh && 29 | chmod +x lvhy.sh modify_node_params.sh bbr_manage.sh install.sh && 30 | bash ./lvhy.sh 31 | ``` 32 | 33 | **命令2. 再次运行可启动脚本,之后可快捷命令: `box`** 34 | 35 | ```bash 36 | sudo bash lvhy.sh 37 | ``` 38 | 39 | 脚本将以 root 权限运行,并显示主菜单。 40 | 41 | **3. 按提示选择菜单,输入数字即可完成安装和管理。** 42 | 43 | - 1:一键安装 Hysteria2 + Reality(共存) 44 | - 2:只装 Hysteria2 45 | - 3:只装 Reality (VLESS) 46 | - 其他选项可管理服务、查看/编辑配置、卸载等 47 | 48 | **4. 安装完成后,终端会显示所有节点和二维码,直接扫码或复制即可食用。** 49 | 50 | --- 51 | 52 | ## 常见问题 53 | 54 | - **需要 root 权限**:请用 `sudo` 运行脚本。 55 | - **依赖自动安装**:脚本会自动检测并安装 curl、openssl、qrencode 等依赖。 56 | - **配置文件路径**:`/usr/local/etc/sing-box/config.json` 57 | - **导入信息保存**:上次安装的节点信息会自动保存,可随时通过菜单查看。 58 | - **防火墙端口**:如有防火墙,需放行你选择的端口(如 443、8443)。 59 | 60 | --- 61 | 62 | ## 菜单选项说明:你会看到类似的页面 63 | 64 | ``` 65 | ================================================ 66 | Sing-Box Hysteria2 & Reality 管理脚本 67 | ================================================ 68 | 作者: Zhong Yuan 69 | ================================================ 70 | 安装选项: 71 | 1. 安装 Hysteria2 + Reality (共存) 72 | 2. 单独安装 Hysteria2 73 | 3. 单独安装 Reality (VLESS) 74 | ------------------------------------------------ 75 | 管理选项: 76 | 4. 启动 Sing-box 服务 77 | 5. 停止 Sing-box 服务 78 | 6. 重启 Sing-box 服务 79 | 7. 查看 Sing-box 服务状态 80 | 8. 查看 Sing-box 实时日志 81 | 9. 查看当前配置文件 82 | 10. 编辑当前配置文件 (使用 nano) 83 | 11. 显示上次保存的导入信息 (含二维码) 84 | ------------------------------------------------ 85 | 其他选项: 86 | 12. 更新 Sing-box 内核 (使用官方beta脚本) 87 | 13. 卸载 Sing-box 88 | 0. 退出脚本 89 | ================================================ 90 | ``` 91 | 92 | --- 93 | 94 | ## 注意事项 95 | 96 | - **防火墙**:如启用 ufw/firewalld,需放行相关端口。 97 | - 例如 Reality 用 443,Hysteria2 用 8443: 98 | ```bash 99 | sudo ufw allow 443/tcp 100 | sudo ufw allow 8443/tcp 101 | sudo ufw allow 8443/udp # Hysteria2 需要 UDP 102 | sudo ufw reload 103 | ``` 104 | - **端口选择:选 443、8443、80、8080 这类常见端口,更容易伪装成正常网站流量。当然,选择其他端口也可以联通!** 105 | 106 | - **在线订阅转换网站**:[订阅转换](https://sub.crazyact.com/) 107 | 108 | --- 109 | 110 | ## 推荐工具箱/三方客户端/实用网站 111 | 112 | - [老王一键工具箱](https://github.com/eooce/ssh_tool):适合小白用户搭建科学上网。 113 | 114 | ```bash 115 | curl -fsSL https://raw.githubusercontent.com/eooce/ssh_tool/main/ssh_tool.sh -o ssh_tool.sh && chmod +x ssh_tool.sh && ./ssh_tool.sh#建议快捷命令改为 w 避免冲突! 116 | ``` 117 | 118 | - [科技lion一键脚本](https://kejilion.sh/index-zh-CN.html):适合无基础小白网站的建设与维护。 119 | 120 | ```bash 121 | bash <(curl -sL kejilion.sh)#建议快捷命令改为 i 122 | ``` 123 | 124 | - 安卓/iOS/PC 推荐客户端: 125 | - [Karing](https://github.com/KaringX/karing/releases)(全平台免费开源,强烈推荐) 126 | - [nekobox](https://github.com/MatsuriDayo/NekoBoxForAndroid/releases) 127 | - [husi](https://github.com/xchacha20-poly1305/husi/releases) 128 | - [Clash-Meta](https://github.com/MetaCubeX/ClashMetaForAndroid/releases) 129 | - [hiddify](https://github.com/hiddify/hiddify-next/releases) 130 | - [v2rayNG](https://github.com/2dust/v2rayNG/releases)(安卓设备首选) 131 | - [Clash-Verge](https://github.com/clash-verge-rev/clash-verge-rev/releases) 132 | - [v2rayN](https://github.com/2dust/v2rayN/releases)(Win电脑PC端) 133 | 134 | - 服务器推荐:[akile](https://akile.io/register?aff_code=99532291-0323-491e-bdd7-fbcfebbd1fa5) 135 | 136 | 137 | - 实用网站推荐: 138 | - [libretv-自建影视](https://053312d1.libretv-edb.pages.dev/)进入密码:123 139 | - [磁力熊](https://www.cilixiong.org/)也是影视! 140 | - [IP质量检测](https://ipjiance.com/) 141 | - [IP纯净度检测](https://scamalytics.com/​) 142 | - [节点测速](https://fiber.google.com/speedtest/) 143 | - [ip.sb](https://ip.sb/) 144 | - [ip泄露真实地址检测](https://dw.jhb.ovh/),非你所处真实地址则没泄露! 145 | - [CF网址:](https://www.cloudflare.com/zh-cn/)CloudFlare 146 | 147 | --- 148 | 149 | ## VPS仅IPV6/IPV4 脚本推荐 150 | 151 | - [WARP 一键脚本](https://gitlab.com/fscarmen/warp)先套IPV4/IPV6: 152 | 153 | ```bash 154 | wget -N https://gitlab.com/fscarmen/warp/-/raw/main/menu.sh && bash menu.sh [option] [lisence/url/token] 155 | ``` 156 | 157 | --- 158 | - 再次感谢兄弟们的支持!不会让兄弟们失望的! 159 | - 未来会在便捷实用的基础上加以完善此项目,敬请关注!•᷄ࡇ•᷅ 160 | --- 161 | 162 | ## 贡献 163 | 164 | 欢迎提交 Pull Requests 或在 Issues 中报告错误、提出建议。 165 | 166 | ## 开源协议 167 | 168 | MIT License | 维护者:Zhong Yuan 169 | 170 | ## 免责声明 171 | 172 | - 本脚本仅供学习和测试,请勿用于非法用途。 173 | - 作者不对使用此脚本可能造成的任何后果负责。 174 | 175 | ## 致谢 176 | 177 | - [Sing-Box](https://github.com/SagerNet/sing-box) 178 | - 感谢[项目](https://github.com/Netflixxp/vlhy2)及其开发者,提供的技术支持与灵感参考。 179 | - 所有为开源社区做出贡献的人 180 | - [副本](https://github.com/shangguan3366/One-Click-Proxy-Installer) 181 | 182 | 183 | ## Star History 184 | 185 | [![Star History 186 | Chart](https://api.star-history.com/svg?repos=shangguancaiyun/One-Click-Proxy-Installer&type=Date)](https://www.star-history.com/#shangguancaiyun/One-Click-Proxy-Installer&Date) 187 | 188 | 189 | 190 | -------------------------------------------------------------------------------- /arm64.config: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shangguancaiyun/One-Click-Proxy-Installer/8a97cdc3968d9300e9e58db153979018e31498c7/arm64.config -------------------------------------------------------------------------------- /bbr_manage.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | GREEN='\033[0;32m' 4 | YELLOW='\033[0;33m' 5 | CYAN='\033[0;36m' 6 | NC='\033[0m' 7 | 8 | while true; do 9 | clear 10 | echo -e "${CYAN}BBR管理主菜单:" 11 | echo " 1. 简单BBR开关" 12 | echo " 2. 高级BBR管理(内核/加速/卸载/检测等)" 13 | echo " 0. 返回" 14 | read -p "请输入选项 [0-2]: " main_opt 15 | case "$main_opt" in 16 | 1) 17 | # 简单BBR开关原功能 18 | while true; do 19 | clear 20 | echo -e "${CYAN}BBR管理(简单开关):" 21 | bbr_status=$(sysctl net.ipv4.tcp_congestion_control 2>/dev/null | grep -q bbr && echo 已开启 || echo 未开启) 22 | echo -e "当前BBR状态:${GREEN}$bbr_status${NC}" 23 | echo " 1. 开启BBR" 24 | echo " 2. 关闭BBR" 25 | echo " 0. 返回" 26 | read -p "请输入选项 [0-2]: " bbr_opt 27 | case "$bbr_opt" in 28 | 1) 29 | sudo modprobe tcp_bbr 30 | echo 'net.core.default_qdisc=fq' | sudo tee -a /etc/sysctl.conf 31 | echo 'net.ipv4.tcp_congestion_control=bbr' | sudo tee -a /etc/sysctl.conf 32 | sudo sysctl -p 33 | echo "BBR已开启。" 34 | ;; 35 | 2) 36 | sudo sed -i '/net.core.default_qdisc/d' /etc/sysctl.conf 37 | sudo sed -i '/net.ipv4.tcp_congestion_control/d' /etc/sysctl.conf 38 | sudo sysctl -p 39 | echo "BBR已关闭。" 40 | ;; 41 | 0) 42 | break 43 | ;; 44 | *) 45 | echo "操作已取消。" 46 | ;; 47 | esac 48 | read -n 1 -s -r -p "按任意键返回..." 49 | done 50 | ;; 51 | 2) 52 | # 高级BBR管理(原install.sh全部功能,直接粘贴原install.sh主循环和函数) 53 | # ========== install.sh代码开始 ========== 54 | # 限制脚本仅支持基于 Debian/Ubuntu 的系统(即支持 apt-get 的系统) 55 | if ! command -v apt-get &> /dev/null; then 56 | echo -e "\033[31m此脚本仅支持基于 Debian/Ubuntu 的系统,请在支持 apt-get 的系统上运行!\033[0m" 57 | read -n 1 -s -r -p "按任意键返回..." 58 | break 59 | fi 60 | REQUIRED_CMDS=("curl" "wget" "dpkg" "awk" "sed" "sysctl" "update-grub" "jq") 61 | DEPS_MARKER="/tmp/.bbr_deps_installed" 62 | if [ ! -f "$DEPS_MARKER" ]; then 63 | for cmd in "${REQUIRED_CMDS[@]}"; do 64 | if ! command -v $cmd &> /dev/null; then 65 | echo -e "\033[31m缺少依赖:$cmd,正在安装...\033[0m" 66 | sudo apt-get update && sudo apt-get install -y $cmd 67 | fi 68 | done 69 | touch "$DEPS_MARKER" 70 | fi 71 | ARCH=$(uname -m) 72 | if [[ "$ARCH" != "aarch64" && "$ARCH" != "x86_64" ]]; then 73 | echo -e "\033[31m( ̄□ ̄)哇!这个脚本只支持 ARM 和 x86_64 架构哦~ 您的系统架构是:$ARCH\033[0m" 74 | read -n 1 -s -r -p "按任意键返回..." 75 | break 76 | fi 77 | SYSCTL_CONF="/etc/sysctl.d/99-zhongyuan.conf" 78 | clean_sysctl_conf() { 79 | if [[ ! -f "$SYSCTL_CONF" ]]; then 80 | sudo touch "$SYSCTL_CONF" 81 | fi 82 | sudo sed -i '/net.core.default_qdisc/d' "$SYSCTL_CONF" 83 | sudo sed -i '/net.ipv4.tcp_congestion_control/d' "$SYSCTL_CONF" 84 | } 85 | ask_to_save() { 86 | echo -n -e "\033[36m(。♥‿♥。) 要将这些配置永久保存到 $SYSCTL_CONF 吗?(y/n): \033[0m" 87 | read -r SAVE 88 | if [[ "$SAVE" == "y" || "$SAVE" == "Y" ]]; then 89 | echo -e "\033[1;31m【高风险操作警告】\033[0m" 90 | echo -e "\033[33m您即将永久修改系统网络参数,可能导致:\033[0m" 91 | echo -e "\033[33m- 网络异常、丢失 SSH 连接\033[0m" 92 | echo -e "\033[33m- 系统重启后参数生效,若配置有误可能无法联网\033[0m" 93 | echo -e "\033[33m- 如为生产环境/重要服务器,建议谨慎操作!\033[0m" 94 | echo -n -e "\033[1;31m是否继续永久保存?(y/N): \033[0m" 95 | read -r confirm_save 96 | if [[ ! "$confirm_save" =~ ^[Yy]$ ]]; then 97 | echo -e "\033[33m未永久保存,操作已取消。\033[0m" 98 | return 99 | fi 100 | clean_sysctl_conf 101 | echo "net.core.default_qdisc=$QDISC" | sudo tee -a "$SYSCTL_CONF" > /dev/null 102 | echo "net.ipv4.tcp_congestion_control=$ALGO" | sudo tee -a "$SYSCTL_CONF" > /dev/null 103 | sudo sysctl --system > /dev/null 104 | echo -e "\033[1;32m(☆^ー^☆) 更改已永久保存啦~\033[0m" 105 | else 106 | echo -e "\033[33m(⌒_⌒;) 好吧,没有永久保存呢~\033[0m" 107 | fi 108 | } 109 | get_download_links() { 110 | # ...原函数内容... 111 | } 112 | install_packages() { 113 | # ...原函数内容... 114 | } 115 | get_specific_version() { 116 | # ...原函数内容... 117 | } 118 | print_separator() { 119 | echo -e "\033[34m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\033[0m" 120 | } 121 | # 进入原install.sh主菜单循环 122 | while true; do 123 | # ...原install.sh主菜单和case全部粘贴于此... 124 | # 退出时break即可 125 | break 126 | done 127 | # ========== install.sh代码结束 ========== 128 | ;; 129 | 0) 130 | break 131 | ;; 132 | *) 133 | echo "无效选项"; sleep 1 134 | ;; 135 | esac 136 | 137 | done 138 | 139 | # 如果是被 source 调用,选0后自动 return 回主脚本 140 | return 2>/dev/null 141 | -------------------------------------------------------------------------------- /config/v2ray.json: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /github/workflows/auto-fix-bbr.yml: -------------------------------------------------------------------------------- 1 | name: 自动修复BBR管理与主脚本适配 2 | on: 3 | workflow_dispatch: 4 | 5 | jobs: 6 | fix-bbr: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: 拉取仓库代码 10 | uses: actions/checkout@v4 11 | 12 | - name: 修正 lvhy.sh BBR 管理菜单路径 13 | run: | 14 | sed -i '/5)/,/\.\.\./c\ 15 | 5)\ 16 | BBR_MANAGE_PATH="$(dirname "\$0")/bbr_manage.sh"\ 17 | if [ -f "\$BBR_MANAGE_PATH" ]; then\ 18 | source "\$BBR_MANAGE_PATH"\ 19 | else\ 20 | echo "未找到 bbr_manage.sh,请检查文件是否存在。";\ 21 | read -n 1 -s -r -p "按任意键返回工具箱...";\ 22 | fi\ 23 | ;;' lvhy.sh 24 | 25 | - name: 修正 bbr_manage.sh 结尾 26 | run: | 27 | echo -e '\necho -e "\\n已返回主菜单"\nread -n 1 -s -r -p "按任意键返回工具箱..."\nreturn 2>/dev/null' >> bbr_manage.sh 28 | 29 | - name: 提交更改 30 | run: | 31 | git config user.name "github-actions[bot]" 32 | git config user.email "41898282+github-actions[bot]@users.noreply.github.com" 33 | git add lvhy.sh bbr_manage.sh 34 | git commit -m "fix: 自动修复BBR菜单与主脚本交互" 35 | git push 36 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 限制脚本仅支持基于 Debian/Ubuntu 的系统(即支持 apt-get 的系统) 4 | if ! command -v apt-get &> /dev/null; then 5 | echo -e "\033[31m此脚本仅支持基于 Debian/Ubuntu 的系统,请在支持 apt-get 的系统上运行!\033[0m" 6 | exit 1 7 | fi 8 | 9 | # 检查并安装必要的依赖,包括 jq 用于解析 JSON 10 | REQUIRED_CMDS=("curl" "wget" "dpkg" "awk" "sed" "sysctl" "update-grub" "jq") 11 | DEPS_MARKER="/tmp/.bbr_deps_installed" 12 | if [ ! -f "$DEPS_MARKER" ]; then 13 | for cmd in "${REQUIRED_CMDS[@]}"; do 14 | if ! command -v $cmd &> /dev/null; then 15 | echo -e "\033[31m缺少依赖:$cmd,正在安装...\033[0m" 16 | sudo apt-get update && sudo apt-get install -y $cmd 17 | fi 18 | done 19 | touch "$DEPS_MARKER" 20 | fi 21 | 22 | # 检测系统架构 23 | ARCH=$(uname -m) 24 | if [[ "$ARCH" != "aarch64" && "$ARCH" != "x86_64" ]]; then 25 | echo -e "\033[31m( ̄□ ̄)哇!这个脚本只支持 ARM 和 x86_64 架构哦~ 您的系统架构是:$ARCH\033[0m" 26 | exit 1 27 | fi 28 | 29 | # 获取当前 BBR 状态 30 | CURRENT_ALGO=$(sysctl net.ipv4.tcp_congestion_control | awk '{print $3}') 31 | CURRENT_QDISC=$(sysctl net.core.default_qdisc | awk '{print $3}') 32 | 33 | # sysctl 配置文件路径 34 | SYSCTL_CONF="/etc/sysctl.d/99-zhongyuan.conf" 35 | 36 | # 函数:清理 sysctl.d 中的旧配置 37 | clean_sysctl_conf() { 38 | if [[ ! -f "$SYSCTL_CONF" ]]; then 39 | sudo touch "$SYSCTL_CONF" 40 | fi 41 | sudo sed -i '/net.core.default_qdisc/d' "$SYSCTL_CONF" 42 | sudo sed -i '/net.ipv4.tcp_congestion_control/d' "$SYSCTL_CONF" 43 | } 44 | 45 | # 函数:询问是否永久保存更改 46 | ask_to_save() { 47 | echo -n -e "\033[36m(。♥‿♥。) 要将这些配置永久保存到 $SYSCTL_CONF 吗?(y/n): \033[0m" 48 | read -r SAVE 49 | if [[ "$SAVE" == "y" || "$SAVE" == "Y" ]]; then 50 | echo -e "\033[1;31m【高风险操作警告】\033[0m" 51 | echo -e "\033[33m您即将永久修改系统网络参数,可能导致:\033[0m" 52 | echo -e "\033[33m- 网络异常、丢失 SSH 连接\033[0m" 53 | echo -e "\033[33m- 系统重启后参数生效,若配置有误可能无法联网\033[0m" 54 | echo -e "\033[33m- 如为生产环境/重要服务器,建议谨慎操作!\033[0m" 55 | echo -n -e "\033[1;31m是否继续永久保存?(y/N): \033[0m" 56 | read -r confirm_save 57 | if [[ ! "$confirm_save" =~ ^[Yy]$ ]]; then 58 | echo -e "\033[33m未永久保存,操作已取消。\033[0m" 59 | return 60 | fi 61 | clean_sysctl_conf 62 | echo "net.core.default_qdisc=$QDISC" | sudo tee -a "$SYSCTL_CONF" > /dev/null 63 | echo "net.ipv4.tcp_congestion_control=$ALGO" | sudo tee -a "$SYSCTL_CONF" > /dev/null 64 | sudo sysctl --system > /dev/null 65 | echo -e "\033[1;32m(☆^ー^☆) 更改已永久保存啦~\033[0m" 66 | else 67 | echo -e "\033[33m(⌒_⌒;) 好吧,没有永久保存呢~\033[0m" 68 | fi 69 | } 70 | 71 | # 函数:从 GitHub 获取最新版本并下载 72 | get_download_links() { 73 | echo -e "\033[36m正在从 GitHub 获取最新版本信息...\033[0m" 74 | BASE_URL="https://api.github.com/repos/byJoey/Actions-bbr-v3/releases" 75 | RELEASE_DATA=$(curl -s "$BASE_URL") 76 | 77 | if [[ "$ARCH" == "aarch64" ]]; then 78 | TAG_NAME=$(echo "$RELEASE_DATA" | jq -r 'sort_by(.published_at) | reverse | .[] | select(.tag_name | contains("arm64")) | .tag_name' | head -n1) 79 | elif [[ "$ARCH" == "x86_64" ]]; then 80 | TAG_NAME=$(echo "$RELEASE_DATA" | jq -r 'sort_by(.published_at) | reverse | .[] | select(.tag_name | contains("x86_64")) | .tag_name' | head -n1) 81 | fi 82 | 83 | if [[ -z "$TAG_NAME" ]]; then 84 | echo -e "\033[31m未找到适合当前架构的版本。\033[0m" 85 | exit 1 86 | fi 87 | 88 | echo -e "\033[36m找到的最新版本:$TAG_NAME\033[0m" 89 | ASSET_URLS=$(echo "$RELEASE_DATA" | jq -r --arg tag "$TAG_NAME" '.[] | select(.tag_name == $tag) | .assets[].browser_download_url') 90 | 91 | for URL in $ASSET_URLS; do 92 | FILE=$(basename "$URL") 93 | echo -e "\033[36m正在下载文件:$URL\033[0m" 94 | wget "$URL" -P /tmp/ || { echo -e "\033[31m下载失败:$URL\033[0m"; exit 1; } 95 | done 96 | } 97 | 98 | # 函数:安装下载的包 99 | install_packages() { 100 | echo -e "\033[36m开始安装下载的包...\033[0m" 101 | sudo dpkg -i /tmp/linux-*.deb 102 | sudo update-grub 103 | echo -e "\033[36m安装完成,请手动重启系统以加载新内核(本脚本已禁用自动重启,确保安全)。\033[0m" 104 | echo -e "\033[33m请手动输入 \033[1;32mreboot\033[0m\033[33m 命令以重启服务器!\033[0m" 105 | read -n 1 -s -r -p "按任意键返回..." 106 | } 107 | 108 | # 函数:安装指定版本 109 | get_specific_version() { 110 | BASE_URL="https://api.github.com/repos/byJoey/Actions-bbr-v3/releases" 111 | RELEASE_DATA=$(curl -s "$BASE_URL") 112 | 113 | if [[ "$ARCH" == "aarch64" ]]; then 114 | MATCH_TAGS=$(echo "$RELEASE_DATA" | jq -r '.[] | select(.tag_name | contains("arm64")) | .tag_name') 115 | else 116 | MATCH_TAGS=$(echo "$RELEASE_DATA" | jq -r '.[] | select(.tag_name | contains("x86_64")) | .tag_name') 117 | fi 118 | 119 | if [[ -z "$MATCH_TAGS" ]]; then 120 | echo -e "\033[31m未找到适合当前架构的版本。\033[0m" 121 | exit 1 122 | fi 123 | 124 | echo -e "\033[36m以下为适用于当前架构的版本:\033[0m" 125 | IFS=$'\n' read -rd '' -a TAG_ARRAY <<<"$MATCH_TAGS" 126 | 127 | for i in "${!TAG_ARRAY[@]}"; do 128 | echo -e "\033[33m $((i+1)). ${TAG_ARRAY[$i]}\033[0m" 129 | done 130 | 131 | echo -n -e "\033[36m请输入要安装的版本编号(例如 1):\033[0m" 132 | read -r CHOICE 133 | INDEX=$((CHOICE-1)) 134 | 135 | if [[ -z "${TAG_ARRAY[$INDEX]}" ]]; then 136 | echo -e "\033[31m输入无效编号,取消操作。\033[0m" 137 | exit 1 138 | fi 139 | 140 | SELECTED_TAG="${TAG_ARRAY[$INDEX]}" 141 | echo -e "\033[36m已选择版本:\033[0m\033[1;32m$SELECTED_TAG\033[0m" 142 | 143 | ASSET_URLS=$(echo "$RELEASE_DATA" | jq -r --arg tag "$SELECTED_TAG" '.[] | select(.tag_name == $tag) | .assets[].browser_download_url') 144 | 145 | for URL in $ASSET_URLS; do 146 | FILE=$(basename "$URL") 147 | echo -e "\033[36m下载中:$URL\033[0m" 148 | wget "$URL" -P /tmp/ || { echo -e "\033[31m下载失败:$URL\033[0m"; exit 1; } 149 | done 150 | } 151 | 152 | # 美化输出的分隔线 153 | print_separator() { 154 | echo -e "\033[34m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\033[0m" 155 | } 156 | 157 | while true; do 158 | print_separator 159 | echo -e "\033[1;35m(☆ω☆)✧*。 欢迎来到 BBR 管理脚本世界哒! ✧*。(☆ω☆)\033[0m" 160 | print_separator 161 | echo -e "\033[36m当前 TCP 拥塞控制算法:\033[0m\033[1;32m$CURRENT_ALGO\033[0m" 162 | echo -e "\033[36m当前队列管理算法:\033[0m\033[1;32m$CURRENT_QDISC\033[0m" 163 | print_separator 164 | echo -e "\033[1;33m作者:zhong yuan\033[0m" 165 | print_separator 166 | echo -e "\033[1;33m╭( ・ㅂ・)و ✧ 你可以选择以下操作哦:\033[0m" 167 | echo -e "\033[33m 1. ️ 安装或更新 BBR v3\033[0m" 168 | echo -e "\033[33m 2. 检查是否为 BBR v3\033[0m" 169 | echo -e "\033[33m 3. ⚡ 使用 BBR + FQ 加速\033[0m" 170 | echo -e "\033[33m 4. ⚡ 使用 BBR + FQ_PIE 加速\033[0m" 171 | echo -e "\033[33m 5. ⚡ 使用 BBR + CAKE 加速\033[0m" 172 | echo -e "\033[33m 6. ️ 卸载\033[0m" 173 | echo -e "\033[33m 0. 返回主菜单\033[0m" 174 | print_separator 175 | echo -n -e "\033[36m请选择一个操作 (0-6) (。・ω・。): \033[0m" 176 | read -r ACTION 177 | case "$ACTION" in 178 | 0) 179 | exit 0 180 | ;; 181 | 1) 182 | echo -e "\033[1;31m【高风险操作警告】\033[0m" 183 | echo -e "\033[33m您即将安装或更新 BBR v3 内核,这可能导致:\033[0m" 184 | echo -e "\033[33m- 系统内核被替换,部分 VPS/云服务器可能无法启动\033[0m" 185 | echo -e "\033[33m- 网络异常、丢失 SSH 连接、甚至系统无法启动\033[0m" 186 | echo -e "\033[33m- 请确保已备份重要数据,并知晓如何通过控制台救援\033[0m" 187 | echo -e "\033[33m- 如为生产环境/重要服务器,强烈建议不要随意更换内核!\033[0m" 188 | echo -n -e "\033[1;31m是否继续?(y/N): \033[0m" 189 | read -r confirm_risk 190 | if [[ ! "$confirm_risk" =~ ^[Yy]$ ]]; then 191 | echo -e "\033[33m操作已取消。\033[0m" 192 | read -n 1 -s -r -p "按任意键返回..." 193 | continue 194 | fi 195 | echo -e "\033[1;32m٩(。•́‿•̀。)۶ 您选择了安装或更新 BBR v3!\033[0m" 196 | sudo apt remove --purge $(dpkg -l | grep "joeyblog" | awk '{print $2}') -y 197 | get_download_links 198 | install_packages 199 | read -n 1 -s -r -p "按任意键返回..." 200 | continue 201 | ;; 202 | 2) 203 | echo -e "\033[1;32m(。・ω・。) 检查是否为 BBR v3...\033[0m" 204 | if modinfo tcp_bbr &> /dev/null; then 205 | BBR_VERSION=$(modinfo tcp_bbr | awk '/^version:/ {print $2}') 206 | if [[ "$BBR_VERSION" == "3" ]]; then 207 | echo -e "\033[36m检测到 BBR 模块版本:\033[0m\033[1;32m$BBR_VERSION\033[0m" 208 | else 209 | echo -e "\033[33m( ̄﹃ ̄) 检测到 BBR 模块,但版本是:$BBR_VERSION,不是 v3!\033[0m" 210 | read -n 1 -s -r -p "按任意键返回..." 211 | continue 212 | fi 213 | fi 214 | CURRENT_ALGO=$(sysctl net.ipv4.tcp_congestion_control | awk '{print $3}') 215 | if [[ "$CURRENT_ALGO" == "bbr" ]]; then 216 | echo -e "\033[36m当前 TCP 拥塞控制算法:\033[0m\033[1;32m$CURRENT_ALGO\033[0m" 217 | else 218 | echo -e "\033[31m(⊙﹏⊙) 当前算法不是 bbr,而是:$CURRENT_ALGO\033[0m" 219 | read -n 1 -s -r -p "按任意键返回..." 220 | continue 221 | fi 222 | echo -e "\033[1;32mヽ(✿゚▽゚)ノ 检测完成,BBR v3 已正确安装并生效!\033[0m" 223 | read -n 1 -s -r -p "按任意键返回..." 224 | continue 225 | ;; 226 | 3) 227 | echo -e "\033[1;32m(ノ◕ヮ◕)ノ*:・゚✧ 使用 BBR + FQ 加速!\033[0m" 228 | ALGO="bbr" 229 | QDISC="fq" 230 | ask_to_save 231 | read -n 1 -s -r -p "按任意键返回..." 232 | continue 233 | ;; 234 | 4) 235 | echo -e "\033[1;32m٩(•‿•)۶ 使用 BBR + FQ_PIE 加速!\033[0m" 236 | ALGO="bbr" 237 | QDISC="fq_pie" 238 | ask_to_save 239 | read -n 1 -s -r -p "按任意键返回..." 240 | continue 241 | ;; 242 | 5) 243 | echo -e "\033[1;32m(ノ≧∀≦)ノ 使用 BBR + CAKE 加速!\033[0m" 244 | ALGO="bbr" 245 | QDISC="cake" 246 | ask_to_save 247 | read -n 1 -s -r -p "按任意键返回..." 248 | continue 249 | ;; 250 | 6) 251 | echo -e "\033[1;31m【高风险操作警告】\033[0m" 252 | echo -e "\033[33m您即将卸载 BBR 内核,这可能导致:\033[0m" 253 | echo -e "\033[33m- 系统内核被移除,若无其他可用内核,系统将无法启动\033[0m" 254 | echo -e "\033[33m- 网络异常、丢失 SSH 连接、甚至系统无法启动\033[0m" 255 | echo -e "\033[33m- 请确保已备份重要数据,并知晓如何通过控制台救援\033[0m" 256 | echo -e "\033[33m- 如为生产环境/重要服务器,强烈建议不要随意卸载内核!\033[0m" 257 | echo -n -e "\033[1;31m是否继续?(y/N): \033[0m" 258 | read -r confirm_risk 259 | if [[ ! "$confirm_risk" =~ ^[Yy]$ ]]; then 260 | echo -e "\033[33m操作已取消。\033[0m" 261 | read -n 1 -s -r -p "按任意键返回..." 262 | continue 263 | fi 264 | echo -e "\033[1;32mヽ(・∀・)ノ 您选择了卸载 BBR 内核!\033[0m" 265 | sudo apt remove --purge $(dpkg -l | grep "joeyblog" | awk '{print $2}') -y 266 | echo -e "\033[33m如需重启服务器,请手动输入 \033[1;32mreboot\033[0m\033[33m 命令!\033[0m" 267 | read -n 1 -s -r -p "按任意键返回..." 268 | continue 269 | ;; 270 | *) 271 | echo -e "\033[31m( ̄▽ ̄)ゞ 无效的选项,请输入 0-6 之间的数字哦~\033[0m" 272 | read -n 1 -s -r -p "按任意键返回..." 273 | continue 274 | ;; 275 | esac 276 | done 277 | -------------------------------------------------------------------------------- /lvhy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Script for Sing-Box Hysteria2 & Reality Management 4 | 5 | # --- 统计信息文件 --- 6 | STATS_FILE="$HOME/.oneclick_stats" 7 | 8 | # --- 统计函数 --- 9 | update_run_stats() { 10 | local today total today_str 11 | today_str=$(date +%Y-%m-%d) 12 | if [ -f "$STATS_FILE" ]; then 13 | source "$STATS_FILE" 14 | else 15 | RUN_TOTAL=0 16 | RUN_TODAY=0 17 | RUN_TODAY_DATE="$today_str" 18 | fi 19 | if [ "$RUN_TODAY_DATE" = "$today_str" ]; then 20 | RUN_TODAY=$((RUN_TODAY+1)) 21 | else 22 | RUN_TODAY=1 23 | RUN_TODAY_DATE="$today_str" 24 | fi 25 | RUN_TOTAL=$((RUN_TOTAL+1)) 26 | cat > "$STATS_FILE" < "$PERSISTENT_INFO_FILE" </dev/null; then 189 | return 0 190 | fi 191 | 192 | read -p "依赖 '${friendly_name}' 未安装。是否尝试自动安装? (y/N): " install_confirm 193 | if [[ ! "$install_confirm" =~ ^[Yy]$ ]]; then 194 | warn "跳过安装 '${friendly_name}'。某些功能可能因此不可用或显示不完整。" 195 | return 1 196 | fi 197 | 198 | info "正在尝试安装 '${friendly_name}'..." 199 | if command -v apt-get &>/dev/null; then 200 | apt-get update -y && apt-get install -y "$package_name" 201 | elif command -v yum &>/dev/null; then 202 | yum install -y "$package_name" 203 | elif command -v dnf &>/dev/null; then 204 | dnf install -y "$package_name" 205 | else 206 | error "未找到已知的包管理器 (apt, yum, dnf)。请手动安装 '${friendly_name}'。" 207 | return 1 208 | fi 209 | 210 | if command -v "$package_name" &>/dev/null; then 211 | success "'${friendly_name}' 安装成功。" 212 | return 0 213 | else 214 | error "'${friendly_name}' 安装失败。请检查错误信息并尝试手动安装。" 215 | return 1 216 | fi 217 | } 218 | 219 | 220 | check_dependencies() { 221 | info "检查核心依赖..." 222 | # 从 core_deps 数组中移除了 "jq" 223 | local core_deps=("curl" "openssl") 224 | local all_deps_met=true 225 | for dep in "${core_deps[@]}"; do 226 | if ! command -v "$dep" &>/dev/null; then 227 | if ! attempt_install_package "$dep"; then 228 | all_deps_met=false 229 | fi 230 | fi 231 | done 232 | 233 | if ! $all_deps_met; then 234 | error "部分核心依赖未能安装。脚本可能无法正常运行。请手动安装后重试。" 235 | exit 1 236 | fi 237 | success "核心依赖检查通过。" 238 | } 239 | 240 | check_and_prepare_qrencode() { 241 | if ! command -v qrencode &>/dev/null; then 242 | if attempt_install_package "qrencode" "二维码生成工具(qrencode)"; then 243 | return 0 244 | else 245 | warn "未安装 'qrencode'。将无法生成二维码。" 246 | return 1 247 | fi 248 | fi 249 | return 0 250 | } 251 | 252 | 253 | find_and_set_singbox_cmd() { 254 | if [ -x "$SINGBOX_INSTALL_PATH_EXPECTED" ]; then 255 | SINGBOX_CMD="$SINGBOX_INSTALL_PATH_EXPECTED" 256 | elif command -v sing-box &>/dev/null; then 257 | SINGBOX_CMD=$(command -v sing-box) 258 | else 259 | SINGBOX_CMD="" 260 | fi 261 | if [ -n "$SINGBOX_CMD" ]; then 262 | info "Sing-box 命令已设置为: $SINGBOX_CMD" 263 | else 264 | warn "初始未找到 Sing-box 命令。" 265 | fi 266 | } 267 | 268 | 269 | get_server_ip() { 270 | local ips=() 271 | ips+=($(curl -s --max-time 5 https://api64.ipify.org)) 272 | ips+=($(curl -s --max-time 5 https://api.ipify.org)) 273 | ips+=($(hostname -I | tr ' ' '\n' | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$')) 274 | ips+=($(hostname -I | tr ' ' '\n' | grep -E '^[0-9a-fA-F:]+$')) 275 | local uniq_ips=($(echo "${ips[@]}" | tr ' ' '\n' | sort -u | grep -v '^$')) 276 | if [ ${#uniq_ips[@]} -eq 0 ]; then 277 | warn "未能自动检测到公网IP,请手动输入。" 278 | read -p "请输入你的服务器公网IP: " SERVER_IP 279 | elif [ ${#uniq_ips[@]} -eq 1 ]; then 280 | SERVER_IP="${uniq_ips[0]}" 281 | info "检测到服务器IP: $SERVER_IP" 282 | else 283 | echo "检测到多个IP地址:" 284 | for i in "${!uniq_ips[@]}"; do 285 | echo " $((i+1)). ${uniq_ips[$i]}" 286 | done 287 | read -p "请选择要使用的IP地址(输入序号): " ip_choice 288 | SERVER_IP="${uniq_ips[$((ip_choice-1))]}" 289 | info "你选择的服务器IP: $SERVER_IP" 290 | fi 291 | LAST_SERVER_IP="$SERVER_IP" 292 | } 293 | 294 | generate_random_password() { 295 | openssl rand -base64 24 | tr -dc 'A-Za-z0-9' | head -c 16 296 | } 297 | 298 | install_singbox_core() { 299 | if [ -f "$SINGBOX_INSTALL_PATH_EXPECTED" ]; then 300 | info "Sing-box 已检测到在 $SINGBOX_INSTALL_PATH_EXPECTED." 301 | find_and_set_singbox_cmd 302 | if [ -n "$SINGBOX_CMD" ]; then 303 | current_version=$($SINGBOX_CMD version | awk '{print $3}' 2>/dev/null) 304 | if [ -n "$current_version" ]; then 305 | info "当前版本: $current_version" 306 | else 307 | info "无法确定当前版本 (可能是旧版sing-box或命令问题)。" 308 | fi 309 | else 310 | info "无法确定当前版本,因为 sing-box 命令未找到。" 311 | fi 312 | read -p "是否重新安装/更新 Sing-box (beta)? (y/N): " reinstall_choice 313 | if [[ ! "$reinstall_choice" =~ ^[Yy]$ ]]; then 314 | return 0 315 | fi 316 | fi 317 | info "正在安装/更新 Sing-box (beta)..." 318 | if bash -c "$(curl -fsSL https://sing-box.vercel.app/)" @ install --beta; then 319 | success "Sing-box 安装/更新成功。" 320 | find_and_set_singbox_cmd 321 | if [ -z "$SINGBOX_CMD" ]; then 322 | error "安装后仍无法找到 sing-box 命令。请检查安装和 PATH。" 323 | return 1 324 | fi 325 | else 326 | error "Sing-box 安装失败。" 327 | return 1 328 | fi 329 | return 0 330 | } 331 | 332 | generate_self_signed_cert() { 333 | local domain_cn="$1" 334 | if [ -f "$HYSTERIA_CERT_PEM" ] && [ -f "$HYSTERIA_CERT_KEY" ]; then 335 | info "检测到已存在的证书: ${HYSTERIA_CERT_PEM} 和 ${HYSTERIA_CERT_KEY}" 336 | existing_cn=$(openssl x509 -in "$HYSTERIA_CERT_PEM" -noout -subject | sed -n 's/.*CN = \([^,]*\).*/\1/p') 337 | if [ "$existing_cn" == "$domain_cn" ]; then 338 | info "证书 CN ($existing_cn) 与目标 ($domain_cn) 匹配,跳过重新生成。" 339 | return 0 340 | else 341 | warn "证书 CN ($existing_cn) 与目标 ($domain_cn) 不匹配。" 342 | read -p "是否使用新的 CN ($domain_cn) 重新生成证书? (y/N): " regen_cert_choice 343 | if [[ ! "$regen_cert_choice" =~ ^[Yy]$ ]]; then 344 | info "保留现有证书。" 345 | return 0 346 | fi 347 | fi 348 | fi 349 | 350 | info "正在为 Hysteria2 生成自签名证书 (CN=${domain_cn})..." 351 | mkdir -p "$HYSTERIA_CERT_DIR" 352 | openssl ecparam -genkey -name prime256v1 -out "$HYSTERIA_CERT_KEY" 353 | openssl req -new -x509 -days 36500 -key "$HYSTERIA_CERT_KEY" -out "$HYSTERIA_CERT_PEM" -subj "/CN=${domain_cn}" 354 | if [ $? -eq 0 ]; then 355 | success "自签名证书生成成功。" 356 | info "证书: ${HYSTERIA_CERT_PEM}" 357 | info "私钥: ${HYSTERIA_CERT_KEY}" 358 | else 359 | error "自签名证书生成失败。" 360 | return 1 361 | fi 362 | } 363 | 364 | generate_reality_credentials() { 365 | if [ -z "$SINGBOX_CMD" ]; then 366 | error "Sing-box command (SINGBOX_CMD) 未设置。无法生成凭证。" 367 | find_and_set_singbox_cmd 368 | if [ -z "$SINGBOX_CMD" ]; then 369 | error "尝试查找后 Sing-box command 仍未设置。" 370 | return 1 371 | fi 372 | fi 373 | info "使用命令 '$SINGBOX_CMD' 生成 Reality UUID 和 Keypair..." 374 | 375 | # 只生成一次 UUID 376 | REALITY_UUID_VAL=$($SINGBOX_CMD generate uuid) 377 | CMD_EXIT_CODE=$? 378 | if [ $CMD_EXIT_CODE -ne 0 ] || [ -z "$REALITY_UUID_VAL" ]; then 379 | error "执行 '$SINGBOX_CMD generate uuid' 失败 (退出码: $CMD_EXIT_CODE) 或输出为空。" 380 | error "UUID 命令输出: '$REALITY_UUID_VAL'" 381 | return 1 382 | fi 383 | info "生成的 UUID: $REALITY_UUID_VAL" 384 | LAST_REALITY_UUID="$REALITY_UUID_VAL" 385 | 386 | # 只生成一次 Reality 密钥对 387 | KEY_PAIR_OUTPUT=$($SINGBOX_CMD generate reality-keypair) 388 | CMD_EXIT_CODE=$? 389 | if [ $CMD_EXIT_CODE -ne 0 ] || [ -z "$KEY_PAIR_OUTPUT" ]; then 390 | error "执行 '$SINGBOX_CMD generate reality-keypair' 失败 (退出码: $CMD_EXIT_CODE) 或输出为空。" 391 | error "Keypair 命令输出: '$KEY_PAIR_OUTPUT'" 392 | return 1 393 | fi 394 | info "原始 Keypair 输出:" 395 | echo "$KEY_PAIR_OUTPUT" 396 | 397 | REALITY_PRIVATE_KEY_VAL=$(echo "$KEY_PAIR_OUTPUT" | awk -F': ' '/PrivateKey:/ {print $2}' | xargs) 398 | REALITY_PUBLIC_KEY_VAL=$(echo "$KEY_PAIR_OUTPUT" | awk -F': ' '/PublicKey:/ {print $2}' | xargs) 399 | 400 | if [ -z "$REALITY_UUID_VAL" ] || [ -z "$REALITY_PRIVATE_KEY_VAL" ] || [ -z "$REALITY_PUBLIC_KEY_VAL" ]; then 401 | error "生成 Reality凭证失败 (UUID, Private Key, 或 Public Key 在解析后为空)." 402 | error "解析得到的 UUID: '$REALITY_UUID_VAL'" 403 | error "解析得到的 Private Key: '$REALITY_PRIVATE_KEY_VAL'" 404 | error "解析得到的 Public Key: '$REALITY_PUBLIC_KEY_VAL'" 405 | return 1 406 | fi 407 | success "Reality UUID: $REALITY_UUID_VAL" 408 | success "Reality Private Key: $REALITY_PRIVATE_KEY_VAL" 409 | success "Reality Public Key: $REALITY_PUBLIC_KEY_VAL" 410 | # 全局变量赋值,后续 config.json 和导入链接都用这组 411 | LAST_REALITY_UUID="$REALITY_UUID_VAL" 412 | LAST_REALITY_PUBLIC_KEY="$REALITY_PUBLIC_KEY_VAL" 413 | TEMP_REALITY_PRIVATE_KEY="$REALITY_PRIVATE_KEY_VAL" 414 | } 415 | 416 | create_config_json() { 417 | local mode="$1" 418 | local hy2_port="$2" 419 | local hy2_password="$3" 420 | local hy2_masquerade_cn="$4" 421 | local reality_port="$5" 422 | local reality_uuid="$6" 423 | local reality_private_key="$7" 424 | local reality_sni="$8" 425 | 426 | if [ -z "$SINGBOX_CMD" ]; then 427 | error "Sing-box command (SINGBOX_CMD) 未设置。无法校验或格式化配置文件。" 428 | return 1 429 | fi 430 | 431 | info "正在创建配置文件: ${SINGBOX_CONFIG_FILE}" 432 | mkdir -p "$SINGBOX_CONFIG_DIR" 433 | 434 | local inbounds_json_array=() 435 | if [ "$mode" == "all" ] || [ "$mode" == "hysteria2" ]; then 436 | inbounds_json_array+=( "$(cat < "$SINGBOX_CONFIG_FILE" < "$SINGBOX_SERVICE_FILE" </dev/null; then 639 | echo -e "${YELLOW}Hysteria2 二维码:${NC}" 640 | qrencode -t ANSIUTF8 "${LAST_HY2_LINK}" 641 | fi 642 | echo -e "${MAGENTA}${BOLD}--------------------------------------------${NC}" 643 | fi 644 | if [ "$mode" == "all" ] || [ "$mode" == "reality" ]; then 645 | LAST_VLESS_LINK="vless://${LAST_REALITY_UUID}@${ip_formatted}:${LAST_REALITY_PORT}?encryption=none&security=reality&sni=${LAST_REALITY_SNI}&fp=chrome&pbk=${LAST_REALITY_PUBLIC_KEY}&sid=${LAST_REALITY_SHORT_ID}&flow=xtls-rprx-vision#Reality-${LAST_SERVER_IP}-$(date +%s)" 646 | echo -e "${GREEN}${BOLD} Reality (VLESS) 配置信息:${NC}" 647 | echo -e "服务器地址: ${GREEN}${LAST_SERVER_IP}${NC}" 648 | echo -e "端口: ${GREEN}${LAST_REALITY_PORT}${NC}" 649 | echo -e "UUID: ${GREEN}${LAST_REALITY_UUID}${NC}" 650 | echo -e "传输协议: ${GREEN}tcp${NC}" 651 | echo -e "安全类型: ${GREEN}reality${NC}" 652 | echo -e "SNI (伪装域名): ${GREEN}${LAST_REALITY_SNI}${NC}" 653 | echo -e "Fingerprint: ${GREEN}${LAST_REALITY_FINGERPRINT}${NC}" 654 | echo -e "PublicKey: ${GREEN}${LAST_REALITY_PUBLIC_KEY}${NC}" 655 | echo -e "ShortID: ${GREEN}${LAST_REALITY_SHORT_ID}${NC}" 656 | echo -e "Flow: ${GREEN}xtls-rprx-vision${NC}" 657 | echo -e "${CYAN}VLESS Reality 导入链接:${NC} ${GREEN}${LAST_VLESS_LINK}${NC}" 658 | if $qrencode_is_ready && command -v qrencode &>/dev/null; then 659 | echo -e "${YELLOW}Reality (VLESS) 二维码:${NC}" 660 | qrencode -t ANSIUTF8 "${LAST_VLESS_LINK}" 661 | fi 662 | echo -e "${MAGENTA}${BOLD}--------------------------------------------${NC}" 663 | fi 664 | save_persistent_info 665 | echo 666 | read -n 1 -s -r -p "按任意键返回主菜单..." 667 | echo 668 | } 669 | 670 | 671 | # --- Installation Functions --- 672 | install_hysteria2_reality() { 673 | info "开始安装 Hysteria2 + Reality (共存)..." 674 | install_singbox_core || return 1 675 | get_server_ip 676 | 677 | read -p "请输入 Hysteria2 监听端口 (默认: ${DEFAULT_HYSTERIA_PORT}): " temp_hy2_port 678 | LAST_HY2_PORT=${temp_hy2_port:-$DEFAULT_HYSTERIA_PORT} 679 | read -p "请输入 Hysteria2 伪装域名/证书CN (默认: ${DEFAULT_HYSTERIA_MASQUERADE_CN}): " temp_hy2_masquerade_cn 680 | LAST_HY2_MASQUERADE_CN=${temp_hy2_masquerade_cn:-$DEFAULT_HYSTERIA_MASQUERADE_CN} 681 | 682 | read -p "请输入 Reality (VLESS) 监听端口 (默认: ${DEFAULT_REALITY_PORT}): " temp_reality_port 683 | LAST_REALITY_PORT=${temp_reality_port:-$DEFAULT_REALITY_PORT} 684 | read -p "请输入 Reality 目标SNI/握手服务器 (默认: ${DEFAULT_REALITY_SNI}): " temp_reality_sni 685 | LAST_REALITY_SNI=${temp_reality_sni:-$DEFAULT_REALITY_SNI} 686 | 687 | LAST_HY2_PASSWORD=$(generate_random_password) 688 | info "生成的 Hysteria2 密码: ${LAST_HY2_PASSWORD}" 689 | 690 | generate_self_signed_cert "$LAST_HY2_MASQUERADE_CN" || return 1 691 | generate_reality_credentials || return 1 692 | 693 | create_config_json "all" \ 694 | "$LAST_HY2_PORT" "$LAST_HY2_PASSWORD" "$LAST_HY2_MASQUERADE_CN" \ 695 | "$LAST_REALITY_PORT" "$LAST_REALITY_UUID" "$TEMP_REALITY_PRIVATE_KEY" "$LAST_REALITY_SNI" \ 696 | || return 1 697 | 698 | create_systemd_service 699 | start_singbox_service || return 1 700 | 701 | success "Hysteria2 + Reality 安装配置完成!" 702 | display_and_store_config_info "all" 703 | } 704 | 705 | install_hysteria2_only() { 706 | info "开始单独安装 Hysteria2..." 707 | install_singbox_core || return 1 708 | get_server_ip 709 | 710 | read -p "请输入 Hysteria2 监听端口 (默认: ${DEFAULT_HYSTERIA_PORT}): " temp_hy2_port 711 | LAST_HY2_PORT=${temp_hy2_port:-$DEFAULT_HYSTERIA_PORT} 712 | read -p "请输入 Hysteria2 伪装域名/证书CN (默认: ${DEFAULT_HYSTERIA_MASQUERADE_CN}): " temp_hy2_masquerade_cn 713 | LAST_HY2_MASQUERADE_CN=${temp_hy2_masquerade_cn:-$DEFAULT_HYSTERIA_MASQUERADE_CN} 714 | 715 | LAST_HY2_PASSWORD=$(generate_random_password) 716 | info "生成的 Hysteria2 密码: ${LAST_HY2_PASSWORD}" 717 | 718 | generate_self_signed_cert "$LAST_HY2_MASQUERADE_CN" || return 1 719 | 720 | LAST_REALITY_PORT="" 721 | LAST_REALITY_UUID="" 722 | LAST_REALITY_PUBLIC_KEY="" 723 | LAST_REALITY_SNI="" 724 | LAST_VLESS_LINK="" 725 | 726 | create_config_json "hysteria2" \ 727 | "$LAST_HY2_PORT" "$LAST_HY2_PASSWORD" "$LAST_HY2_MASQUERADE_CN" \ 728 | "" "" "" "" \ 729 | || return 1 730 | 731 | create_systemd_service 732 | start_singbox_service || return 1 733 | 734 | success "Hysteria2 单独安装配置完成!" 735 | display_and_store_config_info "hysteria2" 736 | } 737 | 738 | install_reality_only() { 739 | info "开始单独安装 Reality (VLESS)..." 740 | install_singbox_core || return 1 741 | get_server_ip 742 | 743 | read -p "请输入 Reality (VLESS) 监听端口 (默认: ${DEFAULT_REALITY_PORT}): " temp_reality_port 744 | LAST_REALITY_PORT=${temp_reality_port:-$DEFAULT_REALITY_PORT} 745 | read -p "请输入 Reality 目标SNI/握手服务器 (默认: ${DEFAULT_REALITY_SNI}): " temp_reality_sni 746 | LAST_REALITY_SNI=${temp_reality_sni:-$DEFAULT_REALITY_SNI} 747 | 748 | generate_reality_credentials || return 1 749 | 750 | LAST_HY2_PORT="" 751 | LAST_HY2_PASSWORD="" 752 | LAST_HY2_MASQUERADE_CN="" 753 | LAST_HY2_LINK="" 754 | 755 | create_config_json "reality" \ 756 | "" "" "" \ 757 | "$LAST_REALITY_PORT" "$LAST_REALITY_UUID" "$TEMP_REALITY_PRIVATE_KEY" "$LAST_REALITY_SNI" \ 758 | || return 1 759 | 760 | create_systemd_service 761 | start_singbox_service || return 1 762 | 763 | success "Reality (VLESS) 单独安装配置完成!" 764 | display_and_store_config_info "reality" 765 | } 766 | 767 | show_current_import_info() { 768 | if [ -z "$LAST_INSTALL_MODE" ]; then 769 | warn "尚未通过此脚本安装任何配置,或上次安装信息未保留。" 770 | info "请先执行安装操作 (选项 1, 2, 或 3),或者确保 ${PERSISTENT_INFO_FILE} 文件存在且包含信息。" 771 | pause_return_menu 772 | return 773 | fi 774 | info "显示上次保存的配置信息 (${LAST_INSTALL_MODE}模式):" 775 | display_and_store_config_info "$LAST_INSTALL_MODE" 776 | pause_return_menu 777 | } 778 | 779 | uninstall_singbox() { 780 | warn "你确定要卸载 Sing-box 吗?" 781 | read -p "此操作将停止并禁用服务,删除可执行文件和相关配置文件目录。是否继续卸载? (y/N): " confirm_uninstall 782 | if [[ ! "$confirm_uninstall" =~ ^[Yy]$ ]]; then 783 | info "卸载已取消。" 784 | return 785 | fi 786 | 787 | info "正在停止 sing-box 服务..." 788 | systemctl stop sing-box &>/dev/null 789 | info "正在禁用 sing-box 服务..." 790 | systemctl disable sing-box &>/dev/null 791 | 792 | if [ -f "$SINGBOX_SERVICE_FILE" ]; then 793 | info "正在删除 systemd 服务文件: ${SINGBOX_SERVICE_FILE}" 794 | rm -f "$SINGBOX_SERVICE_FILE" 795 | systemctl daemon-reload 796 | fi 797 | 798 | local singbox_exe_to_remove="" 799 | if [ -n "$SINGBOX_CMD" ] && [ -f "$SINGBOX_CMD" ]; then 800 | singbox_exe_to_remove="$SINGBOX_CMD" 801 | elif [ -f "$SINGBOX_INSTALL_PATH_EXPECTED" ]; then 802 | singbox_exe_to_remove="$SINGBOX_INSTALL_PATH_EXPECTED" 803 | fi 804 | 805 | local official_install_path="/usr/local/bin/sing-box" 806 | if [ -f "$official_install_path" ]; then 807 | if [ -n "$singbox_exe_to_remove" ] && [ "$singbox_exe_to_remove" != "$official_install_path" ]; then 808 | info "正在删除 sing-box 执行文件: $official_install_path (官方脚本位置)" 809 | rm -f "$official_install_path" 810 | elif [ -z "$singbox_exe_to_remove" ]; then 811 | singbox_exe_to_remove="$official_install_path" 812 | fi 813 | fi 814 | 815 | if [ -n "$singbox_exe_to_remove" ] && [ -f "$singbox_exe_to_remove" ]; then 816 | info "正在删除 sing-box 执行文件: $singbox_exe_to_remove" 817 | rm -f "$singbox_exe_to_remove" 818 | else 819 | warn "未找到明确的 sing-box 执行文件进行删除 (已检查 ${SINGBOX_INSTALL_PATH_EXPECTED} 和 ${official_install_path})。" 820 | fi 821 | 822 | read -p "是否删除配置文件目录 ${SINGBOX_CONFIG_DIR} (包含导入信息缓存)? (y/N): " delete_config_dir_confirm 823 | if [[ "$delete_config_dir_confirm" =~ ^[Yy]$ ]]; then 824 | if [ -d "$SINGBOX_CONFIG_DIR" ]; then 825 | info "正在删除配置目录 (包括 ${PERSISTENT_INFO_FILE})..." 826 | rm -rf "$SINGBOX_CONFIG_DIR" 827 | fi 828 | else 829 | info "配置文件目录 (${SINGBOX_CONFIG_DIR}) 已保留。" 830 | fi 831 | 832 | read -p "是否删除 Hysteria2 证书目录 ${HYSTERIA_CERT_DIR}? (y/N): " delete_cert_dir_confirm 833 | if [[ "$delete_cert_dir_confirm" =~ ^[Yy]$ ]]; then 834 | if [ -d "$HYSTERIA_CERT_DIR" ]; then 835 | info "正在删除 Hysteria2 证书目录..." 836 | rm -rf "$HYSTERIA_CERT_DIR" 837 | fi 838 | else 839 | info "Hysteria2 证书目录 (${HYSTERIA_CERT_DIR}) 已保留。" 840 | fi 841 | 842 | 843 | success "Sing-box 卸载完成。" 844 | LAST_INSTALL_MODE="" 845 | SINGBOX_CMD="" 846 | } 847 | 848 | # --- Management Functions --- 849 | manage_singbox() { 850 | local action=$1 851 | if [ -z "$SINGBOX_CMD" ]; then 852 | warn "Sing-box command 未设置, 尝试查找..." 853 | find_and_set_singbox_cmd 854 | if [ -z "$SINGBOX_CMD" ]; then 855 | error "仍然无法找到 Sing-box command. 操作中止。" 856 | return 1 857 | fi 858 | fi 859 | 860 | case "$action" in 861 | start) 862 | systemctl start sing-box 863 | if systemctl is-active --quiet sing-box; then success "Sing-box 服务已启动。"; else error "Sing-box 服务启动失败。"; fi 864 | pause_return_menu 865 | ;; 866 | stop) 867 | systemctl stop sing-box 868 | if ! systemctl is-active --quiet sing-box; then success "Sing-box 服务已停止。"; else error "Sing-box 服务停止失败。"; fi 869 | pause_return_menu 870 | ;; 871 | restart) 872 | if [ -f "$SINGBOX_CONFIG_FILE" ]; then 873 | info "重启前检查配置文件..." 874 | if ! $SINGBOX_CMD check -c "$SINGBOX_CONFIG_FILE"; then 875 | error "配置文件检查失败,无法重启。请先修复配置文件。" 876 | pause_return_menu 877 | return 1 878 | fi 879 | success "配置文件检查通过。" 880 | fi 881 | systemctl restart sing-box 882 | sleep 1 883 | if systemctl is-active --quiet sing-box; then success "Sing-box 服务已重启。"; else error "Sing-box 服务重启失败。"; fi 884 | pause_return_menu 885 | ;; 886 | status) 887 | systemctl status sing-box --no-pager -l 888 | pause_return_menu 889 | ;; 890 | log) 891 | journalctl -u sing-box -f --no-pager -n 50 892 | pause_return_menu 893 | ;; 894 | view_config) 895 | if [ -f "$SINGBOX_CONFIG_FILE" ]; then 896 | info "当前配置文件 (${SINGBOX_CONFIG_FILE}):" 897 | cat "$SINGBOX_CONFIG_FILE" 898 | else 899 | error "配置文件不存在: ${SINGBOX_CONFIG_FILE}" 900 | fi 901 | pause_return_menu 902 | ;; 903 | edit_config) 904 | if [ -f "$SINGBOX_CONFIG_FILE" ]; then 905 | if command -v nano &> /dev/null; then 906 | nano "$SINGBOX_CONFIG_FILE" 907 | elif command -v vim &> /dev/null; then 908 | vim "$SINGBOX_CONFIG_FILE" 909 | else 910 | error "'nano' 或 'vim' 编辑器未安装。请手动编辑: ${SINGBOX_CONFIG_FILE}" 911 | pause_return_menu 912 | return 913 | fi 914 | read -p "配置文件已编辑,是否立即重启 sing-box 服务? (y/N): " restart_confirm 915 | if [[ "$restart_confirm" =~ ^[Yy]$ ]]; then 916 | manage_singbox "restart" 917 | fi 918 | else 919 | error "配置文件不存在: ${SINGBOX_CONFIG_FILE}" 920 | fi 921 | pause_return_menu 922 | ;; 923 | *) 924 | error "无效的管理操作: $action" 925 | pause_return_menu 926 | ;; 927 | esac 928 | } 929 | 930 | update_script_online() { 931 | local update_url="https://github.com/shangguancaiyun/One-Click-Proxy-Installer/raw/main/lvhy.sh" 932 | local tmpfile="/tmp/lvhy_update_$$.sh" 933 | echo "正在从远程仓库下载最新版脚本..." 934 | if curl -fsSL "$update_url" -o "$tmpfile"; then 935 | chmod +x "$tmpfile" 936 | if [ -f "$0" ] && [ -w "$0" ]; then 937 | cp "$tmpfile" "$0" 938 | echo -e "${GREEN}脚本已更新为最新版!${NC}" 939 | else 940 | echo -e "${YELLOW}当前脚本不是本地文件,或没有写权限,未自动覆盖。${NC}" 941 | echo -e "${YELLOW}你可以手动用如下命令更新:${NC}" 942 | echo -e "${CYAN}curl -fsSL \"$update_url\" -o lvhy.sh && chmod +x lvhy.sh${NC}" 943 | fi 944 | rm -f "$tmpfile" 945 | else 946 | echo -e "${RED}下载失败,请检查网络或稍后重试。${NC}" 947 | fi 948 | echo 949 | read -n 1 -s -r -p "按任意键返回主菜单..." 950 | echo 951 | } 952 | 953 | toolbox_menu() { 954 | while true; do 955 | clear 956 | echo -e "${MAGENTA}${BOLD}================ 工具箱 ================${NC}" 957 | echo " 1. 更新 Sing-box 内核 (使用官方beta脚本)" 958 | echo " 2. 开发所有端口 (一键放行0-65535,风险自负)" 959 | echo " 3. 本机信息" 960 | echo " 4. DNS优化(国内/国外分流)" 961 | echo " 5. BBR管理" 962 | echo " 6. 组件管理" 963 | echo " 7. 系统时区调整" 964 | echo " 8. 切换优先IPv4/IPv6" 965 | echo " 9. 修改Root密码" 966 | echo " 10. 开启Root密码登录" 967 | echo " 11. 重启服务器" 968 | echo " 0. 返回主菜单" 969 | echo -e "${MAGENTA}${BOLD}========================================${NC}" 970 | read -p "请输入选项 [0-13]: " tb_choice 971 | case "$tb_choice" in 972 | 1) 973 | install_singbox_core && manage_singbox "restart" 974 | read -n 1 -s -r -p "按任意键返回工具箱..." 975 | ;; 976 | 2) 977 | echo -e "${YELLOW}警告:此操作将放行所有端口(0-65535),有极大安全风险,仅建议在受信任环境下使用!${NC}" 978 | read -p "确定要继续吗?(y/N): " confirm_open 979 | if [[ "$confirm_open" =~ ^[Yy]$ ]]; then 980 | if command -v ufw &>/dev/null; then 981 | sudo ufw allow 0:65535/tcp 982 | sudo ufw allow 0:65535/udp 983 | sudo ufw reload 984 | echo "已通过 ufw 放行全部端口。" 985 | elif command -v firewall-cmd &>/dev/null; then 986 | sudo firewall-cmd --permanent --add-port=0-65535/tcp 987 | sudo firewall-cmd --permanent --add-port=0-65535/udp 988 | sudo firewall-cmd --reload 989 | echo "已通过 firewalld 放行全部端口。" 990 | else 991 | echo "未检测到常见防火墙(ufw/firewalld),请手动放行端口。" 992 | fi 993 | else 994 | echo "操作已取消。" 995 | fi 996 | read -n 1 -s -r -p "按任意键返回工具箱..." 997 | ;; 998 | 3) 999 | echo -e "${CYAN}${BOLD}\n========= 本机信息 =========${NC}" 1000 | # 主机名、系统 1001 | echo -e "${YELLOW}主机名:${NC} $(hostname)" 1002 | echo -e "${YELLOW}系统:${NC} $(uname -o)" 1003 | echo -e "${YELLOW}Linux版本:${NC} $(uname -r)" 1004 | echo -e "${YELLOW}发行版:${NC} $(. /etc/os-release 2>/dev/null; echo $PRETTY_NAME)" 1005 | # CPU 1006 | echo -e "${YELLOW}CPU架构:${NC} $(uname -m)" 1007 | echo -e "${YELLOW}CPU型号:${NC} $(awk -F: '/model name/ {print $2; exit}' /proc/cpuinfo | xargs)" 1008 | echo -e "${YELLOW}CPU核心数:${NC} $(nproc)" 1009 | echo -e "${YELLOW}CPU占用:${NC} $(top -bn1 | awk '/Cpu/ {print $2"%"; exit}')" 1010 | # 内存 1011 | mem_total=$(free -h | awk '/Mem:/ {print $2}') 1012 | mem_used=$(free -h | awk '/Mem:/ {print $3}') 1013 | swap_total=$(free -h | awk '/Swap:/ {print $2}') 1014 | swap_used=$(free -h | awk '/Swap:/ {print $3}') 1015 | echo -e "${YELLOW}物理内存:${NC} $mem_used / $mem_total" 1016 | echo -e "${YELLOW}虚拟内存:${NC} $swap_used / $swap_total" 1017 | # 硬盘 1018 | disk_total=$(df -h --total | awk '/total/ {print $2}') 1019 | disk_used=$(df -h --total | awk '/total/ {print $3}') 1020 | echo -e "${YELLOW}硬盘占用:${NC} $disk_used / $disk_total" 1021 | # 流量 1022 | rx=$(cat /proc/net/dev | awk '/:/ {sum+=$2} END {print sum/1024/1024 " MB"}') 1023 | tx=$(cat /proc/net/dev | awk '/:/ {sum+=$10} END {print sum/1024/1024 " MB"}') 1024 | echo -e "${YELLOW}总接收流量:${NC} $rx" 1025 | echo -e "${YELLOW}总发送流量:${NC} $tx" 1026 | # 拥堵算法 1027 | cc_alg=$(sysctl -n net.ipv4.tcp_congestion_control 2>/dev/null) 1028 | echo -e "${YELLOW}网络拥堵算法:${NC} $cc_alg" 1029 | # 公网IP 1030 | ipv4=$(curl -s --max-time 3 https://api.ipify.org) 1031 | ipv6=$(curl -s --max-time 3 https://api6.ipify.org) 1032 | echo -e "${YELLOW}公网IPv4:${NC} $ipv4" 1033 | echo -e "${YELLOW}公网IPv6:${NC} $ipv6" 1034 | # 运营商与地理位置 1035 | ipinfo=$(curl -s --max-time 5 ipinfo.io/json) 1036 | isp=$(echo "$ipinfo" | grep 'org' | awk -F: '{print $2}' | tr -d ' ",') 1037 | loc=$(echo "$ipinfo" | grep 'city' | awk -F: '{print $2}' | tr -d ' ",') 1038 | country=$(echo "$ipinfo" | grep 'country' | awk -F: '{print $2}' | tr -d ' ",') 1039 | echo -e "${YELLOW}运营商:${NC} $isp" 1040 | echo -e "${YELLOW}地理位置:${NC} $loc, $country" 1041 | # 系统时间与运行时长 1042 | echo -e "${YELLOW}系统时间:${NC} $(date '+%Y-%m-%d %H:%M:%S')" 1043 | echo -e "${YELLOW}运行时长:${NC} $(uptime -p)" 1044 | echo -e "${CYAN}${BOLD}==============================${NC}\n" 1045 | read -n 1 -s -r -p "按任意键返回工具箱..." 1046 | ;; 1047 | 4) 1048 | # DNS优化 1049 | echo -e "${CYAN}请选择DNS优化方案:" 1050 | echo " 1. 国外DNS (1.1.1.1, 8.8.8.8)" 1051 | echo " 2. 国内DNS (223.5.5.5, 180.76.76.76, 114.114.114.114)" 1052 | echo " 0. 取消" 1053 | read -p "请输入选项 [0-2]: " dns_opt 1054 | case "$dns_opt" in 1055 | 1) 1056 | echo -e "nameserver 1.1.1.1\nnameserver 8.8.8.8" | sudo tee /etc/resolv.conf 1057 | echo "已切换为国外DNS。" 1058 | ;; 1059 | 2) 1060 | echo -e "nameserver 223.5.5.5\nnameserver 180.76.76.76\nnameserver 114.114.114.114" | sudo tee /etc/resolv.conf 1061 | echo "已切换为国内DNS。" 1062 | ;; 1063 | *) 1064 | echo "操作已取消。" 1065 | ;; 1066 | esac 1067 | read -n 1 -s -r -p "按任意键返回工具箱..." 1068 | ;; 1069 | 5) 1070 | if [ -f ./bbr_manage.sh ]; then 1071 | source ./bbr_manage.sh 1072 | else 1073 | echo "未找到 bbr_manage.sh,请检查文件是否存在于当前目录。" 1074 | read -n 1 -s -r -p "按任意键返回工具箱..." 1075 | fi 1076 | ;; 1077 | 6) 1078 | # 组件管理 1079 | while true; do 1080 | clear 1081 | echo -e "${CYAN}组件管理:" 1082 | echo " 1. 安装curl" 1083 | echo " 2. 安装wget" 1084 | echo " 3. 安装sudo" 1085 | echo " 4. 安装unzip" 1086 | echo " 0. 返回" 1087 | read -p "请输入选项 [0-4]: " comp_opt 1088 | case "$comp_opt" in 1089 | 1) 1090 | if command -v curl &>/dev/null; then echo "curl已安装。"; else sudo apt-get install -y curl || sudo yum install -y curl; fi 1091 | ;; 1092 | 2) 1093 | if command -v wget &>/dev/null; then echo "wget已安装。"; else sudo apt-get install -y wget || sudo yum install -y wget; fi 1094 | ;; 1095 | 3) 1096 | if command -v sudo &>/dev/null; then echo "sudo已安装。"; else apt-get install -y sudo || yum install -y sudo; fi 1097 | ;; 1098 | 4) 1099 | if command -v unzip &>/dev/null; then echo "unzip已安装。"; else sudo apt-get install -y unzip || sudo yum install -y unzip; fi 1100 | ;; 1101 | 0) 1102 | break 1103 | ;; 1104 | *) 1105 | echo "无效选项。"; sleep 1 1106 | ;; 1107 | esac 1108 | read -n 1 -s -r -p "按任意键返回组件管理..." 1109 | done 1110 | ;; 1111 | 7) 1112 | # 系统时区调整 1113 | echo -e "${CYAN}请选择时区:" 1114 | echo " 1. Asia/Shanghai (中国)" 1115 | echo " 2. UTC (世界标准)" 1116 | echo " 0. 取消" 1117 | read -p "请输入选项 [0-2]: " tz_opt 1118 | case "$tz_opt" in 1119 | 1) 1120 | sudo timedatectl set-timezone Asia/Shanghai 1121 | echo "已切换为Asia/Shanghai。" 1122 | ;; 1123 | 2) 1124 | sudo timedatectl set-timezone UTC 1125 | echo "已切换为UTC。" 1126 | ;; 1127 | *) 1128 | echo "操作已取消。" 1129 | ;; 1130 | esac 1131 | read -n 1 -s -r -p "按任意键返回工具箱..." 1132 | ;; 1133 | 8) 1134 | # 切换优先IPv4/IPv6 1135 | echo -e "${CYAN}请选择优先协议:" 1136 | echo " 1. 优先IPv4" 1137 | echo " 2. 优先IPv6" 1138 | echo " 0. 取消" 1139 | read -p "请输入选项 [0-2]: " ipver_opt 1140 | case "$ipver_opt" in 1141 | 1) 1142 | sudo sed -i '/^precedence ::ffff:0:0\/96 100$/d' /etc/gai.conf 1143 | echo 'precedence ::ffff:0:0/96 100' | sudo tee -a /etc/gai.conf 1144 | echo "已设置为优先IPv4。" 1145 | ;; 1146 | 2) 1147 | sudo sed -i '/^precedence ::ffff:0:0\/96 100$/d' /etc/gai.conf 1148 | echo "已设置为优先IPv6。" 1149 | ;; 1150 | *) 1151 | echo "操作已取消。" 1152 | ;; 1153 | esac 1154 | read -n 1 -s -r -p "按任意键返回工具箱..." 1155 | ;; 1156 | 9) 1157 | # 修改Root密码 1158 | echo -e "${CYAN}请输入新Root密码:" 1159 | sudo passwd root 1160 | read -n 1 -s -r -p "按任意键返回工具箱..." 1161 | ;; 1162 | 10) 1163 | # 开启Root密码登录 1164 | sudo sed -i 's/^#*PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config 1165 | sudo sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config 1166 | sudo systemctl restart sshd || sudo systemctl restart ssh 1167 | echo "已开启Root密码登录(请确保已设置Root密码)。" 1168 | read -n 1 -s -r -p "按任意键返回工具箱..." 1169 | ;; 1170 | 11) 1171 | # 重启服务器 1172 | echo -e "${YELLOW}警告:即将重启服务器,是否继续?${NC}" 1173 | read -p "输入y确认重启,其他键取消: " reboot_confirm 1174 | if [[ "$reboot_confirm" =~ ^[Yy]$ ]]; then 1175 | sudo reboot 1176 | else 1177 | echo "操作已取消。" 1178 | fi 1179 | read -n 1 -s -r -p "按任意键返回工具箱..." 1180 | ;; 1181 | 0) 1182 | break 1183 | ;; 1184 | *) 1185 | echo "无效选项,请输入 0-13。" 1186 | sleep 1 1187 | ;; 1188 | esac 1189 | done 1190 | } 1191 | 1192 | # --- Main Menu --- 1193 | show_menu() { 1194 | clear 1195 | print_author_info 1196 | echo -e "${MAGENTA}${BOLD}=================【安装相关】==================${NC}" 1197 | echo " 1. 安装 Hysteria2 + Reality (共存)" 1198 | echo " 2. 单独安装 Hysteria2" 1199 | echo " 3. 单独安装 Reality (VLESS)" 1200 | echo -e "${MAGENTA}${BOLD}=================【管理相关】==================${NC}" 1201 | echo " 4. 启动 Sing-box 服务" 1202 | echo " 5. 停止 Sing-box 服务" 1203 | echo " 6. 重启 Sing-box 服务" 1204 | echo " 7. 查看 Sing-box 服务状态" 1205 | echo " 8. 查看 Sing-box 实时日志" 1206 | echo " 9. 查看当前配置文件" 1207 | echo " 10. 编辑当前配置文件 (nano/vim)" 1208 | echo " 11. 显示\"节点\"的导入信息 (含二维码)" 1209 | echo " 12. 修改节点参数(端口/IP/UUID等)" 1210 | echo -e "${MAGENTA}${BOLD}=================【工具箱】====================${NC}" 1211 | echo " 13. 工具箱" 1212 | echo -e "${MAGENTA}${BOLD}=================【其他】======================${NC}" 1213 | echo " 14. 卸载 Sing-box" 1214 | echo " 15. 更改快捷指令" 1215 | echo " 16. 在线更新脚本" 1216 | echo " 0. 退出脚本" 1217 | echo -e "${MAGENTA}${BOLD}===============================================${NC}" 1218 | read -p "请输入选项 [0-16]: " choice 1219 | 1220 | case "$choice" in 1221 | 1) install_hysteria2_reality ;; 1222 | 2) install_hysteria2_only ;; 1223 | 3) install_reality_only ;; 1224 | 4) manage_singbox "start" ;; 1225 | 5) manage_singbox "stop" ;; 1226 | 6) manage_singbox "restart" ;; 1227 | 7) manage_singbox "status" ;; 1228 | 8) manage_singbox "log" ;; 1229 | 9) manage_singbox "view_config" ;; 1230 | 10) manage_singbox "edit_config" ;; 1231 | 11) show_current_import_info ;; 1232 | 12) 1233 | bash ./modify_node_params.sh 1234 | ;; 1235 | 13) toolbox_menu ;; 1236 | 14) uninstall_singbox ;; 1237 | 15) change_quick_cmd ;; 1238 | 16) update_script_online ;; 1239 | 0) exit 0 ;; 1240 | *) error "无效选项,请输入 0 到 16 之间的数字。" ;; 1241 | esac 1242 | echo "" 1243 | } 1244 | 1245 | # --- Script Entry Point --- 1246 | check_root 1247 | check_dependencies # 已移除 jq 依赖检查 1248 | find_and_set_singbox_cmd 1249 | load_persistent_info 1250 | 1251 | # Main loop 1252 | while true; do 1253 | show_menu 1254 | # 只在需要时 pause,show_menu 内部不再 pause 1255 | # read -n 1 -s -r -p "按任意键返回主菜单 (或按 Ctrl+C 退出)..." 1256 | done 1257 | 1258 | # --- 脚本末尾自动化一键设置快捷命令功能 --- 1259 | if [ "$(basename $0)" != "$QUICK_CMD_NAME" ] && [ ! -f "/usr/local/bin/$QUICK_CMD_NAME" ]; then 1260 | sudo cp "$0" "/usr/local/bin/$QUICK_CMD_NAME" 1261 | sudo chmod +x "/usr/local/bin/$QUICK_CMD_NAME" 1262 | echo "\n已自动设置快捷命令:box。你可以在任意目录输入 box 快速管理 Sing-Box 节点!" 1263 | fi 1264 | 1265 | # --- 参数便捷修改与节点删除功能 --- 1266 | modify_node_params() { 1267 | if [ ! -f "$SINGBOX_CONFIG_FILE" ]; then 1268 | error "未检测到配置文件,无法修改参数。" 1269 | pause_return_menu 1270 | return 1271 | fi 1272 | while true; do 1273 | clear 1274 | echo -e "${CYAN}${BOLD}当前节点参数:${NC}" 1275 | echo " 1. Hysteria2 端口: $LAST_HY2_PORT" 1276 | echo " 2. Hysteria2 伪装域名: $LAST_HY2_MASQUERADE_CN" 1277 | echo " 3. Reality 端口: $LAST_REALITY_PORT" 1278 | echo " 4. Reality UUID: $LAST_REALITY_UUID" 1279 | echo " 5. Reality SNI: $LAST_REALITY_SNI" 1280 | echo " 6. 删除当前节点(清空配置)" 1281 | echo " 0. 返回主菜单" 1282 | read -p "请选择要操作的项目 [0-6]: " param_choice 1283 | case "$param_choice" in 1284 | 1) 1285 | read -p "请输入新的 Hysteria2 端口: " new_port 1286 | if [[ -n "$new_port" ]]; then 1287 | sed -i "s/\"listen_port\": $LAST_HY2_PORT/\"listen_port\": $new_port/" "$SINGBOX_CONFIG_FILE" 1288 | LAST_HY2_PORT="$new_port" 1289 | save_persistent_info 1290 | systemctl restart sing-box 1291 | success "Hysteria2 端口已修改并重启服务。" 1292 | fi 1293 | ;; 1294 | 2) 1295 | read -p "请输入新的 Hysteria2 伪装域名: " new_cn 1296 | if [[ -n "$new_cn" ]]; then 1297 | sed -i "s/\"server_name\": \"$LAST_HY2_MASQUERADE_CN\"/\"server_name\": \"$new_cn\"/" "$SINGBOX_CONFIG_FILE" 1298 | LAST_HY2_MASQUERADE_CN="$new_cn" 1299 | save_persistent_info 1300 | systemctl restart sing-box 1301 | success "Hysteria2 伪装域名已修改并重启服务。" 1302 | fi 1303 | ;; 1304 | 3) 1305 | read -p "请输入新的 Reality 端口: " new_port 1306 | if [[ -n "$new_port" ]]; then 1307 | sed -i "s/\"listen_port\": $LAST_REALITY_PORT/\"listen_port\": $new_port/" "$SINGBOX_CONFIG_FILE" 1308 | LAST_REALITY_PORT="$new_port" 1309 | save_persistent_info 1310 | systemctl restart sing-box 1311 | success "Reality 端口已修改并重启服务。" 1312 | fi 1313 | ;; 1314 | 4) 1315 | read -p "请输入新的 Reality UUID: " new_uuid 1316 | if [[ -n "$new_uuid" ]]; then 1317 | sed -i "s/\"uuid\": \"$LAST_REALITY_UUID\"/\"uuid\": \"$new_uuid\"/" "$SINGBOX_CONFIG_FILE" 1318 | LAST_REALITY_UUID="$new_uuid" 1319 | save_persistent_info 1320 | systemctl restart sing-box 1321 | success "Reality UUID已修改并重启服务。" 1322 | fi 1323 | ;; 1324 | 5) 1325 | read -p "请输入新的 Reality SNI: " new_sni 1326 | if [[ -n "$new_sni" ]]; then 1327 | sed -i "s/\"server_name\": \"$LAST_REALITY_SNI\"/\"server_name\": \"$new_sni\"/" "$SINGBOX_CONFIG_FILE" 1328 | LAST_REALITY_SNI="$new_sni" 1329 | save_persistent_info 1330 | systemctl restart sing-box 1331 | success "Reality SNI已修改并重启服务。" 1332 | fi 1333 | ;; 1334 | 6) 1335 | read -p "确定要删除当前节点配置吗?此操作不可恢复!(y/N): " del_confirm 1336 | if [[ "$del_confirm" =~ ^[Yy]$ ]]; then 1337 | rm -f "$SINGBOX_CONFIG_FILE" 1338 | rm -f "$PERSISTENT_INFO_FILE" 1339 | systemctl stop sing-box 1340 | LAST_HY2_PORT="" 1341 | LAST_HY2_MASQUERADE_CN="" 1342 | LAST_REALITY_PORT="" 1343 | LAST_REALITY_UUID="" 1344 | LAST_REALITY_SNI="" 1345 | LAST_INSTALL_MODE="" 1346 | success "节点配置已删除,Sing-box 服务已停止。" 1347 | pause_return_menu 1348 | break 1349 | else 1350 | echo "操作已取消。" 1351 | pause_return_menu 1352 | fi 1353 | ;; 1354 | 0) 1355 | pause_return_menu 1356 | break 1357 | ;; 1358 | *) 1359 | echo "无效选项。" 1360 | ;; 1361 | esac 1362 | pause_return_menu 1363 | done 1364 | } 1365 | -------------------------------------------------------------------------------- /modify_node_params.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 必要变量 4 | SINGBOX_CONFIG_FILE="/usr/local/etc/sing-box/config.json" 5 | PERSISTENT_INFO_FILE="/usr/local/etc/sing-box/.last_singbox_script_info" 6 | 7 | success() { echo -e "\033[0;32m[SUCCESS]\033[0m $1"; } 8 | error() { echo -e "\033[0;31m[ERROR]\033[0m $1"; } 9 | 10 | save_persistent_info() { 11 | cat > "$PERSISTENT_INFO_FILE" <