Pinggy
Public reverse tunnels to localhost using SSH remote forwarding or the Pinggy CLI. Use for authorized dev/test ingress, webhook capture, controlled lab callbacks, and temporary remote access without router port forwarding.
Scope Guard
- Confirm the exposed service, audience, time window, and authorization before creating a public URL or port.
- Default to short-lived tunnels, strong app-layer auth, and IP allowlists for anything sensitive.
- Do not expose admin consoles, databases, model servers, MCP tools, or shells to the internet without explicit access controls and owner approval.
- Prefer
tls for end-to-end encrypted HTTPS services when Pinggy must not inspect HTTP content; HTTP tunnels terminate at Pinggy to provide debugger and header features.
Choose the Mode
| Need |
Mode |
Pattern |
Notes |
| Share web app/API/webhook |
http default |
ssh -p 443 -R0:localhost:8000 free.pinggy.io |
Provides HTTP+HTTPS URLs, debugger, auth, header manipulation. |
| Expose arbitrary TCP service |
tcp |
ssh -p 443 -R0:localhost:22 tcp@free.pinggy.io |
Returns host+port; use for SSH, databases, listeners, raw protocols. |
| End-to-end HTTPS by SNI |
tls |
ssh -p 443 -R0:localhost:8443 tls@free.pinggy.io |
No public TCP port; visitor connects to generated domain on 443; local service terminates TLS. |
| TCP with optional TLS wrapper |
tlstcp |
ssh -p 443 -R0:localhost:8000 tlstcp@free.pinggy.io |
Gives TCP port plus TLS endpoint that terminates at Pinggy then forwards plaintext. |
| Expose UDP service |
udp |
./pinggy --type udp -l 8000 |
UDP requires Pinggy CLI/Docker; SSH-only form is not supported. |
| Persistent name/port |
Pro token |
ssh -p 443 -R0:localhost:8000 TOKEN@pro.pinggy.io |
Use token, dashboard, custom/persistent domains, persistent TCP/UDP ports. |
Quick Starts
# HTTP(S) via OpenSSH
ssh -p 443 -R0:localhost:8000 free.pinggy.io
# HTTP(S) with QR code in terminal
ssh -p 443 -R0:localhost:8000 qr@free.pinggy.io
# TCP tunnel to local SSH
ssh -p 443 -R0:localhost:22 tcp@free.pinggy.io
# TLS tunnel to local HTTPS service
ssh -p 443 -R0:localhost:8443 tls@free.pinggy.io
# CLI equivalents
pinggy -l 8000
pinggy --type tcp -l 22
pinggy --type udp -l 51820
# Docker HTTP tunnel on Linux
docker run --net=host -it pinggy/pinggy -p 443 -R0:localhost:8000 a.pinggy.io
On Windows, if localhost fails through OpenSSH, retry with 127.0.0.1.
SSH Grammar
ssh -p443 -R0:<local_host>:<local_port> [more -R rules] [<token>+<keywords>@]a.pinggy.io [remote options]
Useful SSH flags:
| Flag |
Use |
-p 443 |
Pinggy listens on 443 to pass most egress firewalls. |
-R0:localhost:PORT |
Expose exactly one local service; Pinggy assigns remote URL/port. |
-L4300:localhost:4300 |
Open local access to the Web Debugger UI/API. |
-t |
Allocate TTY; needed for rich UI and command-line options like auth/header controls. |
-T |
Disable rich terminal UI for scripts. |
-N |
Disables remote command execution; avoid when using debugger/header/auth features. |
Username keywords are joined with +: TOKEN+tcp+force@a.pinggy.io, qr@a.pinggy.io, TOKEN+tls@pro.pinggy.io.
| Keyword |
Effect |
http, tcp, tls, tlstcp |
Select tunnel type; HTTP is default. |
qr, aqr |
Print Unicode or ASCII QR code for quick mobile access. |
auth |
Force SSH password prompt compatibility; any string/blank password is acceptable. |
force |
Disconnect an existing tunnel using the same token before reconnecting. |
HTTP Controls
Append these after the SSH destination and use -t:
# Basic auth; username/password cannot contain ':'
ssh -p 443 -R0:localhost:8000 -t free.pinggy.io b:user:pass
# Multiple bearer keys: visitor sends Authorization: Bearer <key>
ssh -p 443 -R0:localhost:8000 -t free.pinggy.io k:key1 k:key2
# IP/CIDR allowlist
ssh -p 443 -R0:localhost:8000 -t free.pinggy.io w:203.0.113.10/32
# HTTPS-only redirect, CORS preflight pass-through, original URL header
ssh -p 443 -R0:localhost:8000 -t free.pinggy.io x:https x:passpreflight x:fullurl
# Local service expects HTTPS/TLS
ssh -p 443 -R0:localhost:8443 -t free.pinggy.io x:localServerTls:example.com
# Header manipulation: append, remove, update
ssh -p 443 -R0:localhost:8080 -t free.pinggy.io a:X-Lab:pinggy r:Referer u:Host:example.com
Other controls:
| Option |
Purpose |
x:xff[:Header-Name] |
Add source IP header, or use a custom header name. |
x:noreverseproxy |
Disable default reverse-proxy headers for HTTP tunnels. |
x:passpreflight |
Let unauthenticated CORS preflight requests pass when auth is enabled. |
a:Header:Value |
Append request header. |
r:Header |
Remove request header. |
u:Header:Value |
Replace request header; useful for Host. |
Web Debugger
ssh -p 443 -R0:localhost:8080 -L4300:localhost:4300 a.pinggy.io
# Open http://localhost:4300
# API examples: GET /urls, GET /ipwhitelist
Use it to inspect requests/responses, replay modified HTTP requests, verify webhook payloads, and compare proxy headers before involving Burp, ZAP, mitmproxy, or app logs. Do not use HTTP debugger mode for secrets that Pinggy should not see; choose tls instead.
Multi-Forwarding and Domains
Pro tokens can route multiple services through one session, especially with wildcard custom domains.
ssh -p 443 \
-R http//app.example.com:1:localhost:3000 \
-R http//api.example.com:1:localhost:8080 \
-R tcp//ssh.example.com/34567:1:localhost:22 \
-R 1:localhost:80 \
TOKEN@pro.pinggy.io
Listen address syntax: [schema//]hostname[/port][@name]. Schemas include http, tcp, tls, tlstcp, and udp. Custom domains use CNAME where possible; apex/root domains use relay setup. Relay-based custom domains do not support UDP, so use persistent subdomains/ports for UDP.
Offensive Lab Synergies
Use Pinggy as the public ingress layer; pair it with specialist tools locally.
| Workflow |
Pinggy role |
Pair with |
| Webhook and API testing |
Public HTTPS receiver to localhost |
Burp Suite, ZAP, mitmproxy, curl, jq, app logs |
| Controlled reverse-callback labs |
Public TCP port to an owned listener |
ncat/socat, Metasploit handlers, tcpdump, Wireshark |
| External service validation |
Temporary public host/port for owned service |
nmap, httpx, nuclei, testssl, browser devtools |
| Header/auth edge cases |
Modify Host, XFF, bearer/basic auth, CORS |
Burp Repeater, ZAP Manual Request, mitmproxy scripts |
| IoT and remote admin |
TCP tunnel to SSH/dashboard on owned device |
ssh, scp, rsync, netdata, Home Assistant |
| Database or cache demos |
TCP tunnel with allowlist to local DB |
psql, mysql, redis-cli, mongosh, sqlmap only against owned labs |
| UDP service tests |
CLI/Docker UDP tunnel |
WireGuard lab, game servers, VoIP/game protocol tooling |
| Reverse proxy routing |
Wildcard domain + multi-forwarding |
Traefik, nginx, Kubernetes port-forward, Docker Compose |
When an operation needs SOCKS pivoting through a compromised host, prefer chisel. Use Pinggy when a public SaaS ingress endpoint is acceptable and fast setup matters more than stealth or routing.
CLI, SDK, Docker, and APIs
# CLI install and basic use
npm install -g pinggy
pinggy --help
pinggy -l 8000
pinggy --type tcp -l 22
pinggy --serve /path/to/files
# Saved configs and auto-start
pinggy config save my-tunnel -l 3000 TOKEN@pro.pinggy.io
pinggy start my-tunnel
pinggy start --all
pinggy start --all --remote-management <API_KEY>
- CLI has auto-reconnect, JSON-style saved configuration, file-server mode, logging, and remote management.
- Node.js SDK: use
@pinggy/pinggy, pinggy.forward({ forwarding: "localhost:5000" }), then read tunnel.urls().
- Python SDK: install
pinggy, then pinggy.start_tunnel(forwardto="localhost:8000").
- Pro API can list active tunnels and query session history with
Authorization: Bearer <API_KEY>.
Egress-Constrained Clients
# HTTP proxy with nc/ncat
ssh -p443 -R0:localhost:4000 -o ProxyCommand="nc -X connect -x 192.0.2.10:3128 %h %p" a.pinggy.io
ssh -p443 -R0:localhost:4000 -o ProxyCommand="ncat --proxy-type http --proxy 192.0.2.10:3128 %h %p" a.pinggy.io
# SSH-over-SSL when only TLS egress is allowed
ssh -p443 -R0:localhost:4000 -o ProxyCommand="openssl s_client -quiet -connect %h:%p" a.pinggy.io
ssh -p7878 -R0:localhost:4000 -o ProxyCommand="ncat --ssl %h %p" a.pinggy.io
Use these only when policy allows outbound proxy/TLS tunneling. On Windows, PuTTY proxy settings or installed OpenSSL/ncat can fill the same role.
Troubleshooting
| Symptom |
Fix |
| Password prompt |
Press Enter, type any string, or generate an SSH key for long-running tunnels. |
| Windows tunnel cannot reach service |
Replace localhost with 127.0.0.1. |
| URL changes |
Free tunnels are random and time-limited; use Pro persistent subdomain/custom domain. |
| UDP not working with SSH |
Use Pinggy CLI or Docker; SSH-only UDP is not supported. |
| Advanced options ignored |
Add -t and avoid -N. |
| Token already active |
Stop it in dashboard or use TOKEN+force@.... |
| Sensitive data visible in debugger |
Switch from HTTP to tls and terminate TLS locally. |
| Public exposure too broad |
Add b:, k:, w:, shorten runtime, or bind local service to a disposable lab instance. |
Resources
| File |
When to load |
references/usage-matrix.md |
Full use-case coverage, offensive lab pairings, quickstart recipe taxonomy, and feature-to-protocol mapping. |
1---2name: pinggy3description: Auth/lab ref: Pinggy localhost tunneling service for HTTP(S), TCP, UDP, TLS, and TLSTCP tunnels over SSH, Pinggy CLI, Docker, GUI app, Node.js SDK, or Python SDK.4license: MIT5---67# Pinggy89Public reverse tunnels to localhost using SSH remote forwarding or the Pinggy CLI. Use for authorized dev/test ingress, webhook capture, controlled lab callbacks, and temporary remote access without router port forwarding.1011## Scope Guard1213- Confirm the exposed service, audience, time window, and authorization before creating a public URL or port.14- Default to short-lived tunnels, strong app-layer auth, and IP allowlists for anything sensitive.15- Do not expose admin consoles, databases, model servers, MCP tools, or shells to the internet without explicit access controls and owner approval.16- Prefer `tls` for end-to-end encrypted HTTPS services when Pinggy must not inspect HTTP content; HTTP tunnels terminate at Pinggy to provide debugger and header features.1718## Choose the Mode1920| Need | Mode | Pattern | Notes |21|---|---|---|---|22| Share web app/API/webhook | `http` default | `ssh -p 443 -R0:localhost:8000 free.pinggy.io` | Provides HTTP+HTTPS URLs, debugger, auth, header manipulation. |23| Expose arbitrary TCP service | `tcp` | `ssh -p 443 -R0:localhost:22 tcp@free.pinggy.io` | Returns host+port; use for SSH, databases, listeners, raw protocols. |24| End-to-end HTTPS by SNI | `tls` | `ssh -p 443 -R0:localhost:8443 tls@free.pinggy.io` | No public TCP port; visitor connects to generated domain on 443; local service terminates TLS. |25| TCP with optional TLS wrapper | `tlstcp` | `ssh -p 443 -R0:localhost:8000 tlstcp@free.pinggy.io` | Gives TCP port plus TLS endpoint that terminates at Pinggy then forwards plaintext. |26| Expose UDP service | `udp` | `./pinggy --type udp -l 8000` | UDP requires Pinggy CLI/Docker; SSH-only form is not supported. |27| Persistent name/port | Pro token | `ssh -p 443 -R0:localhost:8000 TOKEN@pro.pinggy.io` | Use token, dashboard, custom/persistent domains, persistent TCP/UDP ports. |2829## Quick Starts3031```bash32# HTTP(S) via OpenSSH33ssh -p 443 -R0:localhost:8000 free.pinggy.io3435# HTTP(S) with QR code in terminal36ssh -p 443 -R0:localhost:8000 qr@free.pinggy.io3738# TCP tunnel to local SSH39ssh -p 443 -R0:localhost:22 tcp@free.pinggy.io4041# TLS tunnel to local HTTPS service42ssh -p 443 -R0:localhost:8443 tls@free.pinggy.io4344# CLI equivalents45pinggy -l 800046pinggy --type tcp -l 2247pinggy --type udp -l 518204849# Docker HTTP tunnel on Linux50docker run --net=host -it pinggy/pinggy -p 443 -R0:localhost:8000 a.pinggy.io51```5253On Windows, if `localhost` fails through OpenSSH, retry with `127.0.0.1`.5455## SSH Grammar5657```text58ssh -p443 -R0:<local_host>:<local_port> [more -R rules] [<token>+<keywords>@]a.pinggy.io [remote options]59```6061Useful SSH flags:6263| Flag | Use |64|---|---|65| `-p 443` | Pinggy listens on 443 to pass most egress firewalls. |66| `-R0:localhost:PORT` | Expose exactly one local service; Pinggy assigns remote URL/port. |67| `-L4300:localhost:4300` | Open local access to the Web Debugger UI/API. |68| `-t` | Allocate TTY; needed for rich UI and command-line options like auth/header controls. |69| `-T` | Disable rich terminal UI for scripts. |70| `-N` | Disables remote command execution; avoid when using debugger/header/auth features. |7172Username keywords are joined with `+`: `TOKEN+tcp+force@a.pinggy.io`, `qr@a.pinggy.io`, `TOKEN+tls@pro.pinggy.io`.7374| Keyword | Effect |75|---|---|76| `http`, `tcp`, `tls`, `tlstcp` | Select tunnel type; HTTP is default. |77| `qr`, `aqr` | Print Unicode or ASCII QR code for quick mobile access. |78| `auth` | Force SSH password prompt compatibility; any string/blank password is acceptable. |79| `force` | Disconnect an existing tunnel using the same token before reconnecting. |8081## HTTP Controls8283Append these after the SSH destination and use `-t`:8485```bash86# Basic auth; username/password cannot contain ':'87ssh -p 443 -R0:localhost:8000 -t free.pinggy.io b:user:pass8889# Multiple bearer keys: visitor sends Authorization: Bearer <key>90ssh -p 443 -R0:localhost:8000 -t free.pinggy.io k:key1 k:key29192# IP/CIDR allowlist93ssh -p 443 -R0:localhost:8000 -t free.pinggy.io w:203.0.113.10/329495# HTTPS-only redirect, CORS preflight pass-through, original URL header96ssh -p 443 -R0:localhost:8000 -t free.pinggy.io x:https x:passpreflight x:fullurl9798# Local service expects HTTPS/TLS99ssh -p 443 -R0:localhost:8443 -t free.pinggy.io x:localServerTls:example.com100101# Header manipulation: append, remove, update102ssh -p 443 -R0:localhost:8080 -t free.pinggy.io a:X-Lab:pinggy r:Referer u:Host:example.com103```104105Other controls:106107| Option | Purpose |108|---|---|109| `x:xff[:Header-Name]` | Add source IP header, or use a custom header name. |110| `x:noreverseproxy` | Disable default reverse-proxy headers for HTTP tunnels. |111| `x:passpreflight` | Let unauthenticated CORS preflight requests pass when auth is enabled. |112| `a:Header:Value` | Append request header. |113| `r:Header` | Remove request header. |114| `u:Header:Value` | Replace request header; useful for `Host`. |115116## Web Debugger117118```bash119ssh -p 443 -R0:localhost:8080 -L4300:localhost:4300 a.pinggy.io120# Open http://localhost:4300121# API examples: GET /urls, GET /ipwhitelist122```123124Use it to inspect requests/responses, replay modified HTTP requests, verify webhook payloads, and compare proxy headers before involving Burp, ZAP, mitmproxy, or app logs. Do not use HTTP debugger mode for secrets that Pinggy should not see; choose `tls` instead.125126## Multi-Forwarding and Domains127128Pro tokens can route multiple services through one session, especially with wildcard custom domains.129130```bash131ssh -p 443 \132 -R http//app.example.com:1:localhost:3000 \133 -R http//api.example.com:1:localhost:8080 \134 -R tcp//ssh.example.com/34567:1:localhost:22 \135 -R 1:localhost:80 \136 TOKEN@pro.pinggy.io137```138139Listen address syntax: `[schema//]hostname[/port][@name]`. Schemas include `http`, `tcp`, `tls`, `tlstcp`, and `udp`. Custom domains use CNAME where possible; apex/root domains use relay setup. Relay-based custom domains do not support UDP, so use persistent subdomains/ports for UDP.140141## Offensive Lab Synergies142143Use Pinggy as the public ingress layer; pair it with specialist tools locally.144145| Workflow | Pinggy role | Pair with |146|---|---|---|147| Webhook and API testing | Public HTTPS receiver to localhost | Burp Suite, ZAP, mitmproxy, curl, jq, app logs |148| Controlled reverse-callback labs | Public TCP port to an owned listener | ncat/socat, Metasploit handlers, tcpdump, Wireshark |149| External service validation | Temporary public host/port for owned service | nmap, httpx, nuclei, testssl, browser devtools |150| Header/auth edge cases | Modify `Host`, XFF, bearer/basic auth, CORS | Burp Repeater, ZAP Manual Request, mitmproxy scripts |151| IoT and remote admin | TCP tunnel to SSH/dashboard on owned device | ssh, scp, rsync, netdata, Home Assistant |152| Database or cache demos | TCP tunnel with allowlist to local DB | psql, mysql, redis-cli, mongosh, sqlmap only against owned labs |153| UDP service tests | CLI/Docker UDP tunnel | WireGuard lab, game servers, VoIP/game protocol tooling |154| Reverse proxy routing | Wildcard domain + multi-forwarding | Traefik, nginx, Kubernetes port-forward, Docker Compose |155156When an operation needs SOCKS pivoting through a compromised host, prefer chisel. Use Pinggy when a public SaaS ingress endpoint is acceptable and fast setup matters more than stealth or routing.157158## CLI, SDK, Docker, and APIs159160```bash161# CLI install and basic use162npm install -g pinggy163pinggy --help164pinggy -l 8000165pinggy --type tcp -l 22166pinggy --serve /path/to/files167168# Saved configs and auto-start169pinggy config save my-tunnel -l 3000 TOKEN@pro.pinggy.io170pinggy start my-tunnel171pinggy start --all172pinggy start --all --remote-management <API_KEY>173```174175- CLI has auto-reconnect, JSON-style saved configuration, file-server mode, logging, and remote management.176- Node.js SDK: use `@pinggy/pinggy`, `pinggy.forward({ forwarding: "localhost:5000" })`, then read `tunnel.urls()`.177- Python SDK: install `pinggy`, then `pinggy.start_tunnel(forwardto="localhost:8000")`.178- Pro API can list active tunnels and query session history with `Authorization: Bearer <API_KEY>`.179180## Egress-Constrained Clients181182```bash183# HTTP proxy with nc/ncat184ssh -p443 -R0:localhost:4000 -o ProxyCommand="nc -X connect -x 192.0.2.10:3128 %h %p" a.pinggy.io185ssh -p443 -R0:localhost:4000 -o ProxyCommand="ncat --proxy-type http --proxy 192.0.2.10:3128 %h %p" a.pinggy.io186187# SSH-over-SSL when only TLS egress is allowed188ssh -p443 -R0:localhost:4000 -o ProxyCommand="openssl s_client -quiet -connect %h:%p" a.pinggy.io189ssh -p7878 -R0:localhost:4000 -o ProxyCommand="ncat --ssl %h %p" a.pinggy.io190```191192Use these only when policy allows outbound proxy/TLS tunneling. On Windows, PuTTY proxy settings or installed OpenSSL/ncat can fill the same role.193194## Troubleshooting195196| Symptom | Fix |197|---|---|198| Password prompt | Press Enter, type any string, or generate an SSH key for long-running tunnels. |199| Windows tunnel cannot reach service | Replace `localhost` with `127.0.0.1`. |200| URL changes | Free tunnels are random and time-limited; use Pro persistent subdomain/custom domain. |201| UDP not working with SSH | Use Pinggy CLI or Docker; SSH-only UDP is not supported. |202| Advanced options ignored | Add `-t` and avoid `-N`. |203| Token already active | Stop it in dashboard or use `TOKEN+force@...`. |204| Sensitive data visible in debugger | Switch from HTTP to `tls` and terminate TLS locally. |205| Public exposure too broad | Add `b:`, `k:`, `w:`, shorten runtime, or bind local service to a disposable lab instance. |206207## Resources208209| File | When to load |210|---|---|211| `references/usage-matrix.md` | Full use-case coverage, offensive lab pairings, quickstart recipe taxonomy, and feature-to-protocol mapping. |