SSH port-forwarding (Intermediate)
In my previous blog entry I described some basic functionality of SSH in terms of port-forwarding. Now it’s time for a little bit more complex stuff.
In this article I will highlight:
- (forward) piercing of a firewall (getting access to resources behind it);
- dynamic port-forwarding (AKA proxy);
- (reverse) piercing of a firewall (exposing your local services on the remote side).
Forward firewall piercing
Let’s start with the forward firewall piercing, since it is the easiest and was somewhat already described in my previous blog entry on this topic. Now, imagine that you already have SSH access to some host which is multi-home connected (e.g. the host is connected to more than one network). Let’s also assume that the host is a firewall and is masquerading other hosts in the internal network and is translating just a handful set of ports to the servers (looks familiar, doesn’t it? :) ). In other words, we are speaking of a standard firewall/NAT router.
Now, how can you access port 12345 on host behind the firewall given that this port is not “exported” by the NAT on the firewall? This is quite simple. Open a terminal window on your local computer and type the following:
From now on, as long as your SSH session is up and running you will be able to
reach 192.168.1.2:12345
by connecting to localhost:12345
(i.e. the 12345
port on your local computer). Indeed, for this to work you need SSH access
anywhere inside the protected network (not necessarily on the firewall itself)
and if the firewall blocks any SSH access, you are out of luck.
Dynamic port-forwarding
There are at least two usage patterns where I find SSH’s ability to forward requests to many ports useful:
- I need to connect to different services (possibly on different hosts) inside the protected network (as per the configuration described above) and I don’t want to specify all of them on the command line;
- I need to access some resource which is Geo-protected (e.g. allows access from a particular part of the world), e.g. want to watch US Netflix being physically in Australia
In both cases, you use the following SSH command in your terminal window:
As long as you SSH session is active, you can use port 3128
on your local
machine as SOCKS4/SOCKS5 proxy (e.g. you can configure proxy settings in your
browser to use localhost:3128
) and browse the Net through your SSH connection,
and all your requests will look like they are coming from relay.domain.tld
.
There are many uses for this: for example, some payment processors won’t allow you to pay for goods if you are trying to pay through them from some countries even if you are a legitimate user, another use case is when you are concerned re: your privacy – you can conceal your actual location by building a chain of SSH tunnels and access the desired web site through this chain :) .
Reverse firewall piercing
Finally, what if you are behind a very strict firewall that limits almost everything, but you need to provide some services to the outside world from your computer (e.g. sharing your access to company’s confidential information to folks from WikiLeaks… just kidding :) )?
To achieve this you need to have an SSH account somewhere in the Net – just Google for “free ssh account” and you will surely find one for yourself).
Now, when you have the account, you can execute the following on your local computer (which is inside that highly secure network :) ):
The above command will setup such a configuration that connecting on port 60000
at friendly.domain.tld
will forward traffic to your local machine’s port 22
(which is behind a firewall) – this will work as long as your SSH session to
the friendly.domain.tld
is active. Unfortunately, there are several pitfalls
in this approach, but they are all resolvable.
Firstly, you need to ensure that friendly.domain.tld
is using a recent version
of SSH daemon, otherwise you will be limited to bind only to the loopback
interface on the remote host.
Secondly, even if they are using a recent version of the SSH daemon, they can
disallow such binding (e.g. setting “GatewayPorts no” in /etc/ssh/sshd_config
),
and, again, you will be restricted to the loopback interface only.
Finally, you need to find such a friendly host which allows you to connect to the bound ports from the outside (many public ones have a firewall rule preventing such access in order to prevent abuses of their services).
All in all, the best option to try this is to have your own host somewhere (e.g. purchase a small virtual environment from some hosting provider or create an instance on AWS EC2), then you will be able to configure the remote side the way you want it!
Anyway, even if you fail to find a host that allows you to expose your service to the public, you still should be able to access it yourself – using the forward firewall piercing technique described at the beginning of this post:
Once it is done your computer in the highly secure network should be reachable
via SSH on your localhost:60000
, e.g.
Where my_account
is a user allowed to SSH into your computer in the highly
secure network.