📝 planning

main
_ 2021-07-17 06:08:00 +00:00
parent 73d7551215
commit 8a976be3be
1 changed files with 114 additions and 4 deletions

View File

@ -1,14 +1,124 @@
# Testing # Testing
There are 5 processes, so you'll need 5 terminal windows or screen / tmux There are 5 processes, so you'll need 5 terminal windows or screen / tmux
sessions: sessions:
1. TCP end server: `nc -l -p 30382` 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` 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` 3. Server-side proxy: `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` 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` 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. 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.