Skip to content

Latest commit

 

History

History
227 lines (161 loc) · 6.1 KB

File metadata and controls

227 lines (161 loc) · 6.1 KB

Hole — P2P SSH over HyperDHT

Zero port-forwarding. Zero VPN. Zero accounts.

Hole connects any two machines over the Holepunch / HyperDHT stack. Each agent announces itself on a distributed hash table; clients punch through NAT and connect directly — or via a relay when both sides are behind strict CGNAT.

client ──[HyperDHT]── agent
           (or)
client ──[relay]──── agent

What you get

Feature Description
hole ssh One-command interactive SSH through the tunnel
hole exec Run a command remotely, get output, exit
hole copy scp-style file transfer over P2P
hole client Expose any TCP service (RDP, HTTP, DB…) locally
hole dashboard Browser fleet UI — terminals, tunnels, exec, files, ACLs
hole relay Self-hosted relay for CGNAT / mobile networks
hole agent Daemon that announces the machine on the DHT

State lives in ~/.hole/ — keypair, device registry, ACL, audit log.


Install

From source

git clone https://github.com/Annatar3/Hole && cd Hole
npm install
npm link          # puts `hole` on your PATH
hole help

Prebuilt binary

Grab the binary for your OS from the Releases page, then:

chmod +x hole
./hole help

To build your own binaries:

npm run build     # outputs to dist/

Quick start

Step 1 — start the agent (on the remote machine)

./hole agent --name my-server
# Key : 9320641058af2f76abd1...  ← copy this

Leave it running. Optionally install it as a service.

Step 2 — register the key (on your laptop)

hole add my-server 9320641058af2f76abd1... \
  --user alice \
  --identity ~/.ssh/id_ed25519   # optional

Step 3 — connect

hole ssh my-server

That's it. Hole opens the P2P tunnel and drops you into an SSH session. The tunnel closes when you exit.


Relay mode (CGNAT / mobile)

When direct hole-punching fails, run a relay on any VPS with a public IP:

# On the VPS — open UDP 49737 inbound in your firewall
./hole relay

# Agent side
./hole agent --name my-server --relay <vps-ip>:49737

# Client side
hole add my-server <key> --relay <vps-ip>:49737
hole ssh my-server

Traffic is still end-to-end encrypted; the relay only shuffles UDP packets.


Multiple services per host

Each forwarded service gets its own key derived from the agent's master key:

# Agent
./hole agent --name my-pc \
  --forward rdp:3389 \
  --forward web:127.0.0.1:3000

# Client — SSH works as before
hole ssh my-pc

# Open a local port for RDP
hole client my-pc rdp
# → connect your RDP client to localhost:<printed-port>

# Open a local port for the web service
hole client my-pc web --port 8080

Web dashboard

hole dashboard
# → http://localhost:4321/?token=<auto-generated-token>

The token is generated once and stored in ~/.hole/dashboard-token. It's embedded in the URL printed on start, so just open that link.

What the dashboard gives you:

  • Fleet sidebar — all registered devices, online/offline status, latency, search and tag filter
    • + Add device — register a new device from the browser, no CLI needed
    • Remove button in the Details tab to delete a device
  • Details tab — edit per-device user, relay, identity, tags, and service-key mappings
  • Terminal tab — full interactive SSH session in the browser (xterm.js + node-pty)
  • Tunnels tab — open / close local tunnel ports from the UI; tunnels survive dashboard restarts
  • Exec tab — run a shell command on the current device, all devices, or a tag-filtered subset; results shown per-device with timing
  • Files tab — browse and transfer files (15 s timeout per operation)
  • ACL tab — manage ~/.hole/acl.json on the remote host directly from the browser
  • Audit tab — recent connection events, exportable to CSV

ACLs

By default any client that knows a service key can connect. To restrict access:

# On the agent host
hole acl add laptop <64-char-client-public-key>
hole acl list
hole acl remove laptop

An empty ACL means open mode — any key is accepted.


Run as a service

Linux (systemd user service)

# On the agent host
hole install-service --name my-server
systemctl --user status hole-agent

# Remove
hole uninstall-service

Creates ~/.config/systemd/user/hole-agent.service. Starts on login, restarts on failure.

Windows (Task Scheduler)

hole.exe install-service --name my-server
# Remove
hole.exe uninstall-service

Diagnostics

hole doctor           # checks outbound TCP 443, UDP bind, DHT bootstrap
hole ping my-server   # latency + reachability
hole audit --tail 20  # recent connection events

If doctor passes and ping returns a latency, everything is working. If ping shows the device as offline, try adding --relay <host>:<port> to both sides.


Commands

Command What it does
hole agent [--name N] [--relay host:port] [--forward svc:port] Start the agent daemon
hole ssh <device> [user] [-- extra-ssh-args] Open an interactive SSH session
hole exec <device> <user> -- <cmd> Run a command, capture output, exit
hole copy <src> <dest> [user] Copy files (device:/path for remote side)
hole client <device> [service] [--port N] Expose a TCP service locally
hole relay [--port N] Run a relay server
hole dashboard Start the web dashboard
hole add <name> <key> [--user U] [--relay R] [--identity I] Register a device
hole remove <name> Remove a device
hole list List registered devices
hole ping <device> Check reachability
hole status <device> Detailed device status
hole install-service [--name N] Install agent as a system service
hole uninstall-service Remove the system service
hole acl list | add | remove Manage connection ACL on the agent
hole audit [--tail N] View audit log
hole doctor Environment health check