Port Forwarding with SSH

Last modified: 2023-03-19

Network

SSH tunneling, also known as port forwarding, is a method of creating a tunnel between two endpoints through which traffic is forwarded.

Local Port Forwarding

We can forward a port on the local machine to a port on the remote machine by adding the flag "-L" with SSH.
Also, it is required the remote SSH username/password.

ssh -L [<local-ip>:]<local-port>.<destination-ip>:<destination-port> remote-user@<remote-ip>

# -f: Background
# -N Do not execute remote commands
ssh -L [<local-ip>:]<local-port>:<destination-ip>:<destination-port> remote-user@<remote-ip> -fN

Examples

Below are some examples.

# We can access the internal webserver in the remote machin via http://127.0.0.1/
sudo ssh -L 80:127.0.0.1:80 john@example.com
sudo ssh -L localhost:80:127.0.0.1:80 john@example.com

# We can connect the database on local port 3306
ssh -L 3306:db.example.com:3306 john@example.com
ssh -L localhost:3306:db.example.com:3306 john@example.com
# Another port
ssh -L 3336:db.example.com:3306 john@example.com

# Multiple ports
ssh -L 8001:127.0.0.1:8001 -L 9090:127.0.0.1:9090 john@example.com

Stop Local Port Forwarding

To stop the local port forwarding if it is running background, find the process ID and specify it to kill command.

ps aux | grep ssh
kill <PID>

Remote Port Forwarding

We can forward a port on the remote machine to a port on the local machine by adding the flag "-R" with SSH.

ssh -R [<remote-ip>:]<remote-port>:<destination-ip>:<destination-port> remote-user@<remote-ip>

Examples

Below are some examples.

# A remote user can view our local website running on port 3000 by accessing on the port 8080 from the remote machine.
ssh -R 8080:127.0.0.1:3000 john@example.com
ssh -R example.com:8080:127.0.0.1:3000 john@example.com

Dynamic Port Forwarding

If we cannot determine the remote ports opened internally, we can find them using dynamic port forwarding.
First off, execute the dynamic port forwarding using ssh.

ssh -D 1337 remote-user@<remote-ip>

And update the configuration for Proxychains.
In “/etc/proxychains.conf”, comment out “socks4 127.0.0.1 9050" and add “socks5 127.0.0.1 1337” on the bottom of the file.

# socks4 127.0.0.1 9050
socks5 127.0.0.1 1337

After that, try port scanning to find open ports of the remote machine over 127.0.0.1.

proxychains nmap 127.0.0.1

When we found the open ports, we can execute the Local Port Forwarding using the ports we found.
*By the way, we can close the previous dynamic port forwarding if not necessary.

ssh -L <local-port>:127.0.0.1:<port-we-found> remote-user@<remote-ip>

# e.g.
# If we want to open port 80 in local, we need to run as root privilege.
sudo ssh -L 80:127.0.0.1:80 john@example.com
ssh -L 3306:127.0.0.1:3306 john@example.com

For instance, assume that the remote machine opens port 80 internally.
Now access http://127.0.0.1/. We can access the remote webserver.


Reverse Connection

Reverse connections are often used in situations where the server needs to be accessible from the client's network, but the server's network is restricted. By initiating a reverse connection, the client can establish a connection to the server without the need for the server to be accessible on the public internet.

1. Generate SSH Keys in Remote Machine

ssh-keygen

Then save them (public key and private key) to arbitrary folder.

mkdir /home/remote-user/reverse-keys
mv id_rsa /home/remote-user/reverse-keys
mv id_rsa.pub /home/remote-user/reverse-keys

Copy the content of public key (id_rsa.pug).

2. Add Content of Public Key to authorized_key in Your Local Machine

echo 'content of publick key' >> ~/.ssh/authorized_key

To clarify that the key only for reverse connection, add the following line to this content in authorized_key.

# ~/.ssh/authorized_key
command="echo 'This account can only be used for port forwarding'",no-agent-forwarding,no-x11-forwarding,no-pty id-rsa
AAAAAB3NzaC........

Check if SSH server is running.
If the server is not running, start SSH server.

sudo systemctl status ssh

3. Run Reverse Proxy in Remote Machine

Reverse port forwarding using the private key (id_rsa)

ssh -R <local-port>:<remote-ip>:<remote-port> local-user@<local-ip> -i id_rsa -fN

4. Confirmation in Your Local Machine

You can access to <remote-ip>:<remote-port>

5. Close Connection in Remote Machine

After that, stop reverse connection.

ps aux | grep ssh
sudo kill <PID>