In this article I'll 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's the easiest and was somewhat already described in my previous blog entry on this topic. Let's assume 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 the other net hosts 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:
$ ssh -L12345:192.168.1.2:12345 joe@firewall.domain.tld
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)
In both cases, you use the following SSH command in your terminal window:
$ ssh -D3128 joe@relay.domain.tld
As long as you SSH session is active, you can use port 3128 on your localhost 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 :) ):
$ ssh -R:60000:127.0.0.1:22 joe@friendly.domain.tld
The above command will setup such a configuration that connecting on port 60000 at friendly.domain.tld will forward traffic to your localhost's port 22 (which is behind a firewall) -- this will work as long as your SSH session is active. Unfortunately, there are many 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), 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:
# from your home computer
$ ssh -L60000:127.0.0.1:60000 joe@friendly.domain.tld