Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

How does it work?

Recall the architecture:

graph LR

LE(("Let's<br>Encrypt")) --ACME--- bCaddy
p3>"p3.cse561.cfm.yers.net"] --CNAME--> front

ICMP>"ICMP"] --DNAT--> fWireGuard
HTTP>"HTTP<br>tcp/80"] --DNAT--> fWireGuard
HTTPS>"HTTPS<br>tcp/443"] --DNAT--> fWireGuard

HTTP/1337>"HTTP<br>tcp/1337"] --> OliveTin

subgraph front["front [1]"]
fWireGuard["WireGuard<br>10.0.0.2/30"] --> fUdp2Tcp["udp2tcp<br>udp/51280"] --> fSocat["socat<br>tcp/51280"] --> fTor["Tor<br>tcp/9050"]

OliveTin["OliveTin [3]"]
end

fTor -.-> bTor

subgraph "back [2]"
bTor["Tor"] --> bTcp2Udp["tcp2udp<br>tcp/51280"] --> bWireGuard["WireGuard<br>udp/51280<br>10.0.0.1/30"] --> bCaddy --> bMdBook
bTor -."ypg...xid.onion [4]".-> bWireGuard

bCaddy["Caddy<br>tcp/80<br>tcp/443"]
bMdBook["mdBook [5]<br>tcp/3000"]
end

Tunneling

back is a WireGuard server exposing WireGuard’s port 51280 only via the onion service ypgjydaneoergw5mfvktrw24mbxflv545xd2zaehoklg3fm4ddh5mxid.onion.

front establishes a WireGuard tunnel to back:

sequenceDiagram
autonumber

participant you
box front
participant fIptables as iptables
participant fWireGuard as wg0<br>10.0.0.2
participant fUdp2tcp as udp2tcp
participant fSocat as socat
participant fTor as tor
end

box back
participant bTor as tor
participant bTcp2udp as tcp2udp
participant bWireGuard as wg0<br>10.0.0.1
end

fWireGuard ->> fUdp2tcp: IP 127.0.0.1.54321 > 127.0.0.1.51280: UDP
fUdp2tcp ->> fSocat: IP 127.0.0.1.54321 > 127.0.0.1.51280: TCP
fSocat ->> fTor: IP 127.0.0.1.54321 > ypg...xid.onion.51280: TCP
activate fTor
fTor -->> bTor: Tor circuit via<br>onion-service rendezvous
activate bTor
bTor ->> bTcp2udp: IP 127.0.0.1.54321 > 127.0.0.1.51280: TCP
bTcp2udp ->> bWireGuard: IP 127.0.0.1.54321 > 127.0.0.1.51280: UDP

bWireGuard ->> bTcp2udp: IP 127.0.0.1.51280 > 127.0.0.1.54321: UDP
bTcp2udp ->> bTor: IP 127.0.0.1.51280 > 127.0.0.1.54321: TCP
deactivate bTor
bTor -->> fTor: ...

fTor ->> fSocat: IP ypg...xid.onion.51280 > 127.0.0.1.54321: TCP
deactivate fTor

fSocat ->> fUdp2tcp: IP 127.0.0.1.51280 > 127.0.0.1.54321: UDP
fUdp2tcp ->> fWireGuard: IP 127.0.0.1.51280 > 127.0.0.1.54321: UDP

You may notice something a little funky here: Why is it okay for udp2tcp to listen on UDP port 51280 and forward to socat on TCP port 51280? Per (at least) RFC 6335 §7.2, each transport protocol technically has its own multiplexting namespace, even if each draws their multiplexing keys from the same numerical range of ports. So, as notated in the architecture diagram above, udp2tcp and socat aren’t both listening on “port 51280” but on ports udp/51280 and tcp/51820, respectively. This makes the translation they’re performing more transparent.

Forwarding and NAT

Consider the path of a humble ICMP echo request you might send:

$ ping -c 1 p3.cse561.cfm.yers.net
sequenceDiagram
autonumber

participant you
box front
participant fIptables as iptables
participant fWireGuard as wg0<br>10.0.0.2
participant fUdp2tcp as udp2tcp
participant fSocat as socat
participant fTor as tor
end

box back
participant bTor as tor
participant bTcp2udp as tcp2udp
participant bWireGuard as wg0<br>10.0.0.1
end

you ->> fIptables: IP A.B.C.D > 147.182.239.175: ICMP echo request

fIptables ->> fWireGuard: IP 10.0.0.2 > 10.0.0.1: ICMP echo request
activate fWireGuard
Note over fWireGuard, bWireGuard: Tunneled as above:
fWireGuard ->> bWireGuard: IP 10.0.0.2 > 10.0.0.1: ICMP echo request
activate bWireGuard
bWireGuard ->> fWireGuard: IP 10.0.0.1 > 10.0.0.2: ICMP echo reply
deactivate bWireGuard
fWireGuard ->> fIptables: IP 10.0.0.1 > 10.0.0.2: ICMP echo reply
deactivate fWireGuard
fIptables ->> you: IP 147.182.239.175 > A.B.C.D: ICMP echo reply

See “What” for how you can tell that the machine actually replying to your ICMP echo request is behind a Tor onion service.