xray配置入站,个人遇到的一点小问题
Xray VLESS 入站配置:users 还是 clients?
问题
按照 Xray 官方文档 配置 VLESS 入站时,文档要求使用 users 字段:
{
"inbounds": [{
"protocol": "vless",
"settings": {
"users": [
{ "id": "5783a3e7-e373-51cd-8642-c83782b807c5" }
],
"decryption": "none"
}
}]
}
但实际运行时,客户端连接被拒绝,服务器日志报错:
rejected proxy/vless/encoding: invalid request user id
改为 clients 后一切正常。为什么文档和实际行为不一致?
本机环境
| 项目 | 值 |
|---|---|
| Xray 版本 | v26.3.27 |
| 协议 | VLESS |
| 操作系统 | Linux (WSL2) |
| 安装日期 | 2026-06-27 |
| 安装方式 | 官方安装脚本 |
实验:对照测试
实验设计
构建两个仅字段名不同的 VLESS 入站配置,用同一客户端分别连接,观察服务器日志。
步骤 1 — 准备配置文件
配置 A:使用 users 字段(官方文档写法)
{
"log": {"loglevel": "debug"},
"inbounds": [{
"listen": "127.0.0.1",
"port": 19997,
"protocol": "vless",
"settings": {
"users": [
{ "id": "test-user-uuid-00000000000000" }
],
"decryption": "none"
},
"tag": "vless-in-users"
}],
"outbounds": [{"protocol": "freedom", "tag": "direct"}]
}
配置 B:使用 clients 字段(网络教程常见写法)
{
"log": {"loglevel": "debug"},
"inbounds": [{
"listen": "127.0.0.1",
"port": 19996,
"protocol": "vless",
"settings": {
"clients": [
{ "id": "test-user-uuid-00000000000000" }
],
"decryption": "none"
},
"tag": "vless-in-clients"
}],
"outbounds": [{"protocol": "freedom", "tag": "direct"}]
}
客户端配置(出站始终使用 users——VLESS 出站未受影响)
{
"log": {"loglevel": "debug"},
"inbounds": [{
"listen": "127.0.0.1",
"port": 29998,
"protocol": "dokodemo-door",
"settings": {"address": "httpbin.org", "port": 80, "network": "tcp"},
"tag": "dokodemo-in"
}],
"outbounds": [{
"protocol": "vless",
"settings": {
"vnext": [{
"address": "127.0.0.1",
"port": 19997,
"users": [{
"id": "test-user-uuid-00000000000000",
"encryption": "none"
}]
}]
},
"streamSettings": {"network": "tcp"},
"tag": "vless-out"
}]
}
步骤 2 — 运行测试
测试 A:users 配置
# 启动服务器
/tmp/xray run -c server_users.json &
SERVER_PID=$!
# 等待服务器就绪
sleep 2
# 启动客户端并发起请求
/tmp/xray run -c client.json &
CLIENT_PID=$!
# 通过 dokodemo-door 代理访问 httpbin.org
curl -x http://127.0.0.1:29998 http://httpbin.org/ip
测试 B:clients 配置
# 同上,仅将服务器配置和端口替换为 server_clients.json / 19996
步骤 3 — 对比日志
测试 A 的服务器日志(users):
from 127.0.0.1:46619 rejected
proxy/vless/encoding: invalid request user id: 14268965-70cd-5490-ac03-e71afae4f108
[Info] proxy/vless/inbound: firstLen = 159
[Info] app/proxyman/inbound: connection ends > proxy/vless/inbound:
invalid request from 127.0.0.1:46619 >
proxy/vless/encoding: invalid request user id: ...
测试 B 的服务器日志(clients):
[Info] proxy/vless/inbound: firstLen = 159
[Info] proxy/vless/inbound: received request for tcp:httpbin.org:80
[Info] app/dispatcher: default route for tcp:httpbin.org:80
[Info] transport/internet/tcp: dialing TCP to tcp:httpbin.org:80
from 127.0.0.1:43385 accepted tcp:httpbin.org:80 [vless-in-clients >> direct]
[Info] proxy/freedom: connection opened to tcp:httpbin.org:80,
local endpoint 192.168.1.249:44725, remote endpoint 198.18.56.109:80
结论
| 字段名 | 连接结果 | 服务器行为 |
|---|---|---|
users |
❌ 拒绝 | 用户列表为空,不认识任何客户端 |
clients |
✅ 接受 | 正确识别用户,成功转发到目标 |
根因分析
追溯源码
VLESS 入站配置由 Protobuf 定义。检查 Xray-core 源码:
文件:proxy/vless/inbound/config.proto
message Config {
repeated xray.common.protocol.User users = 1;
repeated Fallback fallbacks = 2;
string decryption = 3;
// ...
}
对应生成的 Go 结构体(config.pb.go):
type Config struct {
Users []*protocol.User `protobuf:"bytes,1,rep,name=users,proto3" json:"users,omitempty"`
Fallbacks []*Fallback `protobuf:"bytes,2,rep,name=fallbacks,proto3" json:"fallbacks,omitempty"`
Decryption string `protobuf:"bytes,3,opt,name=decryption,proto3" json:"decryption,omitempty"`
// ...
}
JSON tag 是 json:"users,omitempty"——这和官方文档一致。但本机版本为什么不是这样?
字段名在 2026 年 5 月被重命名
通过 Git 历史追踪,找到了决定性 commit:
c42deab55c 2026-05-07 Config: Rename inbounds' `clients`/`accounts` to `users` (#6083)
PR #6083 的作者(Meo597)将以下入站协议的字段统一重命名:
| 协议 | 旧字段名 | 新字段名 | 向后兼容 |
|---|---|---|---|
| VLESS | clients |
users |
无别名,直接破坏 |
| VMess | clients |
users |
同上 |
| Trojan | clients |
users |
同上 |
| Shadowsocks | clients |
users |
同上 |
| Socks | accounts |
users |
保留别名 |
| HTTP | accounts |
users |
保留别名 |
PR 讨论中明确了 VLESS/VMess/Trojan/Shadowsocks 不保留别名,这意味着旧配置必须手动修改字段名。
版本发布情况
PR 于 2026-05-07 合并。之后的发布记录:
| 版本 | 日期 | 类型 | users 支持 |
|---|---|---|---|
| v26.3.27 | 2026-03-27 | 稳定版 | ❌ 只有 clients |
| v26.3.23 | 2026-03-23 | pre-release | ❌ |
| v26.4.x | 2026-04 | pre-release | ❌ |
| v26.5.3 | 2026-05-03 | pre-release | ❌ |
| v26.5.9 | 2026-05-09 | pre-release | ✅ |
| v26.6.x | 2026-06 | pre-release | ✅ |
| v26.6.27 | 2026-06-27 | pre-release | ✅ |
v26.3.27 是最新的稳定版。 所有带 users 字段的版本(v26.5.9+)至今都是 pre-release。
为什么下载到的是 "旧版"
GitHub 的 /releases/latest API 返回 最新的非 pre-release 版本:
$ curl -s "https://api.github.com/repos/XTLS/Xray-core/releases/latest"
→ "tag_name": "v26.3.27" (2026-03-27)
官方安装脚本默认调用此 API,因此任何用户通过标准方式安装都会得到 v26.3.27——即使有更新的 pre-release。
文件时间戳证实了这一点:
$ stat /tmp/xray
Birth: 2026-06-27 00:01:29 ← 确实是昨天下载的
Version: 26.3.27 ← 但版本是 3 月的
没有做错任何事——官方文档已经更新为 users,但官方稳定版还在用 clients,而安装脚本默认装稳定版。这是一个文档与稳定发布之间的同步滞后问题。
Protobuf 的静默忽略机制
一个关键问题:为什么用 users 字段时 Xray 不报错,而是静默失败?
Protobuf 的 JSON 解析器默认行为是忽略未知字段。在 v26.3.27 的代码中:
- JSON 中出现
"users"→ Protobuf 在Config消息中查找字段名users - v26.3.27 的
Config定义中,字段名叫clients,没有users - Protobuf 将
"users"视为未知字段,静默丢弃 - 结果:
Config.Users(Go 字段)为空切片 → 零个合法用户 - 任何客户端连接都因 "invalid request user id" 被拒绝
这意味着用错字段名的配置可以正常启动、不报任何 warning,但功能完全失效。这对排查问题极为不利。
复现指南
以下步骤可在任何 Linux 环境复现本研究的结论。
环境准备
# 下载最新稳定版 Xray(将得到 v26.3.27)
bash -c "$(curl -sL https://raw.githubusercontent.com/XTLS/Xray-install/main/install-release.sh)" @ install
实验步骤
1. 创建 users 测试配置
cat > /tmp/srv_users.json <<'EOF'
{
"log": {"loglevel": "debug"},
"inbounds": [{
"listen": "127.0.0.1", "port": 19997,
"protocol": "vless",
"settings": {
"users": [{"id": "test-user-uuid-00000000000000"}],
"decryption": "none"
},
"tag": "vless-in"
}],
"outbounds": [{"protocol": "freedom", "tag": "direct"}]
}
EOF
2. 启动服务器并观察日志
xray run -c /tmp/srv_users.json &
sleep 2
3. 用任意 VLESS 客户端连接,观察日志
# 服务器日志将显示:
# rejected proxy/vless/encoding: invalid request user id
4. 将 users 改为 clients,重复测试
# 服务器日志将显示:
# accepted tcp:<target> [vless-in >> direct]
验证版本边界
# 检查本地版本
xray version
# 查看 GitHub 最新稳定版
curl -s https://api.github.com/repos/XTLS/Xray-core/releases/latest | jq '.tag_name'
# 查看所有版本(含 pre-release)
curl -s https://api.github.com/repos/XTLS/Xray-core/releases | jq '.[].tag_name'
解决方案
使用 clients
如果通过标准安装方式获取 Xray,版本就是 v26.3.27 稳定版,使用 clients。
{
"inbounds": [{
"protocol": "vless",
"settings": {
"clients": [
{
"id": "your-uuid-here",
"flow": "xtls-rprx-vision"
}
],
"decryption": "none"
}
}]
}
方案二:升级到 pre-release 并使用 users
# 指定 pre-release 版本安装
XRAY_VERSION=v26.6.27 bash -c "$(curl -sL https://raw.githubusercontent.com/XTLS/Xray-install/main/install-release.sh)" @ install
然后配置文件使用 users。
时间线总结
2026-03-27 v26.3.27 稳定版发布(字段名: clients)
│
│ 4 月期间多个 pre-release(仍为 clients)
│
2026-05-07 PR #6083 合并 → main 分支字段名改为 users
│
2026-05-09 v26.5.9 pre-release(首个使用 users 的版本)
│
│ 5-6 月多个 pre-release(均为 users)
│
2026-06-27 v26.6.27 pre-release 发布
│ 官方文档跟踪 main 分支 → 文档写 users
│ GitHub API /releases/latest → 仍返回 v26.3.27
│
2026-06-28 本文撰写日期
│ 稳定版用户 → 应用 clients
│ 官方文档 → 写的是 users
│ ═══════════════════════════
│ 两者不一致,差距已达 52 天
参考资料
注:本文由deepseek创作
突然意识到为什么xjtu.app叫土原,大概相对于上交的水源吧?
以前一直是x-ui一键配置,这次尝试手动写xray配置文件,方遇到问题
xray 文档有点神人,很多模块都没写清楚,也不知道是不是故意的(
不过写了的部分还挺清楚的
倒是现在可以直接让 agent explore 一下
我当时是真的一点都不想看,直接丢给AI然后让它帮我配了VLESS,最后还是成功了;但是因为我VPS本身烂,是香港的,啥AI服务都用不了,所以实际上没啥用。