这是一个 Xray-core 的包装器,用于改善客户端的开发体验。
- 本仓库维护人员很少。如果你不是报告 bug 或发起 PR,你的问题将被忽略。
- 本仓库不保证 API 稳定,你需要自行适配。
- 本仓库仅与 Xray-core 最新的发布版本保持兼容。
编译脚本。建议始终使用该脚本编译 libXray。我们不解答使用其他编译方式引起的问题。
依赖 git 和 go。
默认情况下,编译脚本不会 clone Xray-core,而是通过 Go modules 的 pseudo-version 将 Xray-core 固定到发布版本 v26.7.28。
传入可选参数 local 时,会通过 Go module replace 改用已有的本地仓库 ../Xray-core。
python3 build/main.py android
python3 build/main.py android local
python3 build/main.py apple gomobile
python3 build/main.py apple go
python3 build/main.py apple gomobile local
python3 build/main.py apple go local
python3 build/main.py linux
python3 build/main.py linux local
python3 build/main.py windows
python3 build/main.py windows localLinux 和 Windows 构建还会生成 bin/xray 或 bin/xray.exe。该会话 Core
会保护 Go DNS 查询不被 VPN 路由重新捕获,并且只接受以下命令:
xray run -dns <IP:port> -interface <网卡名> -config <xray.json>三个参数都必须提供。-dns 必须是 IP endpoint,-config 直接指向 Xray
JSON 配置。
Warning
每个进程只能使用一个 Go runtime。 Go 不支持在同一进程中加载多个独立构建的
Go runtime。libXray 的所有原生产物都会嵌入 Go runtime,无论它们通过 cgo 还是
gomobile 生成。不要在同一个可执行文件或进程中同时加载 libXray 与另一个独立构建的
Go、cgo 或 gomobile 库,否则可能在构建、链接或加载阶段失败,也可能在应用代码执行前
的 runtime 初始化阶段崩溃。
如果同一进程需要多个库中的 Go package,应将这些 package 放入同一次 Go build 或
gomobile bind 并生成一个原生产物,使其共享一个 runtime。仅重新打包或合并已经独立
构建的 framework、archive、AAR、shared library 或 DLL 并不能解决问题。不同的操作系统
进程可以各自加载一个 Go runtime,因此需要分别对每个进程遵守这一限制。参见
Go #18976、
golang/go#15956
和 libXray #116。
使用 gomobile 。
需要 “iOS Simulator Runtime”。
这是常规场景下的最佳选择;与其他基于 Go 的库同时集成时,仍须遵守上方跨平台的 单 runtime 限制。
支持 iOS,iOSSimulator,macOS,macCatalyst。
但无法设置最低 macOS 版本,编译时会引起一些警告。而且不支持 tvOS。
需要 “iOS Simulator Runtime” 和 “tvOS Simulator Runtime”。
支持更多编译选项,输出 c 头文件。
当你使用 ffi 进行集成时,这种方式将十分有效。如与 swift,kotlin,dart 进行集成。
支持 iOS,iOSSimulator,macOS,tvOS。
产物 LibXray.xcframework 包含 module.modulemap。当使用 Swift 时,
可通过 LibXray 模块导入。
依赖 gcc 和 g++ 。
依赖 PATH 中的 gcc 和 g++。
支持原生 amd64 和 arm64 构建。Release workflow 会在对应架构的 GitHub Windows runner 上分别构建产物。
libXray 只暴露一个结构化入口:
func Invoke(requestJSON string) stringC 导出为:
char* CGoInvoke(char* requestJSON);
void CGoFree(char* value);CGoInvoke 会分配返回值。调用方必须使用 CGoFree 释放每个非空返回值,
不要直接使用平台分配器释放。
请求是 JSON 对象:
{
"apiVersion": 2,
"method": "runXray",
"payload": {
"xrayJson": "{\"outbounds\":[...]}"
}
}响应是 JSON 对象:
{
"success": true,
"data": {},
"error": ""
}设计决定:
- Invoke 当前只接受
apiVersion: 2。Xray 配置通过xrayJson传递 UTF-8 JSON 文本;libXray 不读取配置文件路径。 - 顶层
env字段会被忽略且不会生效。Xray-core 运行时环境项应写入 Xray 配置根env对象。 SetTunFd已删除。如果 fd 只能在运行时获得,请在调用runXray前把xray.tun.fd写入 Xray 配置根env对象。countGeoData不依赖 Xray 配置,因此通过 method payload 的datDir传入数据目录。- 完整的 UTF-8 编码 Invoke 请求和响应 JSON 包体限制为 16 MiB。任一方向超过限制时,Invoke 将返回
success: false、data: null和对应的大小限制错误。 convertShareLinksToXrayJson会使用当前 Xray-core 配置构建器校验每个已解析的 outbound。无效 outbound 会被忽略;如果没有剩余的有效 outbound,该方法返回失败。校验不会创建或启动 Xray instance。Xray JSON 输入仅作为节点来源,只保留根级outbounds,忽略其他根字段。响应仅包含 libXray 分享链接支持的字段,不支持的字段和生成的空字段会被省略;XHTTPextra与 FinalMask masksettings中的原始 JSON 保持不变。可选的age.secretKey会在现有解析流程前于内存中解密官方 age ASCII armor;明文输入保持原有行为。- Xray-core 的系统拨号 DNS client 和 outbound manager 属于进程级状态。当
runXray正在运行时,通过pingBatch、testXray或导出的 Go API 创建另一个 Xray instance,可能覆盖这些状态并影响正在运行的 instance。关闭临时 instance 不会恢复之前的状态。libXray 不对并发 instance 进行串行化、隔离或状态恢复;调用方如需同时运行多个 instance,必须将它们放在不同进程中。
支持的 method:
getFreePorts
convertShareLinksToXrayJson
convertXrayJsonToShareLinks
generateAgeKeyPair
countGeoData
pingBatch
testXray
runXray
stopXray
xrayVersion
getXrayState
用于解决 Android 上 socket protect 问题。
Android VPN 运行时可能会向 Go 解析器提供回环 DNS 地址。请在调用
runXray 前调用 SetDNS,让 Go 使用 VPN 配置指定的 DNS,并通过
protectFd 将 DNS socket 排除在 VPN 隧道外。DNS 必须是包含端口的 IP
地址,例如 8.8.8.8:53 或 [2001:4860:4860::8888]:53。
Xray 停止后调用 ResetDNS。这两个 API 仅存在于 Android 产物中,并会
修改 Go 进程级默认解析器。
LibXray.setDNS(controller, "8.8.8.8:53");
LibXray.invoke(runXrayRequest);
// 稍后停止 Core 时:
LibXray.invoke(stopXrayRequest);
LibXray.resetDNS();读取 geo 文件,并对分类和规则进行计数。
下载 geosite.dat 和 geoip.dat,并进行计数。
仅在 iOS 下执行,每秒发起一次 gc。可缓解 iOS 上内存压力。
写入数据到文件。
对 Xray 配置进行测速。
获取空闲端口。
libXray 使用 sendThrough 来存储节点名称。
解析 Clash.Meta 配置。
转换 Xray Json 为 VMessAEAD/VLESS 分享协议。
转换 VMessAEAD/VLESS 分享协议为 Xray Json。
转换 VMessQRCode 为 Xray Json。
convertShareLinksToXrayJson 接受可选的 age 原生私钥。仅支持 X25519
(AGE-SECRET-KEY-1...)和 ML-KEM-768 + X25519 hybrid
(AGE-SECRET-KEY-PQ-1...)identity。识别到 age armor 后会在内存中完成
解密,解密后明文上限为 16 MiB。
{
"apiVersion": 2,
"method": "convertShareLinksToXrayJson",
"payload": {
"text": "-----BEGIN AGE ENCRYPTED FILE-----\n...",
"age": {
"secretKey": "AGE-SECRET-KEY-1..."
}
}
}generateAgeKeyPair 可生成新密钥对,keyType 支持 x25519 或
hybrid;省略时默认为 x25519。hybrid 对应 Mihomo 的
age keygen-pq,生成 AGE-SECRET-KEY-PQ-1... identity 和
age1pq1... recipient:
{
"apiVersion": 2,
"method": "generateAgeKeyPair",
"payload": {
"keyType": "x25519"
}
}响应同时包含 secretKey 和 publicKey。接入 App 必须持久化该密钥对,并且
只将 publicKey 作为 X-Age-Public-Key 发送。libXray 不负责订阅 HTTP 请求、
密钥持久化或请求 Header;严禁通过 HTTP 发送私钥,也不能把解密后的订阅文本
写入磁盘。
转换 VMessQRCode 为 Xray Json。
解析分享链接时用到的一些工具。
在一个临时 Xray instance 内并发测试多份 outbound 配置。每个 xrayJson 文本只
解析 outbounds,其他根字段全部忽略。目标 outbound 依次按 outboundTag、
proxy tag、首个 outbound 选择。
{
"apiVersion": 2,
"method": "pingBatch",
"payload": {
"configs": [
{
"xrayJson": "{\"outbounds\":[...]}"
},
{
"xrayJson": "{\"outbounds\":[...]}",
"outboundTag": "media"
}
],
"timeout": 5,
"url": "https://cp.cloudflare.com/"
}
}每次请求最多接受 5 份配置,并发测试该请求中所有已接受的配置。超过 5 份配置的 请求会在开始测试前直接失败。
批次请求本身被接受时,顶层 response 为成功;每个配置通过自己的结果表示成功或
失败。delay 为 10000 表示错误,11000 表示超时。结果数组与输入配置数组
长度相同且顺序一致。
通过 streamSettings.sockopt.dialerProxy 或 proxySettings.tag 引用的
outbound 依赖会被自动包含。
直接校验传入的 Xray JSON 文本,不读取配置文件:
{
"apiVersion": 2,
"method": "testXray",
"payload": {
"xrayJson": "{\"outbounds\":[...]}"
}
}使用传入的 Xray JSON 文本启动由 libXray 管理的 Xray instance,并通过
stopXray 停止。runXrayFromJson 不再作为独立 method 存在。
统计。
参考如下配置:
{
"metrics" : {
"listen": "127.0.0.1:49227"
},
"policy" : {
"system" : {
"statsInboundDownlink" : true,
"statsInboundUplink" : true,
"statsOutboundDownlink" : true,
"statsOutboundUplink" : true
}
},
"stats" : {}
}metrics 服务通过 HTTP 暴露 Xray 运行时计数。例如 listen 为
127.0.0.1:49227 时,读取:
http://localhost:49227/debug/vars
注意:
- 当进行测试延迟或验证配置时,确保
metrics为null。 - libXray 这里只需要
listen字段。直接用 HTTP 客户端查询/debug/vars,不再通过 libXray 包装。
验证 Xray 配置。
启动和停止 Xray 实例。
MetaCubeX age(BSD 3-Clause)
本仓库基于 MIT License 。