Open a service on your server from your laptop.
Your computer :38080 → SSH server → service :8080. Replies return through the same tunnel.
An application runs on a server, but its web interface is available only on that server. You want to inspect it from your laptop without opening another public port. Or the direction is reversed: a test running on the server needs to reach a development service on your computer.
SSH port forwarding handles both situations. The useful question is not just “which port?” It is where the listener runs and which machine connects to the destination.
This guide shows the same three setups in OpenSSH and Zync. We build Zync, but the commands work independently of the app. Start with a host and services you are authorized to access.
Choose the tunnel by its listening side
| Type | Listener | Destination | Typical use |
|---|---|---|---|
Local, -L |
Your computer | Reached from the SSH server | Internal web UI or database |
Remote, -R |
SSH server | Reached from your computer | A remote test reaching your local dev app |
Dynamic, -D |
Your computer | Chosen by a SOCKS-aware client | Several permitted services through one proxy |
Local and remote describe the listening side, not the direction in which every byte travels. Replies return through the same connection. SSH carries forwarded TCP channels alongside other session traffic. See RFC 4254’s forwarding model.
The examples use demo@staging.example.com, a placeholder SSH account and hostname. Replace them with your permitted host. Authenticate normally and verify an unfamiliar server’s host-key fingerprint through a trusted channel. Your SSH server and account must allow the requested forwarding.
Local forwarding for an internal web interface
Suppose an HTTP service listens on the SSH server at 127.0.0.1:8080. You want to reach it through port 38080 on your computer.
Your browser -> your computer 127.0.0.1:38080 -> SSH connection to staging -> staging server 127.0.0.1:8080OpenSSH setup
Run this on your computer, not inside the remote shell:
ssh -N -o ExitOnForwardFailure=yes -L 127.0.0.1:38080:127.0.0.1:8080 demo@staging.example.comLeave it running and open http://127.0.0.1:38080 in your browser. The two loopback addresses refer to different machines: the listening address is your computer; the destination is reached from the SSH server. OpenSSH’s local-forward option defines that mapping.
-N runs no remote command. ExitOnForwardFailure=yes makes setup failures fail visibly; it does not check whether the target HTTP service is healthy. A quiet foreground command is normal. Use Ctrl+C in that terminal to stop it. These controls are documented in the SSH configuration manual.
Matching Zync setup
Connect the SSH host, open its Port Forwarding view and select New Forward. Choose the local-forward type and enter:
| Setting | Value |
|---|---|
| Local port | 38080 |
| Remote host | 127.0.0.1 |
| Target port | 8080 |
| Bind address | 127.0.0.1 |
| Name | Staging web UI |
Save the forward and use its Start control if it is stopped. Open the same browser address, then stop the forward when finished. Zync’s form labels the target port simply Port for a local forward.
If the service lives on another machine reachable from staging, use that machine’s address as the remote host. Check reachability from staging, not just from your laptop. Keep the application’s own authentication in place.
Remote forwarding for a local development service
Suppose your computer has a development HTTP service on 127.0.0.1:3000. A test on staging needs to call it through staging’s port 39000.
Test running on staging -> staging server 127.0.0.1:39000 -> existing SSH connection back to your computer -> your computer 127.0.0.1:3000OpenSSH setup
With the development service already running, start this on your computer:
ssh -N -o ExitOnForwardFailure=yes -R 127.0.0.1:39000:127.0.0.1:3000 demo@staging.example.comFrom a separate shell on staging, test the listener:
curl --max-time 10 http://127.0.0.1:39000/Here, port 39000 is on staging and port 3000 is on your computer. See OpenSSH’s remote-forward option.
Matching Zync setup
On the connected host, create a remote forward:
| Setting | Value |
|---|---|
| Remote port | 39000 |
| Local host | 127.0.0.1 |
| Local port | 3000 |
| Bind address | 127.0.0.1 |
| Name | Local dev app from staging |
Save and start it, then run the same test from staging. The local target is reached from the machine running Zync, not from the SSH server.
This example is not a public preview link. Remote listening is controlled by the server: AllowTcpForwarding, PermitListen, authorized-key restrictions and GatewayPorts can limit or change the requested bind. Default OpenSSH server policy keeps remote forwards on loopback; GatewayPorts=yes can force a wildcard bind. Confirm the effective policy with the server administrator rather than assuming the requested address always wins. See the server forwarding settings.
Do not broaden the listener merely to make a test pass. Even a loopback listener may be accessible to other users on that server; the local service still needs appropriate access controls.
SOCKS forwarding for application-selected destinations
A local forward has one fixed target. SOCKS lets a compatible application select a destination for each connection through a local proxy.
Proxy-configured application -> your computer SOCKS listener 127.0.0.1:1080 -> SSH connection to staging -> destination chosen by that applicationOpenSSH setup
Run this on your computer:
ssh -N -o ExitOnForwardFailure=yes -D 127.0.0.1:1080 demo@staging.example.comThen use a SOCKS-aware client. For an HTTPS destination that staging is permitted to reach:
curl --max-time 10 --proxy socks5h://127.0.0.1:1080 https://example.com/The socks5h scheme asks the proxy side to resolve the destination hostname. Plain socks5 asks curl to resolve it locally. This choice matters for names known only to the remote network. See curl’s SOCKS hostname documentation.
Matching Zync setup
Choose the SOCKS Proxy preset or dynamic type, set SOCKS port to 1080, keep Bind address at 127.0.0.1, then save and start. There is no fixed target host or target port to enter. Use the same curl test or configure a compatible browser’s SOCKS5 settings.
Do not browse http://127.0.0.1:1080 as though it were an HTTP page. A SOCKS listener expects a proxy handshake. Only traffic from applications configured to use it goes through the proxy; this is not a system-wide VPN.
Zync’s current SOCKS support is TCP CONNECT without proxy username/password authentication. UDP ASSOCIATE and BIND are not supported. Keep the proxy on loopback rather than exposing an unauthenticated listener to your network. The Zync forwarding documentation covers the supported modes.
Manage saved tunnels without confusing them with live connections
Zync keeps tunnel settings with their SSH host. Its global Port Forwarding dashboard groups entries by host, while the per-host view focuses on that connection. You can start, stop and edit the same forwards from either surface.
Saving a configuration does not keep it running. A live tunnel needs the host’s active SSH connection. Disconnecting stops runtime forwarding; after reconnecting, Zync attempts to restore previously active tunnels and those with auto-start enabled. Existing client connections can break during that interruption, so reconnect your application as needed.
Leave Auto-start tunnel when connection opens off while learning. Enable it deliberately for a forward you want on later connections. A manually stopped forward remains stopped across reconnects unless auto-start is enabled.
The command import action can turn -L, -R and -D declarations into saved tunnel entries. Review the selected host, ports and bind addresses before starting them. Import is not a promise to execute every OpenSSH option; forwarding declarations from ~/.ssh/config are not imported by this workflow.
Troubleshoot from the correct side
| Symptom | What to check |
|---|---|
| Listening port already in use | Pick an unused port on the listening machine and update the client address. Zync can suggest another port for local conflicts. |
| Server rejects remote forwarding | Ask the administrator to check forwarding policy and remote port availability. Do not disable restrictions indiscriminately. |
| Tunnel starts but target refuses connections | Check that the destination service is running and reachable from staging for local/SOCKS, or from your computer for remote forwarding. |
| SOCKS works with an IP but not a hostname | Check proxy-side DNS behavior and whether the SSH server can resolve the name. |
| Browser or client stops working after reconnect | Confirm the forward restarted and reconnect the application; saved settings do not preserve its old TCP connection. |
For an OpenSSH setup problem, add -v to the relevant command and inspect the messages locally. Remove hostnames, usernames, paths and other private details before sharing logs. For Zync, check the forward’s status and error before changing its settings.
Keep the exposure narrow
Use explicit loopback binds for these exercises. Binding a local forward or SOCKS proxy to 0.0.0.0 can make it reachable on other interfaces, subject to firewall rules. Forwarding encrypts the SSH leg, not automatically every network hop beyond the SSH endpoint. Use HTTPS or the destination protocol’s own encryption when needed, and retain service authentication.
Zync Public URLs is a separate HTTPS/WSS sharing feature, not another name for SSH forwarding. Use the Public URLs guide when you intentionally need public sharing, and review its separate access boundary.
Start with the local-forward exercise, confirm both endpoints, and stop it deliberately. Once the listener and destination are clear, remote and SOCKS setups become much easier to reason about. For a complete staging task, see the SSH workflow walkthrough; for choosing a client, see the SSH client comparison.
Common questions
Does a tunnel open the service to the internet
Not inherently. Access depends on the listener’s bind address, server policy, firewall and network reachability. These examples request loopback listeners. A remote listener is not automatically a public URL.
Do the two port numbers have to match
No. A local listener on 38080 can forward to a service on 8080. The listening port must be available; the target port must match the actual service.
Can I close the SSH connection and keep the tunnel
Not for these session-bound setups. OpenSSH forwarding ends when its connection closes; Zync can retain the configuration and attempt to restart it after reconnection, but forwarding is unavailable during the disconnect.
Is SOCKS a replacement for a VPN
No. A SOCKS-aware application uses the proxy for configured connections. Other application traffic and unsupported protocols do not automatically follow it.
Put it into practice.
Open a local shell. Connect to your server. Make the workspace yours.