SSH Port Forwarding on iPhone and iPad
Most of the interesting things on a server do not listen on a public address, and that is deliberate. Your database binds to 127.0.0.1. Your Grafana instance sits behind the firewall. An admin panel is reachable only from inside the network. Port forwarding is how you reach them without exposing them. It borrows the encrypted, authenticated SSH connection you already have and carries other traffic through it. There are three kinds and they solve genuinely different problems; picking the wrong one is the usual reason this feels confusing.
Written by the GateShell team at Hefty Innovations
Step by step
- 1
Work out which of the three you need
Local forwarding brings something on the server to you: a port on your device becomes a port on the server, which is what you want for a database, a dashboard, or an internal API. Remote forwarding does the reverse, exposing something on your device to the server, which is rarer and mostly used for callbacks or webhook testing. Dynamic forwarding opens a SOCKS proxy, letting any app that speaks SOCKS route its traffic through the server, which is what you want when you need to reach several internal hosts rather than one specific service.
- 2
Set up a local forward for a specific service
In GateShell, open the server's port-forwarding rules and add a local rule. Give it a local port on your device, then the destination host and port as seen from the server, usually 127.0.0.1 and the service's real port. For PostgreSQL you would forward local 5432 to 127.0.0.1:5432; for a dashboard, local 3000 to 127.0.0.1:3000. Label the rule, because in a month you will not remember what port 8081 was for.
- 3
Understand what 'as seen from the server' means
This is the part that trips people up. The destination is resolved on the server, not on your phone. So 127.0.0.1 means the server's own loopback, not your device's. If the service runs on a different machine that your server can reach, a database host on a private network for instance, you put that host's address as the destination, and the server does the routing. This is what makes a bastion useful: forward through a host that can see the private network, to a destination only it can reach.
- 4
Use dynamic SOCKS when one rule is not enough
If you are reaching several internal services, or browsing an internal site whose pages load resources from other internal hosts, individual rules become tedious and incomplete. A dynamic rule opens a SOCKS proxy instead: configure an app to use it and all of that app's traffic routes through the server. This is the closest thing to being on the network, without a VPN.
- 5
Turn rules on and off per session
Rules are saved per server and can be toggled live rather than only at connect time. Leave the ones you use daily configured and switch them on when you need them. There is no cost to having a rule defined and inactive, and it saves re-entering ports every time.
- 6
Check what is actually listening if a forward fails
A forward that connects but returns nothing almost always means the destination is not listening where you think. Run `ss -tlnp` on the server to see the real bound addresses. A service bound to a specific external interface rather than 127.0.0.1 or 0.0.0.0 will not accept a connection to loopback, which looks identical to the service being down.
Frequently asked questions
What is the difference between local and remote forwarding?+
Direction. Local forwarding makes something on the server reachable from your device, which is the common case and what you want for databases and dashboards. Remote forwarding makes something on your device reachable from the server, which is occasionally useful for webhook callbacks but is not what most people need. If you are unsure, you want local.
Do I need a VPN if I have port forwarding?+
Often not. A dynamic SOCKS forward gives any SOCKS-capable app access to whatever your server can reach, which covers most of what a VPN would be used for here. A VPN is the better tool when you need system-wide routing across every app, or access that does not depend on one SSH session staying open.
Is forwarded traffic encrypted?+
Between your device and the server, yes. It travels inside the SSH connection with the same encryption as your terminal session. Beyond the server it is whatever the underlying protocol is. Forwarding to a plain HTTP service means that last hop, from the server to the service, is unencrypted, which is usually fine when it is loopback on the same machine, worth thinking about when it crosses a network.
Why does my forward work in the app but not in another app?+
The local listener belongs to GateShell, and iOS gives each app its own network sandbox. A forward opened here is reachable by apps that connect to it over local loopback but is not a system-wide route. For browsing internal sites, the built-in preview and SOCKS-aware apps are the reliable path.
Does the tunnel survive backgrounding?+
iOS suspends network activity for backgrounded apps, so a long-idle forward may need reconnecting. Enabling Mosh helps the session itself survive network changes; for work that must continue regardless, run it server-side inside tmux so nothing depends on the tunnel staying up.
Try it in GateShell
GateShell is a zero-backend SSH client for iPhone, iPad, and Mac, with no vendor cloud, no accounts and no telemetry. Everything above works out of the box.
Guide reflects GateShell's shipped features as of September 2026. Steps assume basic familiarity with SSH and the command line; server-side commands may vary by distribution. All product names, logos, and brands are property of their respective owners.