feat(xray): embedded REALITY data-plane runtime on the node#14
Merged
Conversation
The node now owns a second data plane alongside AmneziaWG: an embedded xray-core VLESS+REALITY server, managed entirely in-process so the node stays a single static binary (CGO_ENABLED=0; verified `not a dynamic executable`). - internal/xray/identity.go: the node's REALITY identity — a Curve25519 keypair generated once and persisted (xray-node.json), mirroring the AmneziaWG identity. coxswain caches the base64url public key to build a matching REALITY client; the private key never leaves the node. - internal/xray/runtime.go: the runtime embeds xray-core, renders the VLESS+REALITY server config from the identity + pushed policy, and swaps in a fresh instance on every change (validating the new config before disturbing the running one). Apply (full replace, revision-guarded), AddClient/RemoveClient (live reload), Status, Restart, Stop. - control: PushConfig/AddPeer/RemovePeer/ListPeers now branch on protocol and handle PROTOCOL_XRAY_REALITY (XRayRealityConfig: VLESS clients + REALITY camouflage policy); GetStatus reports the REALITY identity + service health; RestartService is implemented for both protocols (AmneziaWG re-applies its conf, XRay swaps a fresh instance). - cli/run.go loads the XRay identity and wires the runtime into the NodeControl server; the service starts down until coxswain provisions a REALITY device with PushConfig. xray-core (v1.260327.0) embedding is covered by an in-process test that binds a real REALITY server, exercises live client add/remove, and tears it down — the in-repo form of the embedding de-risk probe. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Khalefa <khalefa@alahmad.org>
This was referenced Jun 6, 2026
…er row id The node's xrayClientID read peer.id first, but coxswain carries the VLESS UUID in peer.public_key (peers.public_key = the UUID for XRay; the WireGuard key for AmneziaWG) — peer.id is coxswain's row id. So the REALITY server registered the client under the row id while the client presented its real UUID: REALITY auth succeeded, then VLESS rejected the unknown UUID and the connection EOF'd (observed live: Mac/clean-net -> node-1 REALITY relayed to the decoy, then drop). Reading the UUID from public_key (id as fallback) fixes it. Verified live on the fleet: client -> node-1 VLESS+REALITY -> egress at node-1. Also gofmt internal/netpolicy/netpolicy_test.go under go 1.26 (CI uses `stable` = 1.26, whose gofmt reformats it; unrelated to XRay). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Khalefa <khalefa@alahmad.org>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The node gains a second data plane alongside AmneziaWG: an embedded xray-core VLESS+REALITY server, managed in-process so the node stays a single static binary.
What
internal/xray/identity.go— the node's REALITY identity, a Curve25519 keypair generated once and persisted (xray-node.json), mirroring the AmneziaWG identity. coxswain caches the base64url public key to build a matching REALITY client; the private key never leaves the node.internal/xray/runtime.go— embedsxray-core, renders the VLESS+REALITY server config from the identity + pushed policy, and swaps in a fresh instance on every change (validating the new config before disturbing the running one).Apply(full replace, revision-guarded),AddClient/RemoveClient(live reload),Status,Restart,Stop.PushConfig/AddPeer/RemovePeer/ListPeersbranch on protocol and handlePROTOCOL_XRAY_REALITY(XRayRealityConfig: VLESS clients + REALITY camouflage policy).GetStatusreports the REALITY identity + service health.RestartServiceis now implemented for both protocols (AmneziaWG re-applies its conf; XRay swaps a fresh instance).cli/run.goloads the XRay identity and wires the runtime into the NodeControl server. The service starts down until coxswain provisions a REALITY device.Why this is safe to embed
The user's mandate is a single statically-linked binary. The node with
xray-coreembedded builds clean:(CGO_ENABLED=0,
-tags netgo,osusergo, amd64, 33MB — built on the native builder.)Tests
internal/xray/xray_test.gois the in-repo form of the embedding de-risk probe: it boots a real in-process REALITY server, confirms it binds a TCP port, exercises live client add/remove, and tears it down (port 0). Identity persist/reload is also covered. Fullgo test ./...green;go vetclean.Pairs with the proto contract already on
main(node #13 / helm #49:XRayRealityConfig,XRayRealityInfo,Peer.flow).🤖 Generated with Claude Code