Cheap SSH VPN
Recently (I seem to start a lot of posts with “Recently”), I was on the road needed to access a server that was behind a firewall. There was no VPN and access was limited to a small set of IPs. I could however access another server in that set of IPs. That would let me bounce through for SSH access, but really I needed access from my laptop. One simple thing to do in this situation is set up an SSH tunnel. I’ve covered inbound tunnels before, outbound ones are even simpler:
ssh -N user@gateway-server -L 8080:firewall-server:80
user@gateway-server
is you SSH login on the server you can get
to. -L
says open a tunnel, 8080
being the local port your computer,
firewall-server
is the server behind the firewall, and 80
is the
port on that server you want to connect to. -N
says don’t start a
shell, otherwise ssh
would log you in to gateway-server.
The end results is that anything sent to port 8080 on you local computer is forwarded over SSH and then a connection is may out from gateway-server to port 80 on firewall-server.
Or more simply, once the tunnel is open, you open to http://localhost:8080, and boom, you find you self looking at the web server behind the firewall.
If you need to open multiple ports, you can use -L
multiple times:
ssh -N user@gateway-server -L 2222:firewall-server:22 -L 8080:firewall-server:80 -L 4443:firewall-server:443
And if you aren’t running service locally on the official ports (i.e
you don’t have SSH and a web server running), you can use those ports
if you run ssh
under sudo
to get root privileges.
sudo -E ssh -N user@gateway-server -L 22:firewall-server:22 -L 80:firewall-server:80 -L 443:firewall-server:443
(sudo
’s -E
flag
(covered here)
will allow ssh
to access SSH keys that you have loaded into
ssh-agent
).
With this setup you can just open http://localhost, https://localhost,
and ssh user@localhost
.
However, this still might not be enough, not all service behave nicely when proxied through random IPs and ports. This is especially true of web apps that hard code their cookie domain. The cookie won’t match “localhost”, and won’t be stored, preventing logins and other features that depend on cookies.
What we really want is something that can transparently use an SSH tunnel and send all traffic to an IP over it.
And such a thing exists! sshuttle creates a VPN over SSH. First install it:
brew install sshuttle
(Presuming you are on a Mac, Linux and Windows version exist as well).
Then all you need do is run:
sshuttle -r user@gateway-server firewall-ip/32
Where firewall-ip is the ip address of the server behind the firewall. The /32 routes only that one IP, but you can route whole networks:
sshuttle -r user@gateway-server firewall-network/24
One you start sshuttle
you will be prompted for local sudo
password, this is so local routing can be installed. Then the SSH
connection is set up, prompting for a password if needed. Once this
is in place, all traffic for the firewall IP (or network) will be
transparently routed over the SSH link and out through
gateway-server. SSH and web connections will just work and, since
the DNS is valid, proxy issues will not arise.
Because this is a userland VPN running over SSH, it’s slow. But, slow is better than locked out. You win!
Comments