Ssh forwarding is powerful stuff, but using it can be confusing. For example, let's say we have a machine that our firewall will send traffic to, but we actually want to ssh to another internal machine. To be specific: 192.168.2.1 is the machine that we can access from outside using "server.xyz.com", but we really want to ssh to 192.168.2.10 with user "fred". To make it even more interesting, "fred" isn't a valid username on 192.168.2.1, but "john" is. We know passwords for both accounts.
The first step is to ssh to the server:
That lands us on 192.168.2.1. We now want to create a port that will get us to the other machine:
ssh -L 11601:192.168.2.10:22 -l john localhost
That says to take traffic coming in on port 11601 and send it along to port 22 on machine 192.168.2.10. Ssh requires a user name to do this, so we give it john (the local user).
If we now go to another machine and do:
ssh -p 11601 email@example.com
(If you are playing with this from the same machine, it's going to get confused about "firstname.lastname@example.org" and you may have to edit your known_hosts file to convince it that it's ok to connect.)
The ssh forwarding passes us over to 192.168.2.10. Notice that we used "email@example.com" even though "fred" has no account at this server. Remember that it's being forward to the machine where fred does have an account.
Before we go on, if you've actually tried this, try logging out of the shell that you started with "ssh -L 11601:192.168.2.10:22 -l john localhost". Notice that it hangs until you quit out of your "fred" ssh or kill it here (ctrl-C should work). I used that behaviour to advantage at Spamassassin on Mac OS X to secure a pop connection with ssh forwarding.
Using port 11601 may be fine, but we're assuming that all Internet traffic comes to this machine - perhaps it is a dual-nic gateway. Perhaps instead it is behind a router and only some ports are allowed through. In that case, perhaps what we really want to do is forward port 22 itself. But we can't do that as "john":
ssh -L 22:192.168.2.10:22 -l john localhost Privileged ports can only be forwarded by root.
For security reasons, only root can over-ride the "well-known" or "privileged" ports. Well, no problem: we have root's password or can sudo:
$ sudo ssh -L 22:192.168.2.10:22 -l john localhost Password: Password: Last login: Wed Jun 14 19:19:46 2006 from localhost Welcome to App2!
Notice the two login prompts: the first was for sudo. Also notice that we're still using john for the second: we need to be root to forward port 22 but we still can use the ordinary user account for the login.
We can fork that forwarding off into background:
$ sudo ssh -f -N -L 22:192.168.2.10:22 -l john localhost
The "-f" does the fork, the -N removes the need to run a command (forking would ordinarily require that).
Just because you can forward a port doesn't mean that the application you want to use will be happy with your mangling. For example, I have a customer with a router that can be accessed with a web browser through the local lan only. I can access a machine on their lan with ssh, but the router doesn't work with Lynx. Therefore, I'd like to forward a port to 80 on the router. More restrictions, though: we only pass a few ports inward. One of those is ftp, so you'd think I could do:
$ sudo ssh -L 20:18.104.22.168:80 -l admin localhost
and indeed I can, but Firefox won't play along. If you try "https://xyz.com:20", Firefox refuses you outright.
You don't necessarily need to do these forwardings manually. They can be added to your .ssh/config file:
Host server.xyz.com user john LocalForward 11601 192.168.2.10:22
That sets up the forwarding as we log in. You can get much trickier with that; see Breaking Firewalls with OpenSSH and PuTTY. That could get around the problem I described above with limited ports (though I use VNC for this).
Ssh forwarding is indeed powerful stuff.
Got something to add? Send me email.
More Articles by Anthony Lawrence © 2012-07-13 Anthony Lawrence