Skip to content

Commit a2cba08

Browse files
committed
Upgrade welcome message
1. It promotes a list of known relay servers to use 2. It gives a proof of work challenge to solve The list of known relay servers allows us to not always use the same one, distributing both cost and availability. It also allows to reboot single relay servers for maintenance without bringing the whole service down. Each client should pick one or two, this will result in up to four relays being pinged during relay initialization (remember, there are two clients who both pick at random). Four connection attempts should be enough to give a sufficiently high probability of finding one that is up. The proof of work challenge is added in the attempt to protect the rendezvous server from a DOS overload. It is a single point of failure, and we want to be prepared if some dumb-ass spams it with connection attempts for some reason. The challenge is made in a way that its difficulty is configurable by the server, thus it can dynamically adapt at the load situation. It is also designed in a way to be as light on the server resource as possible (also in order to not accidentally introduce a new DOS vector): - The server can use the first 8 bytes of the challenge as running counter, only that needs to be stored. A binary heap gives - All other required information are stored and forwarded by the client, a MAC protects against clients that make up their challenges.
1 parent 613797c commit a2cba08

File tree

1 file changed

+58
-14
lines changed

1 file changed

+58
-14
lines changed

server-protocol.md

Lines changed: 58 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -70,28 +70,72 @@ messages. Clients must ignore unrecognized message types from the Server.
7070

7171
## Connection-Specific (Client-to-Server) Messages
7272

73-
The first thing each client sends to the server, immediately after the
74-
WebSocket connection is established, is a `bind` message. This specifies the
75-
AppID and side (in keys `appid` and `side`, respectively) that all subsequent
76-
messages will be scoped to. While technically each message could be
77-
independent (with its own `appid` and `side`), I thought it would be less
78-
confusing to use exactly one WebSocket per logical wormhole connection.
79-
8073
The first thing the server sends to each client is the `welcome` message.
8174
This is intended to deliver important status information to the client that
82-
might influence its operation. The Python client currently reacts to the
83-
following keys (and ignores all others):
75+
might influence its operation. Clients should look out for the following fields,
76+
and handle them accordingly, if present:
8477

85-
* `current_cli_version`: prompts the user to upgrade if the server's
78+
* `current_cli_version`: *(deprecated)* prompts the user to upgrade if the server's
8679
advertised version is greater than the client's version (as derived from
8780
the git tag)
88-
* `motd`: prints this message, if present; intended to inform users about
81+
* `motd`: This message is intended to inform users about
8982
performance problems, scheduled downtime, or to beg for donations to keep
90-
the server running
91-
* `error`: causes the client to print the message and then terminate. If a
83+
the server running. Clients should print it or otherwise display prominently
84+
to the user.
85+
* `error`: The client should show this message to the user and then terminate. If a
9286
future version of the protocol requires a rate-limiting CAPTCHA ticket or
9387
other authorization record, the server can send `error` (explaining the
9488
requirement) if it does not see this ticket arrive before the `bind`.
89+
* `relays`: An advertizement list of relay servers. It is a JSON list of which each
90+
entry may look like this:
91+
```json
92+
{
93+
"url": "tcp:myrelay.example.org:12345",
94+
"country": "Italy",
95+
"continent": "EU",
96+
}
97+
```
98+
The only mandatory key is `url`, al others are optional information to help the client
99+
choose an appropriate one. Further keys may be added in the future. Clients must not
100+
expect the protocol to be `tcp` (expect websockets support in the future). Clients
101+
should make a preselection of viable relay servers (which may include entries from other
102+
sources as well), and randomly select one or two.
103+
* `proof_of_work`: A proof of work task to mitigate DOS attacks. The difficulty is dictated
104+
by the server based on its current load. The entry looks like this:
105+
```json
106+
{
107+
"challenge": "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABXXXX",
108+
"sha256": "a66cdd7def34cb0267b83d21c37c429af0a15dcd00465da22402dab9f1cbf10e",
109+
"mac": "<snip>"
110+
}
111+
```
112+
The challenge contains exactly 32 hex-encoded bytes, of which the last nibbles are censored ('X'),
113+
and the `sha256sum` of the uncensored challenge. The goal is to find the complete `challenge` with
114+
the given hash.
115+
116+
The first thing each client sends to the server, immediately after receiving
117+
the welcome message, is a `bind` message. This specifies the
118+
AppID and side (in keys `appid` and `side`, respectively) that all subsequent
119+
messages will be scoped to. While technically each message could be
120+
independent (with its own `appid` and `side`), I thought it would be less
121+
confusing to use exactly one WebSocket per logical wormhole connection.
122+
123+
Due to backwards compatibity, clients are not forced to give a proof of work.
124+
However, it is strongly recommended. Here's how a full "bind" message may look like:
125+
126+
```json
127+
{
128+
"type": "bind",
129+
"appid": "lothar.com/wormhole/text-or-file-xfer",
130+
"side": "123456",
131+
"proof_of_work": {
132+
"challenge": "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABXXXX",
133+
"sha256": "a66cdd7def34cb0267b83d21c37c429af0a15dcd00465da22402dab9f1cbf10e",
134+
"mac": "<snip>",
135+
"response": "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF",
136+
},
137+
}
138+
```
95139

96140
A `ping` will provoke a `pong`: these are only used by unit tests for
97141
synchronization purposes (to detect when a batch of messages have been fully
@@ -201,7 +245,7 @@ This lists all message types, along with the type-specific keys for each (if
201245
any), and which ones provoke direct responses:
202246

203247
* S->C welcome {welcome:}
204-
* (C->S) bind {appid:, side:}
248+
* (C->S) bind {appid:, side:, proof_of_work: {..},}
205249
* (C->S) list {} -> nameplates
206250
* S->C nameplates {nameplates: [{id: str},..]}
207251
* (C->S) allocate {} -> allocated

0 commit comments

Comments
 (0)