Technical overview
This page goes over the technical details about Sandhole's inner workings. Feel free to skip this page if you are only interested in using Sandhole.
Secure Shell
SSH is a powerful protocol, with built-in features such as encryption and authentication. It's widely used to access remote servers, in order to get access to a shell or transfer Git repositories, for example.
One of its less known features is the ability to forward ports between the client and the server. With an OpenSSH server, it's possible to do:
- Local port forwarding: Accessing a port from the server, as if it were a local service on your machine.
- Remote port forwarding: Exposing a port from a local service to the server, as if it were a remote service running on the server.
See this post on SSH tunneling for more information.
Sandhole is capable of handling both, albeit in a different way than a regular OpenSSH server.
Reverse proxy
A reverse proxy is an intermediary server that receives and forwards requests to a backend service. They are commonly used to secure traffic, or expose servers behind a firewall/private network.
Sandhole is itself a reverse proxy. It leverages SSH for authentication and tunneling of services, while transparently handling client requests.
As such, it's possible to expose services publicly without needing a VPN, even when the private server is behind NAT or firewalls.
Example flow
Let's say that client A wishes to expose a local service, running on port 8080, to the Internet.
- Client A connects to a Sandhole instance while requesting a remote port forwarding:
ssh -p 2222 -R mytunnel:80:localhost:8080 sandhole.com.br
-
Sandhole handles the forwarding request and starts proxying requests from
http://mytunnel.sandhole.com.br
to client A's port 8080. -
Client B accesses
http://mytunnel.sandhole.com.br
through a web browser. -
Sandhole opens a tunneling channel over SSH to client A, simulating a TCP stream containing client B's request.
-
Client A's HTTP server replies over the SSH channel.
-
Sandhole forwards the reply to client B.
To client A, requests arrive normally at the socket, despite only having an outbound SSH connection; to client B, Sandhole transparently acts as if it were the service itself.
Here's the same flux in a sequence diagram:
sequenceDiagram participant SC as SSH client participant SS as SSH server participant M as Connection map participant HS as HTTP server participant HC as Web client Note over SC, M: Tunnel setup SC ->> SS: SSH connection + tcpip_forward SS ->> SS: Validate login SS ->> M: Register tunnel handler Note over SC, HC: Traffic routing HC ->>+ HS: HTTP request to assigned domain HS ->>+ M: Look up tunnel for domain M -->>- HS: Return tunnel handler HS ->>+ SS: Forward request via tunnel SS ->>+ SC: Relay to local service SC -->>- SS: Response from local service SS -->>- HS: Forward response HS -->>- HC: Return HTTP response