WebSocket-to-TCP forwarding on Cloudflare Workers.
Epeius is a lightweight network proxy that accepts Trojan-protocol requests over WebSocket and forwards traffic to TCP destinations using the Workers Sockets API. It brings protocol parsing, connection handling, and stream forwarding together in a single JavaScript Worker.
Trojan-compatible client
|
WebSocket over TLS
|
Cloudflare Worker (Epeius)
|
Outbound TCP socket
|
Destination service
- The client opens a WebSocket connection to the Worker and sends its Trojan request.
- The Worker checks the authentication field and reads the destination address and port.
- It opens a TCP connection with
cloudflare:socketsand forwards data in both directions.
TLS protects the client-to-Worker connection. The Worker opens a TCP socket to the destination; any encryption inside the forwarded traffic depends on the application protocol.
You need a Cloudflare account and a client that supports Trojan over WebSocket with TLS.
Choose a strong password and calculate its SHA-224 digest locally. With Python 3:
python3 -c 'import getpass, hashlib; print(hashlib.sha224(getpass.getpass("Password: ").encode("utf-8")).hexdigest())'Keep the original password for the client. The Worker uses the resulting 56-character lowercase hexadecimal digest, not the original password. Treat both values as credentials.
- Create a Worker in the Cloudflare dashboard.
- Add and deploy a Worker secret named
SHA224PASScontaining the digest from step 1. - Open the code editor, replace the starter code with src/worker.js, and deploy it.
- Use the Worker's hostname, or optionally attach a custom domain.
Configure your own SHA224PASS before using the proxy. Without it, the code falls back to a publicly known example credential bundled in the source.
| Setting | Value |
|---|---|
| Protocol | Trojan |
| Server | Your Worker's hostname, without https:// |
| Port | 443 |
| Password | Your original password, not the SHA-224 digest |
| Transport | WebSocket |
| WebSocket path | / |
| TLS | Enabled; use the same hostname for SNI and the WebSocket Host header |
You can also visit https://<your-worker-hostname>/link for a client URI template. The template always contains the literal placeholder ca110us; replace it with your own password before importing it. It does not read or reveal the configured password and does not change when SHA224PASS changes.
If your password contains reserved URI characters, percent-encode the password before inserting it into the link, or configure the client manually using the settings above.
| Name | Purpose |
|---|---|
SHA224PASS |
SHA-224 digest of the client password. Set it as a Worker secret; it overrides sha224Password in the source. |
PROXYIP |
Optional fallback TCP hostname or IP address. Leave unset unless you have a suitable alternative destination. |
The fallback is attempted when the initial outbound read ends or fails without receiving any data. It uses PROXYIP with the original destination port, or retries the original address if PROXYIP is unset. This is a direct TCP connection, not an HTTP or SOCKS proxy handshake.
- TCP
CONNECTrequests only; UDP is not implemented. - The request parser accepts IPv4, IPv6, and domain-name destinations. Actual connectivity is subject to Cloudflare's TCP socket restrictions.
- Clients must support the WebSocket transport. A client using only native Trojan over TCP/TLS cannot connect directly to this Worker.
- Authentication uses a single configured password digest. The project does not include user management, per-user quotas, or application-level rate limiting.
Use the project with network resources you are authorized to access and in accordance with the hosting provider's terms.
This implementation references zizifn/edgetunnel.
See LICENSE for the GNU GPL v2 license text.