Table of contents
Introduction/TLDR
We added Xray support to the network. In contrast to the stunnel-based HTTPS obfuscation we’ve been using for years, Xray’s REALITY mode is capable of mimicking what a normal browser handshake looks like — right down to the JA3 fingerprint and the general traffic profile that accompanies it, which is useful if you’re behind one of those networks that actively tries to identify and interfere with VPN usage.
Xray also works with WireGuard (and UDP OpenVPN), while stunnel only works with TCP OpenVPN.
The Xray config generator is at https://cryptostorm.is/xray/
We also made an Android Xray app, available at:
https://cryptostorm.is/xray/app-latest.apk [sig]
(source code at https://github.com/cryptostorm/CSXRAY)
Port 8443 will give you better speeds, so you should use that if your network allows it and it doesn't make your traffic too unusual. If you must use another port, anything from 1-65535 should work (excluding 5061, 5062 and 5063), though it won't be as fast since it has to go through the haproxy/SNI routing described on https://cryptostorm.is/blog/port-striping-v3. Port 443 is the default since that's the standard HTTPS port.
Instructions
Android
First, setup WireGuard following the instructions on https://cryptostorm.is/android#wg
(don't connect yet). You should have the cs-* configs imported into WireGuard.
Next, download and install https://cryptostorm.is/xray/app-latest.apk [sig] [source]
Most Android web browsers will ask for permission to install applications the first time you download an .apk. It’s safe to allow it for the install, but after installation it’s generally a good idea to turn that permission back off so the browser can't install anything else in the future.
After the app is installed, open it and:

-
Choose the server you want to use.
- Change the port, if needed.
-
Tap Start Xray.
The status indicator near the middle will show a blue icon and:
"Xray is running (waiting for traffic)"
Next, open the WireGuard app:
- Edit the
cs-…config for the same server you selected in the Xray app.
(cs-austria, cs-dallas, etc.) -
In the WireGuard config editor, tap All Applications.
-
In that app exclusion list, exclude the CSXRAY app.
(This is required to prevent a recursive routing loop) -
Back in the config editor, set the Endpoint to:
127.0.0.1:31338 -
Save, then connect WireGuard normally.
If you switch back to the CSXRAY app, you should now see a green status icon with "Xray is forwarding WireGuard traffic" next to that, as well as RX (received bytes) and TX (sent bytes) counters in the top right.
✔️Your WireGuard traffic should now appear as ordinary browser-looking HTTPS traffic.✔️
You can now close this app the same way you would the WireGuard app. Both will run in the background until you re-open the app and tap stop/disconnect.
Note: Don't enable the "Block connections without VPN" option in your Android settings. That would prevent this app from working because then only the WireGuard app would be allowed, but WireGuard is forwarding to Xray, so Xray needs to be allowed too. There's no Android option to "Block connections without VPN except for this one app", so it has to be disabled.
Also, the app has built-in translations for: English, Russian (Русский), Chinese (中文), Japanese (日本語), Swedish (Svenska), Persian (فارسی), and Arabic (العربية). Tap the U.S. flag in the upper right to bring up the language selection menu.
And of course, the most important feature: Dark/light mode

Windows/Linux/Mac
First, setup WireGuard following the instructions for your platform on https://cryptostorm.is/#section6
(just don't connect to anything yet).
Next, download v2rayN from the releases page: https://github.com/2dust/v2rayN/releases
(Choose the version appropriate for your system.
On Windows, the "desktop" zip builds are the simplest: unzip then run v2rayN.exe)
Once v2rayN is running:
-
Go to the Xray config generator page: https://cryptostorm.is/xray/
-
Select the server you want to use.
(For faster speeds, use port 8443 if it's allowed on your network). -
Click SHOW CONFIG, then click Copy to place the config in the clipboard.
-
Switch back to v2rayN and click the main window once then press:
Ctrl + V
and v2rayN will automatically import the config. -
A new entry will appear in the list.
Double-click that entry then click Confirm to actually start Xray.
-
Once running, v2rayN should show a "listening UDP on 127.0.0.1:31337" somewhere in the output.
That means Xray is ready. -
Now switch back to WireGuard and edit the config
(for the same server you selected when generating the Xray config). -
Find the line that begins with:
Endpoint = something.cstorm.is:443
and change it to:
Endpoint = 127.0.0.1:31337 -
Save the WireGuard config then activate it as usual.
Your traffic flow is now:
WireGuard → local Xray → REALITY/VLESS → server → WireGuard → normal routing.
Instead of WireGuard traffic, anyone monitoring will see only ordinary HTTPS (TLSv1.3) browser-looking traffic.
Technical details
The CSXRAY app
On Android, the CSXRAY app is just a GUI wrapper for Xray-core. It doesn't use Android’s vpnService API as most Xray apps do because this app is meant to run alongside another VPN client. All it does is start Xray with a dokodemo-door inbound listening on 127.0.0.1:31338, and displays status changes coming from a few small patches we added to Xray-core (which simply notify the UI when Xray is idle, receiving traffic, or shutting down).
In the main CSXRAY app window, the gear icon in the top left will display the current Xray config. It's read-only unless you choose 'Custom IP' in the server selection list. That's mostly for people who want to use this app with their own (non-cryptostorm) VPN/Xray servers. There's a basic config editor in there that only does simple JSON syntax validation, but otherwise just feeds whatever JSON config you give directly into Xray-core, so all the default inbounds/outbounds are supported (As of v25.10.15, inbounds: dokodemo-door, HTTP, Shadowsocks, SOCKS, Trojan, VLESS, VMess, WireGuard, Outbounds: Blackhole, DNS, Freedom [alias: direct], HTTP, Loopback, Shadowsocks, Socks, Trojan, VLESS, VMess, WireGuard).
The app ships with a built-in list of server IPs so that DNS can be avoided. Those IPs are updated automatically over HTTPS endpoints that are on all of the servers, and it downloads the updates through the same REALITY connection the user's WireGuard traffic will use. This means the app does not leak out of the tunnel to check for updates, and it does not introduce any additional traffic patterns. Update checks are rate-limited (never more than once per hour) and jittered with randomized 60–80 minute intervals, specifically to avoid periodic beacons.
When running, the traffic flow looks like this:
WireGuard app → 127.0.0.1 (dokodemo-door inbound on the client) → REALITY/VLESS → server-side Xray → forwards to the entry IP as raw WireGuard packets → routed normally.
The server-side Xray
The server-side Xray instance runs inside its own network namespace. This prevents it from interfering with the main routing tables and firewall rules, and ensures that obfuscated traffic terminates in a controlled environment. After de-obfuscation, packets are forwarded into the entry/default namespace where the port striping rules identifies WireGuard handshakes and assigns each session to one of several exit namespaces.
To anyone observing on-path (either locally or upstream), the only visible traffic is a normal TLSv1.3 connection on whichever port you chose, with handshake characteristics that resemble a browser rather than a VPN.
