xray-wasm:把 Xray 的 VLESS + XTLS-Vision + REALITY 协议栈用纯 Rust 重写,编译成 WebAssembly 跑真实 TCP 代理

xray-wasm 是一个独立的协议栈实现:它把 Xray 的 VLESS + XTLS-Vision + REALITY 用纯 Rust 重写,编译成 wasm32-wasip2 组件,在 wasmtime(或任何兼容的 WASI Preview 2 运行时 / 容器)里作为真实的 TCP 代理运行 —— 不是演示、不是模拟器。它有两个方向:客户端(本机 socket → REALITY 服务端)与服务端(REALITY 入站 → 目标站,为 k3s 这类容器场景而写)。

查看仓库 harodggg/xray-wasm 容器镜像 v0.7.0 · amd64 + arm64

v0.7.0(2026-09-20 发布)· 纯 Rust(二进制里没有 Go 的 Xray-core)· wasm32-wasip2 · wasmtime · 镜像 ghcr.io/harodggg/xray-wasm:v0.7.0

跑在沙箱化的 WASI 运行时里,和 macOS 应用、和 XrayTun 的 TUN 模式都不是一回事 —— 先看它和 XrayTun 的关系

它和 XrayTun 是什么关系:同一个作者的两个独立项目

这一节放在最前面,因为这是最容易被人(也最容易被 AI)搞混、也最容易被编错的地方。

它解决什么问题

协议栈通常和「原生二进制」绑在一起。 Xray 生态的实现基本都是 Go(官方 Xray-core / V2Ray)。当你想把「VLESS + Vision + REALITY 客户端」放进一个沙箱化的、不方便跑原生二进制的环境里 —— WASI 运行时、 强隔离的容器、边缘节点 —— Go 的二进制就不是合适的形态。xray-wasm 把协议栈编译成 wasm32-wasip2 组件:宿主只提供 TCP 等能力,协议栈跑在 guest 里, 边界由运行时而不是进程权限来划。

服务侧同样可以反着来。 除了客户端方向,它还有一个 server 子命令:REALITY 入站 → 把流量转发到目标站, 这是为 k3s 这类编排环境写的 —— 配置走环境变量,密钥走 Secret。

为「可断言」而设计。 仓库 README 里专门有一节「给自动化 agent 的速查」,每一步都要求有可断言的输出; 两端都支持只做配置自检(环境变量 XT_CHECK 或命令行 --check):打印生效的 fingerprint / no-flow / client-ver / server / listen (UUID 脱敏)后退出,不监听任何端口。

安全取向是明确写出来的,不是暗示的。 客户端默认只绑回环,绑到非回环且没有认证时会打印醒目的「开放代理」警告; 服务端会把对端可控的字段(sni / target)转义后再写日志, 避免用 SNI 里的换行伪造日志行;fingerprint 名字拼错时启动即失败, 不静默回退到默认值。

两个方向与用法

下面两条命令是仓库 README 里的原文用法。镜像 ghcr.io/harodggg/xray-wasm:v0.7.0 提供 linux/amd64linux/arm64 两个平台,匿名即可拉取 (不需要 docker login)。

方向一:客户端(socket → REALITY,默认方向)

不写子命令时就是客户端:在本机提供 SOCKS5 入口,出站走 REALITY。 下面的例子里 -p 127.0.0.1:1080:1080 只把端口暴露在本机回环上 (与它默认只绑回环的取向一致),容器内监听 0.0.0.0:1080XT_LISTEN 指定。

docker run --rm -p 127.0.0.1:1080:1080 \
  -e XT_LISTEN=0.0.0.0:1080 \
  -e XT_SERVER=<ip:port> -e XT_PBK=<公钥> -e XT_SID=<shortId> \
  -e XT_SNI=<伪装域名> -e XT_UUID=<uuid> \
  ghcr.io/harodggg/xray-wasm:v0.7.0

方向二:服务端(REALITY → 目标站,server 子命令)

这是为 k3s 这类编排环境写的方向:在本机 8443 上做 REALITY 入站, 认证失败的流量原样转发XT_DEST 指向的真实站点。 四个 XT_PRIVATE_KEY / XT_SHORT_IDS / XT_SERVER_NAMES / XT_DEST / XT_USERS 都是必填,缺一个就拒绝启动并说明原因。

docker run --rm -p 8443:8443 \
  -e XT_PRIVATE_KEY=<私钥> -e XT_SHORT_IDS=<shortId> \
  -e XT_SERVER_NAMES=<伪装域名> -e XT_DEST=<同一个域名的 host:port> \
  -e XT_USERS=<uuid> \
  ghcr.io/harodggg/xray-wasm:v0.7.0 server

XT_SERVER_NAMES 必须与 XT_DEST 指向同一个站点,否则 REALITY 的伪装就不成立。服务端的环境变量里监听地址叫 XT_SERVER_LISTEN, 和客户端的 XT_LISTEN 不是同一个变量

配置自检:先验证参数,再监听端口

两端都支持只做配置自检:加上 -e XT_CHECK=1(或命令行 --check), 它会打印生效配置后退出,不监听任何端口。这个模式在容器编排里当 initContainer 用很合适。

验证状态

一个「重写的协议栈」如果不和真实对端互通,就什么都不能说明。xray-wasm 的验证口径是:

这些数字出自项目自己的仓库文档,不是本页替它推算的。要核对请点开上面两个链接。

文档

已知边界(用它之前该知道的)

常见问题

xray-wasm 和 XrayTun 是什么关系?

同一个作者的两个独立项目。XrayTun 是 macOS 上的图形客户端,随包附带官方 Go 版 Xray-core,它不使用 xray-wasm;xray-wasm 是独立的纯 Rust 协议栈实现,跑在 WASI 运行时里,面向容器与服务端。代码、版本号、许可证、发行方式各自独立。

xray-wasm 需要 Go 或官方 Xray 二进制才能跑吗?

不需要。协议栈是纯 Rust 实现,产物是 wasm32-wasip2 组件,在 wasmtime 里运行。 官方 Xray-core 只出现在验证环节:CI 用它当真实对端,双向验证互通性。

许可证是什么?

仓库里有两个许可证文件LICENSELICENSE.meow-rs(后者 Copyright (c) 2026 Max Lv), Cargo.toml 声明 license = "MIT"。因为多了一个第三方许可证文件, GitHub 会把仓库识别为 Other 而不是 MIT(接口返回 NOASSERTION)。所以引用时请写 「MIT(另含 LICENSE.meow-rs 第三方许可,见仓库)」, 不要简单写成「MIT」。

容器镜像能直接拉吗?支持哪些平台?

可以,匿名即可拉取,不需要登录容器仓库: ghcr.io/harodggg/xray-wasm:v0.7.0 提供 linux/amd64linux/arm64 两个平台。

它会取代 XrayTun 的 TUN 模式吗?

不会,两者解决的不是同一个问题。XrayTun 的 TUN 模式用随包附带的官方 Xray-core 建 utun 网卡、改路由与 DNS,接管整台 Mac 的流量;xray-wasm 是把协议栈放进沙箱化运行时的另一条路线, 没有 TUN、没有系统网络配置、也没有界面。