STACIO WIKI · Networking Guide
Stacio Tunnels Guide
1. What a tunnel is
Stacio tunnels forward TCP traffic through an existing SSH authentication path. Three types are supported:
| Type | Data entry | Data exit | Typical use |
|---|---|---|---|
| Local forwarding | Listening address and port on this Mac | Target host and port reachable from the SSH host | Access an internal database, web console, or private API. |
| Remote forwarding | Listening address and port on the SSH server | Target host and port reachable from this Mac | Temporarily expose a local development service to a remote environment. |
| Dynamic forwarding | SOCKS5 listening address and port on this Mac | Specified per request by the SOCKS5 client | Browse or debug several private HTTP/TCP targets. |
A tunnel does not create new remote-account permission or bypass firewall, SSH-server forwarding policy, or organizational approval. The feature entry point is controlled by the SSH Tunnels License.
2. Prepare before use
Before starting a tunnel, confirm:
- You saved and verified an SSH, SFTP, or SCP session, or have an active usable SSH/SCP connection.
- The SSH account and authentication method are valid.
- The first connection's host key was checked through a trusted channel.
- The target service really listens on its expected address and port.
- The local port used by Local or Dynamic is not occupied by another process.
- The SSH server permits the required TCP forwarding.
- Production access, reverse exposure, and proxy behavior have approval.
Establish an ordinary SSH terminal and make a minimal read-only check first. It separates authentication and SSH issues from target-service issues.
In most cases an SSH entry point is an IP endpoint such as 192.168.1.20:22 or 192.168.1.20:2222; with stable DNS it can be gateway.example.com:22. A tunnel target may be a different private IP or hostname that the SSH host can reach. Do not confuse these roles.
3. Open the Tunnels panel
- Choose
View > Tunnelsor clickTunnelsin the toolbar. - The inspector lists saved tunnel configurations.
- The table includes type, local endpoint, remote endpoint, state, details, and traffic.
- Use New, Edit, and Delete at the top to manage configuration; use a row's Start or Stop control to manage runtime state.
If the entry point is disabled with an entitlement hint, inspect Help > License. Do not bypass entitlement or approval by editing the local database.
4. Create a tunnel
4.1 Quick Add
After clicking New Tunnel, Quick Add accepts:
- type: Local, Remote, or Dynamic;
- local port;
- target
host:port, such as10.0.0.25:5432ordb.internal:5432; Dynamic does not need a target; - a note used to create a recognizable configuration identifier.
Quick Add defaults the local listening address to 127.0.0.1 and tries to start after saving. Local and Remote targets accept combined host:port; IPv6 may be written as [address]:port.
Remote reverses the meaning of the two sides compared with Local. After a first Remote configuration, save it and enter the full editor to review every field.
4.2 Full editor
Select a configuration and choose Edit Tunnel to set:
| Field | Meaning |
|---|---|
| SSH session endpoint | Choose an available endpoint and authentication context from saved SSH/SFTP/SCP sessions. |
| Configuration ID | Locally unique identifier such as tun_prod_db; cannot duplicate another tunnel. |
| Type | Local, Remote, or Dynamic. |
| Local Host | For Local/Dynamic, the Mac listening address; for Remote, the Mac-side target address. |
| Local Port | For Local/Dynamic, the Mac listening port; for Remote, the Mac-side target port. |
| Remote Host | For Local, the SSH-side target address; for Remote, the SSH-server listening address; unused for Dynamic. |
| Remote Port | For Local, the SSH-side target port; for Remote, the SSH-server listening port; unused for Dynamic. |
Selecting an SSH Session Endpoint fills Remote Host and Remote Port with that session endpoint. After you edit either manually, the configuration no longer matches the selected endpoint. When the SSH transport endpoint and actual forwarding target differ, first open the correct SSH session so the tunnel uses the current connection context, then enter the real forwarding target.
4.3 Distinguish four address roles
At minimum, distinguish these roles:
| Address role | Example | Meaning |
|---|---|---|
| SSH connection endpoint | ops@192.168.1.20:22 |
Stacio uses it for SSH authentication and host-key validation. |
| Mac local listener | 127.0.0.1:15432 |
Local/Dynamic accepts client connections here on this Mac. |
| SSH-side target | 10.0.0.25:5432 |
A private service the SSH host continues to reach for Local. db.internal:5432 is also valid. |
| Remote listener | 127.0.0.1:19000 |
Remote accepts connections on the SSH-server side. |
Quick Add's Target is one combined host:port input. The full editor's Local Host, Local Port, Remote Host, and Remote Port are separate fields. Do not put an SSH login endpoint into the database target, and do not put the complete 10.0.0.25:5432 into a full-editor Host field.
5. Local forwarding
5.1 Data flow
Mac application -> local listening address:port -> SSH connection -> private target:portFor example, access a PostgreSQL service 10.0.0.25:5432, which only SSH entry point ops@192.168.1.20:22 can reach:
| Field | Example |
|---|---|
| Type | Local |
| Local Host | 127.0.0.1 |
| Local Port | 15432 |
| Remote Host | 10.0.0.25 |
| Remote Port | 5432 |
After starting, a database client on the Mac connects to 127.0.0.1:15432. If an internal database uses DNS, Remote Host can be db.internal, while Remote Port remains separately 5432. The database usually sees the SSH-host side as the source, not the Mac's public address.
5.2 Validate
Make read-only checks in a local Mac terminal:
lsof -nP -iTCP:15432 -sTCP:LISTEN
nc -vz 127.0.0.1 15432An open port proves that TCP is established, not that the database account, TLS, or query works. Use the target protocol for a minimal health check as well.
6. Remote forwarding
6.1 Data flow
Remote client -> SSH server listening address:port -> SSH connection -> Mac-side target:portFor example, make a Mac development service at 127.0.0.1:3000 available to the SSH server itself on 127.0.0.1:19000:
| Field | Example |
|---|---|
| Type | Remote |
| Local Host | 127.0.0.1 |
| Local Port | 3000 |
| Remote Host | 127.0.0.1 |
| Remote Port | 19000 |
On the SSH server, verify read-only with:
ss -lnt | grep ':19000'
curl --fail --max-time 5 http://127.0.0.1:19000/healthDo not default a Remote listener to 0.0.0.0 or ::. Non-loopback listening also depends on SSH-server policies such as GatewayPorts; before exposure, confirm authentication, TLS, firewall, allowed scope, and planned stop time.
7. Dynamic forwarding
7.1 Data flow
SOCKS5 client -> Mac SOCKS5 listening address:port -> SSH connection -> client-specified targetRecommended configuration:
| Field | Example |
|---|---|
| Type | Dynamic |
| Local Host | 127.0.0.1 |
| Local Port | 1080 |
Configure 127.0.0.1:1080 in a SOCKS5-capable client. To test an HTTP destination:
curl --socks5-hostname 127.0.0.1:1080 --fail --max-time 10 http://service.internal/health--socks5-hostname resolves hostnames from the SOCKS side, which suits hosts resolved only by private DNS. Direct IP access needs no hostname resolution. A proxy does not mean content encryption: the segment from SSH exit to target still depends on whether the target protocol uses TLS.
8. SSH session context
At start, a tunnel obtains SSH context in this order:
- usable SSH connection context in the current workspace;
- saved SSH/SFTP/SCP session bound by the tunnel record;
- otherwise, it reports that an SSH or SCP session must be opened first.
When the bound session is deleted, changes to an unsupported protocol, has an invalid port, or lacks credentials, edit the tunnel and choose a session again. An SSH context opened through ProxyJump can use the same jump configuration for tunnel runtime, but target and jump host each still perform host-key and authentication flow separately.
9. Start, monitor, and stop
9.1 Start
- Select the configuration and check type plus both endpoints again.
- Click Start in its row.
- Wait for state to change from Starting to Running.
- Perform a targeted validation with a local or remote client.
Local and Dynamic check local-port availability at start. Remote listens on the SSH server and uses different local-port checks.
9.2 Runtime state
The panel uses colored states and text for:
- Running;
- Connecting or Reconnecting;
- Stopped;
- Failed.
Running tunnels poll status every second and show accumulated traffic:
upstream bytes downstream bytesTraffic only shows that bytes passed through. It does not prove request success, response correctness, or transaction completion.
9.3 Copy an equivalent SSH command
Choose Copy SSH Tunnel Command from a tunnel context menu to get equivalent ssh -L, ssh -R, or ssh -D text. This copies text only and does not execute it. Without a bound session, target can show placeholder user@host; complete and inspect it before use.
9.4 Stop and quit
- A row's Stop button closes the tunnel and cancels future automatic reconnect.
- Before deleting a running configuration, Stacio first tries to stop its runtime.
- Quitting Stacio stops all running tunnels and asks for confirmation first.
- Saving a configuration does not make it run automatically on next application launch.
10. Automatic reconnect
When runtime detects a broken link, it retries with increasing delay, up to 10 automatic reconnect attempts. The UI shows Reconnecting... (attempt N).
- Manual stop cancels scheduled reconnects.
- State becomes Failed after the maximum attempts.
- Reauthentication, a changed host key, invalid configuration, or a server forwarding rejection is not repaired by retry alone.
- When it reconnects repeatedly, stop it proactively to avoid continual requests and a blurred failure timeline.
Reconnect restores the tunnel link only; it does not guarantee that a database transaction, HTTP request, file transfer, or long connection through the tunnel resumes from its interruption point.
11. Listening safety
11.1 Use loopback by default
For Local and Dynamic, prefer:
127.0.0.1This permits connections from the current Mac only. 0.0.0.0, ::, and a LAN interface expose the service or SOCKS5 proxy to other devices. The Dynamic editor warns for a listener other than 127.0.0.1.
11.2 Minimum-exposure principle
- Open only the ports needed to finish the task.
- Prefer loopback listeners and short lifetimes.
- Do not publish an administrative interface through an unauthenticated Remote tunnel.
- Continue to use authentication and TLS at client and target service.
- Stop the tunnel after work and confirm the listener disappeared.
- Record owner, purpose, target, and planned close time.
11.3 Credentials and logs
Tunnels use authentication from the current or saved Stacio session. Copied SSH commands, diagnostics, and screenshots must not contain passwords, tokens, private-key contents, or private-key passphrases. A changed host key requires stop and independent verification.
12. Troubleshooting runbook
12.1 Cannot start
Check in order:
- License is valid.
- Type and ports are correct, with a port range of
1...65535. - Current SSH context or a valid bound session exists.
- SSH authentication and host key are healthy.
- Local/Dynamic local port is not occupied.
- SSH server permits TCP forwarding.
- Target service is listening and route is reachable.
12.2 Local port is occupied
lsof -nP -iTCP:<port> -sTCP:LISTENConfirm the process owner before stopping it or using a different port. Do not kill an unknown process only to start a tunnel.
12.3 Local is running but target is unavailable
- Check local listener first.
- Then check target name resolution and port from the SSH terminal.
- Distinguish TCP reachability, TLS handshake, application authentication, and business errors.
- Check whether target listens on the wrong network interface only.
12.4 Remote has no listener
- Check whether the SSH server permits Remote forwarding.
- Check remote-port collision.
- Use
ss -lntto verify the listener. - For non-loopback listening, also inspect
GatewayPortsand firewall. - Verify that the Mac-side target service is still running.
12.5 Dynamic client fails
- Confirm the client uses SOCKS5, not an HTTP proxy.
- Use proxy-side DNS resolution for private hostnames.
- Check whether the client incorrectly bypasses the proxy.
- Test IP and hostname targets separately.
- Inspect TLS and authentication errors of the target protocol itself.
12.6 Reconnects repeatedly
- Stop the tunnel manually.
- Record first-disconnect time and error details.
- Check network, VPN, SSH session, credentials, and host key.
- Verify both endpoint services are still listening.
- Correct root cause, start manually once, and observe.
13. Completion and shutdown checklist
- A client completed a targeted health check through the tunnel.
- The target is not the wrong host, port, or environment.
- No unnecessary listening address is exposed.
- Traffic and application logs match the test time.
- The tunnel is stopped after use.
- Local or remote listener has disappeared.
- Required audit, change record, and residual-risk information is retained.
For production access, follow both Security and Governance and Remote Operations.
