├── 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 |
--------------------------------------------------------------------------------