Local port forwarding in SSH makes remote services accessible as if they were running on the local machine. By tunneling traffic through an encrypted connection, it bypasses firewalls that allow SSH but block direct access to internal web interfaces, databases, or management endpoints. Using a local port forward reduces exposure of sensitive services to the public internet and centralizes access through a single secure entry point.

An OpenSSH client creates a local port forward with the -L option, binding a chosen local port to a target host and port that are reachable from the SSH server. The general form ssh -L [bind_address:]local_port:target_host:target_port user@ssh-gateway instructs ssh to listen on the local port and relay connections over the encrypted session to the target host. Requests from local applications to localhost:local_port then travel through the tunnel and arrive at the target host as if they originated from the SSH gateway.

Incorrectly chosen ports or bind addresses can introduce conflicts or expose private services to other systems on the network. Low-numbered ports below 1024 typically require elevated privileges, and reusing ports already in use causes binding failures. Before deploying local port forwarding in production, confirming that the SSH gateway can reach the target service, restricting bindings to localhost unless sharing is intentional, and monitoring access logs for unexpected connections helps keep access controlled and predictable.

Steps to configure local port forwarding in SSH:

  1. Open a terminal on the local machine that will originate the tunnel.
  2. Start a local port forward from port 8080 on the local host to port 80 on the SSH server using the -L option.
    $ ssh -L 8080:localhost:80 username@remote-server.example
    username@remote-server.example's password:
    Welcome to Ubuntu 22.04.4 LTS
    Last login: Mon May 13 10:15:01 2024 from 198.51.100.23
    ##### snipped #####

    The general local port forwarding syntax is ssh -L [bind_address:]local_port:target_host:target_port user@ssh-gateway; adding -N disables the remote shell when only tunneling traffic.

  3. Configure the tunnel to forward traffic to a host reachable only from the SSH server if access to an internal service is required.
    $ ssh -L 8080:internal-service.example:80 username@ssh-gateway.example
    username@ssh-gateway.example's password:
    ##### snipped #####

    In this form, internal-service.example is contacted from the SSH gateway, not from the local machine.

  4. Restrict or expand the listening address for the local port by specifying an explicit bind_address component when needed.
    $ ssh -L 127.0.0.1:8080:internal-service.example:80 username@ssh-gateway.example

    Using a bind address such as 0.0.0.0 allows other systems on the local network to connect to the forwarded port, which can expose internal services to unintended clients.

  5. Verify that the local port forward works by sending a request to the forwarded port on the local machine.
    $ curl -I http://localhost:8080
    HTTP/1.1 200 OK
    Server: nginx/1.24.0
    Date: Mon, 13 May 2024 10:20:02 GMT
    Content-Type: text/html; charset=UTF-8
    Content-Length: 612
    Connection: keep-alive
    ##### snipped #####

    An HTTP status code in the 2xx range from the curl request confirms that the remote service is reachable through the SSH tunnel while the connection remains open.

  6. End the local port forwarding session by closing the SSH connection when access is no longer required.
    $ exit

    Terminating the SSH session stops the tunnel and releases the local port, preventing further connections through the forward.

Discuss the article:

Comment anonymously. Login not required.