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

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.

A diagram displaying Sandhole’s usage as a reverse proxy. It’s deployed to a public server, where a local service connects to its SSH port. A remote service in a private server also connects to the SSH port over the Internet. Meanwhile, a client’s web browser connects to the HTTPS port of Sandhole over the Internet.

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.

A diagram showing a connection to Sandhole’s HTTP proxy in six steps.

  1. Client A connects to a Sandhole instance while requesting a remote port forwarding:
ssh -p 2222 -R mytunnel:80:localhost:8080 sandhole.com.br
  1. Sandhole handles the forwarding request and starts proxying requests from http://mytunnel.sandhole.com.br to client A’s port 8080.

  2. Client B accesses http://mytunnel.sandhole.com.br through a web browser.

  3. Sandhole opens a tunneling channel over SSH to client A, simulating a TCP stream containing client B’s request.

  4. Client A’s HTTP server replies over the SSH channel.

  5. 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:

A sequence diagram showing an SSH client connecting to Sandhole’s SSH server to register a tunnel handler during tunnel setup, before a web client connects to Sandhole’s HTTP server and their request is forwarded to the local service, while the response follows the opposite path.