7.4 KiB
Tunneling
Holesail Browser supports three tunnel types: virtual hosts (for browsing), server tunnels (for sharing), and service tunnels (for raw TCP forwarding). All tunnels use the Holesail P2P network and are persisted across restarts.
How *.hole.sail browsing works
When you navigate to https://myapp.hole.sail/:
- The PAC script (set by the extension) matches
*.hole.sailand routes the request toPROXY 127.0.0.1:8442 - Chrome sends
CONNECT myapp.hole.sail:443 HTTP/1.1to the CONNECT proxy - The CONNECT proxy replies
200 Connection establishedand pipes the stream to127.0.0.1:8443 - The HTTPS proxy reads the TLS ClientHello, extracts the SNI hostname (
myapp.hole.sail), derives the wildcard parent (hole.sail), and presents the*.hole.sailwildcard cert signed by the local CA - The HTTPS proxy reads the
Hostheader, looks up the Holesail tunnel formyapp.hole.sail, and proxies the HTTP request to the tunnel's local port - The Holesail client tunnel forwards the request to the remote peer over the DHT
All traffic between the browser and proxy is TLS-encrypted using a locally-trusted certificate. Traffic between the native host and the remote peer is encrypted via the Noise protocol.
Virtual hosts
Virtual hosts map an hs:// key to a *.hole.sail hostname. The browser navigates to the hostname; the proxy looks up the tunnel and forwards the request.
Adding a virtual host
- Open the dashboard → Virtual Hosts
- Enter a hostname (e.g.
myapp.hole.sail) and thehs://key for the remote peer - Click Add — the tunnel connects immediately and the entry is saved to
state.json
Hostname rules
- Must have at least 3 labels (e.g.
myapp.hole.sail, nothole.sail) - The TLD portion must be two-tier (e.g.
.hole.sail,.my.internal) — single-label TLDs like.holesailare not allowed - Must not use a real public TLD (
.com,.net,.co.uk, etc.) - Each label may contain only lowercase letters, digits, and hyphens; no leading or trailing hyphens
- Any depth is supported:
myapp.hole.sail,i.love.hole.sail,api.v2.my.internal - You are not limited to
.hole.sail— any valid private two-tier TLD works (see VIRTUAL-HOSTS.md)
Port allocation
Each virtual host gets a local port allocated from 19000 upward. The HTTPS proxy forwards requests for that hostname to 127.0.0.1:<allocated-port>. Ports are released when the virtual host is removed.
Lifecycle events
The native host emits events that the extension relays to subscribed tabs:
| Event | Description |
|---|---|
tunnelReady |
Tunnel connected and ready to serve requests |
tunnelClosed |
Tunnel disconnected (peer went offline or was removed) |
tunnelError |
Tunnel failed to connect |
Persistence
Virtual hosts are saved to state.json and restored on every native host startup. The tunnel reconnects automatically — if the remote peer is temporarily offline, the tunnel will reconnect when it comes back.
Removing a virtual host
Open the dashboard → Virtual Hosts → click the remove button. The tunnel is closed and the entry is deleted from state.json.
Server tunnels
Server tunnels expose a local TCP (or UDP) port as an hs:// key. Other peers can connect to your service using that key.
Creating a server tunnel
- Open the dashboard → Server Tunnels
- Optionally enter a Label (e.g.
My Web App) to identify the tunnel - Enter the local port to expose (e.g.
3000) - Select TCP or UDP
- Optionally enable Secure mode (requires the connecting peer to have the key)
- Click Start — an
hs://key is generated and displayed
Share the hs:// key with anyone who should be able to connect to your service.
Parameters
| Parameter | Description |
|---|---|
label |
Optional human-readable name shown in the dashboard |
port |
Local port to expose |
host |
Local host to bind (default: 127.0.0.1) |
udp |
Use UDP instead of TCP (default: false) |
secure |
Require key authentication (default: true) |
Persistence
Server tunnels are saved to state.json and restarted on every native host startup. The hs:// key is stable — it is derived from the server's keypair, which is preserved in state.
Stopping a server tunnel
Open the dashboard → Server Tunnels → click Stop. The tunnel is closed and the entry is deleted from state.json.
Service tunnels
Service tunnels forward a remote hs:// peer to a local TCP port. Any local application can connect to 127.0.0.1:<port> and communicate with the remote peer directly — without going through the browser proxy.
Use cases:
- Connect a local database client to a remote database over Holesail
- Forward a remote TCP service to a local port for use by any application
- Expose a Minecraft server, game server, or other TCP service locally
Creating a service tunnel
- Open the dashboard → Service Tunnels
- Enter a label (e.g.
Postgres), thehs://key, and the local port to bind - Click Start — the tunnel connects and begins listening on the specified port
Parameters
| Parameter | Description |
|---|---|
label |
Human-readable name |
hsUrl |
hs:// key for the remote peer |
localPort |
Local TCP port to bind |
Persistence
Service tunnels are saved to state.json and restored on startup.
Reconnecting a service tunnel
If a service tunnel enters an error or closed state, click Reconnect in the dashboard. This sends an updateServiceTunnel command to the native host, which stops the old tunnel (if any) and starts a fresh one with the same parameters.
Stopping a service tunnel
Open the dashboard → Service Tunnels → click Stop.
Tunnel lookup
You can check whether an hs:// key is reachable on the DHT without creating a full tunnel. This is useful for verifying a key before adding it as a virtual host or service tunnel.
From the dashboard → Virtual Hosts or Service Tunnels, use the lookup/test button next to the hs:// field.
Tunnel type comparison
| Feature | Virtual Host | Server Tunnel | Service Tunnel |
|---|---|---|---|
| Direction | Inbound (you browse to remote) | Outbound (remote connects to you) | Inbound (you connect to remote) |
| Access method | Browser via *.hole.sail URL |
hs:// key shared with peers |
Local TCP port |
| Protocol | HTTPS (TLS terminated locally) | TCP or UDP | TCP |
| Use case | Browse remote web apps | Share local services | Connect local apps to remote services |
| Persisted | Yes | Yes | Yes |
Troubleshooting
No tunnel for this hostname
The HTTPS proxy received a request for a hostname it has no tunnel for. Causes:
- The tunnel is still connecting — wait a few seconds and refresh
- The native host restarted and is still restoring tunnels — open the dashboard to check
- The hostname doesn't exactly match what was configured (check for typos)
Tunnel shows connecting but never becomes ready
- The remote peer may be offline
- The
hs://key may be incorrect - Check
~/.holesail-browser/holesail-browser.logfor error details - Try setting
readyTimeoutMsto30000in Settings to surface timeout errors
Service tunnel port is already in use
Another process is using the requested local port. Choose a different port, or stop the conflicting process.