# [HOWTO] - SSH Tunneling for Mac Users



## michaelsanford (May 5, 2004)

There are a few great FAQs and HOW-TOs on this, but I figured we deserved our own.

*What is SSH tunneling and what's it good for?*
SSH (secure socket shell) is an encrypted connection between two computers that allows not only a secure remote terminal session but encrypted data transfer as well.

An SSH tunnel is simply one or more parallel data stream that get built when you connect to a remote host. Through this tunnel you can securely access any open service on the remote machine, from FTP to AFP to VNC to printing, and let's not forget X11!

*How does it work?*
Basically when you connect via `ssh` to a remote host, you specify some extra command line arguments that tell ssh something like "get the remote hosts's AFP port (548) to forward to my local port 10548 over the secure channel". This is called a direct port forward.

With this clever tool you can also forward any port on any machine that the remote machine is connected to, to your local machine over the secure channel, like "Tell the remote machine to connect to my router's web interface and forward that over the secure connection to my local port 10080".

*The Syntax*
Let's look at the following line:
*ssh myhost.local -c blowfish -X -L 10548:127.0.0.1:548 -L 10080:192.168.0.0:88*

The first part tells ssh to connect to myhost.local.

The red part tells ssh "Connect to 127.0.0.1 (localhost) at my port 10548, and route it to myhost.local's port 548". Then when you want to access myhost.local's AFP, you choose Connect To from the Finder and enter 127.0.0.1:10548 and voilà, up pops a connection dialogue for myhost.local.

The blue part tells ssh "Connect to 192.168.0.0 port 88 on the LAN to which myhost.local is connected, and forward that to my local port 10080". This is useful when you have a router with a web-based interface and don't want to open it up to the WAN, you can use this method to connect to it. You then enter http://127.0.0.1:10080 in Safari and voilà up pops the web interface for myhost.local's router.

If you want to enable X11 forwarding, you need to add the *-X* command-line flag, but you don't have to enter any host or port information, -X will automatically forward remote X11 sessions to your local machine. You _must_ use an X11-based terminal program to create the tunnel however, or else the $DISPLAY variable won't be set and your local X11 won't know where the display is.

*Tips for better operation*
1. Use a 'shabbier' cypher. By default ssh will use 3des (triple-des) which is an encrypt-decrypt-encrypt triple algorythm with three different keys. As you can imagine for the text of a terminal session it makes little difference, but for AFP for VNC/X11 it will slow the connection immensely on a slow computer. Specify the blowfish algorythm using *-c blowfish* which is secure, and faster. If however you're extremely paranoid about security and have a very fast computer, des or 3des should work all right.

2. Once you connect to the remote machine renice the thread called AppleFileServer (AppleFileS) to something negative. If you have a slow system and have other apps running this may give you a tiny edge on file sharing.

3. Always, always end your tunneled sessions with *~&* instead of logout or ^D. This is an escape character that tells ssh to background itself until all the secured channels are closed.

This means that you can exit the terminal and leave your AFP volumes mounted, then when you unmount them the SSH session closes completely. If, on the other hand, you choose ^D or logout, your drives won't be softly unmounted, they'll be ripped out  and nobody wants that.

Note however that only persistent services (like AFP) will remain open after a background escape (~&) is issued, services like HTTP tunnels (like the router's web interface) will close as soon as the page is loaded (i.e., immediately if no page is loading).


----------



## dlloyd (May 5, 2004)

So technically if I'm behind a firewall that doesn't allow me to use, for example, the right port for the Apache webhost, if I had access to another computer outside of the firewall, I could use that IP address and have it forward the appropriate ports to my computer, and thus set up a 'proxy' type thing?


----------



## rhg (May 6, 2004)

@michael: Thank you for this great HOWTO.

@dlloyd: That's correct, as long as you can reach the system you specify in the -L expression from the system you ssh to.


----------



## dlloyd (May 6, 2004)

Hmmm, that would be really cool .


----------



## rhg (May 6, 2004)

For example, the e-mail server in the internal network is at 111.222.24.25. It is, however, not reachable via ssh because by purpose it doesn't have a default route. The firewall will only let ssh pass through to the 111.222.24.77 machine. If I want to access my company e-mail from home I would do:

ssh -C 111.222.24.77 -L143:111.222.24.25:143

After that I simply connect my IMAP e-mail client to localhost (port 143 is IMAP2) which goes through the ssh tunnel behind the scenes and connects to 111.222.24.25 on port 143. The -C option compresses all the traffic so the tunnel is even faster than plain IMAP


----------



## dlloyd (May 6, 2004)

Wow, sounds REALLY cool!


----------



## scruffy (May 6, 2004)

Perhaps you have a suggestion for this - I'm trying to do essentially the same as X11 forwarding, but in the opposite direction.  The school firewalls allow no incoming connections, so I send out a ssh connection to my home computer, and forward telnet back along it to the school one, with
ssh -R 2323:127.0.0.1:23 scruffy@scruffys.comp
I get home, telnet localhost 2323, works like a charm.

What I can't seem to do is send X11 connections back to my home computer.  I've tried adding
-L 6010:127.0.0.1:6000
Then I telnet back to the shool machine (with X11 running at home), set the display to ":10", but still can't launch any X11 apps.

I know, I could forward inbound ssh over the outbound ssh channel, and 
ssh -p 2222 -X localhost
or whatever, but I'd like to avoid encrypting everything twice.  The nice 2GHz P4 at school could handle it fine, but my poor 300 MHz G3 would be running pretty hot trying to double-encrypt all the X11 traffic...

Incidentally, you can also add the '-fN' flags, which will send ssh to the background immediately after authenticating, and the connection will be persistent.  Actually not entirely persistent, it can still timeout - this was a problem for me, since the connection had to survive hours and hours of idle time till I wanted to telnet back.  I had to download a patch for openSSH that adds a heartbeat - it sends a special ssh 'null' packet every so often to keep the connection going.


----------



## scruffy (May 6, 2004)

Oh, another tip for performance - if you have a slow connection, and the computers at either end are reasonably fast, you can add the -z flag to compress the traffic with gzip.  That way if you're going to be using stuff that generates a lot of traffic, like X11 or file transfers, you can trade some of the connection load for extra CPU load.


----------



## michaelsanford (May 6, 2004)

Scruffy, it sounds like what you need is a 'reverse forward' which is implemented by the -R option (instead of -L), which does something akin to passive FTP...

However, it sounds like the problem isn't the channel but the $DISPLAY setting. I had that problem and it was a real bugger to deduce.

Try *cat /etc/sshd_config | grep #X11* and you should see something like
#X11Forwarding yes (no)
#X11DisplayOffset 10
#X11UseLocalhost yes

The first (no) indicates the default setting. Firstly, you need to make sure that first line is set to yes and uncommented. Secondly, if the displayoffset is set to 10, then your remote display will be :11 not :10

Also make sure that /etc/ssh_config looks like
 Host *
   ForwardAgent yes
   ForwardX11 yes

Just a warning to note that the first file is ssh*d*_config and the second is ssh_config 

Try 'er our and let us know.


----------



## scruffy (May 7, 2004)

Thanks Michael, but that's actually more or less the reverse of what I want to do.  The ssh client is Linux box at school, and the server is my Mac at home.  Problem with that - the school firewall lets nothing in.  So, before I go home I would have to:
ssh -R 2222:127.0.0.1:22

Then when I get home, I can:
ssh -p 2222 -X localhost

which works, but it's dog slow, because I'm tunneling X11 over an ssh channel that's itself tunneled over an ssh channel the other direction - encrypting every mouse click _twice_.


```
Linux                                      Mac
____________ ssh connection -> that way  ______________
|          |-----------------------------|            |
| 22 <----------------------------------------- 2222  |
|            ssh connection <- that way               |
|       -------------------------------------         |
| 6010 ---------------------------------------> 6000  |
|       -------------------------------------         |
|                                                     |
|          |-----------------------------|            |
|__________|                             |____________|
```

What I want to do is ssh from the Linux box at school to the Mac at home,  pass telnet (not ssh, no need to encrypt twice) back form Mac to Linux, and pass X11 connections from Linux x clients to the Mac x server, all over the same ssh connection (or two parallel ones would be fine, just not one inside the other). 

```
Linux                                      Mac 
____________ ssh connection -> that way  ______________
|          |-----------------------------|            |
|    6010 --------------------------------> 6000      |
|      23 <-------------------------------- 2323      |
|          |-----------------------------|            |
|__________|                             |____________|
```

Then I can go home, sit at the Mac
telnet localhost 2323
and I've got a shell on the nice fast Linux box at school, and I can do my work, as long as it doesn't need a graphical application.  But, I would like to set my DISPLAY on the Linux box such that it connects to port 6010 (hence :10) and it will be sent back to the X11 server on the Mac

As far as I know, the ForwardX11 only is for forwarding stuff from the ssh server to the ssh client, since that's the more typical arrangement.  But I can't ssh into the school machine...


----------



## michaelsanford (May 17, 2004)

Even though I, umm, wrote the FAQ, I can't figure out a solution for you at this time


----------



## bossa nova (May 19, 2004)

gee wiz...sounds like you guys are light years ahead of where I am at. I am having trouble with the creation of keys. Specifically, when I login I am told that the connection is not known and "are you sure you want to do this?" Also what am I supposed to do with the key? Copy it onto a usb drive and then take it to the cpu I want a secure connection with?

michael...you have done a nice job and added some great tweaks.

what about just using port 80 which seems to be wide open everywhere?


----------



## scruffy (May 19, 2004)

The keys live in ~/.ssh/known_hosts and known_hosts2.  The first time you connect to a server from a particular client, it has never seen those host keys, so it asks you what to do.  If you do connect that first time, then ssh will add the keys to one of the files.

Every time after that, when you connect to that server from that client, ssh will compare the keys the server sent this time, to the ones in the file from last time.  If they match, it will just carry on; if they differ, then it may be a sign something fishy is up - you might be connecting to a bogus server.


----------



## michaelsanford (May 19, 2004)

bossa nova said:
			
		

> michael...you have done a nice job and added some great tweaks.
> 
> what about just using port 80 which seems to be wide open everywhere?



Thanks 

What exactly do you mean about port 80 though?

PS Scruffy has it totally right, but also of note is the fact that you will need to add a key for every different name you use to connect to the host. For example, I can connect to my other iMac, called homsar, buy either homsar.local, homsar, 192.168.0.22, or homsar.no-info.com, and all those names will prompt you to add a new key to your known_hosts since ssh doesn't know that they're all the same computer...


----------



## bossa nova (May 19, 2004)

michaelsanford said:
			
		

> Thanks
> 
> What exactly do you mean about port 80 though?



You're welcome...with regard to port 80, I was thinking that it would be open to incomming traffic but then I realized that most web servers (in a perfect world), would probably be in a DMZ or outside of the firewall. So I guess I just answered my own question. But this gets me thinking. If you want to use port 22, you would have to ensure that the port was open. Unless you punch a hole through from the other side right?


----------



## michaelsanford (May 20, 2004)

Actually in a perfect world we wouldn't need firewalls at all  However, it's not considered good practice to put big servers in a DMZ and I'm not really sure why you'd need or want to.

As for using port 22, you need to make sure that the port is open for incoming traffic on the server's firewall.

The advantage to all of this is that port 22 is: (a) a privileged port, so you need to be root to run services on it (or any port below 1024) so at, in theory malicious, script-kiddies and hackers can't run arbitrary services on it to say, fake an ssh connection and get your username and password; (b) since the connection is encrypted it's secure; and lastly (c) that you can forward nearly any other insecure service through SSH at port 22 that you can close to the outside world.


----------



## bossa nova (May 20, 2004)

michaelsanford said:
			
		

> it's not considered good practice to put big servers in a DMZ and I'm not really sure why you'd need or want to.



Michael,

Ok I think maybe I misunderstood something along the way in my reading. I thought it was common practice to put a web server in what is called a DMZ, (De-Militarized Zone) so that it can be in a neutral zone when you need to offer services to the general populace but still protect more sensitive data by keeping that data on servers Not in the DMZ but behind a firewall. Did I misunderstand what I was reading?


----------



## Kinniken (May 26, 2004)

I have the following problem:
- iMac A is connected to the web via cable ethernet
- iMac B is connected to iMac A via AirPort, with iMac A acting as a software base station
- I need a way for iMac B to be able to host AoE II internet games. AoE II uses TCP & UDP on port 23978
- I am setting this up from my iBook, which is not in the LAN

I first connect to iMac A via ssh over the web. Inside that ssh session, I type:

ssh 127.0.0.1 -c blowfish -X -L 23978:10.0.1.2:23978

Where 10.0.1.2 is the LAN IP of iMac B. Will that work, including for UDP? Do I need to keep my ssh session open, or is leaving it with ~& ok?

TIA,

Kinniken


----------



## michaelsanford (May 26, 2004)

bossa_nova, no, one should never ever leave a server open and in a DMZ. If you need to offer services, you put up a firewall and open only the ports necessary for the services you're offering.

Kinniken, let me think about that...


----------



## michaelsanford (May 26, 2004)

Ok Kinniken, you don't need to do all that tunneling at all in fact. If I understand you correctly you want to use B, which is connected to A over airport to hose AoK games to the internet?

Why don't you enable Internet Sharing on A and just share your internet connection to B, then you won't have any of these tunneling issues since B will be on the WAN.


----------



## scruffy (May 26, 2004)

It won't be on the WAN though - there's still only one WAN IP address to go around, so A will use NAT to let B onto the net.

Assuming you can't just switch which iMac is connected directly to the net, or get a little hardware router (that would likely be the easiest; and they're pretty cheap these days), you might be able to do something with netcat to forward the UDP part.  It would probably take more cleverness than I can muster right now though, after a big supper and a big beer...


----------



## bossa nova (May 27, 2004)

Kinniken said:
			
		

> ssh 127.0.0.1 -c blowfish -X -L 23978:10.0.1.2:23978



Kinniken, Ok...so just what exactly are you doing there and why? I am assuming that 127.0.0.1 is the local machine you are on?


----------



## Kinniken (May 27, 2004)

scruffy said:
			
		

> It won't be on the WAN though - there's still only one WAN IP address to go around, so A will use NAT to let B onto the net.



Exactly, that's what I'm doing now.



			
				scruffy said:
			
		

> Assuming you can't just switch which iMac is connected directly to the net, or get a little hardware router (that would likely be the easiest; and they're pretty cheap these days)



Sorry, but I can't do that. It's not possible to switch them, and the connection must remain via AirPort. A base station is too expensive to justify the cost.



			
				scruffy said:
			
		

> you might be able to do something with netcat to forward the UDP part.  It would probably take more cleverness than I can muster right now though, after a big supper and a big beer...



I'll look into it.


----------



## Kinniken (May 27, 2004)

bossa nova said:
			
		

> Kinniken, Ok...so just what exactly are you doing there and why? I am assuming that 127.0.0.1 is the local machine you are on?



Well, since I'm typing this inside an ssh session on iMac A, I assume 127.0.0.1 must be iMac A.I'm probably going to show that I am misunderstanding ssh tunnels completely, but what I was hoping this command would do is forward any connection on iMac A on port 23978 to the same port on iMac B. That way, if B hosts a game and someone from outside tries to connect using A's WAN IP, the connection will be forwarded to the same port on iMac B.


----------



## dlloyd (May 27, 2004)

You don't have to get an Airport Base Station, BTW. There are some nice cheap 3rd party 802.11x things out there.


----------



## Kinniken (May 27, 2004)

Well, I would rather avoid buying new hardware at all, especially since I am pretty certain I can do that without it. BrickHouse supports TCP & UDP port forwarding, so I guess I can do it via command line as well (using BH is not an option since that would require me being physically present for the install and I am in an other country currently).


----------



## HercuLeeZ (Jun 16, 2005)

Greetings all,

    I have a developer who wants to connect to 2 Mac servers on my network to move some files, does some configurations, etc.  He is using OSX, and I'm wondering how he might do that, without my having to open ports on different firewalls.  Is there a couple of commands he can use to open MacA and then MacB?

   Based on the example given at the beginning of the thread, his commands might look something like:

#ssh ssh.mynetwork.com -c timbukto 100.200.111.111

and

#ssh ssh.mynetwork.com -c timbukto 100.200.111.222

Believe it or not, I could do this with PuTTy and VNC if it were Windoze, but I'm still far to new to OSX to do it myself, much less advise on it.  As such, any help with this would be greatly appreciated!

Sicncerely,
Herc


----------



## scruffy (Jun 16, 2005)

Er - what is he trying to do exactly?  He wants to connect two Macs on the same network?  Then why would you have to do anything at your firewall?

Never mind the "-c blowfish" stuff - that's about selecting a cipher.


----------



## HercuLeeZ (Jun 16, 2005)

Hi Scruffy,

   Well, he's on the other side of the country, so he needs to get into our network, past a few firewalls.  However, because he is migrating an app from an old server to a new one, he wants access to both so he can bring one up while taking the other one down.  I tried to convince him to do it in one session but he simply can't/won't.

So, if I understand what you are saying, the commands I need to have him issue on his Mac/Timbukto viewer are:

#ssh ssh.mynetwork.com timbukto 100.200.111.111

and

#ssh ssh.mynetwork.com timbukto 100.200.111.222

Thanks alot!
Herc


----------



## scruffy (Jun 17, 2005)

No, you're not there yet.

Let me get this straight - correct whatever I get wrong please

- the two computers are in one network, but your user is outside of this network.
- "ssh.mynetwork.com" is an externally reachable ssh server that the user can reach through the firewall, and that can in turn reach the computers you're interested in.
- "100.200.111.111" and "100.200.111.222" are the internal, non-routable, IP addresses of the two computers he needs to reach
- "timbukto" is - what exactly are you trying to do when you stick that into the command line?

You will need to know 
(1)what port does timbukto listen on (and does it use only one port, and does it use TCP only)?  Let's say for now it uses only TCP port 3434.
(2)is it possible in the timbukto client to specify an alternate port to connect to?  Let's say for now it's done the same as with standard URL specifications.

Then you could have your user go

ssh ssh.mynetwork.com -L 5555:100.200.111.111:3434

and then connect timbukto to 

timbukto://127.0.0.1:5555 

which will forward to 100.200.111.111 on port 3434

And then run 

ssh ssh.mynetwork.com -L 6666:100.200.111.222:3434

and then connect timbukto to 

timbukto://127.0.0.1:6666

which will forward to 100.200.111.222 on port 3434


----------

