Guides · Connecting
Port forwarding and jump hosts
Carry a port you cannot reach directly over an SSH session you can, and reach servers that sit behind one or more bastions. MangoSSH does local, remote and SOCKS forwards, remembers them per host, and builds ProxyJump chains from your saved hosts.
- SSH tunnels
- Windows · macOS · Linux
- About 10 minutes
The three kinds of forward
The only real difference is which end opens the listening port.
| Kind | Who listens | Use it to |
|---|---|---|
| Local (-L) | This computer | Reach something only the SSH host can reach: a database on a private subnet, an admin page bound to localhost on the server. |
| Remote (-R) | The SSH server | Let the far side reach something only you can reach: show a local web app to someone on the server's network, or give a server access to a service on your machine. |
| Dynamic SOCKS5 (-D) | This computer | One local port that goes to any destination the SSH host can reach. Point a browser or tool at it as a SOCKS5 proxy. |
Where forwards live
- The tunnel button on the session toolbar (tooltip SSH Tunneling/Port Forwarding) opens the Port Forwarding page. It lists every forward across every open SSH session as a card with a small map (you, the SSH host, the destination), live in and out rates, open and total connections, and bytes moved. A tunnel nothing has used yet says so, which tells you a problem is before the tunnel, not after it.
- Port Forwarding in the Workspace sidebar opens a dialog with a Host picker, that host's forwards, and illustrated explanations of -L, -R and -D. Pick All hosts — every active forward to see everything at once, or Full view for the full-size map. This is also where you add a forward to a host that is not connected.
Add a forward
Connect to the SSH host that can reach the destination.
Click Add forward on the Port Forwarding page, or pick the host in the Port Forwarding dialog and click Add Forward.
Choose the Type and fill in the ports (see the table below), then click Create Forward.
Use it. For a local forward to a database on port 5432, point your client at
127.0.0.1:5432on your own machine.
| Field | Meaning | Starts as |
|---|---|---|
| Type | Local (-L), Remote (-R) or Dynamic SOCKS5 (-D). | Local |
| Listen address | Which interface the listener binds to. For local and SOCKS forwards this is on your machine; for remote forwards it is on the server. | 127.0.0.1; 0.0.0.0 for Remote |
| Listen port | The port that accepts connections. Required. | Empty |
| Target host | Local: where the SSH server connects, resolved from the server's side, so internal DNS names work. Remote: where this computer connects when traffic comes back. Hidden for SOCKS. | Empty |
| Target port | The port on the target host. | Empty |
Changing a local or SOCKS listen address to 0.0.0.0 lets anyone who can reach your machine use your tunnel, and through it, everything the SSH host can reach. The SOCKS proxy has no password of its own.
Examples
| Goal | Settings |
|---|---|
| Private Postgres | Local · listen 127.0.0.1:5432 · target db.internal:5432. Connect your client to 127.0.0.1:5432. |
| Show your dev app | Remote · listen 0.0.0.0:8080 · target 127.0.0.1:3000. People on the server's network open port 8080 on the server. |
| Browse an internal network | Dynamic · listen 127.0.0.1:1080. Set your browser's SOCKS5 proxy to 127.0.0.1:1080, or curl --socks5-hostname 127.0.0.1:1080 http://intranet/. |
A remote forward on 0.0.0.0 is only reachable from other machines if the server allows it. OpenSSH servers bind remote forwards to loopback unless GatewayPorts is enabled in sshd_config. The SOCKS proxy accepts hostnames, so DNS lookups happen on the SSH host when your client sends names rather than addresses.
Saved forwards restart on connect
Every forward you create with Add forward is also saved on its host. The next time that host connects, from anywhere in the app, its saved forwards start automatically. You can add a forward to a host that is not connected from the Port Forwarding dialog; the title changes to Add port forward (saves — starts on next connect).
- Stop on a card stops the tunnel now. The saved rule stays, and the card reappears dimmed with a Start button while the host is connected, or host not connected when it is not.
- Remove in the Port Forwarding dialog deletes the saved rule, so it no longer starts on connect.
- Edit on a live card starts the changed forward first and only then stops the old one, so a typo leaves the original running.
If one saved forward cannot start (its port is already in use, for example), the others still start and the connection is unaffected.
Auto-detected dev servers
MangoSSH watches the output of your SSH terminals for the banner a development server prints when it starts: a http://localhost:PORT, 127.0.0.1 or 0.0.0.0 URL, listening on port N, or Python's Serving HTTP on … port N. When it sees one it asks:
Detected a dev server on port 5173 — forward it to your machine?
Accept, and it starts a local forward from 127.0.0.1:5173 on your machine to localhost:5173 on the server, then tells you the address to open. This forward lasts for the session and is not saved on the host. It asks once per port per session, so a server that restarts in a loop does not keep prompting. It does not ask on a host where port forwarding is blocked. A bare port number in other output, such as a database connection string, does not trigger it.
Jump hosts (ProxyJump)
A jump host, or bastion, is a server you can reach that can reach the server you want. MangoSSH signs in to the bastion, opens a channel through it to the target, and runs a second, complete SSH connection inside that channel. The bastion relays encrypted bytes and never sees your session with the target.
Set up a jump host
Save the bastion as an ordinary SSH host and make sure you can connect to it on its own.
Open the target host with Edit and go to the Proxy tab.
Under Proxy Jump (bastion), pick the bastion in Via SSH host, then Save changes.
For a chain, give the bastion its own Via SSH host. MangoSSH follows the chain back to the first hop you can reach directly.
Inherit the bastion from a group
When every host in a group goes through the same bastion, set it once. Open Manage SSH Groups (the button next to the Group field, or the ⚙ next to the sidebar's group filter) and choose the group's Default bastion.
- A host's own Via SSH host always wins. The group's bastion is used only when the host leaves it empty.
- The Proxy tab shows the inherited bastion under the field, for example ↳ Inherited from group 'Production': bastion-1 — pick a bastion above to override.
- A bastion can inherit its own jump host from its group too, so chains can be built entirely from group defaults.
Rules worth knowing
- Bastions cannot prompt you. Each hop signs in on its own, in the background. A password bastion needs its password saved in the OS keychain, or it fails with No saved password for bastion …. Keys, SSH Agent, PKCS#11 and Passkey sign-in all work for bastions.
- You do not need agent forwarding for jump hosts. Your device signs in to every hop itself; no key ever has to be available on a bastion.
- One route per host. If the host also has a ProxyCommand or an HTTP / SOCKS proxy on its Proxy tab, that route is used and the jump host is ignored.
- Loops and long chains are refused. A chain that loops back to a bastion already in it fails with ProxyJump chain has a cycle. Chains longer than 8 hops are refused.
- Bastion host keys are trusted on first use without a prompt. Only the final target asks you to confirm a new host key.
- Debug mode names every hop. With Verbose / debug mode on (the default for new hosts), the connection log shows each bastion, whether it was inherited from a group, and where a failure happened.
Agent forwarding
Enable agent forwarding (-A), on the host's Session tab, lets SSH commands you run on the server (a git pull from a private repository, an ssh to the next machine) sign with the keys in your local ssh-agent. The keys never leave your machine; the server asks your agent to sign.
- Windows: MangoSSH uses the OpenSSH agent service (
Start-Service ssh-agent). Pageant is not supported, despite the label's mention of it. - macOS and Linux:
SSH_AUTH_SOCKmust point at a running agent. Check withssh-add -l. - If no local agent is running, the session still works; programs on the server simply find no agent.
While you are connected, anyone with root on that server can ask your agent to sign as you. For hopping between machines, a jump host is the safer choice.
X11 forwarding
Enable X11 forwarding (-X), also on the Session tab, shows graphical Linux programs started on the server (xclock, virt-manager, wireshark) as windows on your desktop.
- You need a local X server that accepts connections on
127.0.0.1:6000(display:0): VcXsrv or X410 on Windows, XQuartz on macOS, or the native X server on Linux. - The server must allow it:
X11Forwarding yesinsshd_config, andxauthinstalled. If it refuses, the session still connects without X11. - If no local X server is listening, remote programs fail to open their window; the session itself is unaffected.
Both switches start from the defaults in Settings → Connection for new hosts. A policy can turn agent and X11 forwarding off for a group of hosts; see Policies.
Blocking and auditing
- Block port forwarding on this host (Session tab) refuses every local, remote and SOCKS forward on that host, including saved forwards and RDP tunnelled through it, and suppresses the dev-server prompt. A policy can set it for a whole group or tag. Like all data-copy controls it is enforced by this app; for a hard boundary use the PAM Broker.
- Every forward that starts or stops is written to the audit log with the host, user, kind, listen address and target. See Audit, recording and alerts.
Troubleshooting
| Symptom | Likely cause |
|---|---|
| “bind 127.0.0.1:PORT failed” | Something on your machine already uses that port. Pick another listen port. |
| “tcpip_forward failed” on a remote forward | The server refused to listen: the port is taken or below 1024, or AllowTcpForwarding is off in sshd_config. |
| The tunnel exists but says nothing has used it | Your client is pointed somewhere else. Check the address and port it connects to. |
| Traffic reaches the tunnel but the app gets no answer | The SSH host cannot reach the target. Try nc -vz TARGET PORT from a terminal on that host. |
| A forward you stopped comes back after reconnecting | Stop leaves the saved rule in place. Remove it in the Port Forwarding dialog. |
| A remote forward on 0.0.0.0 is only reachable from the server itself | The server's GatewayPorts is off, so it bound to loopback. |
| “No saved password for bastion …” | Edit the bastion, enter its password with Save password to OS keychain on, or switch it to key sign-in. |
| “ProxyJump chain has a cycle” | Two hosts name each other as jump host, directly or through their groups. Clear one of them. |
| Forwarding is refused on one host only | Port forwarding is blocked on that host, by its own switch or a policy. |