More actions
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