-
Notifications
You must be signed in to change notification settings - Fork 0
How It Works
etr uses SSH only for the initial bootstrap — to start the server and exchange credentials securely. All subsequent terminal I/O flows over a persistent UDP connection that survives network interruptions.
1. etr SSHes to the remote host and starts etrs
2. etrs binds a random UDP port, prints it to stdout, and forks into the background
3. etr reads the port from SSH stdout; SSH closes
4. etr and etrs complete a 1-RTT encrypted handshake over UDP
5. Terminal I/O flows over the encrypted UDP session
6. On disconnect, etrs exits cleanly
TCP connections are tied to the network path — when your IP changes (Wi-Fi switch) or the link goes down, the TCP connection dies and takes your shell with it. UDP has no connection state in the kernel, so etr can reconnect from any address at any time without the OS getting in the way.
mosh is the inspiration for the bootstrap model. etr differs in a few ways:
- etr uses a proper bidirectional stream with replay and acknowledgement, not mosh's state-sync model
- etr supports post-quantum cryptography
- etr uses a 1-RTT handshake with forward secrecy via KEM key exchange
etr runs:
ssh -p <port> <host> etrs
and writes SESSION_ID/PASSKEY/TERM to the SSH process's stdin. etrs reads this, binds a UDP port, prints PORT <n> to stdout, then forks:
- Parent process: exits immediately → SSH sees the command return and closes cleanly
-
Child process: detaches from the terminal, redirects logs to
~/.local/state/etr/etrs.log, and runs the session
etr reads PORT <n> from SSH stdout before the connection closes, then connects to that UDP port.
The client sends a heartbeat every 5 seconds. If 15 seconds pass without any packet:
-
etrcloses the current UDP path -
etrsends a newClientHellowith the samesession_idand fresh ephemeral keys - The server matches on
session_id, re-runs the KEM handshake, and resumes the session - Both sides replay any unacknowledged data
The server holds session state (shell process, PTY, stream history) for 30 minutes after the last packet. The reconnecting client can come from a different IP or port — sessions are keyed by session_id, not network address.
Multiple logical streams share one session:
| Stream ID | Purpose |
|---|---|
| 0 | Terminal PTY (always present) |
| 1+ | Port-forward connections (future) |
Each stream has independent sequence numbers for ordered, reliable delivery and replay on reconnect.
| Process | Log location |
|---|---|
etr (client) |
~/.local/state/etr/etr.log (when running interactively with -v) |
etrs (server) |
~/.local/state/etr/etrs.log (on the remote host) |