diff --git a/prototypes/quic_demo/README.md b/prototypes/quic_demo/README.md index 1e73d04..38fa11e 100644 --- a/prototypes/quic_demo/README.md +++ b/prototypes/quic_demo/README.md @@ -1,14 +1,124 @@ # Testing - - There are 5 processes, so you'll need 5 terminal windows or screen / tmux sessions: 1. TCP end server: `nc -l -p 30382` 2. QUIC relay server: `RUST_LOG=quic_demo_relay_server=debug cargo run --bin quic_demo_relay_server` -3. Server-side adapter: `RUST_LOG=quic_demo_end_server=debug cargo run --bin quic_demo_end_server` -4. Client-side adapter: `RUST_LOG=quic_demo_client cargo run --bin quic_demo_client` +3. Server-side proxy: `RUST_LOG=quic_demo_end_server=debug cargo run --bin quic_demo_end_server` +4. Client-side proxy: `RUST_LOG=quic_demo_client cargo run --bin quic_demo_client` 5. TCP end client: `nc 127.0.0.1 30381` The netcat processes from steps 1 and 5 should now be connected to each other. + +# Plan + +This is a TCP port forwarding system, like SSH has, but better. + +We'll name the processes in order from clientest to serverest: + +1. TCP end client (e.g. VNC viewer, SSH client) +2. Client-side proxy (Part of PTTH, must run as a desktop app on end user systems) +3. Relay server (Part of ptth_relay) +4. Server-side proxy (Path of ptth_server) +5. TCP end server (e.g. VNC server, SSH server) + +At the highest level, creating a connection means: + +1. Processes 2, 3, and 4 are running and connected by QUIC. +2. Process 5 is running and listening on its TCP port. +(e.g. 22 for SSH) +3. Process 2 sets a port mapping to the server. +(e.g. 2200 on the client is mapped to 22 on the server) +4. Process 1 connects to the client-side port +(e.g. ssh to 2200 on localhost) +5. Processes 2, 3, and 4 forward that connection to Process 5. +Any of the other processes can reject the connection for various reasons. +6. The connection is established, and Processes 2, 3, and 4 relay bytes +for Processes 1 and 5. + +What identifies a connection? + +1. The client ID, because a connection is never shared between 2 clients. +2. The ephemeral port used by P1, because 2 SSH clients may connect to the same +forwarded port in P2 at once. +3. The server ID, because a connection is never shared between 2 servers. +4. The listen port of P5, for the sake of matching TCP theory, and because +this data is needed. I'm not sure if it's technically part of the identifier. + +Because clients can't see each other, each client will store these data +about each of its connections: + +1. The ephemeral port used by P1 +2. The server ID +3. The listen port for P5 + +Because servers can't see each other, each server stores these data: + +1. P1's port +2. The client ID +3. The listen port for P5 + +The relay server must store all 4 data for each connection. + +Each client and each server has exactly one QUIC connection to the relay +server. + +In P2 and P4, each PTTH connection has a TCP bi stream and a QUIC bi stream. + +In P3, each PTTH connection has 2 QUIC bi streams. + +Assume that some kind of framing exists. + +Once a port mapping is established (within P2 only), a connection proceeds +like this: + +1. P1 connects to P2 +2. P2 starts a QUIC bi stream to P3. This has a tip message of +(P1 port, P4 ID, P5 port). +3. If P2 isn't authorized to make the connection, P3 closes it +4. If P4 isn't connected to P3, the connection fails +5. P3 starts a QUIC bi stream to P4. This has a tip message of +(P1 port, P2 ID, P5 port). +6. If P4 doesn't approve, the connection closes +7. If P4 can't connect to P5, the connection closes +8. P4 connects to P5 +9. P4 returns a tip message to P3, equivalent to "200 OK" +10. P3 returns the tip message to P2 +11. The connection goes into relaying mode + +Here's the big things I'm thinking: + +- It's kinda Tor, in that there's 3 middle nodes and onion layers +- It's kinda like HTTP 1, except after the server responds, you turn the +connection into an arbitrary TCP connection. Maybe that's what the CONNECT +verb does? +- I will probably need a control channel some day, but not today + +So I don't need a general control stream, which means luckily I don't need +to worry about synchronizing between streams. The tip messages are enough +to get things going. + +Would the protocol be cleaner if the tip messages were explicitly layered? +I think so. As long as we aren't end-to-end encrypted (AND WE ARE NOT) this +gives P3, the relay server, a chance to be clever if we ever need it. + +So reviewing the above steps: + +In Step 2 the tip message says, "Connect me to P4 with ID 'bogus' and forward +this message to them". + +Between Steps 2 and 5, P3 re-wraps the inner message. P3 says to P4, +"P2 with ID 'bogus' wants to connect, and forwards this message" + +P4 receives that inner tip message in Step 5, and it says "Connect my port 2200 +to your port 22." + +There's no need for the actual port numbers to be used - It could be tokenized. +But for a prototype, I think it's fine. + +Since all parties trust P3, this makes it more clear that P2 and P4 may not +directly trust each other. P3 vouches for the identity of each. The response +from P4 is symmetrical with the request from P2. + +