How to Configure Persistent SSH Local Port Forwarding in Your SSH Config File


2 views

When you run ssh 12.34.56.78 -L 8888:localhost:8000, you're telling SSH to:

  1. Forward local port 8888
  2. To localhost:8000 on the remote server

However, in your SSH config file, you specified:

LocalForward 8888 12.34.56.78:8000

This is actually trying to forward to port 8000 on your local machine (since 12.34.56.78 resolves to your local network when the tunnel is established).

Here's the proper way to configure it in your ~/.ssh/config file:

Host myhost
    User myuser
    Hostname 12.34.56.78
    IdentityFile ~/.ssh/id_rsa
    LocalForward 8888 localhost:8000

The key difference is that the destination address (localhost:8000) is relative to the remote server, not your local machine.

After updating your config, test it with:

ssh -N myhost

The -N flag tells SSH not to execute any remote commands, just establish the connection and port forwarding.

You can add these parameters for more control:

Host myhost
    # ... existing config ...
    LocalForward 8888 localhost:8000
    ExitOnForwardFailure yes
    ServerAliveInterval 60
    ServerAliveCountMax 3

ExitOnForwardFailure will make SSH exit if the port forwarding fails, rather than silently continuing.

If you still see "Connection refused" errors:

  1. Verify the service is running on port 8000 on the remote server
  2. Check firewall rules on both local and remote machines
  3. Try connecting directly to the remote service first

To test the remote service:

ssh myuser@12.34.56.78 "curl -I http://localhost:8000"

Using command-line port forwarding like ssh 12.34.56.78 -L 8888:localhost:8000 works perfectly, but becomes tedious when you need to establish these connections frequently. The logical solution is to move this configuration to your SSH config file, but it's not as straightforward as it seems.

The key issue in your configuration is the destination address in the LocalForward directive:

LocalForward 8888 12.34.56.78:8000  # This is incorrect

When you specify the server's public IP as the destination, SSH tries to connect to that address from the server itself, which won't work for services bound to localhost.

Here's the proper way to set up local forwarding in your SSH config:

Host myappserver
    HostName 12.34.56.78
    User myuser
    IdentityFile ~/.ssh/id_rsa
    LocalForward 8888 localhost:8000  # Note the change here
    ServerAliveInterval 60
    ExitOnForwardFailure yes
  • localhost vs server IP: The destination must be relative to the remote server's perspective
  • ExitOnForwardFailure: Ensures the connection fails if forwarding can't be established
  • ServerAliveInterval: Maintains the connection for long-running forwards

For more complex scenarios, consider these patterns:

# Multiple forwards in one host
Host devserver
    LocalForward 8888 localhost:8000
    LocalForward 8889 localhost:8001

# Dynamic forwarding (SOCKS proxy)
Host remotesite
    DynamicForward 1080

# Gateway ports (allow remote connections to forwarded ports)
Host exposed
    GatewayPorts yes
    LocalForward *:8888 localhost:8000

If you encounter connection problems:

  1. Run SSH in verbose mode: ssh -vvv myhost
  2. Check if the remote service is running: ssh myhost "netstat -tuln | grep 8000"
  3. Verify local port availability: netstat -tuln | grep 8888
  4. Test with raw SSH command first before moving to config

For critical forwards that must stay alive:

# Install autossh first
autossh -M 0 -f -N -L 8888:localhost:8000 myuser@12.34.56.78

# Or in your config:
Host criticalapp
    HostName 12.34.56.78
    User myuser
    LocalForward 8888 localhost:8000
    RemoteCommand "/usr/bin/autossh -M 0 -N -L 8888:localhost:8000 %h"

Remember that port forwarding can expose services in unexpected ways:

  • Avoid using GatewayPorts unless absolutely necessary
  • Consider using AllowTcpForwarding in your server's sshd_config
  • For sensitive services, add PermitOpen restrictions