├── LICENSE ├── MYSELF_EN.md ├── MYSELF_ZH.md ├── README.en.md ├── README.md ├── REALITY.md ├── VLESS-XTLS-uTLS-REALITY ├── myself.json └── server.json ├── XTLS ├── Fallback.json ├── SNI.json ├── Trojan.json ├── Vision.json ├── XHTTP.json ├── config.json ├── mKCP.json ├── rules.json └── serverNames.json ├── cloudflare-warp ├── Dockerfile └── startup.sh ├── cloudreve ├── cloudreve.ini ├── cloudreve.service ├── docker-compose.yaml └── watchtower.sh ├── config ├── config.json ├── myself.json └── sysctl.conf ├── docker.sh ├── myself.sh ├── nginx.sh ├── nginx ├── conf │ ├── conf.d │ │ ├── redirect.conf │ │ └── restrict.conf │ ├── limit.conf │ ├── modules-enabled │ │ └── stream.conf │ ├── nginx.conf │ ├── nginxconfig.io │ │ ├── general.conf │ │ ├── grpc.conf │ │ ├── limit.conf │ │ ├── proxy.conf │ │ ├── security.conf │ │ └── zerossl.conf │ ├── nginxconfig.txt │ └── sites-available │ │ └── example.com.conf ├── limit_test.sh └── nginx.service ├── reality.sh ├── service └── xray.service ├── ssl.sh ├── tool ├── traffic.sh ├── update-dat.sh └── xray_config_manage.sh └── xhttp.sh /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 zxcvos 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 | -------------------------------------------------------------------------------- /MYSELF_EN.md: -------------------------------------------------------------------------------- 1 | 2 | # Xray-REALITY Management Script 3 | 4 | * A purely Shell-scripted REALITY management script 5 | * Configured with VLESS-XTLS-uTLS-REALITY 6 | * Achieves the use of Xray frontend to stealthily employ self-signed certificates, suitable for scenarios with no other website requirements 7 | * Implements Nginx SNI-based traffic shunting, with Xray backend for stealthy use of self-signed certificates, suitable for scenarios with multiple websites coexisting 8 | * Allows custom input of UUID; non-standard UUIDs will be mapped and converted to UUIDv5 using `Xray uuid -i "custom string"` 9 | * Default configuration blocks ads and BitTorrent traffic 10 | * Default deployment of Cloudreve using Docker as a personal cloud drive 11 | * Default deployment of Cloudflare WARP Proxy using Docker 12 | * Traffic to China is routed through Cloudflare WARP Proxy by default 13 | * Implements automatic updating of the geo file 14 | 15 | ## Notes 16 | 17 | 1. This script requires a domain name that resolves to the server. 18 | 19 | 2. The installation process of this script may take a long time. 20 | 21 | 3. This script is designed for individual VPS users. 22 | 23 | 4. It is recommended to use this script on a clean system (VPS console - reset system, or use a DD script to reinstall the system). 24 | 25 | ## Tested Systems 26 | 27 | | Platform | Version | 28 | | -------- | ---------- | 29 | | Debian | 10, 11, 12 | 30 | | Ubuntu | 20, 22, 23 | 31 | | CentOS | 7, 8, 9 | 32 | | Rocky | 8, 9 | 33 | 34 | The above distributions have been tested for installation on Vultr. 35 | 36 | Other Debian-based systems and Red Hat-based systems may work but have not been tested and may encounter issues. 37 | 38 | If there are issues with Docker installation, please install Docker manually and comment out the `install_docker` code in the `install()` function, then run it: 39 | 40 | ```sh 41 | sed -i 's/install_docker$/# install_docker/' ${HOME}/Xray-script.sh 42 | ``` 43 | 44 | ## Installation Duration Explanation 45 | 46 | This script is intended for long-term use after installation and is not suitable for repeated system resets and installations, which can consume a significant amount of your time. If you need to change configurations, domains, etc., corresponding options are available in the management interface. 47 | 48 | ### Installation Duration Reference 49 | 50 | Installation process: 51 | 52 | Update system management packages -> Install dependencies -> Install Docker -> Install Cloudreve -> Install Cloudflare-warp -> Install Xray -> Install Nginx -> Issue certificates -> Configuration files 53 | 54 | **This is the average installation time for a single-core 1G server and is for reference only:** 55 | 56 | | Task | Duration | 57 | | ----------------------- | ------------------ | 58 | | Update system packages | 0-10 minutes | 59 | | Install dependencies | 0-5 minutes | 60 | | Install Docker | 1-2 minutes | 61 | | Install Cloudreve | 3-5 minutes | 62 | | Install Cloudflare-warp | 3-5 minutes | 63 | | Install Xray | < half a minute | 64 | | Install Nginx | 13-15 minutes | 65 | | Issue certificates | 1-2 minutes | 66 | | Configuration files | < 100 milliseconds | 67 | 68 | ### Why does the script installation take so long? 69 | 70 | Nginx in the script is managed by compiling from source. 71 | 72 | The advantages of compiling include: 73 | 74 | 1. High runtime efficiency (optimized with -O3 during compilation) 75 | 2. Newer software versions 76 | 77 | The drawback is that compilation takes a long time. 78 | 79 | ## How to Use 80 | 81 | ### 1. Get/Update the Script 82 | 83 | * wget 84 | 85 | ```sh 86 | wget --no-check-certificate -O ${HOME}/Xray-script.sh https://raw.githubusercontent.com/zxcvos/Xray-script/main/myself.sh 87 | ``` 88 | 89 | * curl 90 | 91 | ```sh 92 | curl -fsSL -o ${HOME}/Xray-script.sh https://raw.githubusercontent.com/zxcvos/Xray-script/main/myself.sh 93 | ``` 94 | 95 | ### 2. Execute the Script 96 | 97 | ```sh 98 | bash ${HOME}/Xray-script.sh 99 | ``` 100 | 101 | ### 3. Script Interface 102 | 103 | ```sh 104 | --------------- Xray-script --------------- 105 | Version : v2023-12-31(beta) 106 | Title : Xray Management Script 107 | Description : Xray frontend or Nginx SNI shunting 108 | : reality dest points to a self-built camouflage site 109 | ----------------- Installation Management ---------------- 110 | 1. Install 111 | 2. Update 112 | 3. Uninstall 113 | ----------------- Operation Management ---------------- 114 | 4. Start 115 | 5. Stop 116 | 6. Restart 117 | ----------------- Configuration Management ---------------- 118 | 101. View Configuration 119 | 102. Change xray uuid 120 | 103. Change xray x25519 121 | 104. Change xray shortIds 122 | 105. Reset cloudreve admin 123 | ----------------- Other Options ---------------- 124 | 201. Update to Latest Stable Kernel 125 | 202. Remove Extra Kernels 126 | 203. Change SSH Port 127 | 204. Optimize Kernel Parameters 128 | ------------------------------------------- 129 | ``` 130 | 131 | ## Installation Paths 132 | 133 | **Xray-script:** `/usr/local/etc/zxcvos_xray_script` 134 | 135 | **Nginx:** `/usr/local/nginx` 136 | 137 | **Cloudreve:** `/usr/local/cloudreve` 138 | 139 | **Cloudflare 140 | 141 | -warp:** `/usr/local/cloudflare_warp` 142 | 143 | **Xray:** See **[Xray-install](https://github.com/XTLS/Xray-install)** 144 | 145 | ## Dependency List 146 | 147 | The script may automatically install the following dependencies: 148 | | Purpose | Debian-based Systems | Red Hat-based Systems | 149 | | ------------------------------------------------- | ------------------------------------------- | --------------------- | 150 | | yumdb set (mark packages for manual installation) | | yum-utils | 151 | | dnf config-manager | | dnf-plugins-core | 152 | | IP retrieval | iproute2 | iproute | 153 | | DNS resolution | dnsutils | bind-utils | 154 | | wget | wget | wget | 155 | | curl | curl | curl | 156 | | wget/curl https | ca-certificates | ca-certificates | 157 | | kill/pkill/ps/sysctl/free | procps | procps-ng | 158 | | epel repository | | epel-release | 159 | | epel repository | | epel-next-release | 160 | | remi repository | | remi-release | 161 | | Firewall | ufw | firewalld | 162 | | **Compilation Basics:** | | | 163 | | Download source files | wget | wget | 164 | | Unzip tar source files | tar | tar | 165 | | Unzip tar.gz source files | gzip | gzip | 166 | | gcc | gcc | gcc | 167 | | g++ | g++ | gcc-c++ | 168 | | make | make | make | 169 | | **acme.sh Dependencies:** | | | 170 | | | curl | curl | 171 | | | openssl | openssl | 172 | | | cron | crontabs | 173 | | **Compile openssl:** | | | 174 | | | perl-base (included in libperl-dev) | perl-IPC-Cmd | 175 | | | perl-modules-5.32 (included in libperl-dev) | perl-Getopt-Long | 176 | | | libperl5.32 (included in libperl-dev) | perl-Data-Dumper | 177 | | | | perl-FindBin | 178 | | **Compile Brotli:** | | | 179 | | | git | git | 180 | | | libbrotli-dev | brotli-devel | 181 | | **Compile Nginx:** | | | 182 | | | libpcre2-dev | pcre2-devel | 183 | | | zlib1g-dev | zlib-devel | 184 | | --with-http_xslt_module | libxml2-dev | libxml2-devel | 185 | | --with-http_xslt_module | libxslt1-dev | libxslt-devel | 186 | | --with-http_image_filter_module | libgd-dev | gd-devel | 187 | | --with-google_perftools_module | libgoogle-perftools-dev | gperftools-devel | 188 | | --with-http_geoip_module | libgeoip-dev | geoip-devel | 189 | | --with-http_perl_module | | perl-ExtUtils-Embed | 190 | | | libperl-dev | perl-devel | 191 | 192 | ## Credits 193 | 194 | [Xray-core][Xray-core] 195 | 196 | [REALITY][REALITY] 197 | 198 | [chika0801 Xray 配置文件模板][chika0801-Xray-examples] 199 | 200 | [部署 Cloudflare WARP Proxy][haoel] 201 | 202 | [cloudflare-warp 镜像][e7h4n] 203 | 204 | [WARP 一键脚本][fscarmen] 205 | 206 | [V2Ray 路由规则文件加强版][v2ray-rules-dat] 207 | 208 | [kirin10000/Xray-script][kirin10000/Xray-script] 209 | 210 | [使用Nginx进行SNI分流并完美和网站共存][nginx-sni-dispatcher] 211 | 212 | [[小白参阅系列] 第〇篇 手搓 Nginx 安装][post-37224-1] 213 | 214 | [Cloudreve][cloudreve] 215 | 216 | **This script is for educational purposes only. Do not use it for illegal activities.** 217 | 218 | [Xray-core]: https://github.com/XTLS/Xray-core (THE NEXT FUTURE) 219 | [REALITY]: https://github.com/XTLS/REALITY (THE NEXT FUTURE) 220 | [chika0801-Xray-examples]: https://github.com/chika0801/Xray-examples (chika0801 Xray 配置文件模板) 221 | [haoel]: https://github.com/haoel/haoel.github.io#943-docker-%E4%BB%A3%E7%90%86 (使用 Docker 快速部署 Cloudflare WARP Proxy) 222 | [e7h4n]: https://github.com/e7h4n/cloudflare-warp (cloudflare-warp 镜像) 223 | [fscarmen]: https://github.com/fscarmen/warp (WARP 一键脚本) 224 | [v2ray-rules-dat]: https://github.com/Loyalsoldier/v2ray-rules-dat (V2Ray 路由规则文件加强版) 225 | [kirin10000/Xray-script]: https://github.com/kirin10000/Xray-script (kirin10000/Xray-script) 226 | [nginx-sni-dispatcher]: https://blog.xmgspace.me/archives/nginx-sni-dispatcher.html (使用Nginx进行SNI分流并完美和网站共存) 227 | [post-37224-1]: https://www.nodeseek.com/post-37224-1 (第〇篇 手搓 Nginx 安装) 228 | [cloudreve]: https://github.com/cloudreve/cloudreve (cloudreve) 229 | -------------------------------------------------------------------------------- /MYSELF_ZH.md: -------------------------------------------------------------------------------- 1 | # Xray-REALITY 管理脚本 2 | 3 | * 一个纯 Shell 编写的 REALITY 管理脚本 4 | * 使用 VLESS-XTLS-uTLS-REALITY 配置 5 | * 实现使用 Xray 前置偷自己证书,适合没有其他网站需求 6 | * 实现使用 Nginx SNI 分流,Xray 后置偷自己证书,适合多网站共存需求 7 | * 可自定义输入 UUID ,非标准 UUID 将使用 `Xray uuid -i "自定义字符串"` 进行映射转化为 UUIDv5 8 | * 默认配置禁广告、bt 9 | * 默认使用 Docker 部署 Cloudreve 作为个人网盘使用 10 | * 默认使用 Docker 部署 Cloudflare WARP Proxy 11 | * 回国流量默认走 Cloudflare WARP Proxy 12 | * 实现 geo 文件的自动更新 13 | 14 | ## 注意事项 15 | 16 | 1. 此脚本需要一个解析到服务器的域名。 17 | 18 | 2. 此脚本安装时间较长。 19 | 20 | 3. 此脚本设计为个人VPS用户使用。 21 | 22 | 4. 建议在纯净的系统上使用此脚本 (VPS控制台-重置系统,或使用 DD 脚本重装系统)。 23 | 24 | ## 已测试系统 25 | 26 | | Platform | Version | 27 | | -------- | ---------- | 28 | | Debian | 10, 11, 12 | 29 | | Ubuntu | 20, 22, 23 | 30 | | CentOS | 7, 8, 9 | 31 | | Rocky | 8, 9 | 32 | 33 | 以上发行版均通过 Vultr 测试安装。 34 | 35 | 其他 Debian 基系统与 Red Hat 基系统可能能用,但未测试过,可能存在问题。 36 | 37 | 如果遇到 Docker 安装失败问题,请自行安装 Docker 后,将代码 `function install()` 函数中的 `install_docker` 注释再运行即可。 38 | 39 | 例如: 40 | 41 | ```sh 42 | sed -i 's/install_docker$/# install_docker/' ${HOME}/Xray-script.sh 43 | ``` 44 | 45 | ## 安装时长说明 46 | 47 | 此脚本适合安装一次后长期使用,不适合反复重置系统安装,这会消耗您的大量时间。如果需要更换配置和域名等,在管理界面都有相应的选项。 48 | 49 | ### 安装时长参考 50 | 51 | 安装流程: 52 | 53 | 更新系统管理包->安装依赖->安装Docker->安装Cloudreve->安装Cloudflare-warp->安装Xray->安装Nginx->申请证书->配置文件 54 | 55 | **这是一台单核1G的服务器的平均安装时长,仅供参考:** 56 | 57 | | 项目 | 时长 | 58 | | ------------------- | --------- | 59 | | 更新系统管理包 | 0-10分钟 | 60 | | 安装依赖 | 0-5分钟 | 61 | | 安装Docker | 1-2分钟 | 62 | | 安装Cloudreve | 3-5分钟 | 63 | | 安装Cloudflare-warp | 3-5分钟 | 64 | | 安装Xray | <半分钟 | 65 | | 安装Nginx | 13-15分钟 | 66 | | 申请证书 | 1-2分钟 | 67 | | 配置文件 | <100毫秒 | 68 | 69 | ### 为什么脚本安装时间那么长? 70 | 71 | 脚本的Nginx是采用源码编译的形式进行管理安装。 72 | 73 | 编译相比直接安装二进制文件的优点有: 74 | 75 | 1. 运行效率高 (编译时采用了-O3优化) 76 | 2. 软件版本新 77 | 78 | 缺点就是编译耗时长。 79 | 80 | ## 如何使用 81 | 82 | ### 1.获取/更新脚本 83 | 84 | * wget 85 | 86 | ```sh 87 | wget --no-check-certificate -O ${HOME}/Xray-script.sh https://raw.githubusercontent.com/zxcvos/Xray-script/main/myself.sh 88 | ``` 89 | 90 | * curl 91 | 92 | ```sh 93 | curl -fsSL -o ${HOME}/Xray-script.sh https://raw.githubusercontent.com/zxcvos/Xray-script/main/myself.sh 94 | ``` 95 | 96 | ### 2.执行脚本 97 | 98 | ```sh 99 | bash ${HOME}/Xray-script.sh 100 | ``` 101 | 102 | ### 3.脚本界面 103 | 104 | ```sh 105 | --------------- Xray-script --------------- 106 | Version : v2023-12-31(beta) 107 | Title : Xray 管理脚本 108 | Description : Xray 前置或 Nginx 分流 109 | : reality dest 目标为自建伪装站 110 | ----------------- 装载管理 ---------------- 111 | 1. 安装 112 | 2. 更新 113 | 3. 卸载 114 | ----------------- 操作管理 ---------------- 115 | 4. 启动 116 | 5. 停止 117 | 6. 重启 118 | ----------------- 配置管理 ---------------- 119 | 101. 查看配置 120 | 102. 修改 id 121 | 103. 修改 x25519 122 | 104. 修改 shortIds 123 | 105. 重置 Cloudreve 初始账号密码 124 | ----------------- 其他选项 ---------------- 125 | 201. 更新至最新稳定版内核 126 | 202. 卸载多余内核 127 | 203. 修改 ssh 端口 128 | 204. 内核参数调优 129 | ------------------------------------------- 130 | ``` 131 | 132 | ## 安装位置 133 | 134 | **Xray-script:** `/usr/local/etc/zxcvos_xray_script` 135 | 136 | **Nginx:** `/usr/local/nginx` 137 | 138 | **Cloudreve:** `/usr/local/cloudreve` 139 | 140 | **Cloudflare-warp:** `/usr/local/cloudflare_warp` 141 | 142 | **Xray:** 见 **[Xray-install](https://github.com/XTLS/Xray-install)** 143 | 144 | ## 依赖列表 145 | 146 | 脚本可能自动安装以下依赖: 147 | | 用途 | Debian基系统 | Red Hat基系统 | 148 | | ------------------------------- | ------------------------------------ | ------------------- | 149 | | yumdb set(标记包手动安装) | | yum-utils | 150 | | dnf config-manager | | dnf-plugins-core | 151 | | IP 获取 | iproute2 | iproute | 152 | | DNS 解析 | dnsutils | bind-utils | 153 | | wget | wget | wget | 154 | | curl | curl | curl | 155 | | wget/curl https | ca-certificates | ca-certificates | 156 | | kill/pkill/ps/sysctl/free | procps | procps-ng | 157 | | epel源 | | epel-release | 158 | | epel源 | | epel-next-release | 159 | | remi源 | | remi-release | 160 | | 防火墙 | ufw | firewalld | 161 | | **编译基础:** | | | 162 | | 下载源码文件 | wget | wget | 163 | | 解压tar源码文件 | tar | tar | 164 | | 解压tar.gz源码文件 | gzip | gzip | 165 | | gcc | gcc | gcc | 166 | | g++ | g++ | gcc-c++ | 167 | | make | make | make | 168 | | **acme.sh依赖:** | | | 169 | | | curl | curl | 170 | | | openssl | openssl | 171 | | | cron | crontabs | 172 | | **编译openssl:** | | | 173 | | | perl-base(包含于libperl-dev) | perl-IPC-Cmd | 174 | | | perl-modules-5.32(包含于libperl-dev) | perl-Getopt-Long | 175 | | | libperl5.32(包含于libperl-dev) | perl-Data-Dumper | 176 | | | | perl-FindBin | 177 | | **编译Brotli:** | | | 178 | | | git | git | 179 | | | libbrotli-dev | brotli-devel | 180 | | **编译Nginx:** | | | 181 | | | libpcre2-dev | pcre2-devel | 182 | | | zlib1g-dev | zlib-devel | 183 | | --with-http_xslt_module | libxml2-dev | libxml2-devel | 184 | | --with-http_xslt_module | libxslt1-dev | libxslt-devel | 185 | | --with-http_image_filter_module | libgd-dev | gd-devel | 186 | | --with-google_perftools_module | libgoogle-perftools-dev | gperftools-devel | 187 | | --with-http_geoip_module | libgeoip-dev | geoip-devel | 188 | | --with-http_perl_module | | perl-ExtUtils-Embed | 189 | | | libperl-dev | perl-devel | 190 | 191 | ## 致谢 192 | 193 | [Xray-core][Xray-core] 194 | 195 | [REALITY][REALITY] 196 | 197 | [chika0801 Xray 配置文件模板][chika0801-Xray-examples] 198 | 199 | [部署 Cloudflare WARP Proxy][haoel] 200 | 201 | [cloudflare-warp 镜像][e7h4n] 202 | 203 | [WARP 一键脚本][fscarmen] 204 | 205 | [V2Ray 路由规则文件加强版][v2ray-rules-dat] 206 | 207 | [kirin10000/Xray-script][kirin10000/Xray-script] 208 | 209 | [使用Nginx进行SNI分流并完美和网站共存][nginx-sni-dispatcher] 210 | 211 | [[小白参阅系列] 第〇篇 手搓 Nginx 安装][post-37224-1] 212 | 213 | [Cloudreve][cloudreve] 214 | 215 | **此脚本仅供交流学习使用,请勿使用此脚本行违法之事。网络非法外之地,行非法之事,必将接受法律制裁。** 216 | 217 | [Xray-core]: https://github.com/XTLS/Xray-core (THE NEXT FUTURE) 218 | [REALITY]: https://github.com/XTLS/REALITY (THE NEXT FUTURE) 219 | [chika0801-Xray-examples]: https://github.com/chika0801/Xray-examples (chika0801 Xray 配置文件模板) 220 | [haoel]: https://github.com/haoel/haoel.github.io#943-docker-%E4%BB%A3%E7%90%86 (使用 Docker 快速部署 Cloudflare WARP Proxy) 221 | [e7h4n]: https://github.com/e7h4n/cloudflare-warp (cloudflare-warp 镜像) 222 | [fscarmen]: https://github.com/fscarmen/warp (WARP 一键脚本) 223 | [v2ray-rules-dat]: https://github.com/Loyalsoldier/v2ray-rules-dat (V2Ray 路由规则文件加强版) 224 | [kirin10000/Xray-script]: https://github.com/kirin10000/Xray-script (kirin10000/Xray-script) 225 | [nginx-sni-dispatcher]: https://blog.xmgspace.me/archives/nginx-sni-dispatcher.html (使用Nginx进行SNI分流并完美和网站共存) 226 | [post-37224-1]: https://www.nodeseek.com/post-37224-1 (第〇篇 手搓 Nginx 安装) 227 | [cloudreve]: https://github.com/cloudreve/cloudreve (cloudreve) 228 | -------------------------------------------------------------------------------- /README.en.md: -------------------------------------------------------------------------------- 1 | 2 | 中文 | English 3 | # Xray-XHTTP Management Script :sparkles: 4 | 5 | * A pure Shell-written XHTTP management script for Xray 6 | * Optional configurations: 7 | * mKCP (VLESS-mKCP-seed) 8 | * Vision (VLESS-Vision-REALITY) 9 | * XHTTP (VLESS-XHTTP-REALITY) 10 | * trojan (Trojan-XHTTP-REALITY) 11 | * Fallback (includes VLESS-Vision-REALITY, VLESS-XHTTP-REALITY) 12 | * SNI (includes Vision_REALITY, XHTTP_REALITY, XHTTP_TLS) 13 | * SNI configuration uses Nginx for SNI traffic splitting, ideal for CDN traversal, upstream/downstream separation, and multi-site coexistence 14 | * SNI share links implement bidirectional separation (upstream: xhttp+TLS+CDN | downstream: xhttp+Reality, upstream: xhttp+Reality | downstream: xhttp+TLS+CDN) 15 | * Rule configurations and custom entries: 16 | * Block BitTorrent traffic (optional) 17 | * Block China IP traffic (optional) 18 | * Ad blocking (optional) 19 | * Add custom WARP Proxy rules 20 | * Add custom block rules 21 | * Cloudflare WARP Proxy toggle (🐳 Docker deployment) 22 | * Geodata auto-update toggle 23 | * Xray ports default/fill: 24 | * VLESS-mKCP: Randomly generated 25 | * ALL-REALITY: 443 26 | * UUID default/fill: 27 | * Randomly generated 28 | * Custom standard UUID input 29 | * Non-standard UUID mapping conversion 30 | * kcp(seed) and trojan(password) default/fill: 31 | * Random generation (format: cw-GEMDYgwIV3_g#) 32 | * Custom input 33 | * target default/fill: 34 | * Random selection from serverNames.json 35 | * TLSv1.3 and H2 validation for custom targets 36 | * Automatic serverNames acquisition for custom targets 37 | * shortId default/fill: 38 | * Random generation (default two shortIds e.g.: 01234567, 0123456789abcdef) 39 | * Custom shortId input 40 | * Numeric input 0-8 generates 0-16 length shortIds 41 | * Comma-separated multiple values 42 | * path default/fill: 43 | * Random generation (format: /8ugSUeNJ.9OEnTErb.dVZMUAFu) 44 | * Custom input (format: /8ugSUeNJ, with/without `/`) 45 | 46 | ## Issues 47 | 48 | 1. If installation succeeds but not working, check if server ports are open 49 | 2. Before using SNI configuration, ensure VPS HTTP(80) and HTTPS(443) ports are open 50 | 3. Before using SNI configuration, disable CDN protection to avoid SSL certificate issues 51 | 4. For upstream/downstream separation details, see [XHTTP: Beyond REALITY][XHTTP] and [xhttp 五合一配置][xhttp 五合一配置] 52 | 53 | Verify port accessibility via `https://tcp.ping.pe/ip:port` 54 | 55 | ## Share Links 56 | 57 | Based on [VMessAEAD / VLESS 分享链接标准提案](https://github.com/XTLS/Xray-core/discussions/716) and [v2rayN](https://github.com/2dust/v2rayN). Modify links manually if other clients have compatibility issues. 58 | 59 | In SNI configurations, CDN share links default Alpn to H2. For H3 requirements, modify client settings manually. 60 | 61 | ## Usage 62 | 63 | * Download: 64 | ```sh 65 | wget --no-check-certificate -O ${HOME}/Xray-script.sh https://raw.githubusercontent.com/zxcvos/Xray-script/main/xhttp.sh 66 | ``` 67 | 68 | * Execute: 69 | ```sh 70 | bash ${HOME}/Xray-script.sh 71 | ``` 72 | 73 | * Quick start: 74 | ```sh 75 | wget --no-check-certificate -O ${HOME}/Xray-script.sh https://raw.githubusercontent.com/zxcvos/Xray-script/main/xhttp.sh && bash ${HOME}/Xray-script.sh 76 | ``` 77 | 78 | ## Script Interface 79 | 80 | ```sh 81 | __ __ _ _ _______ _______ _____ 82 | \ \ / / | | | | |__ __| |__ __| | __ \ 83 | \ V / | |__| | | | | | | |__) | 84 | > < | __ | | | | | | ___/ 85 | / . \ | | | | | | | | | | 86 | /_/ \_\ |_| |_| |_| |_| |_| 87 | 88 | Copyright (C) zxcvos | https://github.com/zxcvos/Xray-script 89 | 90 | ------------------------------------------- 91 | Xray : v24.12.31 92 | CONFIG : VLESS-XHTTP-REALITY 93 | WARP Proxy : Running 94 | ------------------------------------------- 95 | 96 | --------------- Xray-script --------------- 97 | Version : v2024-12-31 98 | Description : Xray Management Script 99 | ----------------- Installation ---------------- 100 | 1. Full installation 101 | 2. Install/Update only 102 | 3. Uninstall 103 | ----------------- Operation ----------------- 104 | 4. Start 105 | 5. Stop 106 | 6. Restart 107 | ----------------- Configuration ------------- 108 | 7. Share links & QR codes 109 | 8. Statistics 110 | 9. Manage configuration 111 | ------------------------------------------- 112 | 0. Exit 113 | ``` 114 | 115 | ## Tested Systems 116 | 117 | | Platform | Version | 118 | | -------- | ---------- | 119 | | Debian | 10, 11, 12 | 120 | | Ubuntu | 20, 22, 24 | 121 | | CentOS | 7, 8, 9 | 122 | | Rocky | 8, 9 | 123 | 124 | All tested on Vultr instances. Other Debian/Red Hat derivatives might work but are untested. 125 | 126 | ## Installation Time Notes 127 | 128 | SNI configuration is designed for long-term use after initial setup. Reinstalling systems frequently will consume significant time. Use configuration management options for domain/setting changes. 129 | 130 | When switching from SNI configuration, Nginx stops but remains installed. Reactivating SNI won't trigger reinstallation. 131 | 132 | ### Installation Time Reference (1CPU/1GB) 133 | 134 | | Process | Duration | 135 | | ----------------------- | ------------------ | 136 | | Update system packages | 0-10 minutes | 137 | | Install dependencies | 0-5 minutes | 138 | | Install Docker | 1-2 minutes | 139 | | Install Cloudreve | 3-5 minutes | 140 | | Install Cloudflare-warp | 3-5 minutes | 141 | | Install Xray | < half a minute | 142 | | Install Nginx | 13-15 minutes | 143 | | Issue certificates | 1-2 minutes | 144 | | Configuration files | < 100 milliseconds | 145 | 146 | ### Why does the script installation take so long? 147 | 148 | Nginx in the script is managed by compiling from source. 149 | 150 | The advantages of compiling include: 151 | 152 | 1. High runtime efficiency (optimized with -O3 during compilation) 153 | 2. Newer software versions 154 | 155 | The drawback is that compilation takes a long time. 156 | 157 | ## Installation Paths 158 | 159 | 160 | **Xray-script:** `/usr/local/etc/xray-script` 161 | 162 | **Nginx:** `/usr/local/nginx` 163 | 164 | **Cloudreve:** `/usr/local/cloudreve` 165 | 166 | **Cloudflare-warp:** `/usr/local/cloudflare_warp` 167 | 168 | **Xray:** See **[Xray-install](https://github.com/XTLS/Xray-install)** 169 | 170 | 171 | ## Dependencies 172 | 173 | SNI configuration may install these dependencies: 174 | 175 | | Purpose | Debian-based Systems | Red Hat-based Systems | 176 | | ------------------------------------------------- | ------------------------------------------- | --------------------- | 177 | | yumdb set (mark packages for manual installation) | | yum-utils | 178 | | dnf config-manager | | dnf-plugins-core | 179 | | IP retrieval | iproute2 | iproute | 180 | | DNS resolution | dnsutils | bind-utils | 181 | | wget | wget | wget | 182 | | curl | curl | curl | 183 | | wget/curl https | ca-certificates | ca-certificates | 184 | | kill/pkill/ps/sysctl/free | procps | procps-ng | 185 | | epel repository | | epel-release | 186 | | epel repository | | epel-next-release | 187 | | remi repository | | remi-release | 188 | | Firewall | ufw | firewalld | 189 | | **Compilation Basics:** | | | 190 | | Download source files | wget | wget | 191 | | Unzip tar source files | tar | tar | 192 | | Unzip tar.gz source files | gzip | gzip | 193 | | gcc | gcc | gcc | 194 | | g++ | g++ | gcc-c++ | 195 | | make | make | make | 196 | | **acme.sh Dependencies:** | | | 197 | | | curl | curl | 198 | | | openssl | openssl | 199 | | | cron | crontabs | 200 | | **Compile openssl:** | | | 201 | | | perl-base (included in libperl-dev) | perl-IPC-Cmd | 202 | | | perl-modules-5.32 (included in libperl-dev) | perl-Getopt-Long | 203 | | | libperl5.32 (included in libperl-dev) | perl-Data-Dumper | 204 | | | | perl-FindBin | 205 | | **Compile Brotli:** | | | 206 | | | git | git | 207 | | | libbrotli-dev | brotli-devel | 208 | | **Compile Nginx:** | | | 209 | | | libpcre2-dev | pcre2-devel | 210 | | | zlib1g-dev | zlib-devel | 211 | | --with-http_xslt_module | libxml2-dev | libxml2-devel | 212 | | --with-http_xslt_module | libxslt1-dev | libxslt-devel | 213 | | --with-http_image_filter_module | libgd-dev | gd-devel | 214 | | --with-google_perftools_module | libgoogle-perftools-dev | gperftools-devel | 215 | | --with-http_geoip_module | libgeoip-dev | geoip-devel | 216 | | --with-http_perl_module | | perl-ExtUtils-Embed | 217 | | | libperl-dev | perl-devel | 218 | 219 | ## Credits 220 | 221 | [Xray-core][Xray-core] 222 | 223 | [REALITY][REALITY] 224 | 225 | [XHTTP: Beyond REALITY][XHTTP] 226 | 227 | [integrated-examples][lxhao61/integrated-examples] 228 | 229 | [xhttp 五合一配置][xhttp 五合一配置] 230 | 231 | [部署 Cloudflare WARP Proxy][haoel] 232 | 233 | [cloudflare-warp 镜像][e7h4n] 234 | 235 | [V2Ray 路由规则文件加强版][v2ray-rules-dat] 236 | 237 | [kirin10000/Xray-script][kirin10000/Xray-script] 238 | 239 | [Cloudreve][cloudreve] 240 | 241 | **This script is for educational purposes only. Do not use it for illegal activities.** 242 | 243 | [Xray-core]: https://github.com/XTLS/Xray-core (THE NEXT FUTURE) 244 | [REALITY]: https://github.com/XTLS/REALITY (THE NEXT FUTURE) 245 | [XHTTP]: https://github.com/XTLS/Xray-core/discussions/4113 (XHTTP: Beyond REALITY) 246 | [lxhao61/integrated-examples]: https://github.com/lxhao61/integrated-examples (以 V2Ray(v4 版) 或 Xray、Nginx 或 Caddy(v2 版)、Hysteria 等打造常用科学上网的优化配置及最优组合示例,且提供集成特定插件的 Caddy(v2 版) 文件,分享给大家食用及自己备份。) 247 | [xhttp 五合一配置]: https://github.com/XTLS/Xray-core/discussions/4118 (xhttp 五合一配置 \( reality 直连与过 CDN 共存, 附小白可抄的配置\)) 248 | [haoel]: https://github.com/haoel/haoel.github.io#943-docker-%E4%BB%A3%E7%90%86 (使用 Docker 快速部署 Cloudflare WARP Proxy) 249 | [e7h4n]: https://github.com/e7h4n/cloudflare-warp (cloudflare-warp 镜像) 250 | [v2ray-rules-dat]: https://github.com/Loyalsoldier/v2ray-rules-dat (V2Ray 路由规则文件加强版) 251 | [kirin10000/Xray-script]: https://github.com/kirin10000/Xray-script (kirin10000/Xray-script) 252 | [cloudreve]: https://github.com/cloudreve/cloudreve (cloudreve) 253 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 中文 | English 2 | # Xray-XHTTP 管理脚本 :sparkles: 3 | 4 | * 一个纯 Shell 编写的 XHTTP 管理脚本 5 | * 可选配置: 6 | * mKCP (VLESS-mKCP-seed) 7 | * Vision (VLESS-Vision-REALITY) 8 | * XHTTP (VLESS-XHTTP-REALITY) 9 | * trojan (Trojan-XHTTP-REALITY) 10 | * Fallback (包含 VLESS-Vision-REALITY、VLESS-XHTTP-REALITY) 11 | * SNI (包含 Vision_REALITY、XHTTP_REALITY、XHTTP_TLS) 12 | * SNI 配置由 Nginx 实现 SNI 分流,适合过 CDN、上下行分离、多网站共存等需求 13 | * SNI 分享链接实现了上下行分离(上行 xhttp+TLS+CDN | 下行 xhttp+Reality、上行 xhttp+Reality | 下行 xhttp+TLS+CDN) 14 | * 规则配置与自填: 15 | * 禁止 bittorrent 流量(可选) 16 | * 禁止回国 ip 流量(可选) 17 | * 屏蔽广告(可选) 18 | * 添加自定义 WARP Proxy 分流 19 | * 添加自定义屏蔽分流 20 | * 开关 Cloudflare WARP Proxy( :whale: Docker 部署) 21 | * 开关 geodata 自动更新功能 22 | * xray 端口默认与自填: 23 | * VLESS-mKCP: 随机生成 24 | * ALL-REALITY: 443 25 | * UUID 默认与自填: 26 | * 随机生成 27 | * 自定义输入标准 UUID 28 | * 非标准 UUID 映射转化为 UUID 29 | * kcp(seed) 和 trojan(password) 默认与自填: 30 | * 随机生成(格式: cw-GEMDYgwIV3_g#) 31 | * 自定义输入 32 | * target 默认与自填: 33 | * 随机在 serverNames.json 中获取 34 | * 实现自填 target 的 TLSv1.3 与 H2 验证 35 | * 实现自填 target 的 serverNames 自动获取 36 | * shortId 默认与自填: 37 | * 随机生成(默认两个 shortId 例如: 01234567, 0123456789abcdef) 38 | * 实现自填 shortId 39 | * 实现输入值为 0 到 8, 则自动生成对 0-16 长度的 shortId 40 | * 支持逗号分隔的多个值 41 | * path 默认与自填: 42 | * 随机生成(格式: /8ugSUeNJ.9OEnTErb.dVZMUAFu) 43 | * 自定义输入(格式: /8ugSUeNJ, 加不加 `/` 都可以) 44 | 45 | ## 问题 46 | 47 | 1. 如果安装成功,但无法使用,请检查服务器是否开启对应端口。 48 | 2. 使用 SNI 配置前,请确保 VPS 的 HTTP(80) 与 HTTPS(443) 端口开放。 49 | 3. 使用 SNI 配置前,请不要开启 CDN 保护,不然无法正常申请 SSL 证书。 50 | 4. 上下行分离详情请看 [XHTTP: Beyond REALITY][XHTTP] 与 [xhttp 五合一配置][xhttp 五合一配置] 了解。 51 | 52 | 可通过 `https://tcp.ping.pe/ip:port` 验证服务器端口是否开放。 53 | 54 | ## 分享链接 55 | 56 | 基于[VMessAEAD / VLESS 分享链接标准提案](https://github.com/XTLS/Xray-core/discussions/716)与[v2rayN](https://github.com/2dust/v2rayN)实现,如果其他客户端无法正常使用,请自行根据分享链接进行修改。 57 | 58 | SNI 配置中,CDN 的分享链接 Alpn 默认为 H2,如有 H3 需求,请自行在客户端修改。 59 | 60 | ## 如何使用 61 | 62 | * 获取 63 | 64 | ```sh 65 | wget --no-check-certificate -O ${HOME}/Xray-script.sh https://raw.githubusercontent.com/zxcvos/Xray-script/main/xhttp.sh 66 | ``` 67 | 68 | * 使用 69 | 70 | ```sh 71 | bash ${HOME}/Xray-script.sh 72 | ``` 73 | 74 | * 快速启动 75 | 76 | ```sh 77 | wget --no-check-certificate -O ${HOME}/Xray-script.sh https://raw.githubusercontent.com/zxcvos/Xray-script/main/xhttp.sh && bash ${HOME}/Xray-script.sh 78 | ``` 79 | 80 | ## 脚本界面 81 | 82 | ```sh 83 | __ __ _ _ _______ _______ _____ 84 | \ \ / / | | | | |__ __| |__ __| | __ \ 85 | \ V / | |__| | | | | | | |__) | 86 | > < | __ | | | | | | ___/ 87 | / . \ | | | | | | | | | | 88 | /_/ \_\ |_| |_| |_| |_| |_| 89 | 90 | Copyright (C) zxcvos | https://github.com/zxcvos/Xray-script 91 | 92 | ------------------------------------------- 93 | Xray : v24.12.31 94 | CONFIG : VLESS-XHTTP-REALITY 95 | WARP Proxy : 已启动 96 | ------------------------------------------- 97 | 98 | --------------- Xray-script --------------- 99 | Version : v2024-12-31 100 | Description : Xray 管理脚本 101 | ----------------- 装载管理 ---------------- 102 | 1. 完整安装 103 | 2. 仅安装/更新 104 | 3. 卸载 105 | ----------------- 操作管理 ---------------- 106 | 4. 启动 107 | 5. 停止 108 | 6. 重启 109 | ----------------- 配置管理 ---------------- 110 | 7. 分享链接与二维码 111 | 8. 信息统计 112 | 9. 管理配置 113 | ------------------------------------------- 114 | 0. 退出 115 | ``` 116 | 117 | ## 已测试系统 118 | 119 | | Platform | Version | 120 | | -------- | ---------- | 121 | | Debian | 10, 11, 12 | 122 | | Ubuntu | 20, 22, 24 | 123 | | CentOS | 7, 8, 9 | 124 | | Rocky | 8, 9 | 125 | 126 | 以上发行版均通过 Vultr 测试安装。 127 | 128 | 其他 Debian 基系统与 Red Hat 基系统可能能用,但未测试过,可能存在问题。 129 | 130 | ## 安装时长说明 131 | 132 | SNI 配置适合安装一次后长期使用,不适合反复重置系统安装,这会消耗您的大量时间。如果需要更换配置和域名等,在管理界面都有相应的选项。 133 | 134 | 更换为非 SNI 配置后,Nginx 将停止服务,但会继续保留在本机,再启用 SNI 配置时不会进行重新安装。 135 | 136 | ### 安装时长参考 137 | 138 | 安装流程: 139 | 140 | 更新系统管理包->安装依赖->安装Docker->安装Cloudreve->[安装Cloudflare-warp]->安装Xray->安装Nginx->申请证书->配置文件 141 | 142 | **这是一台单核1G的服务器的平均安装时长,仅供参考:** 143 | 144 | | 项目 | 时长 | 145 | | ------------------- | --------- | 146 | | 更新系统管理包 | 0-10分钟 | 147 | | 安装依赖 | 0-5分钟 | 148 | | 安装Docker | 1-2分钟 | 149 | | 安装Cloudreve | 3-5分钟 | 150 | | 安装Cloudflare-warp | 3-5分钟 | 151 | | 安装Xray | <半分钟 | 152 | | 安装Nginx | 13-15分钟 | 153 | | 申请证书 | 1-2分钟 | 154 | | 配置文件 | <100毫秒 | 155 | 156 | ### 为什么 SNI 配置安装时间那么长? 157 | 158 | 脚本的 Nginx 是采用源码编译的形式进行管理安装。 159 | 160 | 编译相比直接安装二进制文件的优点有: 161 | 162 | 1. 运行效率高 (编译时采用了-O3优化) 163 | 2. 软件版本新 164 | 165 | 缺点就是编译耗时长。 166 | 167 | ## 安装位置 168 | 169 | **Xray-script:** `/usr/local/xray-script` 170 | 171 | **Nginx:** `/usr/local/nginx` 172 | 173 | **Cloudreve:** `/usr/local/cloudreve` 174 | 175 | **Cloudflare-warp:** `/usr/local/cloudflare_warp` 176 | 177 | **Xray:** 见 **[Xray-install](https://github.com/XTLS/Xray-install)** 178 | 179 | ## 依赖列表 180 | 181 | 使用 SNI 配置时,脚本可能自动安装以下依赖: 182 | | 用途 | Debian基系统 | Red Hat基系统 | 183 | | ------------------------------- | ------------------------------------ | ------------------- | 184 | | yumdb set(标记包手动安装) | | yum-utils | 185 | | dnf config-manager | | dnf-plugins-core | 186 | | IP 获取 | iproute2 | iproute | 187 | | DNS 解析 | dnsutils | bind-utils | 188 | | wget | wget | wget | 189 | | curl | curl | curl | 190 | | wget/curl https | ca-certificates | ca-certificates | 191 | | kill/pkill/ps/sysctl/free | procps | procps-ng | 192 | | epel源 | | epel-release | 193 | | epel源 | | epel-next-release | 194 | | remi源 | | remi-release | 195 | | 防火墙 | ufw | firewalld | 196 | | **编译基础:** | | | 197 | | 下载源码文件 | wget | wget | 198 | | 解压tar源码文件 | tar | tar | 199 | | 解压tar.gz源码文件 | gzip | gzip | 200 | | gcc | gcc | gcc | 201 | | g++ | g++ | gcc-c++ | 202 | | make | make | make | 203 | | **acme.sh依赖:** | | | 204 | | | curl | curl | 205 | | | openssl | openssl | 206 | | | cron | crontabs | 207 | | **编译openssl:** | | | 208 | | | perl-base(包含于libperl-dev) | perl-IPC-Cmd | 209 | | | perl-modules-5.32(包含于libperl-dev) | perl-Getopt-Long | 210 | | | libperl5.32(包含于libperl-dev) | perl-Data-Dumper | 211 | | | | perl-FindBin | 212 | | **编译Brotli:** | | | 213 | | | git | git | 214 | | | libbrotli-dev | brotli-devel | 215 | | **编译Nginx:** | | | 216 | | | libpcre2-dev | pcre2-devel | 217 | | | zlib1g-dev | zlib-devel | 218 | | --with-http_xslt_module | libxml2-dev | libxml2-devel | 219 | | --with-http_xslt_module | libxslt1-dev | libxslt-devel | 220 | | --with-http_image_filter_module | libgd-dev | gd-devel | 221 | | --with-google_perftools_module | libgoogle-perftools-dev | gperftools-devel | 222 | | --with-http_geoip_module | libgeoip-dev | geoip-devel | 223 | | --with-http_perl_module | | perl-ExtUtils-Embed | 224 | | | libperl-dev | perl-devel | 225 | 226 | ## 致谢 227 | 228 | [Xray-core][Xray-core] 229 | 230 | [REALITY][REALITY] 231 | 232 | [XHTTP: Beyond REALITY][XHTTP] 233 | 234 | [integrated-examples][lxhao61/integrated-examples] 235 | 236 | [xhttp 五合一配置][xhttp 五合一配置] 237 | 238 | [部署 Cloudflare WARP Proxy][haoel] 239 | 240 | [cloudflare-warp 镜像][e7h4n] 241 | 242 | [V2Ray 路由规则文件加强版][v2ray-rules-dat] 243 | 244 | [kirin10000/Xray-script][kirin10000/Xray-script] 245 | 246 | [Cloudreve][cloudreve] 247 | 248 | **此脚本仅供交流学习使用,请勿使用此脚本行违法之事。网络非法外之地,行非法之事,必将接受法律制裁。** 249 | 250 | [Xray-core]: https://github.com/XTLS/Xray-core (THE NEXT FUTURE) 251 | [REALITY]: https://github.com/XTLS/REALITY (THE NEXT FUTURE) 252 | [XHTTP]: https://github.com/XTLS/Xray-core/discussions/4113 (XHTTP: Beyond REALITY) 253 | [lxhao61/integrated-examples]: https://github.com/lxhao61/integrated-examples (以 V2Ray(v4 版) 或 Xray、Nginx 或 Caddy(v2 版)、Hysteria 等打造常用科学上网的优化配置及最优组合示例,且提供集成特定插件的 Caddy(v2 版) 文件,分享给大家食用及自己备份。) 254 | [xhttp 五合一配置]: https://github.com/XTLS/Xray-core/discussions/4118 (xhttp 五合一配置 \( reality 直连与过 CDN 共存, 附小白可抄的配置\)) 255 | [haoel]: https://github.com/haoel/haoel.github.io#943-docker-%E4%BB%A3%E7%90%86 (使用 Docker 快速部署 Cloudflare WARP Proxy) 256 | [e7h4n]: https://github.com/e7h4n/cloudflare-warp (cloudflare-warp 镜像) 257 | [v2ray-rules-dat]: https://github.com/Loyalsoldier/v2ray-rules-dat (V2Ray 路由规则文件加强版) 258 | [kirin10000/Xray-script]: https://github.com/kirin10000/Xray-script (kirin10000/Xray-script) 259 | [cloudreve]: https://github.com/cloudreve/cloudreve (cloudreve) 260 | -------------------------------------------------------------------------------- /REALITY.md: -------------------------------------------------------------------------------- 1 | # Xray-REALITY 管理脚本 2 | 3 | * 一个纯 Shell 编写的 REALITY 管理脚本 4 | * 使用 VLESS-XTLS-uTLS-REALITY 配置 5 | * 实现 xray 监听端口的自填 6 | * 可自定义输入 UUID ,非标准 UUID 将使用 `Xray uuid -i "自定义字符串"` 进行映射转化为 UUIDv5 7 | * 实现 dest 的自选与自填 8 | * 实现自填 dest 的 TLSv1.3 与 H2 验证 9 | * 实现自填 dest 的 serverNames 自动获取 10 | * 实现自动获取的 serverNames 通配符域名与 CDN SNI 域名的过滤,dest 如果是子域名将会自动加入到 serverNames 中 11 | * 实现自填 dest 的 spiderX 的自定义显示,例如:自填 dest 为 `fmovies.to/home` 时,client config 会显示 `spiderX: /home` 12 | * 默认配置禁回国流量、广告、bt 13 | * 可使用 Docker 部署 Cloudflare WARP Proxy 14 | * 实现 geo 文件的自动更新 15 | 16 | ## 问题 17 | 18 | 虽然使用 warp 开启了 OpenAI 的正常访问,但是还是无法登陆。 19 | 20 | 已经让肉体在美国的朋友帮忙试了,同一个账号,我这上不去,爆出要联系管理员解决,他那里直接登录成功了,可能是我没刷 IP 的缘故:( 。 21 | 22 | 需要正常访问且能登陆的建议不要使用我提供的这个开启功能,去用脚本[WARP 一键脚本][fscarmen]刷出能用的 IP 后,根据[分流到 WARP Client Proxy 的方法][fscarmen-warpproxy]修改 `/usr/local/etc/xray/config.json`实现 OpenAI 的正常使用。 23 | 24 | ## 如何使用 25 | 26 | * wget 27 | 28 | ```sh 29 | wget --no-check-certificate -O ${HOME}/Xray-script.sh https://raw.githubusercontent.com/zxcvos/Xray-script/main/reality.sh && bash ${HOME}/Xray-script.sh 30 | ``` 31 | 32 | * curl 33 | 34 | ```sh 35 | curl -fsSL -o ${HOME}/Xray-script.sh https://raw.githubusercontent.com/zxcvos/Xray-script/main/reality.sh && bash ${HOME}/Xray-script.sh 36 | ``` 37 | 38 | ## 脚本界面 39 | 40 | ```sh 41 | --------------- Xray-script --------------- 42 | Version : v2023-03-15(beta) 43 | Description : Xray 管理脚本 44 | ----------------- 装载管理 ---------------- 45 | 1. 安装 46 | 2. 更新 47 | 3. 卸载 48 | ----------------- 操作管理 ---------------- 49 | 4. 启动 50 | 5. 停止 51 | 6. 重启 52 | ----------------- 配置管理 ---------------- 53 | 101. 查看配置 54 | 102. 信息统计 55 | 103. 修改 id 56 | 104. 修改 dest 57 | 105. 修改 x25519 key 58 | 106. 修改 shortIds 59 | 107. 修改 xray 监听端口 60 | 108. 刷新已有的 shortIds 61 | 109. 追加自定义的 shortIds 62 | 110. 使用 WARP 分流,开启 OpenAI 63 | ----------------- 其他选项 ---------------- 64 | 201. 更新至最新稳定版内核 65 | 202. 卸载多余内核 66 | 203. 修改 ssh 端口 67 | 204. 网络连接优化 68 | ------------------------------------------- 69 | ``` 70 | 71 | ## 客户端配置 72 | 73 | | 名称 | 值 | 74 | | :---------- | :------------------------------------------ | 75 | | 地址 | IP 或服务端的域名 | 76 | | 端口 | 443 | 77 | | 用户ID | xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx | 78 | | 流控 | xtls-rprx-vision | 79 | | 传输协议 | tcp | 80 | | 传输层安全 | reality | 81 | | SNI | learn.microsoft.com | 82 | | Fingerprint | chrome | 83 | | PublicKey | wC-8O2vI-7OmVq4TVNBA57V_g4tMDM7jRXkcBYGMYFw | 84 | | shortId | 6ba85179e30d4fc2 | 85 | | spiderX | / | 86 | 87 | ## 致谢 88 | 89 | [Xray-core][Xray-core] 90 | 91 | [REALITY][REALITY] 92 | 93 | [chika0801 Xray 配置文件模板][chika0801-Xray-examples] 94 | 95 | [部署 Cloudflare WARP Proxy][haoel] 96 | 97 | [cloudflare-warp 镜像][e7h4n] 98 | 99 | [WARP 一键脚本][fscarmen] 100 | 101 | **此脚本仅供交流学习使用,请勿使用此脚本行违法之事。网络非法外之地,行非法之事,必将接受法律制裁。** 102 | 103 | [Xray-core]: https://github.com/XTLS/Xray-core (THE NEXT FUTURE) 104 | [REALITY]: https://github.com/XTLS/REALITY (THE NEXT FUTURE) 105 | [chika0801-Xray-examples]: https://github.com/chika0801/Xray-examples (chika0801 Xray 配置文件模板) 106 | [haoel]: https://github.com/haoel/haoel.github.io#943-docker-%E4%BB%A3%E7%90%86 (使用 Docker 快速部署 Cloudflare WARP Proxy) 107 | [e7h4n]: https://github.com/e7h4n/cloudflare-warp (cloudflare-warp 镜像) 108 | [fscarmen]: https://github.com/fscarmen/warp (WARP 一键脚本) 109 | [fscarmen-warpproxy]: https://github.com/fscarmen/warp/blob/main/README.md#Netflix-%E5%88%86%E6%B5%81%E5%88%B0-WARP-Client-ProxyWireProxy-%E7%9A%84%E6%96%B9%E6%B3%95 (Netflix 分流到 WARP Client Proxy、WireProxy 的方法) 110 | -------------------------------------------------------------------------------- /VLESS-XTLS-uTLS-REALITY/myself.json: -------------------------------------------------------------------------------- 1 | { 2 | "log": { 3 | "loglevel": "warning", 4 | "error": "/var/log/xray/error.log", 5 | "access": "/var/log/xray/access.log" 6 | }, 7 | "api": { 8 | "services": [ 9 | "HandlerService", 10 | "LoggerService", 11 | "StatsService" 12 | ], 13 | "tag": "api" 14 | }, 15 | "stats": {}, 16 | "policy": { 17 | "levels": { 18 | "0": { 19 | "handshake": 2, 20 | "connIdle": 128, 21 | "statsUserUplink": true, 22 | "statsUserDownlink": true 23 | } 24 | }, 25 | "system": { 26 | "statsInboundUplink": true, 27 | "statsInboundDownlink": true, 28 | "statsOutboundUplink": true, 29 | "statsOutboundDownlink": true 30 | } 31 | }, 32 | "dns": { 33 | "servers": [ 34 | "https+local://cloudflare-dns.com/dns-query", 35 | "1.1.1.1", 36 | "1.0.0.1", 37 | "8.8.8.8", 38 | "8.8.4.4", 39 | "localhost" 40 | ] 41 | }, 42 | "routing": { 43 | "domainStrategy": "IPIfNonMatch", 44 | "rules": [ 45 | { 46 | "inboundTag": [ 47 | "api" 48 | ], 49 | "outboundTag": "api", 50 | "type": "field" 51 | }, 52 | { 53 | "type": "field", 54 | "protocol": [ 55 | "bittorrent" 56 | ], 57 | "outboundTag": "block" 58 | }, 59 | { 60 | "type": "field", 61 | "ip": [ 62 | "geoip:private" 63 | ], 64 | "outboundTag": "block" 65 | }, 66 | { 67 | "type": "field", 68 | "domain": [ 69 | "geosite:category-ads-all" 70 | ], 71 | "outboundTag": "block" 72 | }, 73 | { 74 | "type": "field", 75 | "ip": [ 76 | "geoip:cn" 77 | ], 78 | "outboundTag": "cloudflare-warp" 79 | } 80 | ] 81 | }, 82 | "inbounds": [ 83 | { 84 | "listen": "127.0.0.1", 85 | "port": 32768, 86 | "protocol": "dokodemo-door", 87 | "settings": { 88 | "address": "127.0.0.1" 89 | }, 90 | "tag": "api", 91 | "sniffing": null 92 | }, 93 | { 94 | "tag": "xray-script-xtls-reality", 95 | "listen": "/dev/shm/nginx/raw.sock", 96 | "protocol": "vless", 97 | "settings": { 98 | "clients": [ 99 | { 100 | "email": "vless@xtls.reality", 101 | "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", 102 | "flow": "xtls-rprx-vision", 103 | "level": 0 104 | } 105 | ], 106 | "decryption": "none" 107 | }, 108 | "streamSettings": { 109 | "network": "tcp", 110 | "security": "reality", 111 | "realitySettings": { 112 | "show": false, 113 | "dest": "/dev/shm/nginx/cloudreve.sock", 114 | "xver": 0, 115 | "serverNames": [ 116 | "example.com" 117 | ], 118 | "privateKey": "xray x25519 Private key", 119 | "shortIds": [ 120 | "", 121 | "2", 122 | "4", 123 | "8", 124 | "16" 125 | ] 126 | } 127 | }, 128 | "sniffing": { 129 | "enabled": true, 130 | "destOverride": [ 131 | "http", 132 | "tls", 133 | "quic" 134 | ] 135 | } 136 | } 137 | ], 138 | "outbounds": [ 139 | { 140 | "tag": "direct", 141 | "protocol": "freedom" 142 | }, 143 | { 144 | "tag": "block", 145 | "protocol": "blackhole" 146 | }, 147 | { 148 | "tag": "cloudflare-warp", 149 | "protocol": "socks", 150 | "settings": { 151 | "servers": [ 152 | { 153 | "address": "172.17.0.2", 154 | "port": 40001 155 | } 156 | ] 157 | } 158 | } 159 | ] 160 | } 161 | -------------------------------------------------------------------------------- /VLESS-XTLS-uTLS-REALITY/server.json: -------------------------------------------------------------------------------- 1 | { 2 | "log": { 3 | "loglevel": "warning", 4 | "error": "/var/log/xray/error.log", 5 | "access": "/var/log/xray/access.log" 6 | }, 7 | "api": { 8 | "services": [ 9 | "HandlerService", 10 | "LoggerService", 11 | "StatsService" 12 | ], 13 | "tag": "api" 14 | }, 15 | "stats": {}, 16 | "policy": { 17 | "levels": { 18 | "0": { 19 | "handshake": 2, 20 | "connIdle": 128, 21 | "statsUserUplink": true, 22 | "statsUserDownlink": true 23 | } 24 | }, 25 | "system": { 26 | "statsInboundUplink": true, 27 | "statsInboundDownlink": true, 28 | "statsOutboundUplink": true, 29 | "statsOutboundDownlink": true 30 | } 31 | }, 32 | "dns": { 33 | "servers": [ 34 | "https+local://cloudflare-dns.com/dns-query", 35 | "1.1.1.1", 36 | "1.0.0.1", 37 | "8.8.8.8", 38 | "8.8.4.4", 39 | "localhost" 40 | ] 41 | }, 42 | "routing": { 43 | "domainStrategy": "IPIfNonMatch", 44 | "rules": [ 45 | { 46 | "inboundTag": [ 47 | "api" 48 | ], 49 | "outboundTag": "api", 50 | "type": "field" 51 | }, 52 | { 53 | "type": "field", 54 | "protocol": [ 55 | "bittorrent" 56 | ], 57 | "outboundTag": "block" 58 | }, 59 | { 60 | "type": "field", 61 | "ip": [ 62 | "geoip:private" 63 | ], 64 | "outboundTag": "block" 65 | }, 66 | { 67 | "type": "field", 68 | "ip": [ 69 | "geoip:cn" 70 | ], 71 | "outboundTag": "block" 72 | }, 73 | { 74 | "type": "field", 75 | "domain": [ 76 | "geosite:category-ads-all" 77 | ], 78 | "outboundTag": "block" 79 | } 80 | ] 81 | }, 82 | "inbounds": [ 83 | { 84 | "listen": "127.0.0.1", 85 | "port": 32768, 86 | "protocol": "dokodemo-door", 87 | "settings": { 88 | "address": "127.0.0.1" 89 | }, 90 | "tag": "api", 91 | "sniffing": null 92 | }, 93 | { 94 | "tag": "xray-script-xtls-reality", 95 | "listen": "0.0.0.0", 96 | "port": 443, 97 | "protocol": "vless", 98 | "settings": { 99 | "clients": [ 100 | { 101 | "email": "vless@xtls.reality", 102 | "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", 103 | "flow": "xtls-rprx-vision", 104 | "level": 0 105 | } 106 | ], 107 | "decryption": "none" 108 | }, 109 | "streamSettings": { 110 | "network": "tcp", 111 | "security": "reality", 112 | "realitySettings": { 113 | "show": false, 114 | "dest": "", 115 | "xver": 0, 116 | "serverNames": [], 117 | "privateKey": "xray x25519 Private key", 118 | "shortIds": [ 119 | "", 120 | "01", 121 | "0123", 122 | "01234567", 123 | "0123456789abcdef" 124 | ] 125 | } 126 | }, 127 | "sniffing": { 128 | "enabled": true, 129 | "destOverride": [ 130 | "http", 131 | "tls", 132 | "quic" 133 | ] 134 | } 135 | } 136 | ], 137 | "outbounds": [ 138 | { 139 | "tag": "direct", 140 | "protocol": "freedom" 141 | }, 142 | { 143 | "tag": "block", 144 | "protocol": "blackhole" 145 | } 146 | ] 147 | } 148 | -------------------------------------------------------------------------------- /XTLS/Fallback.json: -------------------------------------------------------------------------------- 1 | { 2 | "log": { 3 | "loglevel": "warning", 4 | "error": "/var/log/xray/error.log", 5 | "access": "/var/log/xray/access.log" 6 | }, 7 | "api": { 8 | "tag": "api", 9 | "services": [ 10 | "HandlerService", 11 | "LoggerService", 12 | "StatsService" 13 | ] 14 | }, 15 | "stats": {}, 16 | "policy": { 17 | "levels": { 18 | "0": { 19 | "statsUserUplink": true, 20 | "statsUserDownlink": true 21 | } 22 | }, 23 | "system": { 24 | "statsInboundUplink": true, 25 | "statsInboundDownlink": true, 26 | "statsOutboundUplink": true, 27 | "statsOutboundDownlink": true 28 | } 29 | }, 30 | "routing": { 31 | "rules": [ 32 | { 33 | "ruleTag": "api", 34 | "inboundTag": [ 35 | "api" 36 | ], 37 | "outboundTag": "api" 38 | }, 39 | { 40 | "ruleTag": "private-ip", 41 | "ip": [ 42 | "geoip:private" 43 | ], 44 | "outboundTag": "block" 45 | } 46 | ] 47 | }, 48 | "inbounds": [ 49 | { 50 | "tag": "api", 51 | "listen": "127.0.0.1", 52 | "port": 32768, 53 | "protocol": "dokodemo-door", 54 | "settings": { 55 | "address": "127.0.0.1" 56 | }, 57 | "sniffing": null 58 | }, 59 | { 60 | "tag": "VLESS-Vision-REALITY", 61 | "listen": "0.0.0.0", 62 | "port": 443, 63 | "protocol": "vless", 64 | "settings": { 65 | "clients": [ 66 | { 67 | "email": "vless@xtls.reality", 68 | "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", 69 | "flow": "xtls-rprx-vision", 70 | "level": 0 71 | } 72 | ], 73 | "decryption": "none", 74 | "fallbacks": [ 75 | { 76 | "dest": "@uds2xhttp.sock", 77 | "xver": 1 78 | } 79 | ] 80 | }, 81 | "streamSettings": { 82 | "network": "raw", 83 | "security": "reality", 84 | "realitySettings": { 85 | "show": false, 86 | "target": "", 87 | "xver": 0, 88 | "serverNames": [], 89 | "privateKey": "xray x25519 Private key", 90 | "shortIds": [ 91 | "", 92 | "01", 93 | "0123", 94 | "01234567", 95 | "0123456789abcdef" 96 | ] 97 | } 98 | }, 99 | "sniffing": { 100 | "enabled": true, 101 | "destOverride": [ 102 | "http", 103 | "tls", 104 | "quic" 105 | ] 106 | } 107 | }, 108 | { 109 | "tag": "VLESS-XHTTP-REALITY", 110 | "listen": "@uds2xhttp.sock", 111 | "protocol": "vless", 112 | "settings": { 113 | "clients": [ 114 | { 115 | "email": "vless@xhttp.reality", 116 | "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", 117 | "level": 0 118 | } 119 | ], 120 | "decryption": "none" 121 | }, 122 | "streamSettings": { 123 | "network": "xhttp", 124 | "xhttpSettings": { 125 | "host": "", 126 | "path": "/yourpath", 127 | "mode": "auto" 128 | }, 129 | "sockopt": { 130 | "acceptProxyProtocol": true 131 | } 132 | }, 133 | "sniffing": { 134 | "enabled": true, 135 | "destOverride": [ 136 | "http", 137 | "tls", 138 | "quic" 139 | ] 140 | } 141 | } 142 | ], 143 | "outbounds": [ 144 | { 145 | "tag": "direct", 146 | "protocol": "freedom" 147 | }, 148 | { 149 | "tag": "block", 150 | "protocol": "blackhole" 151 | } 152 | ] 153 | } -------------------------------------------------------------------------------- /XTLS/SNI.json: -------------------------------------------------------------------------------- 1 | { 2 | "log": { 3 | "loglevel": "warning", 4 | "error": "/var/log/xray/error.log", 5 | "access": "/var/log/xray/access.log" 6 | }, 7 | "api": { 8 | "tag": "api", 9 | "services": [ 10 | "HandlerService", 11 | "LoggerService", 12 | "StatsService" 13 | ] 14 | }, 15 | "stats": {}, 16 | "policy": { 17 | "levels": { 18 | "0": { 19 | "statsUserUplink": true, 20 | "statsUserDownlink": true 21 | } 22 | }, 23 | "system": { 24 | "statsInboundUplink": true, 25 | "statsInboundDownlink": true, 26 | "statsOutboundUplink": true, 27 | "statsOutboundDownlink": true 28 | } 29 | }, 30 | "routing": { 31 | "rules": [ 32 | { 33 | "ruleTag": "api", 34 | "inboundTag": [ 35 | "api" 36 | ], 37 | "outboundTag": "api" 38 | }, 39 | { 40 | "ruleTag": "private-ip", 41 | "ip": [ 42 | "geoip:private" 43 | ], 44 | "outboundTag": "block" 45 | } 46 | ] 47 | }, 48 | "inbounds": [ 49 | { 50 | "tag": "api", 51 | "listen": "127.0.0.1", 52 | "port": 32768, 53 | "protocol": "dokodemo-door", 54 | "settings": { 55 | "address": "127.0.0.1" 56 | }, 57 | "sniffing": null 58 | }, 59 | { 60 | "tag": "VLESS-Vision-REALITY", 61 | "listen": "/dev/shm/nginx/vision_reality.sock,0666", 62 | "protocol": "vless", 63 | "settings": { 64 | "clients": [ 65 | { 66 | "email": "vless@xtls.reality", 67 | "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", 68 | "flow": "xtls-rprx-vision", 69 | "level": 0 70 | } 71 | ], 72 | "decryption": "none", 73 | "fallbacks": [ 74 | { 75 | "dest": "/dev/shm/nginx/xhttp_reality.sock" 76 | } 77 | ] 78 | }, 79 | "streamSettings": { 80 | "network": "raw", 81 | "security": "reality", 82 | "realitySettings": { 83 | "show": false, 84 | "dest": "/dev/shm/nginx/cloudreve.sock", 85 | "xver": 1, 86 | "serverNames": [ 87 | "example.com" 88 | ], 89 | "privateKey": "xray x25519 Private key", 90 | "shortIds": [ 91 | "", 92 | "01", 93 | "0123", 94 | "01234567", 95 | "0123456789abcdef" 96 | ] 97 | }, 98 | "rawSettings": { 99 | "acceptProxyProtocol": true 100 | } 101 | }, 102 | "sniffing": { 103 | "enabled": true, 104 | "destOverride": [ 105 | "http", 106 | "tls", 107 | "quic" 108 | ] 109 | } 110 | }, 111 | { 112 | "tag": "VLESS-XHTTP-REALITY", 113 | "listen": "/dev/shm/nginx/xhttp_reality.sock,0666", 114 | "protocol": "vless", 115 | "settings": { 116 | "clients": [ 117 | { 118 | "email": "vless@xhttp.reality", 119 | "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", 120 | "level": 0 121 | } 122 | ], 123 | "decryption": "none" 124 | }, 125 | "streamSettings": { 126 | "network": "xhttp", 127 | "xhttpSettings": { 128 | "host": "", 129 | "path": "/yourpath", 130 | "mode": "auto" 131 | } 132 | }, 133 | "sniffing": { 134 | "enabled": true, 135 | "destOverride": [ 136 | "http", 137 | "tls", 138 | "quic" 139 | ] 140 | } 141 | } 142 | ], 143 | "outbounds": [ 144 | { 145 | "tag": "direct", 146 | "protocol": "freedom" 147 | }, 148 | { 149 | "tag": "block", 150 | "protocol": "blackhole" 151 | } 152 | ] 153 | } 154 | -------------------------------------------------------------------------------- /XTLS/Trojan.json: -------------------------------------------------------------------------------- 1 | { 2 | "log": { 3 | "loglevel": "warning", 4 | "error": "/var/log/xray/error.log", 5 | "access": "/var/log/xray/access.log" 6 | }, 7 | "api": { 8 | "tag": "api", 9 | "services": [ 10 | "HandlerService", 11 | "LoggerService", 12 | "StatsService" 13 | ] 14 | }, 15 | "stats": {}, 16 | "policy": { 17 | "levels": { 18 | "0": { 19 | "statsUserUplink": true, 20 | "statsUserDownlink": true 21 | } 22 | }, 23 | "system": { 24 | "statsInboundUplink": true, 25 | "statsInboundDownlink": true, 26 | "statsOutboundUplink": true, 27 | "statsOutboundDownlink": true 28 | } 29 | }, 30 | "routing": { 31 | "rules": [ 32 | { 33 | "ruleTag": "api", 34 | "inboundTag": [ 35 | "api" 36 | ], 37 | "outboundTag": "api" 38 | }, 39 | { 40 | "ruleTag": "private-ip", 41 | "ip": [ 42 | "geoip:private" 43 | ], 44 | "outboundTag": "block" 45 | } 46 | ] 47 | }, 48 | "inbounds": [ 49 | { 50 | "tag": "api", 51 | "listen": "127.0.0.1", 52 | "port": 32768, 53 | "protocol": "dokodemo-door", 54 | "settings": { 55 | "address": "127.0.0.1" 56 | }, 57 | "sniffing": null 58 | }, 59 | { 60 | "tag": "Trojan-XHTTP-REALITY", 61 | "listen": "0.0.0.0", 62 | "port": 443, 63 | "protocol": "trojan", 64 | "settings": { 65 | "clients": [ 66 | { 67 | "email": "trojan@xhttp.reality", 68 | "password": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", 69 | "level": 0 70 | } 71 | ], 72 | "decryption": "none" 73 | }, 74 | "streamSettings": { 75 | "network": "xhttp", 76 | "security": "reality", 77 | "realitySettings": { 78 | "show": false, 79 | "target": "", 80 | "xver": 0, 81 | "serverNames": [], 82 | "privateKey": "xray x25519 Private key", 83 | "shortIds": [ 84 | "", 85 | "01", 86 | "0123", 87 | "01234567", 88 | "0123456789abcdef" 89 | ] 90 | }, 91 | "xhttpSettings": { 92 | "host": "", 93 | "path": "/yourpath", 94 | "mode": "auto" 95 | } 96 | }, 97 | "sniffing": { 98 | "enabled": true, 99 | "destOverride": [ 100 | "http", 101 | "tls", 102 | "quic" 103 | ] 104 | } 105 | } 106 | ], 107 | "outbounds": [ 108 | { 109 | "tag": "direct", 110 | "protocol": "freedom" 111 | }, 112 | { 113 | "tag": "block", 114 | "protocol": "blackhole" 115 | } 116 | ] 117 | } -------------------------------------------------------------------------------- /XTLS/Vision.json: -------------------------------------------------------------------------------- 1 | { 2 | "log": { 3 | "loglevel": "warning", 4 | "error": "/var/log/xray/error.log", 5 | "access": "/var/log/xray/access.log" 6 | }, 7 | "api": { 8 | "tag": "api", 9 | "services": [ 10 | "HandlerService", 11 | "LoggerService", 12 | "StatsService" 13 | ] 14 | }, 15 | "stats": {}, 16 | "policy": { 17 | "levels": { 18 | "0": { 19 | "statsUserUplink": true, 20 | "statsUserDownlink": true 21 | } 22 | }, 23 | "system": { 24 | "statsInboundUplink": true, 25 | "statsInboundDownlink": true, 26 | "statsOutboundUplink": true, 27 | "statsOutboundDownlink": true 28 | } 29 | }, 30 | "routing": { 31 | "rules": [ 32 | { 33 | "ruleTag": "api", 34 | "inboundTag": [ 35 | "api" 36 | ], 37 | "outboundTag": "api" 38 | }, 39 | { 40 | "ruleTag": "private-ip", 41 | "ip": [ 42 | "geoip:private" 43 | ], 44 | "outboundTag": "block" 45 | } 46 | ] 47 | }, 48 | "inbounds": [ 49 | { 50 | "tag": "api", 51 | "listen": "127.0.0.1", 52 | "port": 32768, 53 | "protocol": "dokodemo-door", 54 | "settings": { 55 | "address": "127.0.0.1" 56 | }, 57 | "sniffing": null 58 | }, 59 | { 60 | "tag": "VLESS-Vision-REALITY", 61 | "listen": "0.0.0.0", 62 | "port": 443, 63 | "protocol": "vless", 64 | "settings": { 65 | "clients": [ 66 | { 67 | "email": "vless@xtls.reality", 68 | "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", 69 | "flow": "xtls-rprx-vision", 70 | "level": 0 71 | } 72 | ], 73 | "decryption": "none" 74 | }, 75 | "streamSettings": { 76 | "network": "raw", 77 | "security": "reality", 78 | "realitySettings": { 79 | "show": false, 80 | "target": "", 81 | "xver": 0, 82 | "serverNames": [], 83 | "privateKey": "xray x25519 Private key", 84 | "shortIds": [ 85 | "", 86 | "01", 87 | "0123", 88 | "01234567", 89 | "0123456789abcdef" 90 | ] 91 | } 92 | }, 93 | "sniffing": { 94 | "enabled": true, 95 | "destOverride": [ 96 | "http", 97 | "tls", 98 | "quic" 99 | ] 100 | } 101 | } 102 | ], 103 | "outbounds": [ 104 | { 105 | "tag": "direct", 106 | "protocol": "freedom" 107 | }, 108 | { 109 | "tag": "block", 110 | "protocol": "blackhole" 111 | } 112 | ] 113 | } -------------------------------------------------------------------------------- /XTLS/XHTTP.json: -------------------------------------------------------------------------------- 1 | { 2 | "log": { 3 | "loglevel": "warning", 4 | "error": "/var/log/xray/error.log", 5 | "access": "/var/log/xray/access.log" 6 | }, 7 | "api": { 8 | "tag": "api", 9 | "services": [ 10 | "HandlerService", 11 | "LoggerService", 12 | "StatsService" 13 | ] 14 | }, 15 | "stats": {}, 16 | "policy": { 17 | "levels": { 18 | "0": { 19 | "statsUserUplink": true, 20 | "statsUserDownlink": true 21 | } 22 | }, 23 | "system": { 24 | "statsInboundUplink": true, 25 | "statsInboundDownlink": true, 26 | "statsOutboundUplink": true, 27 | "statsOutboundDownlink": true 28 | } 29 | }, 30 | "routing": { 31 | "rules": [ 32 | { 33 | "ruleTag": "api", 34 | "inboundTag": [ 35 | "api" 36 | ], 37 | "outboundTag": "api" 38 | }, 39 | { 40 | "ruleTag": "private-ip", 41 | "ip": [ 42 | "geoip:private" 43 | ], 44 | "outboundTag": "block" 45 | } 46 | ] 47 | }, 48 | "inbounds": [ 49 | { 50 | "tag": "api", 51 | "listen": "127.0.0.1", 52 | "port": 32768, 53 | "protocol": "dokodemo-door", 54 | "settings": { 55 | "address": "127.0.0.1" 56 | }, 57 | "sniffing": null 58 | }, 59 | { 60 | "tag": "VLESS-XHTTP-REALITY", 61 | "listen": "0.0.0.0", 62 | "port": 443, 63 | "protocol": "vless", 64 | "settings": { 65 | "clients": [ 66 | { 67 | "email": "vless@xhttp.reality", 68 | "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", 69 | "level": 0 70 | } 71 | ], 72 | "decryption": "none" 73 | }, 74 | "streamSettings": { 75 | "network": "xhttp", 76 | "security": "reality", 77 | "realitySettings": { 78 | "show": false, 79 | "target": "", 80 | "xver": 0, 81 | "serverNames": [], 82 | "privateKey": "xray x25519 Private key", 83 | "shortIds": [ 84 | "", 85 | "01", 86 | "0123", 87 | "01234567", 88 | "0123456789abcdef" 89 | ] 90 | }, 91 | "xhttpSettings": { 92 | "host": "", 93 | "path": "/yourpath", 94 | "mode": "auto" 95 | } 96 | }, 97 | "sniffing": { 98 | "enabled": true, 99 | "destOverride": [ 100 | "http", 101 | "tls", 102 | "quic" 103 | ] 104 | } 105 | } 106 | ], 107 | "outbounds": [ 108 | { 109 | "tag": "direct", 110 | "protocol": "freedom" 111 | }, 112 | { 113 | "tag": "block", 114 | "protocol": "blackhole" 115 | } 116 | ] 117 | } -------------------------------------------------------------------------------- /XTLS/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "tag": "xhttp", 3 | "port": 443, 4 | "uuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", 5 | "fallback": "uuid", 6 | "kcp": "seed", 7 | "trojan": "password", 8 | "path": "/yourpath/", 9 | "privateKey": "xray x25519 Private key", 10 | "publicKey": "xray x25519 Public key", 11 | "target": "www.fandom.com", 12 | "status": 0, 13 | "warp": 0, 14 | "sni": { 15 | "domain": "", 16 | "cdn": "", 17 | "uuid": "", 18 | "nginx": 0, 19 | "status": 0 20 | }, 21 | "cloudreve": { 22 | "version": "", 23 | "username": "", 24 | "password": "" 25 | }, 26 | "shortIds": [ 27 | "", 28 | "01", 29 | "0123", 30 | "012345", 31 | "01234567", 32 | "0123456789", 33 | "0123456789ab", 34 | "0123456789abcd", 35 | "0123456789abcdef" 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /XTLS/mKCP.json: -------------------------------------------------------------------------------- 1 | { 2 | "log": { 3 | "loglevel": "warning", 4 | "error": "/var/log/xray/error.log", 5 | "access": "/var/log/xray/access.log" 6 | }, 7 | "api": { 8 | "tag": "api", 9 | "services": [ 10 | "HandlerService", 11 | "LoggerService", 12 | "StatsService" 13 | ] 14 | }, 15 | "stats": {}, 16 | "policy": { 17 | "levels": { 18 | "0": { 19 | "statsUserUplink": true, 20 | "statsUserDownlink": true 21 | } 22 | }, 23 | "system": { 24 | "statsInboundUplink": true, 25 | "statsInboundDownlink": true, 26 | "statsOutboundUplink": true, 27 | "statsOutboundDownlink": true 28 | } 29 | }, 30 | "routing": { 31 | "rules": [ 32 | { 33 | "ruleTag": "api", 34 | "inboundTag": [ 35 | "api" 36 | ], 37 | "outboundTag": "api" 38 | }, 39 | { 40 | "ruleTag": "private-ip", 41 | "ip": [ 42 | "geoip:private" 43 | ], 44 | "outboundTag": "block" 45 | } 46 | ] 47 | }, 48 | "inbounds": [ 49 | { 50 | "tag": "api", 51 | "listen": "127.0.0.1", 52 | "port": 32768, 53 | "protocol": "dokodemo-door", 54 | "settings": { 55 | "address": "127.0.0.1" 56 | }, 57 | "sniffing": null 58 | }, 59 | { 60 | "tag": "VLESS-mKCP", 61 | "listen": "0.0.0.0", 62 | "port": 9527, 63 | "protocol": "vless", 64 | "settings": { 65 | "clients": [ 66 | { 67 | "email": "vless@xtls.mkcp", 68 | "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", 69 | "level": 0 70 | } 71 | ], 72 | "decryption": "none" 73 | }, 74 | "streamSettings": { 75 | "network": "kcp", 76 | "kcpSettings": { 77 | "uplinkCapacity": 100, 78 | "downlinkCapacity": 100, 79 | "congestion": true, 80 | "readBufferSize": 5, 81 | "writeBufferSize": 5, 82 | "seed": "{{ speed }}" 83 | } 84 | }, 85 | "sniffing": { 86 | "enabled": true, 87 | "destOverride": [ 88 | "http", 89 | "tls", 90 | "quic" 91 | ] 92 | } 93 | } 94 | ], 95 | "outbounds": [ 96 | { 97 | "tag": "direct", 98 | "protocol": "freedom", 99 | "settings": {} 100 | }, 101 | { 102 | "tag": "block", 103 | "protocol": "blackhole", 104 | "settings": {} 105 | } 106 | ] 107 | } -------------------------------------------------------------------------------- /XTLS/rules.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "ruleTag": "api", 4 | "inboundTag": [ 5 | "api" 6 | ], 7 | "outboundTag": "api" 8 | }, 9 | { 10 | "ruleTag": "bt", 11 | "protocol": [ 12 | "bittorrent" 13 | ], 14 | "outboundTag": "block" 15 | }, 16 | { 17 | "ruleTag": "private-ip", 18 | "ip": [ 19 | "geoip:private" 20 | ], 21 | "outboundTag": "block" 22 | }, 23 | { 24 | "ruleTag": "cn-ip", 25 | "ip": [ 26 | "geoip:cn" 27 | ], 28 | "outboundTag": "block" 29 | }, 30 | { 31 | "ruleTag": "warp-domain", 32 | "domain": [ 33 | "domain:ipinfo.io", 34 | "domain:cloudflare.com", 35 | "domain:nel.cloudflare.com", 36 | "domain:reddit.com" 37 | ], 38 | "outboundTag": "warp" 39 | }, 40 | { 41 | "ruleTag": "ad-domain", 42 | "domain": [ 43 | "geosite:category-ads-all" 44 | ], 45 | "outboundTag": "block" 46 | } 47 | ] -------------------------------------------------------------------------------- /XTLS/serverNames.json: -------------------------------------------------------------------------------- 1 | { 2 | "www.fandom.com": [ 3 | "fandom.com", 4 | "www.fandom.com", 5 | "toarumajutsunoindex.fandom.com", 6 | "dragonball.fandom.com", 7 | "pokemon.fandom.com", 8 | "nichijou.fandom.com", 9 | "bleach.fandom.com", 10 | "naruto.fandom.com", 11 | "onepiece.fandom.com" 12 | ], 13 | "tidal.com": [ 14 | "tidal.com" 15 | ], 16 | "mxj.myanimelist.net": [ 17 | "mxj.myanimelist.net" 18 | ], 19 | "www.lovelive-anime.jp": [ 20 | "www.lovelive-anime.jp" 21 | ], 22 | "www.pixiv.co.jp": [ 23 | "www.pixiv.co.jp" 24 | ], 25 | "mora.jp": [ 26 | "mora.jp" 27 | ], 28 | "www.j-wave.co.jp": [ 29 | "www.j-wave.co.jp" 30 | ], 31 | "booth.pm": [ 32 | "booth.pm" 33 | ], 34 | "www.ivi.tv": [ 35 | "www.ivi.tv" 36 | ], 37 | "www.leercapitulo.co": [ 38 | "www.leercapitulo.co" 39 | ], 40 | "www.sky.com": [ 41 | "www.sky.com" 42 | ] 43 | } -------------------------------------------------------------------------------- /cloudflare-warp/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:jammy 2 | 3 | RUN apt update && \ 4 | apt install socat curl gpg -y && \ 5 | curl https://pkg.cloudflareclient.com/pubkey.gpg | gpg --yes --dearmor --output /usr/share/keyrings/cloudflare-warp-archive-keyring.gpg && \ 6 | apt remove curl gpg -y && \ 7 | echo "deb [arch=amd64 signed-by=/usr/share/keyrings/cloudflare-warp-archive-keyring.gpg] https://pkg.cloudflareclient.com/ jammy main" | tee /etc/apt/sources.list.d/cloudflare-client.list && \ 8 | apt update &&\ 9 | apt install cloudflare-warp -y && \ 10 | apt-get autoremove --yes && \ 11 | apt-get autoclean && \ 12 | rm -rf /var/lib/{apt,dpkg,cache,log}/ 13 | 14 | COPY startup.sh /bin/startup.sh 15 | RUN chmod a+x /bin/startup.sh 16 | ENTRYPOINT [ "/bin/startup.sh" ] 17 | -------------------------------------------------------------------------------- /cloudflare-warp/startup.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [ -f /var/lib/cloudflare-warp/reg.json ]; then 4 | echo "Forwarding 0.0.0.0:40001 to 127.0.0.1:40000" 5 | socat TCP-LISTEN:40001,reuseaddr,fork TCP:127.0.0.1:40000 & 6 | 7 | echo "Starting Cloudflare WARP" 8 | warp-svc 9 | else 10 | echo "Cloudflare WARP not registered, try start a daemon and register it." 11 | warp-svc >&/dev/null & 12 | sleep 5 13 | echo "Registering Cloudflare WARP" 14 | warp-cli --accept-tos registration new 15 | echo "Setting Cloudflare WARP mode to proxy" 16 | warp-cli --accept-tos mode proxy 17 | echo "Connecting Cloudflare WARP" 18 | warp-cli --accept-tos connect 19 | echo "Done, killing daemon and exiting. This container should work after restart." 20 | exit 1 21 | fi 22 | -------------------------------------------------------------------------------- /cloudreve/cloudreve.ini: -------------------------------------------------------------------------------- 1 | [System] 2 | Mode = master 3 | Debug = false 4 | 5 | [UnixSocket] 6 | Listen = /dev/shm/cloudreve/cloudreve.sock 7 | Perm = 0666 8 | -------------------------------------------------------------------------------- /cloudreve/cloudreve.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Cloudreve 3 | Documentation=https://docs.cloudreve.org 4 | After=network.target 5 | After=mysqld.service 6 | Wants=network.target 7 | 8 | [Service] 9 | WorkingDirectory=/usr/local/cloudreve 10 | ExecStartPre=/bin/rm -rf /dev/shm/cloudreve 11 | ExecStartPre=/bin/mkdir /dev/shm/cloudreve 12 | ExecStartPre=/bin/chmod 0666 /dev/shm/cloudreve 13 | ExecStart=/usr/local/cloudreve/cloudreve 14 | ExecStopPost=/bin/rm -rf /dev/shm/cloudreve 15 | Restart=on-abnormal 16 | RestartSec=5s 17 | KillMode=mixed 18 | 19 | StandardOutput=null 20 | StandardError=syslog 21 | 22 | [Install] 23 | WantedBy=multi-user.target 24 | -------------------------------------------------------------------------------- /cloudreve/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | services: 3 | cloudreve: 4 | container_name: cloudreve 5 | image: cloudreve/cloudreve:latest 6 | restart: unless-stopped 7 | networks: 8 | - share_net 9 | ports: 10 | - "5212:5212" 11 | volumes: 12 | - temp_data:/data 13 | - /usr/local/cloudreve/cloudreve/uploads:/cloudreve/uploads 14 | - /usr/local/cloudreve/cloudreve/conf.ini:/cloudreve/conf.ini 15 | - /usr/local/cloudreve/cloudreve/cloudreve.db:/cloudreve/cloudreve.db 16 | - /usr/local/cloudreve/cloudreve/avatar:/cloudreve/avatar 17 | depends_on: 18 | - aria2 19 | aria2: 20 | container_name: aria2 21 | image: p3terx/aria2-pro 22 | restart: unless-stopped 23 | networks: 24 | - share_net 25 | environment: 26 | - RPC_SECRET=your_aria_rpc_token 27 | - RPC_PORT=6800 28 | volumes: 29 | - /usr/local/cloudreve/aria2/config:/config 30 | - temp_data:/data 31 | watchtower: 32 | image: containrrr/watchtower 33 | container_name: watchtower 34 | restart: always 35 | volumes: 36 | - /var/run/docker.sock:/var/run/docker.sock 37 | command: cloudreve aria2 watchtower --cleanup --schedule "0 30 6 * * *" 38 | networks: 39 | - share_net 40 | volumes: 41 | temp_data: 42 | driver: local 43 | driver_opts: 44 | type: none 45 | device: /usr/local/cloudreve/data 46 | o: bind 47 | networks: 48 | share_net: 49 | driver: bridge 50 | -------------------------------------------------------------------------------- /cloudreve/watchtower.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [ $# -eq 0 ]; then 4 | echo "Please enter the zxcvos xray script configuration dirctory path." 5 | exit 1 6 | fi 7 | 8 | declare XRAY_SCRIPT_PATH="$1" 9 | cloudreve_version=$(docker logs cloudreve | grep -Eoi "v[0-9]+.[0-9]+.[0-9]+" | cut -c2-) 10 | jq --arg version "${cloudreve_version}" '.cloudreve.version = $version' ${XRAY_SCRIPT_PATH}/config.json >${XRAY_SCRIPT_PATH}/tmp.json && mv -f ${XRAY_SCRIPT_PATH}/tmp.json ${XRAY_SCRIPT_PATH}/config.json 11 | -------------------------------------------------------------------------------- /config/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "xray": { 3 | "version": "1.8.0", 4 | "port": 443, 5 | "privateKey": "xray x25519 Private key", 6 | "publicKey": "xray x25519 Public key", 7 | "dest": "learn.microsoft.com", 8 | "serverNames": { 9 | "learn.microsoft.com": [ 10 | "learn.microsoft.com", 11 | "www.learn.microsoft.com" 12 | ], 13 | "www.apple.com": [ 14 | "www.apple.com", 15 | "images.apple.com" 16 | ], 17 | "music.apple.com": [ 18 | "music.apple.com" 19 | ], 20 | "www.fandom.com": [ 21 | "fandom.com", 22 | "www.fandom.com", 23 | "toarumajutsunoindex.fandom.com", 24 | "onepiece.fandom.com", 25 | "naruto.fandom.com", 26 | "bleach.fandom.com" 27 | ], 28 | "www.lovelive-anime.jp": [ 29 | "lovelive-anime.jp", 30 | "www.lovelive-anime.jp" 31 | ], 32 | "tidal.com": [ 33 | "tidal.com", 34 | "www.tidal.com" 35 | ], 36 | "zoro.to": [ 37 | "zoro.to", 38 | "www.zoro.to" 39 | ], 40 | "www.pixiv.co.jp": [ 41 | "www.pixiv.co.jp" 42 | ], 43 | "mxj.myanimelist.net": [ 44 | "mxj.myanimelist.net" 45 | ], 46 | "mora.jp": [ 47 | "mora.jp" 48 | ], 49 | "www.j-wave.co.jp": [ 50 | "j-wave.co.jp", 51 | "www.j-wave.co.jp" 52 | ], 53 | "www.dmm.com": [ 54 | "dmm.com", 55 | "www.dmm.com" 56 | ], 57 | "booth.pm": [ 58 | "booth.pm", 59 | "www.booth.pm" 60 | ], 61 | "www.ivi.tv": [ 62 | "ivi.tv", 63 | "www.ivi.tv" 64 | ], 65 | "fmovies.to/home": [ 66 | "fmovies.to", 67 | "www.fmovies.to" 68 | ], 69 | "www.leercapitulo.com": [ 70 | "leercapitulo.com", 71 | "www.leercapitulo.com" 72 | ], 73 | "www.sky.it": [ 74 | "sky.it", 75 | "www.sky.it" 76 | ], 77 | "www.sky.com": [ 78 | "sky.com", 79 | "www.sky.com" 80 | ], 81 | "www.smdyy.cc": [ 82 | "www.smdyy.cc" 83 | ], 84 | "www.telecinco.es": [ 85 | "telecinco.es", 86 | "www.telecinco.es", 87 | "www.yasss.es", 88 | "www.uppers.es", 89 | "www.cincomas.com", 90 | "www.bemad.es" 91 | ] 92 | } 93 | }, 94 | "nginx": { 95 | "version": "1.22.1", 96 | "domain": "example.com", 97 | "openssl": "3.1.0" 98 | }, 99 | "cloudreve": { 100 | "version": "3.7.1", 101 | "username": "admin@cloudreve.org", 102 | "password": "12345678" 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /config/myself.json: -------------------------------------------------------------------------------- 1 | { 2 | "xray": { 3 | "version": "1.8.6", 4 | "tag": "xray-script-xtls-reality", 5 | "email": "vless@xtls.reality", 6 | "listen": "/dev/shm/nginx/raw.sock", 7 | "port": 443, 8 | "dest": "/dev/shm/nginx/cloudreve.sock", 9 | "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", 10 | "serverNames": [ 11 | "example.com" 12 | ], 13 | "privateKey": "xray x25519 Private key", 14 | "publicKey": "xray x25519 Public key", 15 | "shortIds": [ 16 | "", 17 | "01", 18 | "0123", 19 | "01234567", 20 | "0123456789abcdef" 21 | ] 22 | }, 23 | "nginx": { 24 | "version": "1.25.3", 25 | "openssl": "3.2.0", 26 | "brotli": 1, 27 | "http": 80, 28 | "https": 443 29 | }, 30 | "domain": { 31 | "type": 1, 32 | "name": "example.com" 33 | }, 34 | "cloudreve": { 35 | "version": "3.8.3", 36 | "username": "admin@cloudreve.org", 37 | "password": "12345678" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /config/sysctl.conf: -------------------------------------------------------------------------------- 1 | # Ref: https://github.com/MoeClub/Note 2 | # Ref: https://github.com/leitbogioro/Tools 3 | # Ref: https://www.nodeseek.com/post-37225-1 4 | # Ref: https://blog.cloudflare.com/optimizing-tcp-for-high-throughput-and-low-latency/ 5 | 6 | # 注意:模块 "tcp_collapse_max_bytes "由 Cloudflare 完成,需要自行下载并应用补丁,否则该模块将无法生效。 7 | # 补丁: https://github.com/cloudflare/linux/blob/master/patches/0014-add-a-sysctl-to-enable-disable-tcp_collapse-logic.patch 8 | 9 | # ------ 网络调优: 基本 ------ 10 | # TTL 配置, Linux 默认 64 11 | # net.ipv4.ip_default_ttl = 64 12 | 13 | # 参阅 RFC 1323. 应当启用. 14 | net.ipv4.tcp_timestamps = 1 15 | # ------ END 网络调优: 基本 ------ 16 | 17 | # ------ 网络调优: 内核 Backlog 队列和缓存相关 ------ 18 | # 有条件建议依据实测结果调整相关数值 19 | # 缓冲区相关配置均和内存相关 20 | net.core.wmem_default = 524288 21 | net.core.rmem_default = 524288 22 | net.core.rmem_max = 536870912 23 | net.core.wmem_max = 536870912 24 | net.ipv4.tcp_mem = 2097152 8388608 536870912 25 | net.ipv4.tcp_rmem = 16384 524288 536870912 26 | net.ipv4.tcp_wmem = 16384 524288 536870912 27 | net.ipv4.tcp_adv_win_scale = -2 28 | # net.ipv4.tcp_collapse_max_bytes = 6291456 29 | net.ipv4.tcp_notsent_lowat = 131072 30 | net.ipv4.ip_local_port_range = 1024 65535 31 | net.core.netdev_max_backlog = 65536 32 | net.ipv4.tcp_max_syn_backlog = 65535 33 | net.core.somaxconn = 65535 34 | net.core.optmem_max = 33554432 35 | net.ipv4.tcp_abort_on_overflow = 1 36 | # 流控和拥塞控制相关调优 37 | # Egress traffic control 相关. 可选 fq, cake 38 | # 实测二者区别不大, 保持默认 fq 即可 39 | net.core.default_qdisc = fq 40 | # Xanmod 内核 6.X 版本目前默认使用 bbr3, 无需设置 41 | # 实测比 bbr, bbr2 均有提升 42 | # 不过网络条件不同会影响. 有需求请实测. 43 | # net.ipv4.tcp_congestion_control = bbr3 44 | net.ipv4.tcp_congestion_control = bbr 45 | # 显式拥塞通知 46 | # 已被发现在高度拥塞的网络上是有害的. 47 | # net.ipv4.tcp_ecn = 1 48 | net.ipv4.tcp_ecn = 0 49 | net.ipv4.tcp_ecn_fallback = 1 50 | # TCP 自动窗口 51 | # 要支持超过 64KB 的 TCP 窗口必须启用 52 | net.ipv4.tcp_window_scaling = 1 53 | # 开启后, TCP 拥塞窗口会在一个 RTO 时间 54 | # 空闲之后重置为初始拥塞窗口 (CWND) 大小. 55 | # 大部分情况下, 尤其是大流量长连接, 设置为 0. 56 | # 对于网络情况时刻在相对剧烈变化的场景, 设置为 1. 57 | net.ipv4.tcp_slow_start_after_idle = 0 58 | # nf_conntrack 调优 59 | net.nf_conntrack_max = 1000000 60 | net.netfilter.nf_conntrack_max = 1000000 61 | net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 30 62 | net.netfilter.nf_conntrack_tcp_timeout_time_wait = 30 63 | net.netfilter.nf_conntrack_tcp_timeout_close_wait = 15 64 | net.netfilter.nf_conntrack_tcp_timeout_established = 300 65 | # net.ipv4.netfilter.ip_conntrack_tcp_timeout_established = 7200 66 | # TIME-WAIT 状态调优 67 | # 4.12 内核中此参数已经永久废弃, 不用纠结是否需要开启 68 | # net.ipv4.tcp_tw_recycle = 0 69 | ## 只对客户端生效, 服务器连接上游时也认为是客户端 70 | net.ipv4.tcp_tw_reuse = 1 71 | # 系统同时保持TIME_WAIT套接字的最大数量 72 | # 如果超过这个数字 TIME_WAIT 套接字将立刻被清除 73 | net.ipv4.tcp_max_tw_buckets = 65536 74 | # ------ END 网络调优: 内核 Backlog 队列和缓存相关 ------ 75 | 76 | # ------ 网络调优: 其他 ------ 77 | # 启用选择应答 78 | # 对于广域网通信应当启用 79 | net.ipv4.tcp_dsack = 1 80 | net.ipv4.tcp_sack = 1 81 | # 启用转发应答 82 | # 对于广域网通信应当启用 83 | net.ipv4.tcp_fack = 1 84 | # TCP SYN 连接超时重传次数 85 | net.ipv4.tcp_syn_retries = 3 86 | net.ipv4.tcp_synack_retries = 3 87 | # TCP SYN 连接超时时间, 设置为 5 约为 30s 88 | net.ipv4.tcp_retries1 = 3 89 | net.ipv4.tcp_retries2 = 5 90 | # 开启 SYN 洪水攻击保护 91 | # 注意: tcp_syncookies 启用时, 此时实际上没有逻辑上的队列长度, 92 | # Backlog 设置将被忽略. syncookie 是一个出于对现实的妥协, 93 | # 严重违反 TCP 协议的设计, 会造成 TCP option 不可用, 且实现上 94 | # 通过计算 hash 避免维护半开连接也是一种 tradeoff 而非万金油, 95 | # 勿听信所谓“安全优化教程”而无脑开启 96 | net.ipv4.tcp_syncookies = 0 97 | # 禁止 ping 98 | # net.ipv4.icmp_echo_ignore_all = 1 99 | # 禁止 tcp 快速打开 100 | net.ipv4.tcp_fastopen = 0 101 | # ip 转发配置 102 | net.ipv4.ip_forward = 1 103 | 104 | # 开启反向路径过滤 105 | # Aliyun 负载均衡实例后端的 ECS 需要设置为 0 106 | net.ipv4.conf.default.rp_filter = 2 107 | net.ipv4.conf.all.rp_filter = 2 108 | 109 | # 减少处于 FIN-WAIT-2 连接状态的时间使系统可以处理更多的连接 110 | net.ipv4.tcp_fin_timeout = 10 111 | 112 | # 默认情况下一个 TCP 连接关闭后, 把这个连接曾经有的参数保存到dst_entry中 113 | # 只要 dst_entry 没有失效,下次新建立相同连接的时候就可以使用保存的参数来初始化这个连接.通常情况下是关闭的 114 | net.ipv4.tcp_no_metrics_save = 1 115 | # unix socket 最大队列 116 | net.unix.max_dgram_qlen = 1024 117 | # 路由缓存刷新频率 118 | net.ipv4.route.gc_timeout = 100 119 | 120 | # 启用 MTU 探测,在链路上存在 ICMP 黑洞时候有用(大多数情况是这样) 121 | net.ipv4.tcp_mtu_probing = 1 122 | 123 | # 开启并记录欺骗, 源路由和重定向包 124 | net.ipv4.conf.all.log_martians = 1 125 | net.ipv4.conf.default.log_martians = 1 126 | # 处理无源路由的包 127 | net.ipv4.conf.all.accept_source_route = 0 128 | net.ipv4.conf.default.accept_source_route = 0 129 | # TCP KeepAlive 调优 130 | # 最大闲置时间 131 | net.ipv4.tcp_keepalive_time = 600 132 | # 最大失败次数, 超过此值后将通知应用层连接失效 133 | net.ipv4.tcp_keepalive_probes = 5 134 | # 发送探测包的时间间隔 135 | net.ipv4.tcp_keepalive_intvl = 3 136 | # 系统所能处理不属于任何进程的TCP sockets最大数量 137 | net.ipv4.tcp_max_orphans = 262144 138 | # arp_table的缓存限制优化 139 | net.ipv4.neigh.default.gc_thresh1 = 128 140 | net.ipv4.neigh.default.gc_thresh2 = 512 141 | net.ipv4.neigh.default.gc_thresh3 = 4096 142 | net.ipv4.neigh.default.gc_stale_time = 120 143 | net.ipv4.conf.default.arp_announce = 2 144 | net.ipv4.conf.lo.arp_announce = 2 145 | net.ipv4.conf.all.arp_announce = 2 146 | # ------ END 网络调优: 其他 ------ 147 | 148 | # ------ 内核调优 ------ 149 | 150 | # 内核 Panic 后 1 秒自动重启 151 | kernel.panic = 1 152 | # 允许更多的PIDs, 减少滚动翻转问题 153 | kernel.pid_max = 32768 154 | # 内核所允许的最大共享内存段的大小(bytes) 155 | kernel.shmmax = 4294967296 156 | # 在任何给定时刻, 系统上可以使用的共享内存的总量(pages) 157 | kernel.shmall = 1073741824 158 | # 设定程序core时生成的文件名格式 159 | kernel.core_pattern = core_%e 160 | # 当发生oom时, 自动转换为panic 161 | vm.panic_on_oom = 1 162 | # 表示强制Linux VM最低保留多少空闲内存(Kbytes) 163 | # vm.min_free_kbytes = 1048576 164 | # 该值高于100, 则将导致内核倾向于回收directory和inode cache 165 | vm.vfs_cache_pressure = 250 166 | # 表示系统进行交换行为的程度, 数值(0-100)越高, 越可能发生磁盘交换 167 | vm.swappiness = 10 168 | # 仅用10%做为系统cache 169 | vm.dirty_ratio = 10 170 | vm.overcommit_memory = 1 171 | # 增加系统文件描述符限制 172 | # Fix error: too many open files 173 | fs.file-max = 104857600 174 | fs.inotify.max_user_instances = 8192 175 | fs.nr_open = 1048576 176 | # 内核响应魔术键 177 | kernel.sysrq = 1 178 | # 弃用 179 | # net.ipv4.tcp_low_latency = 1 180 | 181 | # 当某个节点可用内存不足时, 系统会倾向于从其他节点分配内存. 对 Mongo/Redis 类 cache 服务器友好 182 | vm.zone_reclaim_mode = 0 183 | -------------------------------------------------------------------------------- /docker.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # System Required: CentOS 7+, Debian 10+, Ubuntu 20+ 4 | # Description: Script to Docker manage 5 | # 6 | # Copyright (C) 2025 zxcvos 7 | # 8 | # optimized by AI(Qwen2.5-Max-QwQ) 9 | # 10 | # Xray-script: 11 | # https://github.com/zxcvos/Xray-script 12 | # 13 | # docker-install: 14 | # https://github.com/docker/docker-install 15 | # 16 | # Cloudflare WARP: 17 | # https://github.com/haoel/haoel.github.io?tab=readme-ov-file#1043-docker-%E4%BB%A3%E7%90%86 18 | # https://github.com/e7h4n/cloudflare-warp 19 | # 20 | # Cloudreve: 21 | # https://cloudreve.org 22 | 23 | PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/snap/bin 24 | export PATH 25 | 26 | # 颜色定义 27 | readonly RED='\033[1;31;31m' 28 | readonly GREEN='\033[1;31;32m' 29 | readonly YELLOW='\033[1;31;33m' 30 | readonly NC='\033[0m' 31 | 32 | # 目录 33 | readonly CUR_DIR="$(cd -P -- "$(dirname -- "$0")" && pwd -P)" 34 | readonly CUR_FILE="$(basename $0)" 35 | 36 | # 状态打印函数 37 | function print_info() { 38 | printf "${GREEN}[信息] ${NC}%s\n" "$*" 39 | } 40 | 41 | function print_warn() { 42 | printf "${YELLOW}[警告] ${NC}%s\n" "$*" 43 | } 44 | 45 | function print_error() { 46 | printf "${RED}[错误] ${NC}%s\n" "$*" 47 | exit 1 48 | } 49 | 50 | # 工具函数 51 | function _exists() { 52 | local cmd="$1" 53 | if eval type type >/dev/null 2>&1; then 54 | eval type "$cmd" >/dev/null 2>&1 55 | elif command >/dev/null 2>&1; then 56 | command -v "$cmd" >/dev/null 2>&1 57 | else 58 | which "$cmd" >/dev/null 2>&1 59 | fi 60 | local rt=$? 61 | return ${rt} 62 | } 63 | 64 | function _os() { 65 | local os="" 66 | [[ -f "/etc/debian_version" ]] && source /etc/os-release && os="${ID}" && printf -- "%s" "${os}" && return 67 | [[ -f "/etc/redhat-release" ]] && os="centos" && printf -- "%s" "${os}" && return 68 | } 69 | 70 | function _os_full() { 71 | [[ -f /etc/redhat-release ]] && awk '{print ($1,$3~/^[0-9]/?$3:$4)}' /etc/redhat-release && return 72 | [[ -f /etc/os-release ]] && awk -F'[= "]' '/PRETTY_NAME/{print $3,$4,$5}' /etc/os-release && return 73 | [[ -f /etc/lsb-release ]] && awk -F'[="]+' '/DESCRIPTION/{print $2}' /etc/lsb-release && return 74 | } 75 | 76 | function _os_ver() { 77 | local main_ver="$(echo $(_os_full) | grep -oE "[0-9.]+")" 78 | printf -- "%s" "${main_ver%%.*}" 79 | } 80 | 81 | # 检查操作系统 82 | function check_os() { 83 | [[ -z "$(_os)" ]] && print_error "不支持的操作系统。" 84 | case "$(_os)" in 85 | ubuntu) 86 | [[ -n "$(_os_ver)" && "$(_os_ver)" -lt 20 ]] && print_error "不支持的操作系统,请切换到 Ubuntu 20+ 并重试。" 87 | ;; 88 | debian) 89 | [[ -n "$(_os_ver)" && "$(_os_ver)" -lt 10 ]] && print_error "不支持的操作系统,请切换到 Debian 10+ 并重试。" 90 | ;; 91 | centos) 92 | [[ -n "$(_os_ver)" && "$(_os_ver)" -lt 7 ]] && print_error "不支持的操作系统,请切换到 CentOS 7+ 并重试。" 93 | ;; 94 | *) 95 | print_error "不支持的操作系统。" 96 | ;; 97 | esac 98 | } 99 | 100 | # 安装 docker 101 | function install_docker() { 102 | if ! _exists "docker"; then 103 | wget -O /usr/local/xray-script/install-docker.sh https://get.docker.com 104 | if [[ "$(_os)" == "centos" && "$(_os_ver)" -eq 8 ]]; then 105 | sed -i 's|$sh_c "$pkg_manager install -y -q $pkgs"| $sh_c "$pkg_manager install -y -q $pkgs --allowerasing"|' /usr/local/xray-script/install-docker.sh 106 | fi 107 | sh /usr/local/xray-script/install-docker.sh --dry-run 108 | sh /usr/local/xray-script/install-docker.sh 109 | fi 110 | } 111 | 112 | # 获取 Docker 容器 IP 113 | function get_container_ip() { 114 | docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$1" 115 | } 116 | 117 | # 构建 WARP 镜像 118 | function build_warp() { 119 | if ! docker images --format "{{.Repository}}" | grep -q xray-script-warp; then 120 | print_info '正在构建 WARP 镜像' 121 | mkdir -p /usr/local/xray-script/warp 122 | mkdir -p ${HOME}/.warp 123 | wget -O /usr/local/xray-script/warp/Dockerfile https://raw.githubusercontent.com/zxcvos/Xray-script/main/cloudflare-warp/Dockerfile || print_error "WARP Dockerfile 下载失败" 124 | wget -O /usr/local/xray-script/warp/startup.sh https://raw.githubusercontent.com/zxcvos/Xray-script/main/cloudflare-warp/startup.sh || print_error "WARP startup.sh 下载失败" 125 | docker build -t xray-script-warp /usr/local/xray-script/warp || print_error "WARP 镜像构建失败" 126 | fi 127 | } 128 | 129 | # 启动 WARP 容器 130 | function enable_warp() { 131 | if ! docker ps --format "{{.Names}}" | grep -q "^xray-script-warp\$"; then 132 | print_info '正在开启 WARP 容器' 133 | docker run -d --restart=always --name=xray-script-warp -v "${HOME}/.warp":/var/lib/cloudflare-warp:rw xray-script-warp || print_error "WARP 容器启动失败" 134 | # 更新配置 135 | local container_ip=$(get_container_ip xray-script-warp) 136 | local socks_config='[{"tag":"warp","protocol":"socks","settings":{"servers":[{"address":"'"${container_ip}"'","port":40001}]}}]' 137 | jq --argjson socks_config $socks_config '.outbounds += $socks_config' /usr/local/etc/xray/config.json >/usr/local/xray-script/tmp.json && mv -f /usr/local/xray-script/tmp.json /usr/local/etc/xray/config.json 138 | jq --argjson warp 1 '.warp = $warp' /usr/local/xray-script/config.json >/usr/local/xray-script/tmp.json && mv -f /usr/local/xray-script/tmp.json /usr/local/xray-script/config.json 139 | print_info "WARP 容器已启用 (IP: ${container_ip})" 140 | fi 141 | } 142 | 143 | # 禁用 WARP 容器 144 | function disable_warp() { 145 | if docker ps --format "{{.Names}}" | grep -q "^xray-script-warp\$"; then 146 | print_warn '正在停止 WARP 容器' 147 | docker stop xray-script-warp 148 | docker rm xray-script-warp 149 | docker image rm xray-script-warp 150 | rm -rf /usr/local/xray-script/warp 151 | rm -rf ${HOME}/.warp 152 | # 清理配置 153 | jq 'del(.outbounds[] | select(.tag == "warp")) | del(.routing.rules[] | select(.outboundTag == "warp"))' /usr/local/etc/xray/config.json >/usr/local/xray-script/tmp.json && mv -f /usr/local/xray-script/tmp.json /usr/local/etc/xray/config.json 154 | jq --argjson warp 0 '.warp = $warp' /usr/local/xray-script/config.json >/usr/local/xray-script/tmp.json && mv -f /usr/local/xray-script/tmp.json /usr/local/xray-script/config.json 155 | print_info "WARP 容器已停止" 156 | fi 157 | } 158 | 159 | # 安装 Cloudreve 160 | function install_cloudreve() { 161 | if ! docker ps --format "{{.Names}}" | grep -q "^cloudreve\$"; then 162 | print_info "创建 Cloudreve 相关目录。" 163 | mkdir -vp /usr/local/cloudreve && 164 | mkdir -vp /usr/local/cloudreve/cloudreve/{uploads,avatar} && 165 | touch /usr/local/cloudreve/cloudreve/conf.ini && 166 | touch /usr/local/cloudreve/cloudreve/cloudreve.db && 167 | mkdir -vp /usr/local/cloudreve/aria2/config && 168 | mkdir -vp /usr/local/cloudreve/data/aria2 && 169 | chmod -R 777 /usr/local/cloudreve/data/aria2 170 | print_info "下载管理 Cloudreve 的 docker-compose.yaml。" 171 | wget -O /usr/local/cloudreve/docker-compose.yaml https://raw.githubusercontent.com/zxcvos/Xray-script/main/cloudreve/docker-compose.yaml 172 | print_info "启动 Cloudreve 服务" 173 | cd /usr/local/cloudreve 174 | docker compose up -d 175 | sleep 5 176 | fi 177 | } 178 | 179 | # 获取 Cloudreve 信息 180 | function get_cloudreve_info() { 181 | if docker ps --format "{{.Names}}" | grep -q "^cloudreve\$"; then 182 | local cloudreve_version="$(docker logs cloudreve | grep -Eoi "v[0-9]+.[0-9]+.[0-9]+" | cut -c2-)" 183 | local cloudreve_username="$(docker logs cloudreve | grep Admin | awk '{print $NF}' | head -1)" 184 | local cloudreve_password="$(docker logs cloudreve | grep Admin | awk '{print $NF}' | tail -1)" 185 | jq --arg version "${cloudreve_version}" '.cloudreve.version = $version' /usr/local/xray-script/config.json >/usr/local/xray-script/tmp.json && mv -f /usr/local/xray-script/tmp.json /usr/local/xray-script/config.json 186 | jq --arg username "${cloudreve_username}" '.cloudreve.username = $username' /usr/local/xray-script/config.json >/usr/local/xray-script/tmp.json && mv -f /usr/local/xray-script/tmp.json /usr/local/xray-script/config.json 187 | jq --arg password "${cloudreve_password}" '.cloudreve.password = $password' /usr/local/xray-script/config.json >/usr/local/xray-script/tmp.json && mv -f /usr/local/xray-script/tmp.json /usr/local/xray-script/config.json 188 | fi 189 | } 190 | 191 | # 重置 Cloudreve 信息 192 | function reset_cloudreve_info() { 193 | if docker ps --format "{{.Names}}" | grep -q "^cloudreve\$"; then 194 | print_info "正在重置 Cloudreve 信息" 195 | cd /usr/local/cloudreve 196 | docker compose down 197 | rm -rf /usr/local/cloudreve/cloudreve/cloudreve.db 198 | touch /usr/local/cloudreve/cloudreve/cloudreve.db 199 | docker compose up -d 200 | sleep 5 201 | get_cloudreve_info 202 | fi 203 | } 204 | 205 | # 卸载 cloudreve 206 | function purge_cloudreve() { 207 | if docker ps --format "{{.Names}}" | grep -q "^cloudreve\$"; then 208 | print_warn "停止 Cloudreve 服务" 209 | cd /usr/local/cloudreve 210 | docker compose down 211 | cd ${HOME} 212 | rm -rf /usr/local/cloudreve 213 | fi 214 | } 215 | 216 | # 显示帮助信息 217 | function show_help() { 218 | cat </dev/null 2>&1; then 66 | eval type "$cmd" >/dev/null 2>&1 67 | elif command >/dev/null 2>&1; then 68 | command -v "$cmd" >/dev/null 2>&1 69 | else 70 | which "$cmd" >/dev/null 2>&1 71 | fi 72 | local rt=$? 73 | return ${rt} 74 | } 75 | 76 | function _os() { 77 | local os="" 78 | [[ -f "/etc/debian_version" ]] && source /etc/os-release && os="${ID}" && printf -- "%s" "${os}" && return 79 | [[ -f "/etc/redhat-release" ]] && os="centos" && printf -- "%s" "${os}" && return 80 | } 81 | 82 | function _os_full() { 83 | [[ -f /etc/redhat-release ]] && awk '{print ($1,$3~/^[0-9]/?$3:$4)}' /etc/redhat-release && return 84 | [[ -f /etc/os-release ]] && awk -F'[= "]' '/PRETTY_NAME/{print $3,$4,$5}' /etc/os-release && return 85 | [[ -f /etc/lsb-release ]] && awk -F'[="]+' '/DESCRIPTION/{print $2}' /etc/lsb-release && return 86 | } 87 | 88 | function _os_ver() { 89 | local main_ver="$(echo $(_os_full) | grep -oE "[0-9.]+")" 90 | printf -- "%s" "${main_ver%%.*}" 91 | } 92 | 93 | function _error_detect() { 94 | local cmd="$1" 95 | print_info "正在执行命令: ${cmd}" 96 | eval ${cmd} 97 | if [[ $? -ne 0 ]]; then 98 | print_error "执行命令 (${cmd}) 失败,请检查并重试。" 99 | fi 100 | } 101 | 102 | function _version_ge() { 103 | test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" == "$1" 104 | } 105 | 106 | function _install() { 107 | local packages_name="$@" 108 | local installed_packages="" 109 | case "$(_os)" in 110 | centos) 111 | if _exists "dnf"; then 112 | packages_name="dnf-plugins-core epel-release epel-next-release ${packages_name}" 113 | installed_packages="$(dnf list installed 2>/dev/null)" 114 | if [[ -n "$(_os_ver)" && "$(_os_ver)" -eq 9 ]]; then 115 | # 启用 EPEL 和 Remi 仓库 116 | if [[ "${packages_name}" =~ "geoip-devel" ]] && ! echo "${installed_packages}" | grep -iwq "geoip-devel"; then 117 | dnf update -y 118 | _error_detect "dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm" 119 | _error_detect "dnf install -y https://dl.fedoraproject.org/pub/epel/epel-next-release-latest-9.noarch.rpm" 120 | _error_detect "dnf install -y https://rpms.remirepo.net/enterprise/remi-release-9.rpm" 121 | # 启用 Remi 模块化仓库 122 | _error_detect "dnf config-manager --set-enabled remi-modular" 123 | # 刷新包信息 124 | _error_detect "dnf update --refresh" 125 | # 安装 GeoIP-devel,指定使用 Remi 仓库 126 | dnf update -y 127 | _error_detect "dnf --enablerepo=remi install -y GeoIP-devel" 128 | fi 129 | elif [[ -n "$(_os_ver)" && "$(_os_ver)" -eq 8 ]]; then 130 | if ! dnf module list 2>/dev/null | grep container-tools | grep -iwq "\[x\]"; then 131 | _error_detect "dnf module disable -y container-tools" 132 | fi 133 | fi 134 | dnf update -y 135 | for package_name in ${packages_name}; do 136 | if ! echo "${installed_packages}" | grep -iwq "${package_name}"; then 137 | _error_detect "dnf install -y "${package_name}"" 138 | fi 139 | done 140 | else 141 | packages_name="epel-release yum-utils ${packages_name}" 142 | installed_packages="$(yum list installed 2>/dev/null)" 143 | yum update -y 144 | for package_name in ${packages_name}; do 145 | if ! echo "${installed_packages}" | grep -iwq "${package_name}"; then 146 | _error_detect "yum install -y "${package_name}"" 147 | fi 148 | done 149 | fi 150 | ;; 151 | ubuntu | debian) 152 | apt update -y 153 | installed_packages="$(apt list --installed 2>/dev/null)" 154 | for package_name in ${packages_name}; do 155 | if ! echo "${installed_packages}" | grep -iwq "${package_name}"; then 156 | _error_detect "apt install -y "${package_name}"" 157 | fi 158 | done 159 | ;; 160 | esac 161 | } 162 | 163 | # 检查操作系统 164 | function check_os() { 165 | [[ -z "$(_os)" ]] && print_error "不支持的操作系统。" 166 | case "$(_os)" in 167 | ubuntu) 168 | [[ -n "$(_os_ver)" && "$(_os_ver)" -lt 20 ]] && print_error "不支持的操作系统,请切换到 Ubuntu 20+ 并重试。" 169 | ;; 170 | debian) 171 | [[ -n "$(_os_ver)" && "$(_os_ver)" -lt 10 ]] && print_error "不支持的操作系统,请切换到 Debian 10+ 并重试。" 172 | ;; 173 | centos) 174 | [[ -n "$(_os_ver)" && "$(_os_ver)" -lt 7 ]] && print_error "不支持的操作系统,请切换到 CentOS 7+ 并重试。" 175 | ;; 176 | *) 177 | print_error "不支持的操作系统。" 178 | ;; 179 | esac 180 | } 181 | 182 | # 启用交换分区 183 | function swap_on() { 184 | local mem=${1} 185 | if [[ ${mem} -ne '0' ]]; then 186 | if dd if=/dev/zero of="${TMPFILE_DIR}/swap" bs=1M count=${mem} 2>&1; then 187 | chmod 0600 "${TMPFILE_DIR}/swap" 188 | mkswap "${TMPFILE_DIR}/swap" 189 | swapon "${TMPFILE_DIR}/swap" 190 | fi 191 | fi 192 | } 193 | 194 | # 备份文件 195 | function backup_files() { 196 | local backup_dir="$1" 197 | local current_date="$(date +%F)" 198 | for file in "${backup_dir}/"*; do 199 | if [[ -f "$file" ]]; then 200 | local file_name="$(basename "$file")" 201 | local backup_file="${backup_dir}/${file_name}_${current_date}" 202 | mv "$file" "$backup_file" 203 | echo "备份: ${file} -> ${backup_file}。" 204 | fi 205 | done 206 | } 207 | 208 | # 编译依赖项 209 | function compile_dependencies() { 210 | # 常规依赖 211 | _install ca-certificates curl wget gcc make git openssl tzdata 212 | case "$(_os)" in 213 | centos) 214 | # 工具链 215 | _install gcc-c++ perl-IPC-Cmd perl-Getopt-Long perl-Data-Dumper 216 | # 编译依赖 217 | _install pcre2-devel zlib-devel libxml2-devel libxslt-devel gd-devel geoip-devel perl-ExtUtils-Embed gperftools-devel perl-devel brotli-devel 218 | if ! perl -e "use FindBin" &>/dev/null; then 219 | _install perl-FindBin 220 | fi 221 | ;; 222 | debian | ubuntu) 223 | # 工具链 224 | _install g++ perl-base perl 225 | # 编译依赖 226 | _install libpcre2-dev zlib1g-dev libxml2-dev libxslt1-dev libgd-dev libgeoip-dev libgoogle-perftools-dev libperl-dev libbrotli-dev 227 | ;; 228 | esac 229 | } 230 | 231 | # 生成编译选项 232 | function gen_cflags() { 233 | cflags=('-g0' '-O3') 234 | if gcc -v --help 2>&1 | grep -qw "\\-fstack\\-reuse"; then 235 | cflags+=('-fstack-reuse=all') 236 | fi 237 | if gcc -v --help 2>&1 | grep -qw "\\-fdwarf2\\-cfi\\-asm"; then 238 | cflags+=('-fdwarf2-cfi-asm') 239 | fi 240 | if gcc -v --help 2>&1 | grep -qw "\\-fplt"; then 241 | cflags+=('-fplt') 242 | fi 243 | if gcc -v --help 2>&1 | grep -qw "\\-ftrapv"; then 244 | cflags+=('-fno-trapv') 245 | fi 246 | if gcc -v --help 2>&1 | grep -qw "\\-fexceptions"; then 247 | cflags+=('-fno-exceptions') 248 | elif gcc -v --help 2>&1 | grep -qw "\\-fhandle\\-exceptions"; then 249 | cflags+=('-fno-handle-exceptions') 250 | fi 251 | if gcc -v --help 2>&1 | grep -qw "\\-funwind\\-tables"; then 252 | cflags+=('-fno-unwind-tables') 253 | fi 254 | if gcc -v --help 2>&1 | grep -qw "\\-fasynchronous\\-unwind\\-tables"; then 255 | cflags+=('-fno-asynchronous-unwind-tables') 256 | fi 257 | if gcc -v --help 2>&1 | grep -qw "\\-fstack\\-check"; then 258 | cflags+=('-fno-stack-check') 259 | fi 260 | if gcc -v --help 2>&1 | grep -qw "\\-fstack\\-clash\\-protection"; then 261 | cflags+=('-fno-stack-clash-protection') 262 | fi 263 | if gcc -v --help 2>&1 | grep -qw "\\-fstack\\-protector"; then 264 | cflags+=('-fno-stack-protector') 265 | fi 266 | if gcc -v --help 2>&1 | grep -qw "\\-fcf\\-protection="; then 267 | cflags+=('-fcf-protection=none') 268 | fi 269 | if gcc -v --help 2>&1 | grep -qw "\\-fsplit\\-stack"; then 270 | cflags+=('-fno-split-stack') 271 | fi 272 | if gcc -v --help 2>&1 | grep -qw "\\-fsanitize"; then 273 | >temp.c 274 | if gcc -E -fno-sanitize=all temp.c >/dev/null 2>&1; then 275 | cflags+=('-fno-sanitize=all') 276 | fi 277 | rm temp.c 278 | fi 279 | if gcc -v --help 2>&1 | grep -qw "\\-finstrument\\-functions"; then 280 | cflags+=('-fno-instrument-functions') 281 | fi 282 | } 283 | 284 | # 源码编译 285 | function source_compile() { 286 | cd "${TMPFILE_DIR}" 287 | # 最新版本 288 | print_info "检索 Nginx 和 OpenSSL 的最新版本。" 289 | local nginx_version="$(wget -qO- --no-check-certificate https://api.github.com/repos/nginx/nginx/tags | grep 'name' | cut -d\" -f4 | grep 'release' | head -1 | sed 's/release/nginx/')" 290 | local openssl_version="openssl-$(wget -qO- --no-check-certificate https://api.github.com/repos/openssl/openssl/tags | grep 'name' | cut -d\" -f4 | grep -Eoi '^openssl-([0-9]\.?){3}$' | head -1)" 291 | # 生成编译选项 292 | gen_cflags 293 | # nginx 294 | print_info "下载最新版本的 Nginx。" 295 | _error_detect "curl -fsSL -o ${nginx_version}.tar.gz https://nginx.org/download/${nginx_version}.tar.gz" 296 | tar -zxf "${nginx_version}.tar.gz" 297 | # openssl 298 | print_info "下载最新版本的 OpenSSL。" 299 | _error_detect "curl -fsSL -o ${openssl_version}.tar.gz https://github.com/openssl/openssl/archive/${openssl_version#*-}.tar.gz" 300 | tar -zxf "${openssl_version}.tar.gz" 301 | if [[ "${is_enable_brotli}" =~ ^[Yy]$ ]]; then 302 | # brotli 303 | print_info "检索 ngx_brotli 并构建依赖项。" 304 | _error_detect "git clone https://github.com/google/ngx_brotli && cd ngx_brotli && git submodule update --init" 305 | cd "${TMPFILE_DIR}" 306 | fi 307 | # 配置 308 | cd "${nginx_version}" 309 | sed -i "s/OPTIMIZE[ \\t]*=>[ \\t]*'-O'/OPTIMIZE => '-O3'/g" src/http/modules/perl/Makefile.PL 310 | sed -i 's/NGX_PERL_CFLAGS="$CFLAGS `$NGX_PERL -MExtUtils::Embed -e ccopts`"/NGX_PERL_CFLAGS="`$NGX_PERL -MExtUtils::Embed -e ccopts` $CFLAGS"/g' auto/lib/perl/conf 311 | sed -i 's/NGX_PM_CFLAGS=`$NGX_PERL -MExtUtils::Embed -e ccopts`/NGX_PM_CFLAGS="`$NGX_PERL -MExtUtils::Embed -e ccopts` $CFLAGS"/g' auto/lib/perl/conf 312 | if [[ "${is_enable_brotli}" =~ ^[Yy]$ ]]; then 313 | ./configure --prefix="${NGINX_PATH}" --user=root --group=root --with-threads --with-file-aio --with-http_ssl_module --with-http_v2_module --with-http_v3_module --with-http_realip_module --with-http_addition_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_geoip_module=dynamic --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_auth_request_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_slice_module --with-http_stub_status_module --with-http_perl_module=dynamic --with-mail=dynamic --with-mail_ssl_module --with-stream --with-stream_ssl_module --with-stream_realip_module --with-stream_geoip_module=dynamic --with-stream_ssl_preread_module --with-google_perftools_module --add-module="../ngx_brotli" --with-compat --with-cc-opt="${cflags[*]}" --with-openssl="../${openssl_version}" --with-openssl-opt="${cflags[*]}" 314 | else 315 | ./configure --prefix="${NGINX_PATH}" --user=root --group=root --with-threads --with-file-aio --with-http_ssl_module --with-http_v2_module --with-http_v3_module --with-http_realip_module --with-http_addition_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_geoip_module=dynamic --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_auth_request_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_slice_module --with-http_stub_status_module --with-http_perl_module=dynamic --with-mail=dynamic --with-mail_ssl_module --with-stream --with-stream_ssl_module --with-stream_realip_module --with-stream_geoip_module=dynamic --with-stream_ssl_preread_module --with-google_perftools_module --with-compat --with-cc-opt="${cflags[*]}" --with-openssl="../${openssl_version}" --with-openssl-opt="${cflags[*]}" 316 | fi 317 | print_info "申请 512MB 虚拟内存。" 318 | swap_on 512 319 | # 编译 320 | print_info "编译 Nginx。" 321 | _error_detect "make -j$(nproc)" 322 | } 323 | 324 | # 安装 nginx 325 | function source_install() { 326 | source_compile 327 | print_info "安装 Nginx。" 328 | make install 329 | ln -sf "${NGINX_PATH}/sbin/nginx" /usr/sbin/nginx 330 | } 331 | 332 | # 更新 nginx 333 | function source_update() { 334 | # 最新版本 335 | print_info "检索 Nginx 和 OpenSSL 的最新版本。" 336 | local latest_nginx_version="$(wget -qO- --no-check-certificate https://api.github.com/repos/nginx/nginx/tags | grep 'name' | cut -d\" -f4 | grep 'release' | head -1 | sed 's/release/nginx/')" 337 | local latest_openssl_version="$(wget -qO- --no-check-certificate https://api.github.com/repos/openssl/openssl/tags | grep 'name' | cut -d\" -f4 | grep -Eoi '^openssl-([0-9]\.?){3}$' | head -1)" 338 | # 当前版本 339 | print_info "读取 Nginx 和 OpenSSL 的当前版本。" 340 | local current_version_nginx="$(nginx -V 2>&1 | grep "^nginx version:.*" | cut -d / -f 2)" 341 | local current_version_openssl="$(nginx -V 2>&1 | grep "^built with OpenSSL" | awk '{print $4}')" 342 | # 比较 343 | print_info "判断是否需要更新。" 344 | if _version_ge "${latest_nginx_version#*-}" "${current_version_nginx}" || _version_ge "${latest_openssl_version#*-}" "${current_version_openssl}"; then 345 | source_compile 346 | print_info "更新 Nginx。" 347 | mv "${NGINX_PATH}/sbin/nginx" "${NGINX_PATH}/sbin/nginx_$(date +%F)" 348 | backup_files "${NGINX_PATH}/modules" 349 | cp objs/nginx "${NGINX_PATH}/sbin/" 350 | cp objs/*.so "${NGINX_PATH}/modules/" 351 | ln -sf "${NGINX_PATH}/sbin/nginx" /usr/sbin/nginx 352 | if systemctl is-active --quiet nginx; then 353 | kill -USR2 $(cat /run/nginx.pid) 354 | if [[ -e "/run/nginx.pid.oldbin" ]]; then 355 | kill -WINCH $(cat /run/nginx.pid.oldbin) 356 | kill -HUP $(cat /run/nginx.pid.oldbin) 357 | kill -QUIT $(cat /run/nginx.pid.oldbin) 358 | else 359 | print_info "未找到旧的 Nginx 进程。跳过后续步骤。" 360 | fi 361 | fi 362 | return 0 363 | fi 364 | return 1 365 | } 366 | 367 | # 卸载 nginx 368 | function purge_nginx() { 369 | systemctl stop nginx 370 | rm -rf "${NGINX_PATH}" 371 | rm -rf /usr/sbin/nginx 372 | rm -rf /etc/systemd/system/nginx.service 373 | rm -rf "${NGINX_LOG_PATH}" 374 | systemctl daemon-reload 375 | } 376 | 377 | function systemctl_config_nginx() { 378 | cat >/etc/systemd/system/nginx.service </dev/null 2>&1; then 55 | eval type "$cmd" >/dev/null 2>&1 56 | elif command >/dev/null 2>&1; then 57 | command -v "$cmd" >/dev/null 2>&1 58 | else 59 | which "$cmd" >/dev/null 2>&1 60 | fi 61 | local rt=$? 62 | return ${rt} 63 | } 64 | 65 | function _os() { 66 | local os="" 67 | [[ -f "/etc/debian_version" ]] && source /etc/os-release && os="${ID}" && printf -- "%s" "${os}" && return 68 | [[ -f "/etc/redhat-release" ]] && os="centos" && printf -- "%s" "${os}" && return 69 | } 70 | 71 | function _os_full() { 72 | [[ -f /etc/redhat-release ]] && awk '{print ($1,$3~/^[0-9]/?$3:$4)}' /etc/redhat-release && return 73 | [[ -f /etc/os-release ]] && awk -F'[= "]' '/PRETTY_NAME/{print $3,$4,$5}' /etc/os-release && return 74 | [[ -f /etc/lsb-release ]] && awk -F'[="]+' '/DESCRIPTION/{print $2}' /etc/lsb-release && return 75 | } 76 | 77 | function _os_ver() { 78 | local main_ver="$(echo $(_os_full) | grep -oE "[0-9.]+")" 79 | printf -- "%s" "${main_ver%%.*}" 80 | } 81 | 82 | function _error_detect() { 83 | local cmd="$1" 84 | _info "${cmd}" 85 | eval ${cmd} 86 | if [[ $? -ne 0 ]]; then 87 | _error "Execution command (${cmd}) failed, please check it and try again." 88 | fi 89 | } 90 | 91 | function _is_digit() { 92 | local input=${1} 93 | if [[ "$input" =~ ^[0-9]+$ ]]; then 94 | return 0 95 | else 96 | return 1 97 | fi 98 | } 99 | 100 | function _version_ge() { 101 | test "$(echo "$@" | tr ' ' '\n' | sort -rV | head -n 1)" == "$1" 102 | } 103 | 104 | function _is_tlsv1_3_h2() { 105 | local check_url=$(echo $1 | grep -oE '[^/]+(\.[^/]+)+\b' | head -n 1) 106 | local check_num=$(echo QUIT | stdbuf -oL openssl s_client -connect "${check_url}:443" -tls1_3 -alpn h2 2>&1 | grep -Eoi '(TLSv1.3)|(^ALPN\s+protocol:\s+h2$)|(X25519)' | sort -u | wc -l) 107 | if [[ ${check_num} -eq 3 ]]; then 108 | return 0 109 | else 110 | return 1 111 | fi 112 | } 113 | 114 | function _install() { 115 | local packages_name="$@" 116 | case "$(_os)" in 117 | centos) 118 | if _exists "dnf"; then 119 | dnf update -y 120 | dnf install -y dnf-plugins-core 121 | dnf update -y 122 | for package_name in ${packages_name}; do 123 | dnf install -y ${package_name} 124 | done 125 | else 126 | yum update -y 127 | yum install -y epel-release yum-utils 128 | yum update -y 129 | for package_name in ${packages_name}; do 130 | yum install -y ${package_name} 131 | done 132 | fi 133 | ;; 134 | ubuntu | debian) 135 | apt update -y 136 | for package_name in ${packages_name}; do 137 | apt install -y ${package_name} 138 | done 139 | ;; 140 | esac 141 | } 142 | 143 | function _systemctl() { 144 | local cmd="$1" 145 | local server_name="$2" 146 | case "${cmd}" in 147 | start) 148 | _info "正在启动 ${server_name} 服务" 149 | systemctl -q is-active ${server_name} || systemctl -q start ${server_name} 150 | systemctl -q is-enabled ${server_name} || systemctl -q enable ${server_name} 151 | sleep 2 152 | systemctl -q is-active ${server_name} && _info "已启动 ${server_name} 服务" || _error "${server_name} 启动失败" 153 | ;; 154 | stop) 155 | _info "正在暂停 ${server_name} 服务" 156 | systemctl -q is-active ${server_name} && systemctl -q stop ${server_name} 157 | systemctl -q is-enabled ${server_name} && systemctl -q disable ${server_name} 158 | sleep 2 159 | systemctl -q is-active ${server_name} || _info "已暂停 ${server_name} 服务" 160 | ;; 161 | restart) 162 | _info "正在重启 ${server_name} 服务" 163 | systemctl -q is-active ${server_name} && systemctl -q restart ${server_name} || systemctl -q start ${server_name} 164 | systemctl -q is-enabled ${server_name} || systemctl -q enable ${server_name} 165 | sleep 2 166 | systemctl -q is-active ${server_name} && _info "已重启 ${server_name} 服务" || _error "${server_name} 启动失败" 167 | ;; 168 | reload) 169 | _info "正在重载 ${server_name} 服务" 170 | systemctl -q is-active ${server_name} && systemctl -q reload ${server_name} || systemctl -q start ${server_name} 171 | systemctl -q is-enabled ${server_name} || systemctl -q enable ${server_name} 172 | sleep 2 173 | systemctl -q is-active ${server_name} && _info "已重载 ${server_name} 服务" 174 | ;; 175 | dr) 176 | _info "正在重载 systemd 配置文件" 177 | systemctl daemon-reload 178 | ;; 179 | esac 180 | } 181 | 182 | function _print_list() { 183 | local p_list=($@) 184 | for ((i = 1; i <= ${#p_list[@]}; i++)); do 185 | hint="${p_list[$i - 1]}" 186 | echo -e "${GREEN}${i}${NC}) ${hint}" 187 | done 188 | } 189 | 190 | function select_data() { 191 | local data_list=($(awk -v FS=',' '{for (i=1; i<=NF; i++) arr[i]=$i} END{for (i in arr) print arr[i]}' <<<"${1}")) 192 | local index_list=($(awk -v FS=',' '{for (i=1; i<=NF; i++) arr[i]=$i} END{for (i in arr) print arr[i]}' <<<"${2}")) 193 | local result_list=() 194 | if [[ ${#index_list[@]} -ne 0 ]]; then 195 | for i in "${index_list[@]}"; do 196 | if _is_digit "${i}" && [ ${i} -ge 1 ] && [ ${i} -le ${#data_list[@]} ]; then 197 | i=$((i - 1)) 198 | result_list+=("${data_list[${i}]}") 199 | fi 200 | done 201 | else 202 | result_list=("${data_list[@]}") 203 | fi 204 | if [[ ${#result_list[@]} -eq 0 ]]; then 205 | result_list=("${data_list[@]}") 206 | fi 207 | echo "${result_list[@]}" 208 | } 209 | 210 | function select_dest() { 211 | local dest_list=($(jq '.xray.serverNames | keys_unsorted' /usr/local/etc/xray-script/config.json | grep -Eoi '".*"' | sed -En 's|"(.*)"|\1|p')) 212 | local cur_dest=$(jq -r '.xray.dest' /usr/local/etc/xray-script/config.json) 213 | local pick_dest="" 214 | local all_sns="" 215 | local sns="" 216 | local prompt="请选择你的 dest, 当前默认使用 \"${cur_dest}\", 自填选 0: " 217 | until [[ ${is_dest} =~ ^[Yy]$ ]]; do 218 | echo -e "---------------- dest 列表 -----------------" 219 | _print_list "${dest_list[@]}" 220 | read -p "${prompt}" pick 221 | if [[ "${pick}" == "" && "${cur_dest}" != "" ]]; then 222 | pick_dest=${cur_dest} 223 | break 224 | fi 225 | if ! _is_digit "${pick}" || [[ "${pick}" -lt 0 || "${pick}" -gt ${#dest_list[@]} ]]; then 226 | prompt="输入错误, 请输入 0-${#dest_list[@]} 之间的数字: " 227 | continue 228 | fi 229 | if [[ "${pick}" == "0" ]]; then 230 | _warn "如果输入列表中已有域名将会导致 serverNames 被修改" 231 | _warn "使用自填域名时,请确保该域名在国内的连通性" 232 | read_domain 233 | _info "正在检查 \"${domain}\" 是否支持 TLSv1.3 与 h2" 234 | if ! _is_tlsv1_3_h2 "${domain}"; then 235 | _warn "\"${domain}\" 不支持 TLSv1.3 或 h2 ,亦或者 Client Hello 不是 X25519" 236 | continue 237 | fi 238 | _info "\"${domain}\" 支持 TLSv1.3 与 h2" 239 | _info "正在获取 Allowed domains" 240 | pick_dest=${domain} 241 | all_sns=$(xray tls ping ${pick_dest} | sed -n '/with SNI/,$p' | sed -En 's/\[(.*)\]/\1/p' | sed -En 's/Allowed domains:\s*//p' | jq -R -c 'split(" ")' | jq --arg sni "${pick_dest}" '. += [$sni]') 242 | sns=$(echo ${all_sns} | jq 'map(select(test("^[^*]+$"; "g")))' | jq -c 'map(select(test("^((?!cloudflare|akamaized|edgekey|edgesuite|cloudfront|azureedge|msecnd|edgecastcdn|fastly|googleusercontent|kxcdn|maxcdn|stackpathdns|stackpathcdn).)*$"; "ig")))') 243 | _info "过滤通配符前的 SNI" 244 | _print_list $(echo ${all_sns} | jq -r '.[]') 245 | _info "过滤通配符后的 SNI" 246 | _print_list $(echo ${sns} | jq -r '.[]') 247 | read -p "请选择要使用的 serverName ,用英文逗号分隔, 默认全选: " pick_num 248 | sns=$(select_data "$(awk 'BEGIN{ORS=","} {print}' <<<"$(echo ${sns} | jq -r -c '.[]')")" "${pick_num}" | jq -R -c 'split(" ")') 249 | _info "如果有更多的 serverNames 请在 /usr/local/etc/xray-script/config.json 中自行编辑" 250 | else 251 | pick_dest="${dest_list[${pick} - 1]}" 252 | fi 253 | read -r -p "是否使用 dest: \"${pick_dest}\" [y/n] " is_dest 254 | prompt="请选择你的 dest, 当前默认使用 \"${cur_dest}\", 自填选 0: " 255 | echo -e "-------------------------------------------" 256 | done 257 | _info "正在修改配置" 258 | [[ "${domain_path}" != "" ]] && pick_dest="${pick_dest}${domain_path}" 259 | if echo ${pick_dest} | grep -q '/$'; then 260 | pick_dest=$(echo ${pick_dest} | sed -En 's|/+$||p') 261 | fi 262 | [[ "${sns}" != "" ]] && jq --argjson sn "{\"${pick_dest}\": ${sns}}" '.xray.serverNames += $sn' /usr/local/etc/xray-script/config.json >/usr/local/etc/xray-script/new.json && mv -f /usr/local/etc/xray-script/new.json /usr/local/etc/xray-script/config.json 263 | jq --arg dest "${pick_dest}" '.xray.dest = $dest' /usr/local/etc/xray-script/config.json >/usr/local/etc/xray-script/new.json && mv -f /usr/local/etc/xray-script/new.json /usr/local/etc/xray-script/config.json 264 | } 265 | 266 | function read_domain() { 267 | until [[ ${is_domain} =~ ^[Yy]$ ]]; do 268 | read -p "请输入域名:" domain 269 | check_domain=$(echo ${domain} | grep -oE '[^/]+(\.[^/]+)+\b' | head -n 1) 270 | read -r -p "请确认域名: \"${check_domain}\" [y/n] " is_domain 271 | done 272 | domain_path=$(echo "${domain}" | sed -En "s|.*${check_domain}(/.*)?|\1|p") 273 | domain=${check_domain} 274 | } 275 | 276 | function read_port() { 277 | local prompt="${1}" 278 | local cur_port="${2}" 279 | until [[ ${is_port} =~ ^[Yy]$ ]]; do 280 | echo "${prompt}" 281 | read -p "请输入自定义的端口(1-65535), 默认不修改: " new_port 282 | if [[ "${new_port}" == "" || ${new_port} -eq ${cur_port} ]]; then 283 | new_port=${cur_port} 284 | _info "不修改,继续使用原端口: ${cur_port}" 285 | break 286 | fi 287 | if ! _is_digit "${new_port}" || [[ ${new_port} -lt 1 || ${new_port} -gt 65535 ]]; then 288 | prompt="输入错误, 端口范围是 1-65535 之间的数字" 289 | continue 290 | fi 291 | read -r -p "请确认端口: \"${new_port}\" [y/n] " is_port 292 | prompt="${1}" 293 | done 294 | } 295 | 296 | function read_uuid() { 297 | _info '自定义输入的 uuid ,如果不是标准格式,将会使用 xray uuid -i "自定义字符串" 进行 UUIDv5 映射后填入配置' 298 | read -p "请输入自定义 UUID, 默认则自动生成: " in_uuid 299 | } 300 | 301 | # check os 302 | function check_os() { 303 | [[ -z "$(_os)" ]] && _error "Not supported OS" 304 | case "$(_os)" in 305 | ubuntu) 306 | [[ -n "$(_os_ver)" && "$(_os_ver)" -lt 16 ]] && _error "Not supported OS, please change to Ubuntu 16+ and try again." 307 | ;; 308 | debian) 309 | [[ -n "$(_os_ver)" && "$(_os_ver)" -lt 9 ]] && _error "Not supported OS, please change to Debian 9+ and try again." 310 | ;; 311 | centos) 312 | [[ -n "$(_os_ver)" && "$(_os_ver)" -lt 7 ]] && _error "Not supported OS, please change to CentOS 7+ and try again." 313 | ;; 314 | *) 315 | _error "Not supported OS" 316 | ;; 317 | esac 318 | } 319 | 320 | function install_dependencies() { 321 | _info "正在下载相关依赖" 322 | _install "ca-certificates openssl curl wget jq tzdata" 323 | case "$(_os)" in 324 | centos) 325 | _install "crontabs util-linux iproute procps-ng" 326 | ;; 327 | debian | ubuntu) 328 | _install "cron bsdmainutils iproute2 procps" 329 | ;; 330 | esac 331 | } 332 | 333 | function install_update_xray() { 334 | _info "正在安装或更新 Xray" 335 | _error_detect 'bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install -u root --beta' 336 | jq --arg ver "$(xray version | head -n 1 | cut -d \( -f 1 | grep -Eoi '[0-9.]*')" '.xray.version = $ver' /usr/local/etc/xray-script/config.json >/usr/local/etc/xray-script/new.json && mv -f /usr/local/etc/xray-script/new.json /usr/local/etc/xray-script/config.json 337 | wget -O /usr/local/etc/xray-script/update-dat.sh https://raw.githubusercontent.com/zxcvos/Xray-script/main/tool/update-dat.sh 338 | chmod a+x /usr/local/etc/xray-script/update-dat.sh 339 | (crontab -l 2>/dev/null; echo "30 22 * * * /usr/local/etc/xray-script/update-dat.sh >/dev/null 2>&1") | awk '!x[$0]++' | crontab - 340 | /usr/local/etc/xray-script/update-dat.sh 341 | } 342 | 343 | function purge_xray() { 344 | _info "正在卸载 Xray" 345 | crontab -l | grep -v "/usr/local/etc/xray-script/update-dat.sh >/dev/null 2>&1" | crontab - 346 | _systemctl "stop" "xray" 347 | bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ remove --purge 348 | rm -rf /etc/systemd/system/xray.service 349 | rm -rf /etc/systemd/system/xray@.service 350 | rm -rf /usr/local/bin/xray 351 | rm -rf /usr/local/etc/xray 352 | rm -rf /usr/local/share/xray 353 | rm -rf /var/log/xray 354 | } 355 | 356 | function service_xray() { 357 | _info "正在配置 xray.service" 358 | wget -O ${HOME}/xray.service https://raw.githubusercontent.com/zxcvos/Xray-script/main/service/xray.service 359 | mv -f ${HOME}/xray.service /etc/systemd/system/xray.service 360 | _systemctl dr 361 | } 362 | 363 | function config_xray() { 364 | _info "正在配置 xray config.json" 365 | "${xray_config_manage}" --path ${HOME}/config.json --download 366 | local xray_x25519=$(xray x25519) 367 | local xs_private_key=$(echo ${xray_x25519} | awk '{print $3}') 368 | local xs_public_key=$(echo ${xray_x25519} | awk '{print $6}') 369 | # Xray-script config.json 370 | jq --arg privateKey "${xs_private_key}" '.xray.privateKey = $privateKey' /usr/local/etc/xray-script/config.json >/usr/local/etc/xray-script/new.json && mv -f /usr/local/etc/xray-script/new.json /usr/local/etc/xray-script/config.json 371 | jq --arg publicKey "${xs_public_key}" '.xray.publicKey = $publicKey' /usr/local/etc/xray-script/config.json >/usr/local/etc/xray-script/new.json && mv -f /usr/local/etc/xray-script/new.json /usr/local/etc/xray-script/config.json 372 | # Xray-core config.json 373 | "${xray_config_manage}" --path ${HOME}/config.json -p ${new_port} 374 | "${xray_config_manage}" --path ${HOME}/config.json -u ${in_uuid} 375 | "${xray_config_manage}" --path ${HOME}/config.json -d "$(jq -r '.xray.dest' /usr/local/etc/xray-script/config.json | grep -Eoi '([a-zA-Z0-9](\-?[a-zA-Z0-9])*\.)+[a-zA-Z]{2,}')" 376 | "${xray_config_manage}" --path ${HOME}/config.json -sn "$(jq -c -r '.xray | .serverNames[.dest] | .[]' /usr/local/etc/xray-script/config.json | tr '\n' ',')" 377 | "${xray_config_manage}" --path ${HOME}/config.json -x "${xs_private_key}" 378 | "${xray_config_manage}" --path ${HOME}/config.json -rsid 379 | mv -f ${HOME}/config.json /usr/local/etc/xray/config.json 380 | _systemctl "restart" "xray" 381 | } 382 | 383 | function tcp2raw() { 384 | local current_xray_version=$(xray version | awk '$1=="Xray" {print $2}') 385 | local tcp2raw_xray_version='24.9.30' 386 | if _version_ge "${current_xray_version}" "${tcp2raw_xray_version}"; then 387 | sed -i 's/"network": "tcp"/"network": "raw"/' /usr/local/etc/xray/config.json 388 | _systemctl "restart" "xray" 389 | fi 390 | } 391 | 392 | function dest2target() { 393 | local current_xray_version=$(xray version | awk '$1=="Xray" {print $2}') 394 | local dest2target_xray_version='24.10.31' 395 | if _version_ge "${current_xray_version}" "${dest2target_xray_version}"; then 396 | sed -i 's/"dest"/"target"/' /usr/local/etc/xray/config.json 397 | _systemctl "restart" "xray" 398 | fi 399 | } 400 | 401 | function show_config() { 402 | local IPv4=$(wget -qO- -t1 -T2 ipv4.icanhazip.com) 403 | local xs_inbound=$(jq '.inbounds[] | select(.tag == "xray-script-xtls-reality")' /usr/local/etc/xray/config.json) 404 | local xs_port=$(echo ${xs_inbound} | jq '.port') 405 | local xs_protocol=$(echo ${xs_inbound} | jq '.protocol') 406 | local xs_ids=$(echo ${xs_inbound} | jq '.settings.clients[] | .id' | tr '\n' ',') 407 | local xs_public_key=$(jq '.xray.publicKey' /usr/local/etc/xray-script/config.json) 408 | local xs_serverNames=$(echo ${xs_inbound} | jq '.streamSettings.realitySettings.serverNames[]' | tr '\n' ',') 409 | local xs_shortIds=$(echo ${xs_inbound} | jq '.streamSettings.realitySettings.shortIds[]' | tr '\n' ',') 410 | local xs_spiderX=$(jq '.xray.dest' /usr/local/etc/xray-script/config.json) 411 | [[ "${xs_spiderX}" == "${xs_spiderX##*/}" ]] && xs_spiderX='"/"' || xs_spiderX="\"/${xs_spiderX#*/}" 412 | echo -e "-------------- client config --------------" 413 | echo -e "address : \"${IPv4}\"" 414 | echo -e "port : ${xs_port}" 415 | echo -e "protocol : ${xs_protocol}" 416 | echo -e "id : ${xs_ids%,}" 417 | echo -e "flow : \"xtls-rprx-vision\"" 418 | echo -e "network : \"tcp\"" 419 | echo -e "TLS : \"reality\"" 420 | echo -e "SNI : ${xs_serverNames%,}" 421 | echo -e "Fingerprint : \"chrome\"" 422 | echo -e "PublicKey : ${xs_public_key}" 423 | echo -e "ShortId : ${xs_shortIds%,}" 424 | echo -e "SpiderX : ${xs_spiderX}" 425 | echo -e "------------------------------------------" 426 | read -p "是否生成分享链接[y/n]: " is_show_share_link 427 | echo 428 | if [[ ${is_show_share_link} =~ ^[Yy]$ ]]; then 429 | show_share_link 430 | else 431 | echo -e "------------------------------------------" 432 | echo -e "${RED}此脚本仅供交流学习使用,请勿使用此脚本行违法之事。${NC}" 433 | echo -e "${RED}网络非法外之地,行非法之事,必将接受法律制裁。${NC}" 434 | echo -e "------------------------------------------" 435 | fi 436 | } 437 | 438 | function show_share_link() { 439 | local sl="" 440 | # share lnk contents 441 | local sl_host=$(wget -qO- -t1 -T2 ipv4.icanhazip.com) 442 | local sl_inbound=$(jq '.inbounds[] | select(.tag == "xray-script-xtls-reality")' /usr/local/etc/xray/config.json) 443 | local sl_port=$(echo ${sl_inbound} | jq -r '.port') 444 | local sl_protocol=$(echo ${sl_inbound} | jq -r '.protocol') 445 | local sl_ids=$(echo ${sl_inbound} | jq -r '.settings.clients[] | .id') 446 | local sl_public_key=$(jq -r '.xray.publicKey' /usr/local/etc/xray-script/config.json) 447 | local sl_serverNames=$(echo ${sl_inbound} | jq -r '.streamSettings.realitySettings.serverNames[]') 448 | local sl_shortIds=$(echo ${sl_inbound} | jq '.streamSettings.realitySettings.shortIds[]') 449 | # share link fields 450 | local sl_uuid="" 451 | local sl_security='security=reality' 452 | local sl_flow='flow=xtls-rprx-vision' 453 | local sl_fingerprint='fp=chrome' 454 | local sl_publicKey="pbk=${sl_public_key}" 455 | local sl_sni="" 456 | local sl_shortId="" 457 | local sl_spiderX='spx=%2F' 458 | local sl_descriptive_text='VLESS-XTLS-uTLS-REALITY' 459 | # select show 460 | _print_list "${sl_ids[@]}" 461 | read -p "请选择生成分享链接的 UUID ,用英文逗号分隔, 默认全选: " pick_num 462 | sl_id=($(select_data "$(awk 'BEGIN{ORS=","} {print}' <<<"${sl_ids[@]}")" "${pick_num}")) 463 | _print_list "${sl_serverNames[@]}" 464 | read -p "请选择生成分享链接的 serverName ,用英文逗号分隔, 默认全选: " pick_num 465 | sl_serverNames=($(select_data "$(awk 'BEGIN{ORS=","} {print}' <<<"${sl_serverNames[@]}")" "${pick_num}")) 466 | _print_list "${sl_shortIds[@]}" 467 | read -p "请选择生成分享链接的 shortId ,用英文逗号分隔, 默认全选: " pick_num 468 | sl_shortIds=($(select_data "$(awk 'BEGIN{ORS=","} {print}' <<<"${sl_shortIds[@]}")" "${pick_num}")) 469 | echo -e "--------------- share link ---------------" 470 | for sl_id in "${sl_ids[@]}"; do 471 | sl_uuid="${sl_id}" 472 | for sl_serverName in "${sl_serverNames[@]}"; do 473 | sl_sni="sni=${sl_serverName}" 474 | echo -e "---------- serverName ${sl_sni} ----------" 475 | for sl_shortId in "${sl_shortIds[@]}"; do 476 | [[ "${sl_shortId//\"/}" != "" ]] && sl_shortId="sid=${sl_shortId//\"/}" || sl_shortId="" 477 | sl="${sl_protocol}://${sl_uuid}@${sl_host}:${sl_port}?${sl_security}&${sl_flow}&${sl_fingerprint}&${sl_publicKey}&${sl_sni}&${sl_spiderX}&${sl_shortId}" 478 | echo "${sl%&}#${sl_descriptive_text}" 479 | done 480 | echo -e "------------------------------------------------" 481 | done 482 | done 483 | echo -e "------------------------------------------" 484 | echo -e "${RED}此脚本仅供交流学习使用,请勿使用此脚本行违法之事。${NC}" 485 | echo -e "${RED}网络非法外之地,行非法之事,必将接受法律制裁。${NC}" 486 | echo -e "------------------------------------------" 487 | } 488 | 489 | function menu() { 490 | check_os 491 | clear 492 | echo -e "--------------- Xray-script ---------------" 493 | echo -e " Version : ${GREEN}v2023-03-15${NC}(${RED}beta${NC})" 494 | echo -e " Description : Xray 管理脚本" 495 | echo -e "----------------- 装载管理 ----------------" 496 | echo -e "${GREEN}1.${NC} 安装" 497 | echo -e "${GREEN}2.${NC} 更新" 498 | echo -e "${GREEN}3.${NC} 卸载" 499 | echo -e "----------------- 操作管理 ----------------" 500 | echo -e "${GREEN}4.${NC} 启动" 501 | echo -e "${GREEN}5.${NC} 停止" 502 | echo -e "${GREEN}6.${NC} 重启" 503 | echo -e "----------------- 配置管理 ----------------" 504 | echo -e "${GREEN}101.${NC} 查看配置" 505 | echo -e "${GREEN}102.${NC} 信息统计" 506 | echo -e "${GREEN}103.${NC} 修改 id" 507 | echo -e "${GREEN}104.${NC} 修改 dest" 508 | echo -e "${GREEN}105.${NC} 修改 x25519 key" 509 | echo -e "${GREEN}106.${NC} 修改 shortIds" 510 | echo -e "${GREEN}107.${NC} 修改 xray 监听端口" 511 | echo -e "${GREEN}108.${NC} 刷新已有的 shortIds" 512 | echo -e "${GREEN}109.${NC} 追加自定义的 shortIds" 513 | echo -e "${GREEN}110.${NC} 使用 WARP 分流,开启 OpenAI" 514 | echo -e "----------------- 其他选项 ----------------" 515 | echo -e "${GREEN}201.${NC} 更新至最新稳定版内核" 516 | echo -e "${GREEN}202.${NC} 卸载多余内核" 517 | echo -e "${GREEN}203.${NC} 修改 ssh 端口" 518 | echo -e "${GREEN}204.${NC} 网络连接优化" 519 | echo -e "-------------------------------------------" 520 | echo -e "${RED}0.${NC} 退出" 521 | read -rp "Choose: " idx 522 | ! _is_digit "${idx}" && _error "请输入正确的选项值" 523 | if [[ ! -d /usr/local/etc/xray-script && (${idx} -ne 0 && ${idx} -ne 1 && ${idx} -lt 201) ]]; then 524 | _error "未使用 Xray-script 进行安装" 525 | fi 526 | if [ -d /usr/local/etc/xray-script ] && ([ ${idx} -gt 102 ] || [ ${idx} -lt 111 ]); then 527 | wget -qO ${xray_config_manage} https://raw.githubusercontent.com/zxcvos/Xray-script/main/tool/xray_config_manage.sh 528 | chmod a+x ${xray_config_manage} 529 | fi 530 | case "${idx}" in 531 | 1) 532 | if [[ ! -d /usr/local/etc/xray-script ]]; then 533 | mkdir -p /usr/local/etc/xray-script 534 | wget -O /usr/local/etc/xray-script/config.json https://raw.githubusercontent.com/zxcvos/Xray-script/main/config/config.json 535 | wget -O ${xray_config_manage} https://raw.githubusercontent.com/zxcvos/Xray-script/main/tool/xray_config_manage.sh 536 | chmod a+x ${xray_config_manage} 537 | install_dependencies 538 | install_update_xray 539 | local xs_port=$(jq '.xray.port' /usr/local/etc/xray-script/config.json) 540 | read_port "xray config 配置默认使用: ${xs_port}" "${xs_port}" 541 | read_uuid 542 | select_dest 543 | config_xray 544 | tcp2raw 545 | dest2target 546 | show_config 547 | fi 548 | ;; 549 | 2) 550 | _info "判断 Xray 是否用新版本" 551 | local current_xray_version="$(jq -r '.xray.version' /usr/local/etc/xray-script/config.json)" 552 | local latest_xray_version="$(wget -qO- --no-check-certificate https://api.github.com/repos/XTLS/Xray-core/releases | jq -r '.[0].tag_name ' | cut -d v -f 2)" 553 | if _version_ge "${latest_xray_version}" "${current_xray_version}"; then 554 | _info "检测到有新版可用" 555 | install_update_xray 556 | tcp2raw 557 | dest2target 558 | else 559 | _info "当前已是最新版本: ${current_xray_version}" 560 | fi 561 | ;; 562 | 3) 563 | purge_xray 564 | [[ -f /usr/local/etc/xray-script/sysctl.conf.bak ]] && mv -f /usr/local/etc/xray-script/sysctl.conf.bak /etc/sysctl.conf && _info "已还原网络连接设置" 565 | rm -rf /usr/local/etc/xray-script 566 | if docker ps | grep -q cloudflare-warp; then 567 | _info '正在停止 cloudflare-warp' 568 | docker container stop cloudflare-warp 569 | docker container rm cloudflare-warp 570 | fi 571 | if docker images | grep -q e7h4n/cloudflare-warp; then 572 | _info '正在卸载 cloudflare-warp' 573 | docker image rm e7h4n/cloudflare-warp 574 | fi 575 | rm -rf ${HOME}/.warp 576 | _info 'Docker 请自行卸载' 577 | _info "已经完成卸载" 578 | ;; 579 | 4) 580 | _systemctl "start" "xray" 581 | ;; 582 | 5) 583 | _systemctl "stop" "xray" 584 | ;; 585 | 6) 586 | _systemctl "restart" "xray" 587 | ;; 588 | 101) 589 | show_config 590 | ;; 591 | 102) 592 | [[ -f /usr/local/etc/xray-script/traffic.sh ]] || wget -O /usr/local/etc/xray-script/traffic.sh https://raw.githubusercontent.com/zxcvos/Xray-script/main/tool/traffic.sh 593 | bash /usr/local/etc/xray-script/traffic.sh 594 | ;; 595 | 103) 596 | read_uuid 597 | _info "正在修改用户 id" 598 | "${xray_config_manage}" -u ${in_uuid} 599 | _info "已成功修改用户 id" 600 | _systemctl "restart" "xray" 601 | show_config 602 | ;; 603 | 104) 604 | _info "正在修改 dest(target) 与 serverNames" 605 | select_dest 606 | local current_xray_version=$(xray version | awk '$1=="Xray" {print $2}') 607 | local dest2target_xray_version='24.10.31' 608 | if _version_ge "${current_xray_version}" "${dest2target_xray_version}"; then 609 | "${xray_config_manage}" -d "$(jq -r '.xray.target' /usr/local/etc/xray-script/config.json | grep -Eoi '([a-zA-Z0-9](\-?[a-zA-Z0-9])*\.)+[a-zA-Z]{2,}')" 610 | "${xray_config_manage}" -sn "$(jq -c -r '.xray | .serverNames[.target] | .[]' /usr/local/etc/xray-script/config.json | tr '\n' ',')" 611 | else 612 | "${xray_config_manage}" -d "$(jq -r '.xray.dest' /usr/local/etc/xray-script/config.json | grep -Eoi '([a-zA-Z0-9](\-?[a-zA-Z0-9])*\.)+[a-zA-Z]{2,}')" 613 | "${xray_config_manage}" -sn "$(jq -c -r '.xray | .serverNames[.dest] | .[]' /usr/local/etc/xray-script/config.json | tr '\n' ',')" 614 | fi 615 | _info "已成功修改 dest(target) 与 serverNames" 616 | _systemctl "restart" "xray" 617 | show_config 618 | ;; 619 | 105) 620 | _info "正在修改 x25519 key" 621 | local xray_x25519=$(xray x25519) 622 | local xs_private_key=$(echo ${xray_x25519} | awk '{print $3}') 623 | local xs_public_key=$(echo ${xray_x25519} | awk '{print $6}') 624 | # Xray-script config.json 625 | jq --arg privateKey "${xs_private_key}" '.xray.privateKey = $privateKey' /usr/local/etc/xray-script/config.json >/usr/local/etc/xray-script/new.json && mv -f /usr/local/etc/xray-script/new.json /usr/local/etc/xray-script/config.json 626 | jq --arg publicKey "${xs_public_key}" '.xray.publicKey = $publicKey' /usr/local/etc/xray-script/config.json >/usr/local/etc/xray-script/new.json && mv -f /usr/local/etc/xray-script/new.json /usr/local/etc/xray-script/config.json 627 | # Xray-core config.json 628 | "${xray_config_manage}" -x "${xs_private_key}" 629 | _info "已成功修改 x25519 key" 630 | _systemctl "restart" "xray" 631 | show_config 632 | ;; 633 | 106) 634 | _info "shortId 值定义: 接受一个十六进制数值 ,长度为 2 的倍数,长度上限为 16" 635 | _info "shortId 列表默认为值为[\"\"],若有此项,客户端 shortId 可为空" 636 | read -p "请输入自定义 shortIds 值,多个值以英文逗号进行分隔: " sid_str 637 | _info "正在修改 shortIds" 638 | "${xray_config_manage}" -sid "${sid_str}" 639 | _info "已成功修改 shortIds" 640 | _systemctl "restart" "xray" 641 | show_config 642 | ;; 643 | 107) 644 | local xs_port=$(jq '.inbounds[] | select(.tag == "xray-script-xtls-reality") | .port' /usr/local/etc/xray/config.json) 645 | read_port "当前 xray 监听端口为: ${xs_port}" "${xs_port}" 646 | if [[ "${new_port}" && ${new_port} -ne ${xs_port} ]]; then 647 | "${xray_config_manage}" -p ${new_port} 648 | _info "当前 xray 监听端口已修改为: ${new_port}" 649 | _systemctl "restart" "xray" 650 | show_config 651 | fi 652 | ;; 653 | 108) 654 | _info "正在修改 shortIds" 655 | "${xray_config_manage}" -rsid 656 | _info "已成功修改 shortIds" 657 | _systemctl "restart" "xray" 658 | show_config 659 | ;; 660 | 109) 661 | until [ ${#sid_str} -gt 0 ] && [ ${#sid_str} -le 16 ] && [ $((${#sid_str} % 2)) -eq 0 ]; do 662 | _info "shortId 值定义: 接受一个十六进制数值 ,长度为 2 的倍数,长度上限为 16" 663 | read -p "请输入自定义 shortIds 值,不能为空,多个值以英文逗号进行分隔: " sid_str 664 | done 665 | _info "正在添加自定义 shortIds" 666 | "${xray_config_manage}" -asid "${sid_str}" 667 | _info "已成功添加自定义 shortIds" 668 | _systemctl "restart" "xray" 669 | show_config 670 | ;; 671 | 110) 672 | if ! _exists "docker"; then 673 | read -r -p "脚本使用 Docker 进行 WARP 管理,是否安装 Docker [y/n] " is_docker 674 | if [[ ${is_docker} =~ ^[Yy]$ ]]; then 675 | curl -fsSL -o /usr/local/etc/xray-script/install-docker.sh https://get.docker.com 676 | if [[ "$(_os)" == "centos" && "$(_os_ver)" -eq 8 ]]; then 677 | sed -i 's|$sh_c "$pkg_manager install -y -q $pkgs"| $sh_c "$pkg_manager install -y -q $pkgs --allowerasing"|' /usr/local/etc/xray-script/install-docker.sh 678 | fi 679 | sh /usr/local/etc/xray-script/install-docker.sh --dry-run 680 | sh /usr/local/etc/xray-script/install-docker.sh 681 | else 682 | _warn "取消分流操作" 683 | exit 0 684 | fi 685 | fi 686 | if docker ps | grep -q cloudflare-warp; then 687 | _info "WARP 已开启,请勿重复设置" 688 | else 689 | _info "正在获取并启动 cloudflare-warp 镜像" 690 | docker run -v $HOME/.warp:/var/lib/cloudflare-warp:rw --restart=always --name=cloudflare-warp e7h4n/cloudflare-warp 691 | _info "正在配置 routing" 692 | local routing='{"type":"field","domain":["domain:ipinfo.io","domain:ip.sb","geosite:openai"],"outboundTag":"warp"}' 693 | _info "正在配置 outbounds" 694 | local outbound=$(echo '{"tag":"warp","protocol":"socks","settings":{"servers":[{"address":"172.17.0.2","port":40001}]}}' | jq -c --arg addr "$(docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' cloudflare-warp)" '.settings.servers[].address = $addr') 695 | jq --argjson routing "${routing}" '.routing.rules += [$routing]' /usr/local/etc/xray/config.json >/usr/local/etc/xray-script/new.json && mv -f /usr/local/etc/xray-script/new.json /usr/local/etc/xray/config.json 696 | jq --argjson outbound "${outbound}" '.outbounds += [$outbound]' /usr/local/etc/xray/config.json >/usr/local/etc/xray-script/new.json && mv -f /usr/local/etc/xray-script/new.json /usr/local/etc/xray/config.json 697 | _systemctl "restart" "xray" 698 | show_config 699 | fi 700 | ;; 701 | 201) 702 | bash <(wget -qO- https://raw.githubusercontent.com/zxcvos/system-automation-scripts/main/update-kernel.sh) 703 | ;; 704 | 202) 705 | bash <(wget -qO- https://raw.githubusercontent.com/zxcvos/system-automation-scripts/main/remove-kernel.sh) 706 | ;; 707 | 203) 708 | local ssh_port=$(sed -En "s/^[#pP].*ort\s*([0-9]*)$/\1/p" /etc/ssh/sshd_config) 709 | read_port "当前 ssh 连接端口为: ${ssh_port}" "${ssh_port}" 710 | if [[ "${new_port}" && ${new_port} -ne ${ssh_port} ]]; then 711 | sed -i "s/^[#pP].*ort\s*[0-9]*$/Port ${new_port}/" /etc/ssh/sshd_config 712 | systemctl restart sshd 713 | _info "当前 ssh 连接端口已修改为: ${new_port}" 714 | fi 715 | ;; 716 | 204) 717 | read -r -p "是否选择网络连接优化 [y/n] " is_opt 718 | if [[ ${is_opt} =~ ^[Yy]$ ]]; then 719 | [[ -f /usr/local/etc/xray-script/sysctl.conf.bak ]] || cp -af /etc/sysctl.conf /usr/local/etc/xray-script/sysctl.conf.bak 720 | wget -O /etc/sysctl.conf https://raw.githubusercontent.com/zxcvos/Xray-script/main/config/sysctl.conf 721 | sysctl -p 722 | fi 723 | ;; 724 | 0) 725 | exit 0 726 | ;; 727 | *) 728 | _error "请输入正确的选项值" 729 | ;; 730 | esac 731 | } 732 | 733 | [[ $EUID -ne 0 ]] && _error "This script must be run as root" 734 | 735 | menu 736 | -------------------------------------------------------------------------------- /service/xray.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Xray Service 3 | Documentation=https://github.com/xtls 4 | After=network.target nss-lookup.target 5 | 6 | [Service] 7 | User=root 8 | #CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE 9 | #AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE 10 | #NoNewPrivileges=true 11 | ExecStart=/usr/local/bin/xray run -config /usr/local/etc/xray/config.json 12 | Restart=on-failure 13 | RestartPreventExitStatus=23 14 | LimitNPROC=10000 15 | LimitNOFILE=1048576 16 | 17 | [Install] 18 | WantedBy=multi-user.target 19 | -------------------------------------------------------------------------------- /ssl.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # System Required: CentOS 7+, Debian 10+, Ubuntu 20+ 4 | # Description: Script to SSL manage 5 | # 6 | # Copyright (C) 2025 zxcvos 7 | # 8 | # optimized by AI(Qwen2.5-Max-QwQ) 9 | # 10 | # acme.sh: https://github.com/acmesh-official/acme.sh 11 | 12 | # 颜色定义 13 | readonly RED='\033[1;31;31m' 14 | readonly GREEN='\033[1;31;32m' 15 | readonly YELLOW='\033[1;31;33m' 16 | readonly NC='\033[0m' 17 | 18 | # 可选参数正则表达式 19 | readonly OP_REGEX='(^--(help|update|purge|issue|(stop-)?renew|check-cron|info|www|domain|email|nginx|webroot|tls)$)|(^-[upirscdenwt]$)' 20 | 21 | # 用户操作 22 | declare action='' 23 | 24 | # 可选值 25 | declare -a domains=() 26 | declare account_email='' 27 | declare nginx_config_path='' 28 | declare acme_webroot_path='' 29 | declare ssl_cert_path='' 30 | 31 | # 状态打印函数 32 | function print_info() { 33 | printf "${GREEN}[信息] ${NC}%s\n" "$*" 34 | } 35 | 36 | function print_warn() { 37 | printf "${YELLOW}[警告] ${NC}%s\n" "$*" 38 | } 39 | 40 | function print_error() { 41 | printf "${RED}[错误] ${NC}%s\n" "$*" 42 | exit 1 43 | } 44 | 45 | # 安装 acme.sh 46 | function install_acme_sh() { 47 | [[ -e "${HOME}/.acme.sh/acme.sh" ]] && exit 0 48 | print_info "正在安装 acme.sh..." 49 | curl https://get.acme.sh | sh -s email=${account_email} || print_error "acme.sh 安装失败。" 50 | "${HOME}/.acme.sh/acme.sh" --upgrade --auto-upgrade || print_error "acme.sh 自动升级设置失败。" 51 | "${HOME}/.acme.sh/acme.sh" --set-default-ca --server zerossl || print_error "设置默认 CA 失败。" 52 | } 53 | 54 | # 更新 acme.sh 55 | function update_acme_sh() { 56 | print_info "正在更新 acme.sh..." 57 | "${HOME}/.acme.sh/acme.sh" --upgrade || print_error "acme.sh 更新失败。" 58 | } 59 | 60 | # 卸载 acme.sh 61 | function purge_acme_sh() { 62 | print_info "正在卸载 acme.sh..." 63 | "${HOME}/.acme.sh/acme.sh" --upgrade --auto-upgrade 0 || print_error "禁用 acme.sh 自动升级失败。" 64 | "${HOME}/.acme.sh/acme.sh" --uninstall || print_error "acme.sh 卸载失败。" 65 | rm -rf "${HOME}/.acme.sh" "${acme_webroot_path}" "${nginx_config_path}/certs" 66 | } 67 | 68 | # 签发证书 69 | function issue_certificate() { 70 | print_info "正在签发 SSL 证书..." 71 | 72 | # 创建必要的目录 73 | [[ -d "${acme_webroot_path}" ]] || mkdir -vp "${acme_webroot_path}" || print_error "无法创建 ACME 验证目录: ${acme_webroot_path}" 74 | [[ -d "${ssl_cert_path}" ]] || mkdir -vp "${ssl_cert_path}" || print_error "无法创建 SSL 证书目录: ${ssl_cert_path}" 75 | 76 | # 备份原始配置 77 | mv -f /usr/local/nginx/conf/nginx.conf /usr/local/nginx/conf/nginx.conf.bak 78 | 79 | # 创建申请证书专用配置 80 | cat >/usr/local/nginx/conf/nginx.conf <>>"); 16 | printf "%s:%s->%s\t", p[1],p[2],p[4]; 17 | } 18 | else if (match($1, /"value":/) && f){ 19 | f = 0; 20 | gsub(/"/, "", $2); 21 | printf "%.0f\n", $2; 22 | } 23 | else if (match($0, /}/) && f) { f = 0; print 0; } 24 | }' 25 | } 26 | 27 | print_sum() { 28 | local DATA="$1" 29 | local PREFIX="$2" 30 | local SORTED=$(echo "$DATA" | grep "^${PREFIX}" | sort -r) 31 | local SUM=$(echo "$SORTED" | awk ' 32 | /->up/{us+=$2} 33 | /->down/{ds+=$2} 34 | END{ 35 | printf "SUM->up:\t%.0f\nSUM->down:\t%.0f\nSUM->TOTAL:\t%.0f\n", us, ds, us+ds; 36 | }') 37 | echo -e "${SORTED}\n${SUM}" \ 38 | | numfmt --field=2 --suffix=B --to=iec \ 39 | | column -t 40 | } 41 | 42 | DATA=$(apidata $1) 43 | echo "------------Inbound----------" 44 | print_sum "$DATA" "inbound" 45 | echo "-----------------------------" 46 | echo "------------Outbound----------" 47 | print_sum "$DATA" "outbound" 48 | echo "-----------------------------" 49 | echo 50 | echo "-------------User------------" 51 | print_sum "$DATA" "user" 52 | echo "-----------------------------" 53 | -------------------------------------------------------------------------------- /tool/update-dat.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | XRAY_DIR="/usr/local/share/xray" 6 | 7 | GEOIP_URL="https://github.com/Loyalsoldier/v2ray-rules-dat/raw/release/geoip.dat" 8 | GEOSITE_URL="https://github.com/Loyalsoldier/v2ray-rules-dat/raw/release/geosite.dat" 9 | 10 | [ -d $XRAY_DIR ] || mkdir -p $XRAY_DIR 11 | cd $XRAY_DIR 12 | 13 | curl -L -o geoip.dat.new $GEOIP_URL 14 | if [ $? -ne 0 ]; then 15 | rm -f geoip.dat.new 16 | exit 1 17 | fi 18 | 19 | curl -L -o geosite.dat.new $GEOSITE_URL 20 | if [ $? -ne 0 ]; then 21 | rm -f geoip.dat.new geosite.dat.new 22 | exit 1 23 | fi 24 | 25 | rm -f geoip.dat geosite.dat 26 | 27 | mv geoip.dat.new geoip.dat 28 | mv geosite.dat.new geosite.dat 29 | 30 | systemctl -q is-active xray && systemctl restart xray 31 | -------------------------------------------------------------------------------- /tool/xray_config_manage.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # This script is used to manage xray configuration 4 | # 5 | # Usage: 6 | # ./xray_config_manage.sh [--path PATH] [--download|--reset] [-t TAG] [-l [LISTEN]] [-p [PORT]] [-e EMAIL] [-prcl [PROTOCOL]] [-u [UUID]] [-n [NETWORK]] [-d DEST] [-sn SERVERNAMES] [-asn SERVERNAMES] [-x PRIVATE KEY] [-sid [SHORTIDS]] [-rsid] [-asid SHORTIDS] 7 | # 8 | # Options: 9 | # -h, --help Display help message. 10 | # --path Xray config full path, default: /usr/local/etc/xray/config.json 11 | # --download, --reset Download xray config template 12 | # -t, --tag The inbounds match tag. default: xray-script-xtls-reality 13 | # -l, --listen Set listen, default: 0.0.0.0 14 | # -p, --port Set port, default: 443 15 | # -prcl, --protocol Set protocol, 1: vless, default: 1 (Protocol supports only vless) 16 | # -e, --email Clients match email, default: vless@xtls.reality 17 | # -u, --uuid Reset UUID, default: random UUID 18 | # -n, --network Pick network, 1: tcp, 2: h2, 3: grpc, default: 1 19 | # tcp -> flow: "xtls-rprx-vision", h2 or grpc -> flow: "", grpc -> random serviceName 20 | # -d, --dest Set dest 21 | # -sn, --server-names Set server names, e.g. xxx.com,www.xxx.com 22 | # -asn, --append-server-names Append server names, e.g. xxx.com,www.xxx.com 23 | # --not-validate Do not validate serverNames 24 | # -x, --x25519 Set x25519 25 | # -sid, --shortIds Set shortIds, e.g. -sid ; -sid 402a ; -sid fd,81d5,,2d5ac952d7a7 26 | # -rsid, --reset-shortIds Reset shortIds 27 | # -asid, --append-shortIds Append shortIds, e.g. -asid 402a ; -asid fd,81d5,,2d5ac952d7a7 28 | # 29 | # Explanation: 30 | # - All parameters, except for "tag" itself, should be used with the "tag" parameter. The "tag" parameter is used to find the inbound object in the inbounds array that contains the corresponding "tag". If the -t/--tag parameter is not used, the default value is "xray-script-xtls-reality". 31 | # - After finding the inbound element corresponding to the "tag", use the "email" parameter to find the client object in the clients array that contains the corresponding "email". If the -e/--email parameter is not used, the default value is "vless@xtls.reality". 32 | # 33 | # Examples: 34 | # ./xray_config_manage.sh -t xray-script-xtls-reality -e vless@xtls.reality -l 0.0.0.0 -p 443 -prcl vless -n 1 -d dest -sn servernames -u -x 2KZ4uouMKgI8nR-LDJNP1_MHisCJOmKGj9jUjZLncVU -sid 35 | # ./xray_config_manage.sh --tag xray-script-xtls-reality --email vless@xtls.reality --listen 0.0.0.0 --port 443 --protocol vless --network 1 --dest dest --server-names servernames --uuid --x25519 2KZ4uouMKgI8nR-LDJNP1_MHisCJOmKGj9jUjZLncVU --short-ids 36 | # 37 | # Dependencies: [xray jq openssl] 38 | # 39 | # Disclaimer: This document was generated by ChatGPT and has been modified by the author before publication. 40 | # 41 | # Author: zxcvos 42 | # Version: 0.1 43 | # Date: 2023-03-21 44 | 45 | PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/snap/bin 46 | export PATH 47 | 48 | readonly op_regex='^(^--(help|path|download|reset|tag|listen|port|protocol|email|uuid|network|dest|(append-)?server-names|not-validate|x25519|((reset|append)-)?shortIds)$)|(^-(prcl|a?sn|(r|a)?sid|[htpeundxl])$)$' 49 | readonly proto_list=('vless') 50 | 51 | function _version_ge() { 52 | test "$(echo "$@" | tr ' ' '\n' | sort -rV | head -n 1)" == "$1" 53 | } 54 | 55 | declare current_xray_version=$(xray version | awk '$1=="Xray" {print $2}') 56 | declare tcp2raw_xray_version='24.9.30' 57 | if _version_ge "${current_xray_version}" "${tcp2raw_xray_version}"; then 58 | network_list=('raw' 'h2' 'grpc') 59 | else 60 | network_list=('tcp' 'h2' 'grpc') 61 | fi 62 | 63 | declare configPath='/usr/local/etc/xray/config.json' 64 | declare isDownload=0 65 | declare matchTag='xray-script-xtls-reality' 66 | declare isSetListen=0 67 | declare setListen='' 68 | declare isSetPort=0 69 | declare setPort=0 70 | declare isSetProto=0 71 | declare setProto=0 72 | declare matchEmail='vless@xtls.reality' 73 | declare isResetUUID=0 74 | declare resetUUID='' 75 | declare isPickNetwork=0 76 | declare pickNetwork=0 77 | declare setDest='' 78 | declare setServerNames='' 79 | declare appendServerNames='' 80 | declare isNotValidate=0 81 | declare x25519PrivateKey='' 82 | declare isResetShortIds=0 83 | declare isSetShortIds=0 84 | declare setShortIds='' 85 | declare appendShortIds='' 86 | 87 | if [ $# -eq 0 ]; then 88 | set -- '-h' 89 | fi 90 | 91 | while [[ $# -ge 1 ]]; do 92 | case "${1}" in 93 | --path) 94 | shift 95 | (printf "%s" "${1}" | grep -Eq "${op_regex}" || [ -z "$1" ]) && echo 'Error: path not provided' && exit 1 96 | configPath="$1" 97 | shift 98 | ;; 99 | --download | --reset) 100 | shift 101 | isDownload=1 102 | ;; 103 | -t | --tag) 104 | shift 105 | (printf "%s" "${1}" | grep -Eq "${op_regex}" || [ -z "$1" ]) && echo 'Error: tag not provided' && exit 1 106 | matchTag="$1" 107 | shift 108 | ;; 109 | -l | --listen) 110 | shift 111 | isSetListen=1 112 | if printf "%s" "${1}" | grep -Evq "${op_regex}"; then 113 | setListen="$1" 114 | shift 115 | fi 116 | ;; 117 | -p | --port) 118 | shift 119 | isSetPort=1 120 | if printf "%s" "${1}" | grep -Evq "${op_regex}"; then 121 | setPort="$1" 122 | shift 123 | fi 124 | ;; 125 | -prcl | --protocol) 126 | shift 127 | isSetProto=1 128 | if printf "%s" "${1}" | grep -Evq "${op_regex}"; then 129 | ([ "$1" -lt 1 ] || [ "$1" -gt ${#proto_list[@]} ]) && echo "Error: -prcl|--protocol [1-${#proto_list[@]}]" && exit 1 130 | setProto="$1" 131 | shift 132 | fi 133 | ;; 134 | -e | --email) 135 | shift 136 | (printf "%s" "${1}" | grep -Eq "${op_regex}" || [ -z "$1" ]) && echo 'Error: email not provided' && exit 1 137 | matchEmail="$1" 138 | shift 139 | ;; 140 | -u | --uuid) 141 | shift 142 | isResetUUID=1 143 | if printf "%s" "${1}" | grep -Evq "${op_regex}"; then 144 | resetUUID="$1" 145 | shift 146 | fi 147 | ;; 148 | -n | --network) 149 | shift 150 | isPickNetwork=1 151 | if printf "%s" "${1}" | grep -Evq "${op_regex}"; then 152 | ([ "$1" -lt 1 ] || [ "$1" -gt ${#network_list[@]} ]) && echo "Error: -n|--network [1-${#network_list[@]}]" && exit 1 153 | pickNetwork="$1" 154 | shift 155 | fi 156 | ;; 157 | -d | --dest) 158 | shift 159 | (printf "%s" "${1}" | grep -Eq "${op_regex}" || [ -z "$1" ]) && echo 'Error: dest not provided' && exit 1 160 | setDest="$1" 161 | shift 162 | ;; 163 | -sn | --server-names) 164 | shift 165 | (printf "%s" "${1}" | grep -Eq "${op_regex}" || [ -z "$1" ]) && echo 'Error: server names not provided' && exit 1 166 | setServerNames="$1" 167 | shift 168 | ;; 169 | -asn | --append-server-names) 170 | shift 171 | (printf "%s" "${1}" | grep -Eq "${op_regex}" || [ -z "$1" ]) && echo 'Error: server names not provided' && exit 1 172 | appendServerNames="$1" 173 | shift 174 | ;; 175 | --not-validate) 176 | shift 177 | isNotValidate=1 178 | ;; 179 | -x | --x25519) 180 | shift 181 | (printf "%s" "${1}" | grep -Eq "${op_regex}" || [ -z "$1" ]) && echo 'Error: x25519 private key not provided' && exit 1 182 | x25519PrivateKey="$1" 183 | shift 184 | ;; 185 | -sid | --shortIds) 186 | shift 187 | isSetShortIds=1 188 | if printf "%s" "${1}" | grep -Evq "${op_regex}"; then 189 | setShortIds="$1" 190 | shift 191 | fi 192 | ;; 193 | -rsid | --reset-shortIds) 194 | shift 195 | isResetShortIds=1 196 | ;; 197 | -asid | --append-shortIds) 198 | shift 199 | (printf "%s" "${1}" | grep -Eq "${op_regex}" || [ -z "$1" ]) && echo 'Error: shortIds not provided' && exit 1 200 | appendShortIds="$1" 201 | shift 202 | ;; 203 | -h | --help) 204 | echo 205 | echo "$0 - A script to xray config manage." 206 | echo 207 | awk '/^# Usage:/,/^# Disclaimer:/ {if (/^# Disclaimer:/) exit;gsub(/^#\s?/,"");print $0}' "$0" 208 | exit 0 209 | ;; 210 | *) 211 | echo -ne "\nInvalid option: '$1'.\n" 212 | shift $# 213 | set -- '-h' 214 | ;; 215 | esac 216 | done 217 | 218 | function _exists() { 219 | local cmd="$1" 220 | if eval type type >/dev/null 2>&1; then 221 | eval type "$cmd" >/dev/null 2>&1 222 | elif command >/dev/null 2>&1; then 223 | command -v "$cmd" >/dev/null 2>&1 224 | else 225 | which "$cmd" >/dev/null 2>&1 226 | fi 227 | local rt=$? 228 | return ${rt} 229 | } 230 | 231 | function is_digit() { 232 | local input=${1} 233 | if [[ "${input}" =~ ^[0-9]+$ ]]; then 234 | return 0 235 | else 236 | return 1 237 | fi 238 | } 239 | 240 | function is_port() { 241 | local input=${1} 242 | local port_regex='^((6553[0-5])|(655[0-2][0-9])|(65[0-4][0-9]{2})|(6[0-4][0-9]{3})|([1-5][0-9]{4})|([0-5]{0,5})|([0-9]{1,4}))$' 243 | if [[ "${input}" =~ ${port_regex} ]]; then 244 | return 0 245 | else 246 | return 1 247 | fi 248 | } 249 | 250 | function is_valid_IPv4_address() { 251 | local ip_regex='^((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}$' 252 | local IPv4="${1}" 253 | local fields=() 254 | if [[ ! "${IPv4}" =~ ${ip_regex} ]]; then 255 | return 1 256 | fi 257 | fields=($(awk -v FS='.' '{for (i = 1; i<=NF; i++) arr[i] = $i} END{for (i in arr) print arr[i]}' <<<"${IPv4}")) 258 | for field in "${fields[@]}"; do 259 | if ((field > 255)); then 260 | return 1 261 | fi 262 | done 263 | if ((${#fields[@]} != 4)); then 264 | return 1 265 | fi 266 | return 0 267 | } 268 | 269 | function is_valid_IPv6_address() { 270 | local ip_regex='^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$' 271 | local IPv6="${1}" 272 | if [[ "${IPv6}" =~ ${ip_regex} ]]; then 273 | return 0 274 | else 275 | return 1 276 | fi 277 | } 278 | 279 | function is_UDS() { 280 | local input="${1}" 281 | if echo "${input}" | grep -Eq "^(\/[a-zA-Z0-9\_\-\+\.]+)*\/[a-zA-Z0-9\_\-\+]+\.sock$" || echo "${input}" | grep -Eq "^@{1,2}[a-zA-Z0-9\_\-\+\.]+$"; then 282 | return 0 283 | else 284 | return 1 285 | fi 286 | } 287 | 288 | function is_config_path() { 289 | local input="${1}" 290 | if echo "${input}" | grep -Eq "^(\/[a-zA-Z0-9\_\-\+\.]+)*\/[a-zA-Z0-9\_\-\+]+\.json$"; then 291 | return 0 292 | else 293 | return 1 294 | fi 295 | } 296 | 297 | function is_domain() { 298 | local input="${1}" 299 | local domain_regex='^((https?:\/\/)?([a-zA-Z0-9](\-?[a-zA-Z0-9])*\.)+[a-zA-Z]{2,}(:((6553[0-5])|(655[0-2][0-9])|(65[0-4][0-9]{2})|(6[0-4][0-9]{3})|([1-5][0-9]{4})|([0-5]{0,5})|([0-9]{1,4})))?)$' 300 | if [[ "${input}" =~ ${domain_regex} ]]; then 301 | return 0 302 | else 303 | return 1 304 | fi 305 | } 306 | 307 | function is_valid_uuid() { 308 | local input="${1}" 309 | if printf "%s" ${input} | grep -Eq '^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$'; then 310 | return 0 311 | else 312 | return 1 313 | fi 314 | } 315 | 316 | function set_listen() { 317 | local in_tag="${1}" 318 | local in_listen="${2}" 319 | [ -z "${in_listen}" ] && in_listen='0.0.0.0' 320 | if is_valid_IPv4_address "${in_listen}" || is_valid_IPv6_address "${in_listen}" || is_UDS "${in_listen}"; then 321 | jq --arg in_tag "${in_tag}" --arg in_listen "${in_listen}" '.inbounds |= map(if .tag == $in_tag then .listen = $in_listen else . end)' "${configPath}" >"${HOME}"/new.json && mv -f "${HOME}"/new.json "${configPath}" 322 | else 323 | echo "Invalid IPv4 address format: ${in_listen}" 324 | echo "Invalid IPv6 address format: ${in_listen}" 325 | echo "Invalid UDS file path or abstract socket format: ${in_listen}" 326 | exit 1 327 | fi 328 | } 329 | 330 | function set_port() { 331 | local in_tag="${1}" 332 | local in_port="${2}" 333 | [ ${in_port} -eq 0 ] && in_port=443 334 | if is_port "${in_port}"; then 335 | jq --arg in_tag "${in_tag}" --argjson in_port ${in_port} '.inbounds |= map(if .tag == $in_tag then .port = $in_port else . end)' "${configPath}" >"${HOME}"/new.json && mv -f "${HOME}"/new.json "${configPath}" 336 | else 337 | echo "Error: Please enter a valid port number between 1-65535" 338 | exit 1 339 | fi 340 | } 341 | 342 | function select_proto() { 343 | local in_tag="${1}" 344 | local pick="${2}" 345 | local in_proto='' 346 | [ ${pick} -eq 0 ] && pick=1 347 | if is_digit "${pick}" && [ ${pick} -ge 1 ] && [ "${pick}" -le ${#proto_list[@]} ]; then 348 | in_proto="${proto_list[$((${pick} - 1))]}" 349 | jq --arg in_tag "${in_tag}" --arg in_proto "${in_proto}" '.inbounds |= map(if .tag == $in_tag then .protocol = $in_proto else . end)' "${configPath}" >"${HOME}"/new.json && mv -f "${HOME}"/new.json "${configPath}" 350 | else 351 | echo "Error: Please enter a valid protocol list index between 1-${#proto_list[@]}" 352 | exit 1 353 | fi 354 | } 355 | 356 | function reset_uuid() { 357 | local in_tag="${1}" 358 | local c_email="${2}" 359 | local c_id="${3}" 360 | if [ -z "${c_id}" ]; then 361 | c_id=$(xray uuid) 362 | elif ! is_valid_uuid "${c_id}"; then 363 | c_id=$(xray uuid -i "${c_id}") 364 | fi 365 | jq --arg in_tag "${in_tag}" --arg c_email "${c_email}" --arg c_id "${c_id}" '.inbounds |= map(if .tag == $in_tag then .settings.clients |= map(if .email == $c_email then .id = $c_id else . end) else . end)' "${configPath}" >"${HOME}"/new.json && mv -f "${HOME}"/new.json "${configPath}" 366 | } 367 | 368 | function select_network() { 369 | local in_tag="${1}" 370 | local pick="${2}" 371 | local in_network='' 372 | [ ${pick} -eq 0 ] && pick=1 373 | if is_digit "${pick}" && [ ${pick} -ge 1 ] && [ "${pick}" -le ${#network_list[@]} ]; then 374 | in_network="${network_list[$((${pick} - 1))]}" 375 | jq --arg in_tag "${in_tag}" '.inbounds |= map(if .tag == $in_tag then del(.streamSettings.grpcSettings) else . end)' "${configPath}" >"${HOME}"/new.json && mv -f "${HOME}"/new.json "${configPath}" 376 | jq --arg in_tag "${in_tag}" '.inbounds |= map(if .tag == $in_tag then .settings.clients |= map(.flow = "") else . end)' "${configPath}" >"${HOME}"/new.json && mv -f "${HOME}"/new.json "${configPath}" 377 | jq --arg in_tag "${in_tag}" --arg in_network "${in_network}" '.inbounds |= map(if .tag == $in_tag then .streamSettings.network = $in_network else . end)' "${configPath}" >"${HOME}"/new.json && mv -f "${HOME}"/new.json "${configPath}" 378 | case "${in_network}" in 379 | tcp) 380 | jq --arg in_tag "${in_tag}" '.inbounds |= map(if .tag == $in_tag then .settings.clients |= map(.flow = "xtls-rprx-vision") else . end)' "${configPath}" >"${HOME}"/new.json && mv -f "${HOME}"/new.json "${configPath}" 381 | ;; 382 | grpc) 383 | jq --arg in_tag "${in_tag}" --arg serviceName "$(head -c 32 /dev/urandom | md5sum | head -c 8)" '.inbounds |= map(if .tag == $in_tag then .streamSettings.grpcSettings |= {"serviceName": $serviceName} else . end)' "${configPath}" >"${HOME}"/new.json && mv -f "${HOME}"/new.json "${configPath}" 384 | ;; 385 | esac 386 | else 387 | echo "Error: Please enter a valid network list index between 1-${#network_list[@]}" 388 | exit 1 389 | fi 390 | } 391 | 392 | function set_dest() { 393 | local in_tag="${1}" 394 | local dest="${2}" 395 | local dest2target_xray_version='24.10.31' 396 | if is_UDS "${dest}" || is_domain "${dest}"; then 397 | dest="${dest#*//}" 398 | if ! is_UDS "${dest}" && [ "${dest}" == "${dest%:*}" ]; then 399 | dest="${dest}:443" 400 | fi 401 | if _version_ge "${current_xray_version}" "${dest2target_xray_version}"; then 402 | jq --arg in_tag "${in_tag}" --arg dest "${dest}" '.inbounds |= map(if .tag == $in_tag then .streamSettings.realitySettings.target = $dest else . end)' "${configPath}" >"${HOME}"/new.json && mv -f "${HOME}"/new.json "${configPath}" 403 | else 404 | jq --arg in_tag "${in_tag}" --arg dest "${dest}" '.inbounds |= map(if .tag == $in_tag then .streamSettings.realitySettings.dest = $dest else . end)' "${configPath}" >"${HOME}"/new.json && mv -f "${HOME}"/new.json "${configPath}" 405 | fi 406 | else 407 | echo "Error: Please enter a valid domain name or socket path" 408 | exit 1 409 | fi 410 | } 411 | 412 | function set_server_names() { 413 | local in_tag="${1}" 414 | local sns_str="${2}" 415 | local is_append="${3}" 416 | local sns_list='' 417 | for domain in $(printf '%s' "${sns_str}" | jq -R -s -c -r 'split(",") | map(select(length > 0)) | .[]'); do 418 | if [[ ${isNotValidate} -eq 1 ]]; then 419 | sns_list+="${domain}," 420 | else 421 | xray tls ping ${domain} >/dev/null 2>&1 && sns_list+="${domain}," 422 | fi 423 | done 424 | sns_list=$(printf '%s' "${sns_list}" | jq -R -s -c 'split(",") | map(select(length > 0))') 425 | if [ ${sns_list} != '[]' ]; then 426 | [ ${is_append} -eq 0 ] && jq --arg in_tag "${in_tag}" '.inbounds |= map(if .tag == $in_tag then .streamSettings.realitySettings.serverNames = [] else . end)' "${configPath}" >"${HOME}"/new.json && mv -f "${HOME}"/new.json "${configPath}" 427 | jq --arg in_tag "${in_tag}" --argjson sns "${sns_list}" '.inbounds |= map(if .tag == $in_tag then .streamSettings.realitySettings.serverNames += $sns else . end)' "${configPath}" >"${HOME}"/new.json && mv -f "${HOME}"/new.json "${configPath}" 428 | [ ${is_append} -eq 1 ] && jq --arg in_tag "${in_tag}" --argjson sns "${sns_list}" '.inbounds |= map(if .tag == $in_tag then .streamSettings.realitySettings.serverNames = (.streamSettings.realitySettings.serverNames | unique) else . end)' "${configPath}" >"${HOME}"/new.json && mv -f "${HOME}"/new.json "${configPath}" 429 | else 430 | echo "Error: Please enter a valid domain name, e.g. xxx.com,www.xxx.com" 431 | exit 1 432 | fi 433 | } 434 | 435 | function reset_x25519() { 436 | local in_tag="${1}" 437 | local private_key="${2}" 438 | if [ "${private_key}" ]; then 439 | jq --arg in_tag "${in_tag}" --arg private_key "${private_key}" '.inbounds |= map(if .tag == $in_tag then .streamSettings.realitySettings.privateKey = $private_key else . end)' "${configPath}" >"${HOME}"/new.json && mv -f "${HOME}"/new.json "${configPath}" 440 | else 441 | echo 'Error: x25519 private key not provided' 442 | exit 1 443 | fi 444 | } 445 | 446 | function set_sid() { 447 | local in_tag="${1}" 448 | local is_append="${2}" 449 | local sids_str="${3}" 450 | local sids_list='' 451 | for sid in $(printf '%s' "${sids_str}" | jq -R -s -c -r 'split(",") | .[]'); do 452 | [ $((${#sid} % 2)) -eq 0 ] && [ ${#sid} -le 16 ] && sids_list+="${sid}," 453 | done 454 | sids_list=$(printf '%s' "${sids_list}" | jq -R -s -c 'split(",")') 455 | if [ ${is_append} -eq 0 ]; then 456 | jq --arg in_tag "${in_tag}" '.inbounds |= map(if .tag == $in_tag then .streamSettings.realitySettings.shortIds = [""] else . end)' "${configPath}" >"${HOME}"/new.json && mv -f "${HOME}"/new.json "${configPath}" 457 | elif [ ${sids_list} == '[]' ]; then 458 | echo "Error: Please enter a valid shortIds, e.g. 402a or fd,81d5,2d5ac952d7a7" 459 | exit 1 460 | fi 461 | jq --arg in_tag "${in_tag}" --argjson sids "${sids_list}" '.inbounds |= map(if .tag == $in_tag then .streamSettings.realitySettings.shortIds += $sids else . end)' "${configPath}" >"${HOME}"/new.json && mv -f "${HOME}"/new.json "${configPath}" 462 | jq --arg in_tag "${in_tag}" --argjson sids "${sids_list}" '.inbounds |= map(if .tag == $in_tag then .streamSettings.realitySettings.shortIds = (.streamSettings.realitySettings.shortIds | unique) else . end)' "${configPath}" >"${HOME}"/new.json && mv -f "${HOME}"/new.json "${configPath}" 463 | jq --arg in_tag "${in_tag}" --argjson sids "${sids_list}" '.inbounds |= map(if .tag == $in_tag then .streamSettings.realitySettings.shortIds = (.streamSettings.realitySettings.shortIds | sort_by(length)) else . end)' "${configPath}" >"${HOME}"/new.json && mv -f "${HOME}"/new.json "${configPath}" 464 | } 465 | 466 | function reset_sid() { 467 | local in_tag="${1}" 468 | local sids_len=0 469 | local sid_len=0 470 | local sid='' 471 | sids_len=$(jq --arg in_tag "${in_tag}" '.inbounds[] | select(.tag == $in_tag) | .streamSettings.realitySettings.shortIds | length' "${configPath}") 472 | if [ ${sids_len} -gt 0 ]; then 473 | for i in $(seq 1 ${sids_len}); do 474 | sid_len=$(jq --arg in_tag "${in_tag}" --argjson i $((i - 1)) '.inbounds[] | select(.tag == $in_tag) | .streamSettings.realitySettings.shortIds[$i] | length' "${configPath}") 475 | sid_len=$((${sid_len} / 2)) 476 | [ ${sid_len} -eq 0 ] && continue 477 | sid=$(openssl rand -hex ${sid_len}) 478 | jq --arg in_tag "${in_tag}" --arg sid "${sid}" --argjson i $((i - 1)) '.inbounds |= map(if .tag == $in_tag then .streamSettings.realitySettings.shortIds[$i] = $sid else . end)' "${configPath}" >"${HOME}"/new.json && mv -f "${HOME}"/new.json "${configPath}" 479 | done 480 | else 481 | echo 'Error: shortIds is empty' 482 | exit 1 483 | fi 484 | } 485 | 486 | if ! _exists 'jq' || ! _exists 'xray'; then 487 | echo 'Error: jq or Xray not found, please install jq and Xray first' 488 | exit 1 489 | fi 490 | 491 | if ! is_config_path "${configPath}"; then 492 | echo 'Error: Please use a full Xray configuration file path' 493 | exit 1 494 | fi 495 | 496 | if [ ${isDownload} -eq 1 ]; then 497 | wget -O "${configPath}" https://raw.githubusercontent.com/zxcvos/Xray-script/main/VLESS-XTLS-uTLS-REALITY/server.json 498 | fi 499 | 500 | if [ ${isSetListen} -eq 1 ]; then 501 | set_listen "${matchTag}" "${setListen}" 502 | fi 503 | 504 | if [ ${isSetPort} -eq 1 ]; then 505 | set_port "${matchTag}" "${setPort}" 506 | fi 507 | 508 | if [ ${isSetProto} -eq 1 ]; then 509 | select_proto "${matchTag}" "${setProto}" 510 | fi 511 | 512 | if [ ${isResetUUID} -eq 1 ]; then 513 | reset_uuid "${matchTag}" "${matchEmail}" "${resetUUID}" 514 | fi 515 | 516 | if [ ${isPickNetwork} -eq 1 ]; then 517 | select_network "${matchTag}" "${pickNetwork}" 518 | fi 519 | 520 | if [ "${setDest}" ]; then 521 | set_dest "${matchTag}" "${setDest}" 522 | fi 523 | 524 | if [ "${setServerNames}" ]; then 525 | set_server_names "${matchTag}" "${setServerNames}" 0 526 | fi 527 | 528 | if [ "${appendServerNames}" ]; then 529 | set_server_names "${matchTag}" "${appendServerNames}" 1 530 | fi 531 | 532 | if [ "${x25519PrivateKey}" ]; then 533 | reset_x25519 "${matchTag}" "${x25519PrivateKey}" 534 | fi 535 | 536 | if [ ${isSetShortIds} -eq 1 ]; then 537 | set_sid "${matchTag}" 0 "${setShortIds}" 538 | fi 539 | 540 | if [ ${isResetShortIds} -eq 1 ]; then 541 | reset_sid "${matchTag}" 542 | fi 543 | 544 | if [ "${appendShortIds}" ]; then 545 | set_sid "${matchTag}" 1 "${appendShortIds}" 546 | fi 547 | --------------------------------------------------------------------------------