WIP: feat(relay): Add an initial implementation for the relay server #17

Draft
warren wants to merge 34 commits from relay into main
Collaborator

This PR introduces a proposed implementation for the relay server.

It features a set of queues managed over a HTTP API, including capability for routing arbitrary messages, creating queues, adding messages to queues, retrieving them from queues, etc... Cryptography is assumed to be supplied by HTTPS; I believe for 2-hop routing that should be enough.

This is far from production ready.

Notably missing:

  • Some "bikeshedding" and review of the protocol as it stands here.
  • Review of the metadata privacy implications if done this way
  • A way to add an (optional) authorization mechanism of some sort for senders (I personally find relaying completely arbitrary messages a bit too spicy, at least if I'm to host it)
  • Consider traffic mixing functionality, noise traffic generation
  • Needs a way to push messages out to clients; maybe use WebSocket or long-polling there?
  • Proper integration tests. This thing needs to work.
  • Consider how spicy it is to store arbitrary blobs of data in the queue... Can that be horrendously abused somehow?
  • Denial-of-service attacks are always a pain in the ass and not really possible to fully prevent, but can we look into doing a bit of it at least?
  • Double-check that HTTPS is enough to hide IP addresses (without considering timing, traffic correlation and similar side-channel attacks). We're effectively emulating a form of 2-hop onion-routing through HTTPS.
This PR introduces a proposed implementation for the relay server. It features a set of queues managed over a HTTP API, including capability for routing arbitrary messages, creating queues, adding messages to queues, retrieving them *from* queues, etc... Cryptography is assumed to be supplied by HTTPS; I believe for 2-hop routing that should be enough. This is far from production ready. Notably missing: - Some "bikeshedding" and review of the protocol as it stands here. - Review of the metadata privacy implications if done this way - A way to add an (optional) authorization mechanism of some sort for senders (I personally find relaying completely arbitrary messages a bit *too* spicy, at least if I'm to host it) - Consider traffic mixing functionality, noise traffic generation - Needs a way to push messages out to clients; maybe use WebSocket or long-polling there? - Proper integration tests. This thing needs to work. - Consider how spicy it is to store arbitrary blobs of data in the queue... Can that be horrendously abused somehow? - Denial-of-service attacks are always a pain in the ass and not really possible to fully prevent, but can we look into doing a *bit* of it at least? - Double-check that HTTPS is enough to hide IP addresses (without considering timing, traffic correlation and similar side-channel attacks). We're effectively emulating a form of 2-hop onion-routing through HTTPS.
Added the "relay" subcrate for writing the relay/message-queue server.
Added the basic Queue type with data members.
The Queue type was expanded to add useful methods, as well as maximum size tracking and validation.

Additional messages are refused if the queue is full.
Introduced a `new_genkey` constructor method to the `Queue` type that generates a random hexadecimal key using the `rand` and `hex` crates; this key can then be handed out to whoever requests queue creation and lets them access the queue.
Introduced the `queue_set` module, allowing the creation and management of a set of queues by their uuid.
Implemented an HTTP server using `axum` to handle queue management via RESTful endpoints. Added routes for creating queues, adding messages, extracting messages, and deleting queues. Includes a comprehensive suite of tests for each API operation. Updated dependencies and Cargo configuration for the new features.
Introduced a `/forward-message` handler to forward messages to a remote queue using `reqwest`. Updated `shell.nix` to include `pkg-config` and `openssl`. Added `reqwest` dependency to `Cargo.toml`, along with updates for library compatibility.
Author
Collaborator

Argument in favor of 3-hop HTTPS.

Alice and Bob are blind to each others' IPs.

I will argue here why HTTPS (or even HTTP by itself) provides enough guarantees to not reveal IP addresses.

Consider: Alice wishes to send a message to Bob. Alice and Bob must not learn of each others' IP addresses.

Bob provides to Alice through a trusted pre-existing channel the URL of a relay trusted by Bob, hereafter "Bob's Relay". Alice chooses a relay trusted by Alice, hereafter "Alice's Relay". The relays are assumed to be potentially fully-controlled by the parties that trust them.

(Alice) -- HTTP --> (Alice Relay) -- HTTPS --> (Bob Relay) -- HTTPS --> (Bob)

  • Alice makes a HTTP request to her relay, supplying to it both her message and the URL of Bob's relay.
  • Alice's relay makes a HTTP request to Bob's relay, based on the aforementioned URL.
  • Bob's relay finally sends the message to Bob's device.

In this exchange, Alice's IP address is revealed only to Alice's relay, and Bob's IP address is revealed only to Bob's relay. At no point is there any exchange of network traffic directly between Alice's device and any device she does not trust. Same for Bob.

Hence, Alice and Bob never learn of each others' IP addresses.

# Argument in favor of 3-hop HTTPS. ## Alice and Bob are blind to each others' IPs. I will argue here why HTTPS (or even HTTP by itself) provides enough guarantees to not reveal IP addresses. Consider: Alice wishes to send a message to Bob. Alice and Bob must not learn of each others' IP addresses. Bob provides to Alice through a trusted pre-existing channel the URL of a relay trusted by Bob, hereafter "Bob's Relay". Alice chooses a relay trusted by Alice, hereafter "Alice's Relay". The relays are assumed to be potentially fully-controlled by the parties that trust them. (Alice) -- HTTP --> (Alice Relay) -- HTTPS --> (Bob Relay) -- HTTPS --> (Bob) - Alice makes a HTTP request to her relay, supplying to it both her message and the URL of Bob's relay. - Alice's relay makes a HTTP request to Bob's relay, based on the aforementioned URL. - Bob's relay finally sends the message to Bob's device. In this exchange, Alice's IP address is revealed only to Alice's relay, and Bob's IP address is revealed only to Bob's relay. At no point is there any exchange of network traffic directly between Alice's device and any device she does not trust. Same for Bob. **Hence, Alice and Bob never learn of each others' IP addresses.**
Author
Collaborator

Eve spying on a single request never learns anything new

In the exchange below, consider that Eve might peek into at most one of the requests. That's one of three situations:

  1. (Alice) -- Eve --> (Alice Relay) -- HTTPS --> (Bob Relay) -- HTTPS --> (Bob)
  2. (Alice) -- HTTPS --> (Alice Relay) -- Eve --> (Bob Relay) -- HTTPS --> (Bob)
  3. (Alice) -- HTTPS --> (Alice Relay) -- HTTPS --> (Bob Relay) -- Eve --> (Bob)

In 1, Eve already knows Alice's IP address and Alice's Relay address (how else does she gain the MITM position?). By breaking into the request, Eve will learn Bob's Relay address too. However, Bob's address is never revealed to Eve, as Alice's request or message contains no information about Bob himself, only his relay. Eve thus never learns anything she doesn't know already.

In 2. Eve knows Alice's Relay and Bob's Relay. However, from this position, Eve never sees either Alice or Bob's IP addresses; at most, Eve learns of the servers... but she already knows this from the MITM position.

In 3, we get a mirror situation of 1. Eve knows Bob and Bob's Relay already even before breaking in. This request also contains no information about Alice or her relay, so Eve here learns even less.

In all three situations, Eve learns nothing that she didn't already know from her MITM position. Any single-hop MITM attempt thus never reveals additional information, even when breaking the single-hop's encryption.

## Eve spying on a single request never learns anything new In the exchange below, consider that Eve might peek into at most one of the requests. That's one of three situations: 1. (Alice) -- Eve --> (Alice Relay) -- HTTPS --> (Bob Relay) -- HTTPS --> (Bob) 2. (Alice) -- HTTPS --> (Alice Relay) -- Eve --> (Bob Relay) -- HTTPS --> (Bob) 3. (Alice) -- HTTPS --> (Alice Relay) -- HTTPS --> (Bob Relay) -- Eve --> (Bob) In 1, Eve already knows Alice's IP address and Alice's Relay address (how else does she gain the MITM position?). By breaking into the request, Eve will learn Bob's Relay address too. However, Bob's address is never revealed to Eve, as Alice's request or message contains no information about Bob himself, only his relay. Eve thus never learns anything she doesn't know already. In 2. Eve knows Alice's Relay and Bob's Relay. However, from this position, Eve never sees either Alice or Bob's IP addresses; at most, Eve learns of the servers... but she already knows this from the MITM position. In 3, we get a mirror situation of 1. Eve knows Bob and Bob's Relay already even before breaking in. This request also contains no information about Alice or her relay, so Eve here learns even less. In all three situations, Eve learns nothing that she didn't already know from her MITM position. **Any single-hop MITM attempt thus never reveals additional information, even when breaking the single-hop's encryption.**
Author
Collaborator

Eve compromising a relay never reveals anything beyond other relays

In the exchange (Alice) -- HTTP --> (Alice Relay) -- HTTPS --> (Bob Relay) -- HTTPS --> (Bob), consider that Eve gains full control over either (Alice Relay) or (Bob Relay).

Alice's relay never observes any traffic going to (Bob). Bob's relay never observes any traffic coming from (Alice).

Thus, if Eve controls Alice's relay, Bob's IP address is protected. Similarly, if Eve controls Bob's relay, Alice's IP address is protected.

Thus: A bad trust decision by Alice never reveals Bob's IP. A bad trust decision by Bob never reveals Alice's IP.

Thus: A bad trust decision by one party cannot compromise another party's IP. Only that of their relay.

## Eve compromising a relay never reveals anything beyond other relays In the exchange (Alice) -- HTTP --> (Alice Relay) -- HTTPS --> (Bob Relay) -- HTTPS --> (Bob), consider that Eve gains full control over either (Alice Relay) or (Bob Relay). Alice's relay never observes any traffic going to (Bob). Bob's relay never observes any traffic coming from (Alice). Thus, if Eve controls Alice's relay, Bob's IP address is protected. Similarly, if Eve controls Bob's relay, Alice's IP address is protected. Thus: A bad trust decision by Alice never reveals Bob's IP. A bad trust decision by Bob never reveals Alice's IP. Thus: **A bad trust decision by one party cannot compromise another party's IP. Only that of their relay.**
This pull request is marked as a work in progress.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin relay:relay
git switch relay
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
nemalixi/chat-app!17
No description provided.