Skip to content
Zync
All posts
Guide8 min read

SSH port forwarding explained with OpenSSH and Zync

Learn local, remote and SOCKS SSH tunnels with OpenSSH commands, matching Zync settings, loopback binding and troubleshooting examples.

In this article

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:8080

OpenSSH setup

Run this on your computer, not inside the remote shell:

Terminal window
ssh -N -o ExitOnForwardFailure=yes -L 127.0.0.1:38080:127.0.0.1:8080 demo@staging.example.com

Leave 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:3000

OpenSSH setup

With the development service already running, start this on your computer:

Terminal window
ssh -N -o ExitOnForwardFailure=yes -R 127.0.0.1:39000:127.0.0.1:3000 demo@staging.example.com

From a separate shell on staging, test the listener:

Terminal window
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 application

OpenSSH setup

Run this on your computer:

Terminal window
ssh -N -o ExitOnForwardFailure=yes -D 127.0.0.1:1080 demo@staging.example.com

Then use a SOCKS-aware client. For an HTTPS destination that staging is permitted to reach:

Terminal window
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.

Get Zync