SSH Dynamic Port Forwarding
Local port forwarding has one glaring limitation:
we can only connect to one socket per SSH connection.
This can make it quite tedious to use at scale.
Luckily, OpenSSH also provides dynamic port forwarding.
From a single listening port on the SSH client,
packets can be forwarded to any socket that the SSH server host has access to.
SSH dynamic port forwarding works
because the listening port that the SSH client creates
is a SOCKS proxy server port.
This is powerful.
In SSH dynamic port forwarding,
packets can be sent to a single listening SOCKS port
on the SSH client machine.
These will be pushed through the SSH connection,
then forwarded to anywhere the SSH server machine can route.
The only limitation is that the packets have to be properly formatted
most often by SOCKcompatible client software.
In some cases, software is not SOCKS-compatible by default.
We will work through this limitation later in this section.
Let’s illustrate an SSH dynamic port forward in our network diagram.
The layout is very similar to SSH local port forwarding.
We are listening on TCP port 999 on the WAN interface of CONFLUENCE01.
Packets sent to this port, in SOCKS format,
are pushed through the SSH tunnel to PGDATABASE01,
then forwarded wherever they are addressed.
This means we will still be able to access the SMB port on HRSHARES,
but we can also access any other port on any other host
that PGDATABASE01 has access to,
through this single port.
However, in order to take advantage of this flexibility,
we need to ensure that whatever software we use
can send packets in the correct SOCKS protocol format.
Let’s extend the previous scenario.
As well as connecting to the SMB port on HRSHARES,
we also want to be able to do a full portscan of HRSHARES.
We can ensure that we’re in a TTY shell using Python3’s pty module.
We will create our SSH connection to PGDATABASE01
using the database_admin credentials again.
In OpenSSH, a dynamic port forward is created with the -D option.
The only argument this takes is the IP address and port we want to bind to.
In this case, we want it to listen on all interfaces on port 9999.
We don’t have to specify a socket address to forward to.
We’ll also pass the -N flag to prevent a shell from being spawned.
As with the previous example,
we don’t receive any immediate output after we enter the password.
As we did earlier, let’s connect to port 445 on HRSHARES.
However, this time we will do it through the SOCKS proxy port
created by our SSH dynamic port forward command.
To accomplish this, we’ll want to use smbclient again.
However, we find that smbclient
doesn’t natively provide an option to use a SOCKS proxy.
Without a native option to use a SOCKS proxy in smbclient,
we can’t take advantage of our dynamic port forward.
The SOCKS proxy can’t determine how to handle traffic
that isn’t encapsulated in the SOCKS protocol format.
To use smbclient in this situation, we’ll leverage Proxychains.
Proxychains is a tool that can force network traffic
from third party tools over HTTP or SOCKS proxies.
As the name suggests,
it can also be configured to push traffic over a chain of concurrent proxies.
Let’s try Proxychains with smbclient.
Proxychains uses a configuration file for almost everything,
stored by default at /etc/proxychains4.
We need to edit this file to ensure that Proxychains
can locate our SOCKS proxy port,
and confirm that it’s a SOCKS proxy, rather than any other kind of proxy.
By default, proxies are defined at the end of the file.
We can simply replace any existing proxy definition in that file
with a single line defining the proxy type,
IP address, and port of the SOCKS proxy running on CONFLUENCE01.
After editing the file, it should appear as follows:
With Proxychains configured,
we can now list the available shares on HRSHARES
using smbclient from our Kali machine.
Rather than connecting to the port on CONFLUENCE01,
we’ll write the smbclient command
as though we have a direct connection to PGDATABASE01.
As before, we will specify -L to list the available shares,
pass the username with -U,
and password with --password.
Next, we can simply prepend proxychains to the command.
Proxychains will read the configuration file,
hook into the smbclient process,
and force all traffic through the SOCKS proxy we specified.
The connection was a success!
We’ve managed to connect to HRSHARES and list its shares,
including an interesting folder called scripts.
We receive some extra output from Proxychains too,
including the ports that were interacted with while the process was running.
Let’s escalate this and port scan HRSHARES through our SOCKS proxy using Nmap.
We’ll use a TCP-connect scan,
skip DNS resolution,
skip the host discovery stage,
and only check the top 20 ports.
We will then prepend proxychains to the command again
to push all packets through the SSH dynamic port forward SOCKS proxy.
We’ll also increase the verbosity using -vvv.
The scan was a success!
Proxychains gives us insight into each socket that was attempted and,
if the connection failed, notes how.
Nmap found TCP ports 135, 139, 445, and 3389 are open.
In this section, we set up a dynamic port forward
and used Proxychains to push traffic from both smbclient and Nmap
through the SOCKS proxy port that was created.
We subsequently managed to list the shares on,
as well as port scan, HRSHARES.