SSH Port Forwarding ⤳ aka SSH Tunneling.
SSH port forwarding (SSH Tunneling) is a method for safely transmitting data over an encrypted SSH; tunneling application ports from a connection between a local and distant server or vice versa.
What Is SSH Tunneling?
SSH tunneling is a powerful feature widely used by system administrators and developers to securely access services across different networks or to bypass restrictive firewall rules.
At a high level, SSH tunneling allows you to forward any TCP/IP port through an encrypted SSH connection. Instead of application traffic traveling directly over the network, it is encapsulated inside the SSH session. This ensures that the data remains confidential and protected from eavesdropping, interception, or manipulation while in transit.
Because the traffic is encrypted end-to-end, SSH tunnels are commonly used to:
- Access internal services from untrusted networks
- Secure legacy or unencrypted protocols
- Reach restricted resources behind firewalls or NAT devices
- Safely manage remote systems over insecure networks
⚠️ Security Considerations
While SSH tunneling is a legitimate and essential administrative tool, it can also be misused. Attackers and malware may abuse SSH tunnels to:
- Create covert backdoors from the Internet into internal networks
- Exfiltrate data through encrypted channels that evade inspection
- Obscure their activity by routing attacks through multiple intermediate hosts that allow unrestricted tunneling
For this reason, SSH tunneling should be carefully monitored, controlled, and restricted to trusted users and well-defined use cases, especially in enterprise or production environments.
Let Us Explore: How SSH Port Forwarding Works
SSH tunneling enables secure port forwarding, which can be implemented in three main ways: local, remote, and dynamic port forwarding. Each method serves different use cases depending on where the traffic originates and where it needs to go.
- Local port forwarding: Redirects traffic from a local port on the client machine to a specified port on a remote server via an SSH connection.
- Remote port forwarding: Redirects traffic from a port on the remote server to a specified port on the client machine.
- Dynamic port forwarding: Creates a SOCKS proxy on the client machine, enabling the forwarding of traffic from various applications through the SSH connection.
Case Study: Secure Application Access
Here, in our SNUBmonkey VM lab environment, we host multiple application projects, each running on its own local service port. These applications are isolated within their respective development environments and are not directly exposed to external networks for security reasons.
The challenge is to provide secure, controlled access to these application ports for testing, collaboration, or remote administration—without opening firewall rules or publicly exposing the services.
To address this, we use SSH tunneling as a secure transport mechanism. By forwarding specific local application ports through an encrypted SSH connection, authorized users can access these services remotely as if they were running on their own machines. All traffic between the client and the VM is encapsulated within SSH, ensuring confidentiality and integrity.
Objectives of This Lab
- Securely expose multiple local application ports without public network access
- Avoid modifying firewall or NAT configurations
- Maintain strict access control using SSH authentication
- Provide a reproducible and auditable access method for developers and administrators
Clarifying Some Key Concepts
Let's take a moment to clarify a few fundamental notions. If you’re already familiar with them, feel free to skip this section.
What is a localhost?
The term "localhost" refers to the computer or device you are currently using. It is commonly associated with the loopback IP address 127.0.0.1. This address allows your computer to send network traffic to itself.
Why it's useful:
- Testing network applications locally without exposing them to the network
- Accessing services that are running only on your own machine, such as a local web server or database
Think of it as a "private network within your own computer."
What is a Bind-address?
A bind address specifies the network interface or IP address that an application listens on for incoming connections. Essentially, it tells the application: "Listen for traffic on this IP and port combination."
Key points:
- When a socket is associated with an IP address and a port number, it is said to be bound to that address
- The action of assigning a port number to a socket is called binding
- Only applications bound to an address can receive network data sent to that address
This concept is crucial when configuring servers or SSH tunnels, as it determines which clients can reach your service.
What is a Proxy Server?
A proxy server acts as an intermediary between a client and a destination server. It forwards requests from the client to the destination and can return responses back.
Common uses:
- Caching: Improve performance by storing frequently accessed content
- Security/Filtering: Control access to certain resources or block malicious traffic
- Anonymity: Hide the client's real IP address from the destination server
In SSH tunneling, a dynamic port forward effectively creates a local SOCKS proxy, allowing multiple applications to route traffic securely through an SSH tunnel.
1. Local Port Forwarding
Local port forwarding is the most commonly used type of SSH tunneling. It allows you to access a service on a remote machine that is otherwise not directly accessible from your local device—all over a secure, encrypted connection.
Typical Use Cases
Local port forwarding is useful in scenarios such as:
- Accessing a database (MySQL, MariaDB, Redis, Postgres, etc.) from your local machine
- Accessing a container or VM port without exposing it on the server’s public interface
- Using a browser to access a web application that is restricted to a private network
How It Works
Consider a remote application that listens on localhost of the remote server (127.0.0.1:3914).
From your local machine, there is no direct way to connect to this port because it is not publicly exposed.
This is where SSH local port forwarding comes into play: you can forward a local port to the remote service over SSH, making it accessible on your machine as if it were local.
Example Command
Using OpenSSH, local port forwarding is initiated with the -L flag. The -N flag prevents starting an interactive shell session, which is useful if you only want to forward ports.
$ ssh -N -L source_port:forward_to_host:destination_port via_host
$ ssh -N -L 3914:localhost:3914 [REMOTE_USER]@[REMOTE-SERVER_IP]
([REMOTE_USER]@[REMOTE-SERVER_IP]) Password:
In the above example, the SSH command opens a connection to the jump server at 192.168.1.xxx and forwards traffic from a local port on your machine to port 3914 on the remote server.
- The local port does not need to match the remote port. For example, you could forward local port
5000to remote port3914. - Once the tunnel is established, visiting
http://localhost:5000in your browser will securely connect to the remote service running on127.0.0.1:3914on the jump server.
Forwarding Multiple Ports
You can forward multiple ports in a single SSH session by specifying multiple -L flags in the same command:
$ ssh -N -L 4562:localhost:3305 -N -L 3286:127.0.0.1:6512 [REMOTE_USER]@[REMOTE-SERVER_IP]
([REMOTE_USER]@[REMOTE-SERVER_IP]) Password:Securing Access to Remote Services
By default, when you forward a port using SSH, the local port on your machine may be accessible to other machines on the same network. This can be a security risk if untrusted devices exist on the network.
To restrict access so that only programs running on your own host can connect to the forwarded port, you can specify a bind address when creating the SSH tunnel.
Example: Binding to Localhost
$ ssh -N -L 127.0.0.1:3914:localhost:3914 [REMOTE_USER]@[REMOTE-SERVER_IP]
([REMOTE_USER]@[REMOTE-SERVER_IP]) Password:2. Remote Port Forwarding (Reverse tunneling)
Remote port forwarding, also called reverse SSH tunneling, allows you to make a local service accessible to a remote server.
The term "reverse" refers to the flipping of the usual data direction:
- Normally, SSH connections originate from your local machine to a remote server
- With reverse tunneling, the remote server can initiate a connection back to your local machine
This is particularly useful when your local machine is behind NAT, firewalls, or other network restrictions, preventing direct inbound connections.
How It Works
- You run an SSH command on your local machine using the
-Rflag - The remote server opens a listening port that forwards traffic through the SSH tunnel to your local service
Example Command
Suppose you have a web service running on your local machine at localhost:2399 and you want it accessible from a remote server:
$ ssh -N -R source_port:forward_to_host:destination_port via_host
$ ssh -N -R 2393:localhost:2399 [REMOTE_USER]@[REMOTE-SERVER_IP]
([REMOTE_USER]@[REMOTE-SERVER_IP]) Password:
In this example, SSH establishes a connection to [REMOTE-SERVER_IP].
- The
-Rflag instructs SSH to listen on port2393on the remote server - Any process on
[REMOTE-SERVER_IP]that connects to port2393will have its traffic forwarded through the SSH tunnel - That traffic is then delivered to your local machine at
localhost:2399
In effect, a service running locally on port 2399 becomes accessible from the remote server via port 2393, with all communication securely encapsulated inside the SSH connection.
This mechanism allows remote systems to reach services that are otherwise unreachable due to NAT, firewall rules, or private network boundaries.
Remember, you don’t have to use localhost; any valid hostname or IP can be the tunnel’s destination. This enables remote access to internal services, such as private web servers.
Caution:
Although useful for legitimate tasks like remote testing, reverse tunnels can be abused to expose internal applications. Always restrict and monitor their use.
Controlling Remote Port Access with GatewayPorts
By default, OpenSSH only allows connections to remote forwarded ports from the server itself. The GatewayPorts option in the SSH server configuration file (/etc/ssh/sshd_config) controls whether external hosts can connect to these ports.
Available Options
GatewayPorts no(default)
Only the server host can connect to the forwarded port. External connections are blocked.GatewayPorts yes
Any host can connect to the forwarded port. If the server is public, this exposes the port to the Internet.GatewayPorts clientspecified
The client can choose which IP address the remote port listens on.
Example:
$ ssh -R 15.152.66.244:8080:localhost:80 host232.whatever.com- Only connections from
15.152.66.244to port8080on the remote server are allowed - Traffic is securely forwarded to your local
localhost:80
Security Note:
GatewayPorts yescan expose services to the public and is generally riskyGatewayPorts clientspecifiedis safer, allowing fine-grained control over which hosts can connect
3. Dynamic port forwarding
Dynamic port forwarding, allows you to create a secure, general-purpose tunnel between your machine and a remote SSH server. Unlike local or remote port forwarding, which forward specific ports, dynamic forwarding can redirect traffic from any application or port through the SSH connection.
Effectively, this turns the remote SSH server into a SOCKS proxy, making it harder for third parties to intercept or track your activities.
Common Use Cases
- Accessing websites or services that are blocked or restricted
- Bypassing network censorship
- Protecting your privacy when browsing or using network applications
How to Use
In OpenSSH, dynamic port forwarding is initiated using the -D flag, followed by a local port number that will act as the SOCKS proxy:
$ ssh -D [local_port] [REMOTE_USER]@[REMOTE-SERVER_IP]
$ ssh -D 45337 -C -N -f -p 1234 [REMOTE_USER]@[REMOTE-SERVER_IP]
([REMOTE_USER]@[REMOTE-SERVER_IP]) Password:The options used are as follows:
-D 45337
Allocates a local dynamic port (45337) for application-level forwarding. This acts as a SOCKS proxy, optionally bound to a specific address.-C(optional)
Compresses all data (stdin, stdout, stderr, and forwarded connections) using the same algorithm asgzip. Useful for slow connections; may slightly reduce speed on fast networks.-N
Tells SSH not to execute a remote command, keeping the session dedicated to forwarding.-f(optional)
Sends SSH to the background, allowing the tunnel to run silently.-p 1234
Specifies the SSH server port if it is not the default22.[REMOTE_USER]@[REMOTE-SERVER_IP]
Your SSH login credentials.
Dynamic port forwarding uses the SOCKS protocol, with SSH acting as a local SOCKS proxy that routes traffic securely through the tunnel. The client must be SOCKS-aware—for example, a browser configured to use the proxy.
Configuring your Browser to Use a Proxy Server
Now that the SSH SOCKS tunnel has opened, the last step is to configure your preferred browser.
Chrome# on macOS.
The steps below might but different on Windows or Linux.
- In the upper left-hand, click on Chrome's menu.
- Settings... ⌘,
- Scroll down to the
System menusection and click onOpen your computer's proxy settings. - MacOS
System settingswill pop up; right on theProxies tab.- Select and enable
SOCKS proxy. - Enter
127.0.0.1orlocalhostin theServerfield and whatever port number you have previously chosen in thePortfield. - Click on the
OKbutton to save the settings.
- Select and enable
At this point, your Chrome should be configured and you can browse the Internet through the SSH tunnel.
Check for LISTEN| ESTABLISHED ports
Let's inspect for open TCP ports that are actively listening like PROS.
Run the below command on the host where you initiated the proxy.
$ lsof -nP -i4TCP:45337 | grep LISTEN
OUTPUT
ssh 29300 xxxxx 6u IPv4 0xb89bd28ef6dd03ff 0t0 TCP 127.0.0.1:45337 (LISTEN)
As you can see the SOCKET is waiting to be connected. (LISTEN)
A listening port refers to a port on a computer that is actively awaiting inbound requests, ready to receive incoming data or connections on that specific port number.
Again, we will run the below this time on the SERVER side.
$ lsof -nP -i4TCP | grep 192.168.1.xxx
OUTPUT
sshd 26073 xxxxx 4u IPv4 0x1e84b24b17ed2aad 0t0 TCP 192.168.1.xxx:22->192.168.1.xxx:52025 (ESTABLISHED)
sshd 26073 xxxxx 5u IPv4 0x1e84b24b17ed2aad 0t0 TCP 192.168.1.xxx:22->192.168.1.xxx:52025 (ESTABLISHED)
As you can see the SOCKET is connected. (ESTABLISHED)
An established port refers to a port on a computer that is actively receiving and processing data from another computer.
Security Concerns of Port Forwarding
While port forwarding can be a useful technique for accessing remote devices and services, if not implemented correctly, it can pose security risks.
The following are the primary safety concerns with port forwarding:
- Exposure of Services: Port forwarding exposes internal services to the internet, potentially allowing unauthorized access to those services if not properly secured.
- Target for Attacks: Open ports created by port forwarding can become targets for attackers who may attempt to exploit vulnerabilities in the exposed services.
- Misconfiguration: Incorrectly configured port forwarding rules may inadvertently expose sensitive data or services, leading to data breaches or unauthorized access.
- Increased Attack Surface: Port forwarding increases the attack surface of a network by providing more entry points for potential attackers.
It's essential to carefully consider the security implications and follow best practices when implementing port forwarding to mitigate these risks.
There are a few steps you can take to mitigate the security risks associated with port forwarding. These include:
- Limit Exposure: Only forward ports that are absolutely necessary for your intended use. Close any unused ports to reduce the attack surface.
- Implement Access Controls: Restrict access to forwarded ports by using firewall rules or access control lists (ACLs) to allow only authorized IP addresses or networks to connect.
- Regularly Update Software: Keep all software and services running on forwarded ports up to date with the latest security patches to address known vulnerabilities.
- Enable Logging and Monitoring: Enable logging and monitoring for forwarded ports to detect and respond to suspicious activities or unauthorized access attempts.
- Employ Intrusion Detection/Prevention Systems (IDS/IPS): Use IDS/IPS solutions to monitor network traffic for signs of malicious activity and block or alert on suspicious behavior.
- Implement Two-Factor Authentication (2FA): Require two-factor authentication for accessing sensitive services or systems exposed through port forwarding to add an extra layer of security.
By following these steps, you can significantly reduce the security risks associated with port forwarding and better protect your network and systems.
Wrapping up this tutorial, I want to express my sincere gratitude to each participant for their invaluable contributions. Learning is a collaborative journey, and I encourage everyone to stay curious and continue asking questions. This tutorial marks just the beginning of our quest for deeper understanding.
Thank you all once again, and best wishes on your learning journey ahead!