Skip to content

Port Forwarding

Port forwarding creates an encrypted tunnel between your device and a remote server, letting you reach services that are not directly accessible from where you are. Think of it as a private pipeline: data enters one end, travels securely through the SSH connection, and exits at the other end.

ZestSSH supports three types of port forwarding. Each one answers a different question:

TypeThe question it answersSSH flag
Local”I want to reach a service over there from right here.”-L
Remote”I want to expose a service on my device to the server.”-R
Dynamic (SOCKS5)“I want to route all my traffic through the server.”-D

If you are unsure which one you need, you almost certainly need Local. It covers 99% of real-world use cases.


This is where most confusion lives. Before you configure anything, ask yourself one question:

“Where is the service I want to reach, and where am I sitting right now?”

  • The service is on the remote side, and I am sitting on my local device —> Local forward.
  • The service is on my local device, and I want someone on the remote side to reach it —> Remote forward.
  • I want to browse the web or route arbitrary traffic through the remote server —> Dynamic/SOCKS5.

Imagine two buildings connected by a locked underground tunnel. You are standing in Building A (your phone or laptop). Building B is the SSH server.

  • Local forward: You drill a hole in the floor of Building A. Anything you drop into it slides through the tunnel and pops out at a specific room in Building B. You are pulling a remote service toward you.
  • Remote forward: You drill a hole in the floor of Building B. Anyone in Building B can drop something in, and it slides through the tunnel to a specific room in Building A. You are pushing a local service toward the server.
  • Dynamic/SOCKS5: Instead of drilling to one specific room, you install a switchboard in Building A. For each request, the switchboard decides which room in Building B to route it to. You are routing everything through the tunnel.

Local forwarding — “reach a service on the server”

Section titled “Local forwarding — “reach a service on the server””

This is the workhorse. Use it whenever you need to access a web UI, database, or any TCP service that is only available on the server or its private network.

How it works in ZestSSH: ZestSSH opens a TCP listener on your device at the address and port you specify (the Source Port). When anything connects to that listener, ZestSSH opens an SSH channel to the destination host and port on the remote side, then relays data in both directions. Every new connection gets its own SSH channel, so multiple clients can use the tunnel simultaneously.

ScenarioSource PortDestination HostDestination PortThen open
Proxmox web UI at 192.168.1.108006192.168.1.108006https://localhost:8006
PostgreSQL on the server5432localhost5432Connect your DB client to localhost:5432
VNC on the server5900localhost5900Point VNC viewer at localhost:5900
Grafana on a LAN host300010.0.0.503000http://localhost:3000
RDP to a Windows machine behind the server3389192.168.1.203389Remote Desktop to localhost:3389
Pi-hole admin panel8080192.168.1.180http://localhost:8080

Note on Destination Host: The value localhost in the Destination Host field means the SSH server’s own localhost — not your device. If the service is running directly on the SSH server, use localhost. If it is on another machine that the server can reach, use that machine’s IP address or hostname.

  1. Connect to your server and tap the port forwarding icon (swap arrows) in the session toolbar.
  2. Tap Add Forward.
  3. Select the Local type (it is selected by default).
  4. Fill in the fields:
    • Nickname (optional): A human-readable label like “Proxmox” or “Postgres.”
    • Source Port: The port on YOUR device. Pick any unused port (8080, 9090, etc.).
    • Destination Host: Where the tunnel exits on the remote side. Use localhost for the server itself, or an IP/hostname for another machine on the server’s network.
    • Destination Port: The actual port of the service you want to reach (80, 443, 5432, 8006, etc.).
    • Bind Address: Leave as 127.0.0.1 unless you want other devices on your local network to use the tunnel (set to 0.0.0.0).
  5. Toggle Auto-activate on if you want this forward to start every time you connect.
  6. Tap Add, then tap the play button to start the forward.

ZestSSH also provides quick presets for Web, Database, and SOCKS5 configurations to speed up common setups.


Remote forwarding — “expose a service to the server”

Section titled “Remote forwarding — “expose a service to the server””

Remote forwarding is the reverse of local forwarding. It opens a listening port on the SSH server and tunnels connections back to a host and port on your local device.

This is uncommon. You would use it when you are developing a web service on your laptop and want a colleague who has access to the server to reach it, or when a server-side application needs to call back to your device.

Important: The SSH server must have GatewayPorts enabled in its sshd_config for remote forwards to accept connections from hosts other than the server’s own localhost. Without this setting, the remote listening port is only reachable from the server itself.

See the dedicated Remote Forwards guide for configuration details.


Dynamic forwarding (SOCKS5) — “route traffic through the server”

Section titled “Dynamic forwarding (SOCKS5) — “route traffic through the server””

Dynamic forwarding starts a SOCKS5 proxy on your device. Any application that supports SOCKS5 can route its traffic through the SSH connection, effectively browsing the internet or a private network as if you were sitting at the server.

ZestSSH’s SOCKS5 implementation follows RFC 1928 and supports IPv4, IPv6, and domain name address types. The proxy uses no-authentication mode because it only listens on your local device (127.0.0.1 by default).

See the dedicated SOCKS5 Proxy guide for browser configuration and use cases.


FeatureFreePro
Active port forwards2 concurrentUnlimited
Forward typesLocal, Remote, DynamicLocal, Remote, Dynamic
Auto-activate on connectYesYes
Saved rules per connectionUnlimitedUnlimited

Port forward rules are saved per connection and persist across app restarts. Even on the free tier, you can create as many rules as you want — the limit applies only to how many can be active at the same time.


FieldWhat it means
NicknameAn optional label for your reference. Does not affect the tunnel.
Source PortThe port on YOUR device that you will connect to.
Destination HostThe host the tunnel reaches from the SSH server’s perspective. localhost = the server itself.
Destination PortThe port of the actual service on the destination host.
Bind AddressWhich local interface to listen on. 127.0.0.1 = only your device. 0.0.0.0 = your entire LAN.
Auto-activateWhen on, the forward starts automatically every time you connect to this server.

Swapping source and destination ports. Source is YOUR side. Destination is the REMOTE side. If you want to reach port 8006 on the server but you set source to 8006 and destination to 8080, you will connect to localhost:8006 on your device and the tunnel will try to reach port 8080 on the server — which is probably not what you intended.

Using port 22 as a source port. Port 22 is the SSH port itself. If something is already listening there (and it likely is), the forward will fail to bind. Pick a high port like 8080, 9090, or anything above 1024.

Forgetting that “localhost” in Destination Host means the server. When you type localhost in the Destination Host field, you are telling the SSH server to connect to its own loopback address. You are NOT referring to your own device. If the service is on a different machine on the server’s LAN, type that machine’s IP address instead.

Closing the SSH session. All port forwards die when the SSH connection closes. Keep the session open for as long as you need the tunnels. On iOS, backgrounding the app may also disconnect tunnels — ZestSSH shows a warning banner about this.

Choosing Remote when you mean Local. If you want to reach something on the server from your device, that is a Local forward. Remote is only for when something on the server needs to reach back to your device. When in doubt, pick Local.


On iOS, port forwards remain active only while ZestSSH is in the foreground. iOS suspends network activity for backgrounded apps, which will interrupt active tunnels. ZestSSH displays a warning banner in the port forwarding screen reminding you of this behavior. For persistent connections on iOS, consider using Mosh or running tmux/screen on the server.


  • Local Forwards — deeper dive into local forwarding with bind address options and more examples.
  • Remote Forwards — when you actually need remote forwarding and how to configure the server.
  • SOCKS5 Proxy — dynamic forwarding, browser setup, and performance considerations.
  • Jump Hosts — combining jump hosts with port forwarding to reach services on nested private networks.