In the world of system administration and network management, having the ability to securely access remote systems is crucial. Traditional SSH (Secure Shell) allows users to connect to remote servers from a local machine, facilitating secure command-line access, file transfers, and system management. However, there are situations where the target system is behind a firewall or NAT (Network Address Translation) and direct access is not possible. This is where Reverse SSH comes into play as a powerful solution.
In this article, we will explore what Reverse SSH is, how it works, and how to set it up.
What is Reverse SSH?
Reverse SSH is a technique that allows a remote system (typically behind a firewall or NAT) to establish an outgoing SSH connection to a more accessible, public-facing machine, and then forward the traffic back to the local machine. Essentially, it “reverses” the typical SSH connection flow.
How does Reverse SSH differ from regular SSH?
- Regular SSH: In a typical SSH connection, the client (local machine) connects to a remote server (the target machine) to establish a secure session.
- Reverse SSH: In reverse SSH, the remote machine initiates the connection to a more publicly accessible machine, and the traffic is forwarded to the local machine. This is especially useful for remote support or accessing a system behind restrictive firewalls or NAT.
How Reverse SSH Works
Imagine you have a machine (let’s call it Machine A) behind a firewall or NAT that you want to access remotely, but you can’t directly connect to it because of network restrictions. Reverse SSH allows you to establish a connection by following these steps:
- Establishing the Reverse Tunnel: Machine A initiates an SSH connection to a publicly accessible server (called Machine B) on a specific port. Machine A forwards the traffic through this SSH connection back to itself.
- Accessing Machine A: You can now access Machine A by connecting to Machine B on the specified port. This effectively allows you to bypass the firewall or NAT restrictions and access the remote system.
Use Cases for Reverse SSH
Reverse SSH can be extremely useful in a variety of scenarios:
- Remote Support: If you’re a system administrator or IT support professional, you might need to access a remote system behind a restrictive firewall. Reverse SSH allows you to troubleshoot and resolve issues without needing to configure port forwarding on the target machine’s firewall.
- Secure Access to IoT Devices: Many Internet of Things (IoT) devices are deployed behind NATs or firewalls, making it difficult to access them for management or updates. Reverse SSH can be used to create a secure access point for such devices, enabling remote management.
- Bypassing Firewall Restrictions: If you’re working in an environment where outbound traffic is allowed but inbound traffic is blocked (such as in a corporate network), reverse SSH provides a workaround to maintain secure remote access.
- Penetration Testing: Ethical hackers can use reverse SSH to test the security of a target network. By exploiting vulnerabilities, they can establish reverse SSH tunnels to exfiltrate data or maintain persistent access.
- Accessing Home Networks: If you’re traveling or away from home but need to access a computer or server behind a home router, reverse SSH provides a secure way to do this without setting up complex VPNs or port forwarding.
Implementing Reverse SSH:
Example 1 : Simple Reverse SSH tunnel
Let’s walk through a simple example to illustrate the process.
- Machine A (Office) is located behind a corporate firewall or a NAT, and you can’t directly access it from outside.
- Machine B (Public Server) is a publicly accessible server, such as a VPS, that acts as a bridge between your home and office network.
- Machine C (Home) is your personal machine,
The plan is to create a reverse SSH tunnel from Machine A (office) to Machine B (public server), and then access Machine A from Machine C (home) through Machine B.
Step-by-Step Setup
1. Establish Reverse SSH Tunnel from Machine A (Office) to Machine B (Public Server)
On Machine A (the office machine), you will create a reverse SSH tunnel that connects to Machine B (the public server). This command will forward traffic from Machine B back to Machine A, specifically targeting SSH (port 22) on Machine A.
Run the following command on Machine A (office):
ssh -R -N 2222:localhost:22 user@machine_b_ip
# The -N option means "don't execute any commands, just set up the tunnel."
Explanation:
- -R 2222:localhost:22: This tells SSH to create a reverse tunnel. The -R option forwards port 2222 on Machine B to localhost:22 (SSH port) on Machine A. So, any SSH connection made to Machine B on port 2222 will be forwarded to Machine A’s SSH port (port 22).
- user@machine_b_ip: The SSH login credentials for Machine B (public server).
Once the SSH connection is established, Machine A will be able to access Machine B via port 2222. This port will be forwarded to port 22 (SSH) on Machine A.
2. Connect from Machine C (Home) to Machine A (Office) via Machine B (Public Server)
Now that the reverse SSH tunnel is established from Machine A to Machine B, you can connect to Machine A from Machine C (your home) by connecting to Machine B on port 2222
Run the following command on Machine C (home):
# using single step
# ssh int Machine B with port 2222 from Machine C
ssh userB@machine_b_ip -p 2222
# You can also achieve this in 2 steps
# First ssh into machine B (public server) from Machine C
ssh userB@machine_b_ip
# one you have sshed into machine B form Machine 8
# Now from the same machine B ssh session , you can ssh into Machine A but with port 2222
ssh userA@localhost -p 2222
This command connects to Machine A’s SSH server via the reverse SSH tunnel established by the -R option earlier. The traffic flows through Machine B, which acts as a bridge to Machine A.
Example 2 : Sharing your local web server to internet
To share a web service, such as a simple Python HTTP server running on Machine A (behind a firewall or NAT), and make it accessible over the internet via Machine B (a public server), we can use a combination of Reverse SSH with port forwarding and a reverse proxy configuration on Machine B. By setting up GatewayPorts yes and AllowTcpForwarding yes on Machine B, we can make Machine A’s local web service available externally to any machine, including Machine C.
Scenario Overview:
- Machine A (Office): A machine running a simple Python HTTP server (e.g., python3 -m http.server 8000) behind a firewall or NAT.
- Machine B (Public Server): A publicly accessible server with a public IP address. This machine will forward incoming HTTP requests to Machine A via a reverse SSH tunnel.
- Machine C (Client): A remote machine (could be your home or another machine) that will access the Python web server hosted on Machine A through Machine B.
Step-by-Step Guide:
Step 1: Start the Python HTTP Server on Machine A
First, you need to run a simple HTTP server on Machine A. Open a terminal on Machine A and run the following command to start the server on port 8000 (you can choose any available port):
python3 -m http.server 8000
This will start a web server on Machine A that serves files from the current directory on port 8000. The server will only be accessible locally from Machine A unless we set up port forwarding.
Step 2: Configure SSH Daemon on Machine B (Public Server)
In order for the reverse SSH tunnel to work correctly and for the web service to be accessible, you need to ensure that the SSH server on Machine B is configured to allow TCP forwarding and gateway ports. This enables the public server to accept incoming connections and forward them correctly to Machine A.
Open the SSH configuration file on Machine B:
sudo nano /etc/ssh/sshd_config
# Ensure the following settings are enabled:
AllowTcpForwarding yes
GatewayPorts yes
- AllowTcpForwarding yes: Allows SSH to forward network connections.
- GatewayPorts yes: Makes forwarded ports open to external clients, so that other machines (like Machine C) can access the web service via Machine B.
After making the changes, restart the SSH service on Machine B to apply the new configuration:
sudo systemctl restart sshd
Step 3: Set Up Reverse SSH Tunnel from Machine A to Machine B
Next, we’ll set up a reverse SSH tunnel from Machine A to Machine B. This will allow traffic to port 8000 on Machine B to be forwarded to Machine A’s port 8000 (where the Python HTTP server is running).
Run this command on Machine A:
ssh -R 8000:localhost:8000 user@machine_b_ip
This establishes an SSH connection from Machine A to Machine B, creating a reverse SSH tunnel. Now, Machine B will forward any incoming traffic on port 8000 to Machine A on port 8000.
Step 4: Access the Web Service from Machine C
At this point, the reverse SSH tunnel is set up, and Machine B is now forwarding requests from port 8000 to Machine A.
Now, you can access the web service from Machine C (your home machine or any other client machine) by pointing your browser to Machine B’s public IP address on port 8000.
On Machine C (client machine), open a web browser and go to:
http://machine_b_ip:8000
Replace machine_b_ip with the actual public IP address of Machine B (the public server). You should now see the web page served by the Python HTTP server running on Machine A.
Recap of the Process
- Machine A: Run a Python HTTP server on port 8000.
- Machine A: Set up a reverse SSH tunnel to Machine B, forwarding Machine B’s port 8000 to Machine A’s port 8000.
- Machine B: Ensure the SSH server allows TCP forwarding and sets GatewayPorts yes to expose the forwarded port to external connections.
- Machine C: Access the web service by connecting to Machine B’s public IP address at http://machine_b_ip:8000.
Example 3 : Sharing your local web server to internet with ssl certificate
In this example, we will build upon the second scenario by securing the connection with a self-signed certificate. To achieve this, we’ll create a custom Python HTTP server script that enables SSL. Then, we’ll use a reverse proxy to expose this locally running server to the internet via a public server.
Generating the self signed certificate
# Generate key-cert pair (without passphase)
openssl req -new -x509 -keyout key.pem -out server.pem -days 365 -nodes
# The common name should be set to the domain name or IP address of the public server, while the remaining fields can be left blank.
# if you want to create cerk and key non intractively
## Non interactive [but with passphrase]
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -subj "/CN=<domain name/ip of public server"
Modified python server to include our self signed certificate and key file
import http.server
import ssl
certfile = 'server.pem'
keyfile = 'key.pem'
# Create an SSL context
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ssl_context.load_cert_chain(certfile=certfile, keyfile=keyfile)
server_address = ('localhost', 4443)
httpd = http.server.HTTPServer(server_address, http.server.SimpleHTTPRequestHandler)
httpd.socket = ssl_context.wrap_socket(httpd.socket)
print(f"Starting server on https://{server_address[0]}:{server_address[1]}...")
httpd.serve_forever()
To expose this to the internet
Run this on your linux machine A on which python server is running
ssh -R 5554:localhost:4443 root@machineB.com -i key.pem
To test this : we will use curl command
curl https://machineB.com:5554/
# -k = ignore self signed error
curl -k https://machineB.com:5554/
Security Considerations
While Reverse SSH is a powerful tool, it is important to keep a few security considerations in mind:
- SSH Key Authentication: Use SSH keys for authentication rather than passwords. This enhances security by ensuring that only machines with the correct private key can establish a connection.
- Restrict Access: Limit the users who can establish reverse SSH tunnels on the server (Machine B). For example, you can specify which users are allowed to connect via AllowUsers in the /etc/ssh/sshd_config file on Machine B.
- Monitoring and Logging: Always monitor the SSH logs on the public-facing server (Machine B). Look for unusual activity, as reverse SSH can potentially be exploited by attackers to create backdoors.
- Firewall Rules: Ensure that the reverse SSH tunnel does not inadvertently open unwanted ports or expose sensitive services to the outside world. Proper firewall configuration is essential to prevent unauthorized access.
- Timeouts and Sessions: You may want to set up session timeouts or automatic disconnects to ensure that reverse SSH sessions do not stay open indefinitely, which could be exploited in the event of a compromise.
While setting up Reverse SSH is relatively straightforward, it’s crucial to remain vigilant about security, especially when allowing external systems to establish tunnels into your network. When configured properly, Reverse SSH can be a valuable addition to your toolkit for managing remote systems securely and efficiently.
Conclusion
Reverse SSH is a powerful technique that allows you to securely access a machine behind a firewall or NAT by creating a reverse tunnel through a public-facing server. Whether you’re performing remote administration, providing tech support, or accessing an IoT device, reverse SSH can help you bypass network restrictions and establish secure communication with remote systems.