How Tor actually routes your traffic
May 31, 2026
This is the first post in a three-part series built around hop6, a peer-to-peer terminal messenger I wrote that speaks only over Tor.
- How Tor actually routes your traffic (this post)
- Onion services and the rendezvous protocol
- Building hop6
Before any of hop6 makes sense, you need a clear picture of what Tor does to a packet. So this post ignores hop6 entirely and builds onion routing up from ordinary networking.
What ordinary routing leaks
When you open a normal TCP connection, every packet carries a source IP and a destination IP in the clear. Routers along the path read those addresses to forward the packet. That is the whole point: the network has to know where a packet is going.
you ISP / backbone routers server
1.2.3.4 ───▶ R1 ───▶ R2 ───▶ R3 ───▶ R4 ───▶ 93.184.x.x
src=1.2.3.4 dst=93.184.x.x (visible to every hop)
Even with TLS, the contents are encrypted but the metadata is not. Your ISP sees which servers you talk to, when, and how much. The server sees your IP. Any router in between sees both endpoints. The link between “who you are” and “what you are doing” is sitting right there in every packet header.
Onion routing breaks that link.
The core idea: layered encryption
Instead of talking to the destination directly, a Tor client relays its traffic through a chain of three volunteer relays, and wraps the data in three layers of encryption, one per relay. Each relay can peel exactly one layer. That layer tells it only one thing: who to hand the packet to next.
message wrapped in 3 layers (think of an onion):
┌─────────────────────────────────────────┐
│ E_guard( E_middle( E_exit( data ) ) ) │
└─────────────────────────────────────────┘
guard peels E_guard → sees "send rest to middle"
middle peels E_middle → sees "send rest to exit"
exit peels E_exit → sees the actual data + destination
No single relay holds the whole picture:
relay knows who sent to it knows final destination knows payload
────── ──────────────────── ─────────────────────── ────────────
guard YES (your IP) no no
middle no (only guard) no no
exit no (only middle) YES YES (if not TLS)
The guard knows your IP but not where you are going. The exit knows the destination but not who you are. The middle knows neither and exists precisely so the guard and exit never talk directly.
Building the circuit (telescoping)
The client cannot just send a triple-wrapped packet out of nowhere; it first has to agree on a separate encryption key with each relay, without the later relays learning the client’s identity. Tor does this by extending the circuit one hop at a time, a process called telescoping.
step 1: you ⇄ guard (handshake, derive key K1)
step 2: you ⇄ guard ⇄ middle (handshake through guard, derive K2)
step 3: you ⇄ guard ⇄ middle ⇄ exit (handshake through middle, derive K3)
Each handshake is an authenticated Diffie-Hellman exchange (Tor’s “ntor” handshake, built on Curve25519). Two things matter about it:
- The client authenticates the relay using the relay’s published identity key, so a man in the middle cannot impersonate a relay.
- The shared key is derived from fresh ephemeral values, which gives forward secrecy: recording the traffic and stealing a relay’s long-term key later does not let an attacker decrypt past sessions.
Crucially, the middle and exit relays complete their handshakes through the existing partial circuit. They never see the client’s IP; they only ever see the hop before them.
Cells: everything is the same size
Tor does not send arbitrary-length packets between relays. It chops traffic into fixed-size cells (512 bytes in the classic design). Fixed-size units make it much harder for an observer to fingerprint traffic by packet size, and they keep the relay logic uniform.
variable-length app data
│ split + padded
▼
[cell][cell][cell][cell] ... all identical in size
Where the relay list comes from
A client cannot trust a random relay it found somewhere. Tor runs a small set of directory authorities: trusted servers that, once an hour, vote on and sign a consensus document listing every known relay, its keys, and its flags (is it a valid guard, an exit, how much bandwidth, and so on). Clients download this consensus and pick relays from it. The signatures are what stop an attacker from feeding you a list of relays they control.
Guards: why the first hop is sticky
If a client picked three fresh random relays for every circuit, then over enough circuits it would eventually pick an attacker-controlled relay as the first hop, and an attacker who controls your first and last hop can often de-anonymize you by correlating timing. To limit this exposure, Tor picks a small, stable set of entry guards and reuses them for a long time. You are either unlucky once and stuck with it, or (much more likely) fine for months. It trades a little unlinkability for a large reduction in the chance of full compromise.
What Tor does and does not protect
Onion routing hides the link between your identity and your destination from any single relay and from network observers. It does not magically encrypt the last hop to the destination: the exit relay sees whatever the client sends it, so if you speak plain HTTP, the exit can read it. Use TLS end to end and the exit sees only ciphertext and the hostname.
It is also not a defense against a global passive adversary who can watch both ends of a circuit at once; traffic-correlation attacks remain the hard, open problem of low-latency anonymity networks.
The piece this leaves out
Everything above describes reaching the ordinary internet through an exit relay.
But hop6 has no servers and never touches the clearnet: two peers talk directly,
each reachable at a .onion address, with no exit node anywhere in the path. That
needs a different mechanism entirely, the one that makes the address itself a
public key and lets two hidden parties meet without either learning the other’s
location.
That is onion services and the rendezvous protocol, in part 2.