Toggle menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

SSH Port Forwarding

From John's Wiki

Intro

It is possible to use SSH to take some port on machine A and redirect traffic to it securely through an encrypted tunnel to some other port on machine B. This is called SSH port forwarding and its a powerful yet niche usecase technique for redirecting ports when they may otherwise be inaccessible.

Example Use Case

Say we have two machines. We'll call them "server" and "client". Say on server, Apache is running on localhost port 80. However, server is firewalled off and from the outside port 80 is not accessible. All that server has open is SSH on 22.

  • Internal nmap scan of server
root@server:~> nmap localhost
...
Nmap scan report for localhost (127.0.0.1)
Host is up (0.00011s latency).
Not shown: 998 closed ports
PORT     STATE SERVICE
22/tcp  open  ssh
80/tcp   open  http
  • External nmap scan of server
user@client:~> nmap -Pn SERVER_IP_ADDRESS
...
Nmap scan report for SERVER_IP_ADDRESS
Host is up (0.00015s latency).
Not shown: 999 closed ports
PORT     STATE SERVICE
22/tcp  open  ssh

So say we want to see what is on port 80 on the server in a web browser. Well one way of doing that is to forward server port 80 to some port (we'll say 1234) on our client machine. Then we should just be able to open up a browser and go to localhost:1234 on our client machine to see what is running internally on port 80 on the server.

Its important to note that the client must have normal SSH access to the server in order for this to work.

Port Forwarding Command

We can use the command below to create such a tunnel.

ssh -L 1234:SERVER_IP_ADDRESS:80 -f -N SERVER_IP_ADDRESS

Let's break that down.

  • -L: Stands for Local Forwarding, its the magic that allows the port forwarding.
  • 1234: Is the port of our client machine we want to forward the remote port to
  • SERVER_IP_ADDRESS:80: Is the remote server and port we want forwarded
  • -N: Means just forwarding ports, don't start a shell.
  • -f: Means fork into background after a successful SSH connection and log-in.

Once the above is run it will launch a secret tunnel in the background forwarding traffic from internal server:80 to client:1234.

To kill the above command first find it using ps.

ps auxwww|grep ssh
user   42753  0.0  0.0  14832  2960 ?        Ss   12:38   0:00 ssh -L 1234:SERVER_IP_ADDRESS:80 -f -N SERVER_IP_ADDRESS

Then kill the pid

kill -9 42753

Alternatively, omit the '-f' option to keep the ssh port forwarding session running in your shell. Then press "ctrl + c" to break it when finished.

Other Use Cases

Local Forwarding On Remote Machines

Its possible to use ssh port forwarding to redirect an internal port to an external port running on the same machine. Say for example we omit the client entirely from the first example and only have one machine, set up thusly.

  • Internal nmap scan of server
root@server:~> nmap localhost
...
Nmap scan report for localhost (127.0.0.1)
Host is up (0.00011s latency).
Not shown: 997 closed ports
PORT     STATE SERVICE
22/tcp  open  ssh
80/tcp   open  http
1234/tcp closed hotline
  • External nmap scan of server
user@client:~> nmap -Pn SERVER_IP_ADDRESS
...
Nmap scan report for SERVER_IP_ADDRESS
Host is up (0.00015s latency).
Not shown: 998 closed ports
PORT     STATE SERVICE
22/tcp  open  ssh
1234/tcp closed hotline

Again port 80 on server is not exposed to the outside world. But port 1234 is! So how do we get server port 80 to appear on server port 1234? Well we just use a variation of the same SSH port forwarding command from above and run it on the server.

ssh -L 1234:localhost:80 -N SERVER_IP_ADDRESS

Or alternatively you can use the -g for global flag to open it up to every IP address your machine answers for.

ssh -g -L 1234:localhost:80 -N localhost

Remote Forwarding

When you need to send a connection from localhost:8080 to external-host:80 you can use the remote forwarding syntax below.

ssh -R 8080:localhost:80 SERVER_IP_ADDRESS

Remote forwarding is enabled by the -R switch which does the magic here.

Forward Web Traffic to Remote Machine

Its possible to direct all of your web traffic securely through a remote server using the ssh port forwarding command below.

ssh -N -D 8080 SERVER_IP_ADDRESS

You'll notice this option is slightly different than what we've seen so far. Here were opening up a SOCKS proxy using the -D flag. Man ssh describes the -D flag thusly.

     -D [bind_address:]port
             Specifies a local “dynamic” application-level port forwarding.  This works by allocating
             a socket to listen to port on the local side, optionally bound to the specified
             bind_address.  Whenever a connection is made to this port, the connection is forwarded
             over the secure channel, and the application protocol is then used to determine where to
             connect to from the remote machine.  Currently the SOCKS4 and SOCKS5 protocols are sup‐
             ported, and ssh will act as a SOCKS server.  Only root can forward privileged ports.
             Dynamic port forwardings can also be specified in the configuration file.

To make this work we also have to configure our web browser to use the socks proxy we've set up on port 8080.

  • In Firefox:

Network Settings > Settings... > ✔️ Manual proxy configuration > SOCKS Host: 127.0.0.1 Port: 8080 > ✔️ Proxy DNS when using SOCKS v5 > Ok