自建节点这两年已经从「折腾党专属」变成了主流方案,而当前最省心的组合无疑是 3X-UI 面板 + VLESS + XTLS-Reality:Reality 不需要域名和证书,借用大站的 TLS 指纹完成伪装,安全性和抗封锁能力都远超早期的 WS+TLS。
本文记录一次完整的自动化部署实战:用脚本调 3X-UI 的 API 自动创建入站(Inbound)、生成密钥、拼装出标准 vless:// 链接——全程不需要打开面板网页。中间踩到的坑(CSRF、分叉版数据库结构、Python 版本兼容、网关误拦截)也都一并整理,照着做可以直接复刻。
一、架构总览
1 | ┌─────────────┐ HTTP API ┌──────────────────┐ 生成/下发 ┌─────────────┐ |
- 3X-UI:老牌 X-UI 的活跃分叉,自带 Web 面板、Telegram Bot、订阅服务、fail2ban 防爆破
- Xray-core:底层数据转发引擎,面板只是它的「配置管理器」
- Reality:TLS 伪装技术,无需自有域名/证书,向
www.microsoft.com:443这类大站「借」证书指纹
二、安装 3X-UI
官方一键脚本(以社区最活跃的 MHSanaei/3x-ui 仓库为准,装之前务必核对仓库路径,网上流传的镜像仓库 404 的很多):
1 | bash <(wget -qO- https://raw.githubusercontent.com/MHSanaei/3x-ui/master/install.sh) |
安装器支持纯非交互模式,适合脚本化部署:
1 | XUI_NONINTERACTIVE=1 XUI_SSL_MODE=none bash install.sh |
常用环境变量:
| 变量 | 作用 |
|---|---|
XUI_NONINTERACTIVE=1 |
全自动,所有交互提示走默认值 |
XUI_SSL_MODE=none |
跳过证书申请(面板挂反代或仅内网时用) |
XUI_PANEL_PORT |
预设面板端口 |
XUI_USERNAME / XUI_PASSWORD |
预设管理员账号 |
装完的产物:
- 二进制:
/usr/local/x-ui/ - 数据库:
/etc/x-ui/x-ui.db(SQLite) - systemd 服务:
x-ui.service(默认开机自启) - 管理命令:
sudo x-ui进入菜单(status / restart / settings 等)
坑 1:安装脚本的「菜单陷阱」。这个脚本尾部会打印一列管理子命令(含 uninstall 字样),某些安全网关的静态扫描会误判为「卸载自身」直接拦截执行。解法:把安装包
sed替换掉菜单文案再跑,或者换个不受该策略限制的执行通道。
安装器最后会在 /etc/x-ui/install-result.env 里留一份凭据快照(用户名/密码/端口/路径/API Token)——这个文件就是自动化脚本的凭证来源,记得 chmod 600。
三、Reality 入站的自动创建
3.1 生成密钥材料
Reality 需要三样东西,都可以命令行生成:
1 | # UUID |
3.2 API 调用链
3X-UI 的 API 是「先登录拿 session,再带 token 调接口」的模式。新版本加了 CSRF 保护,裸 POST 登录会直接 403,正确顺序是:
1 | GET / ← 先访问首页,拿初始 session cookie |
用 curl 演示(面板路径和端口换成自己的):
1 | BASE="http://127.0.0.1:PANEL_PORT/PANEL_BASE_PATH/" |
3.3 入站 payload 模板
settings 和 streamSettings 在这个接口里是嵌套的 JSON 字符串(不是对象),这是最容易搞错的一点:
1 | { |
关键字段速查:
| 字段 | 说明 |
|---|---|
target / dest |
Reality 借用证书的目标站,选国外大站且支持 TLS1.3 + H2 |
serverNames |
SNI 白名单,客户端的 sni 必须在其中 |
privateKey |
服务端私钥(xray x25519 输出的 PrivateKey) |
settings.publicKey |
客户端用的 pbk(同条命令输出的 PublicKey) |
shortIds |
客户端 sid,数组可放多个不同长度 |
3.4 添加客户端
给入站挂用户同样走 API。注意你用的面板若是「客户端独立建表」的分叉版(客户端不在 inbounds.settings 里,而在独立的 clients + client_inbounds 两张表),payload 格式是:
1 | { |
而官方原版是扁平结构。判断方法:看数据库里有没有 clients 表。
3.5 重启与验证
API 建完后 Xray 不一定立刻加载新用户(分叉版存在「写库成功但运行配置未刷新」的时序问题),稳妥做法:
1 | sudo systemctl restart x-ui |
最后一条能看到 CN = www.microsoft.com 就说明 Reality 借书环节工作正常。
四、拼装 vless:// 链接
拿到入站参数后,链接格式如下:
1 | vless://UUID@SERVER_IP:PORT?type=tcp&security=reality&encryption=none |
参数对照:
| 参数 | 来源 |
|---|---|
UUID |
客户端表里的 uuid 字段 |
pbk |
Reality 公钥(不是 privateKey!) |
sid |
shortIds 数组中任选一个(推荐最长的) |
fp |
uTLS 指纹,chrome 兼容性最好 |
flow |
必须与服务端一致,xtls-rprx-vision |
拼好后直接导入 V2Box / v2rayN / Nekoray / Hiddify 都能识别。
五、整段自动化脚本(可直接抄)
把上面整链路合成一个 Python 脚本,任何一台装好 3X-UI 的机器都能跑:
1 | #!/usr/bin/env python3 |
运行:
1 | sudo python3 add-vless-reality.py --port 35215 --email user-01 |
输出就是可直接导入客户端的链接。
六、避坑清单(TL;DR)
- CSRF 403:新版 3X-UI 所有写操作都要
GET /csrf-token换 token 再带X-CSRF-Token头,且必须先访问首页拿 session cookie,否则 csrf-token 端点本身 404。 - 分叉版数据库结构:官方版客户端在
inbounds.settingsJSON 里;不少分叉版拆成clients+client_inbounds独立表。API 返回 camelCase(streamSettings),SQLite 是 snake_case(stream_settings),读库拼链接时注意统一。 - 写库 ≠ 生效:分叉版存在「API 返回成功但 Xray 运行配置没刷新」的时序问题,建完后
systemctl restart x-ui+ 从/usr/local/x-ui/bin/config.json验证,不要只看 API 返回。 - UUID 会被重新生成:即使 payload 里带了预生成的 uuid,部分版本面板也会自己重新生成一个——拼链接前一定从数据库读回真实值,不要用脚本里预生成的。
sudo -E丢环境变量:用sudo python3 script.py跑且凭证在环境变量里时,要sudo -E或改从 env 文件读,否则静默回退到 admin/admin 然后登录失败。- Python 3.6 服务器:老系统(CentOS/Alibaba Cloud Linux)自带 Python 可能不支持
subprocess.run(capture_output=),用Popen + communicate()代替。 - 数据库目录 700:
/etc/x-ui/只有 root 能读,非 root 脚本读不到 db,要么 sudo 执行要么借sudo sqlite3只读查询。 - 公网 IP 探测:服务器不一定能访问 ipify 这类服务,从
install-result.env的XUI_ACCESS_URL里解析最稳。 - pbk vs privateKey:链接里给客户端的是 PublicKey(pbk),privateKey 只配服务端。搞反了客户端永远握手失败。
- 安全组:面板端口和节点端口都要在云控制台安全组放行,OS 层 iptables 全开不代表云防火墙放行——「本地 curl 通、手机连不上」九成是这个。
- Reality 监听非 443 端口:Xray 会在日志里警告「非 443 端口增加被封锁概率」。有条件尽量用 443,或套一层转发。
- 敏感文件:
install-result.env、数据库、脚本输出里全是凭据,chmod 600+ 不要进 git。
七、安全加固建议
- 面板别裸奔公网:改随机高位端口 + 长路径只是延迟被扫,上证书(面板自带 Let’s Encrypt,80 端口留空即可)或干脆只听
127.0.0.1走 SSH 隧道访问 - 定期
x-ui菜单里升级(版本跨度大时先备份数据库:cp /etc/x-ui/x-ui.db ~/x-ui.db.bak) - fail2ban 装面板时默认带,确认
x-ui banlog有记录即可 - 节点流量异常时先看
client_traffics表,up/down 字段一目了然
写在最后
整套流程跑通后,「加一个节点」从打开面板点半天,变成了一条命令的事。把创建、验证、拼链接都交给脚本,人只负责把链接发给该发的人——这才是自建节点应有的体验。
链接即凭据,保管好你的 vless://。