How MURX works
This is the friendly walkthrough. For the byte-exact wire format, see the full specification.
The client-facing flow (TCP + TLS, port 2743)
-
Client connects and sends
AUTH_CONNECTA single short-lived TLS connection to the MURX server (ALPN
murx/1), carrying a Client ID (e.g.[email protected]) and opaque Auth Data (a password, a hashed credential, a signed assertion — whatever the deployment'sAuthBackendexpects). -
Server verifies credentials
The MURX server unwraps the Auth Data and checks it against whatever identity store it's configured with. This is the only place client credentials are ever seen.
-
Server computes a route
Using its live node registry (see below), the server picks the best eligible backend node for this client — by load, by capacity, or by whatever routing policy is configured.
-
Server signs a one-time token
The token names the client and the chosen node, expires after about 30 seconds, and carries a random nonce. It is signed with a key the server shares with that node only, so no token store has to be shared between the server and the backends.
-
Server replies and closes the connection
ROUTE_REDIRECTcarries the backend's address (an IP or a DNS name), port, and the token; the MURX connection then closes immediately. If authentication failed or no backend was available, the server sendsAUTH_REJECTwith a reason code instead, and no token is minted. -
Client connects directly to the backend
A brand-new connection, straight to the target node, with no MURX server involved. The node checks the token's signature, expiry and that it hasn't been used before, and the real application session begins.
Client-facing opcodes
| Opcode | Name | Direction | Meaning |
|---|---|---|---|
0x01 | AUTH_CONNECT | client → server | Request authentication and routing. |
0x02 | ROUTE_REDIRECT | server → client | Success: here is your backend and token. |
0x03 | AUTH_REJECT | server → client | Failure: reason code + optional text. |
The node registry (UDP, port 2743)
MURX servers don't discover backend nodes by polling them — nodes announce themselves. This is what makes "Dynamic Connection Routing" possible without a client request ever blocking on a liveness check.
| Opcode | Name | Direction | Meaning |
|---|---|---|---|
0x10 | NODE_ANNOUNCE | node → server | "I exist and I'm eligible for routing" — sent on startup and periodically. |
0x11 | NODE_HEARTBEAT | node → server | Lightweight liveness/load update between announcements. |
0x12 | HEARTBEAT_ACK | server → node | Optional acknowledgement; nodes don't have to wait for it. |
Every datagram ends with a timestamp and a MAC made with the node's own key. The server drops datagrams from unknown nodes, with a bad MAC, with a clock skew of more than 30 seconds, or that replay an earlier timestamp, so an untrusted host can't register itself as a backend.
A node not heard from within a server-configured TTL (15s in the reference implementation) is dropped from the registry. UDP is unreliable, so nodes simply keep re-sending.
Token semantics
Signed, verified locally
Tokens carry an HMAC-SHA256 signature made with a key derived from the node's secret. The backend verifies them itself, with no call back to the MURX server and no shared cache.
Bound to one node
A token names the node it was issued for. A token stolen on its way to one node is useless at any other.
Short-lived, single-use
Tokens expire after about 30 seconds, and each node remembers the nonces it has already accepted until they expire, so a token works exactly once.
Security considerations, in short
- TLS is required on the client-facing side in any real deployment, and recommended on the backend leg. Redirects can carry DNS names so clients can verify the backend's certificate.
- Tokens are bearer credentials for about 30 seconds. They are signed, bound to one node and single-use, which keeps that window small.
- A leaked node secret lets an attacker impersonate that node, so treat node secrets like private keys, and still keep 2743/udp on the backend network.
- Use the same reject reason for "no such user" and "wrong password", and rate-limit login attempts.