What's Actually Happening

You're trying to set up SSH local port forwarding to access a remote service, but the connection fails because SSH isn't binding to the correct interface, or you're encountering permission issues when trying to bind to a privileged port or specific IP address.

The Error You'll See

When attempting to establish port forwarding with a specific bind address, you might see:

bash
bind: Cannot assign requested address
channel_setup_fwd_listener_tcpip: cannot listen to port 8080

Or when trying to forward a privileged port:

bash
bind: Permission denied
channel_setup_fwd_listener_tcpip: cannot listen to port 80

Or the connection appears to work but only listens on localhost when you need it on a specific IP.

Why This Happens

SSH port forwarding binds to localhost (127.0.0.1) by default for security reasons. Binding to a specific IP address requires explicit configuration. Additionally, binding to privileged ports (below 1024) requires root privileges, and the specified IP address must actually be configured on your system's network interfaces.

Step 1: Check Your Network Interfaces

First, verify the IP address you want to bind to exists on your system:

bash
ip addr show

or on older systems:

bash
ifconfig

Look for the IP address in the output. If it's not there, you cannot bind to it.

Step 2: Use the Correct Syntax for Specific IP Binding

For local port forwarding (-L), the syntax is:

bash
ssh -L bind_address:local_port:remote_host:remote_port user@server

To bind to a specific IP (e.g., 192.168.1.100):

bash
ssh -L 192.168.1.100:8080:localhost:80 user@remote-server

For binding to all interfaces, use 0.0.0.0:

bash
ssh -L 0.0.0.0:8080:localhost:80 user@remote-server

Step 3: Configure Gateway Ports in SSH Config

If you need external access to the forwarded port, edit your ~/.ssh/config:

bash
Host myserver
    HostName remote-server.example.com
    User myuser
    LocalForward 8080 localhost:80
    GatewayPorts yes

The GatewayPorts yes option allows the forwarded port to bind to all interfaces, not just localhost.

Step 4: Handle Privileged Port Issues

For ports below 1024, you have two options:

Use sudo:

bash
sudo ssh -L 80:localhost:8080 user@remote-server

Or use a higher port number instead:

bash
ssh -L 8080:localhost:80 user@remote-server

Step 5: Verify the Binding

After establishing the connection, verify the port is listening on the correct interface:

bash
netstat -tlnp | grep 8080

or using ss:

bash
ss -tlnp | grep 8080

You should see the IP address you specified in the "Local Address" column.

Verify the Fix

Test the connection from another machine or a different terminal:

bash
curl http://192.168.1.100:8080

If binding to all interfaces with 0.0.0.0, test both localhost and your external IP to confirm both work. The port should be accessible from the network when GatewayPorts yes is configured.