SSH Port Forwarding on Mac OS X
After spending about an hour configuring what should, in theory, be a simple matter, I figured I’d write a blog post that might one day save another soul an hour or so from his or her life. So, for good karma, basically. In the past, I have set up port forwarding on Linux, Mac OS X and Windows, so I was a little worried that it took me about an hour trying to appease the SSH deities (and daemons).
The command itself is just a single line; the devil is in the parameters. I’m splitting the command over several lines and adding line numbers to illustrate the details and separate the parts of the long-ish command for easier explanation. Feel free to type it all on a single line (after removing the line numbers and the line-break markers ("\") of course!)
1. ssh \ 2. -L local_port:service_host:service_port \ 3. -p ssh_server_port \ 4. -l ssh_server_username \ 5. -N \ 6. ssh_server_host
Parameters
Now for the various parameters used in the command above. Some of them may be omitted if the defaults are used, but I have included all of them in the example above to cover the most general case.
-
local_port -
The port on your local machine that your local program expects to be able to connect to. If this is one of the reserved ports (i.e., under 1023), you will have to run your ssh tunnel command as root (using sudo). Ports above 1024 are freely available for any user to listen on.
-
service_host -
The fully-qualified domain name or the IP address of the server that is hosting the service that you wish to connect to. For example, if this is a web site, it could be google.com or yahoo.com. It does not have to be under your control, nor does it have to be the machine that you’re SSHing into. It is just any host on the Internet that you can access from
ssh_server_host. Often this is a server you are not allowed to access from your own machine, e.g. a chat server or IRC server. Or you may wish to hide the fact from the administrator of your local network that you are connecting to this server (e.g. when you’re out at a coffee shop on a sniffable insecure wireless network, or in a country with laws forbidding access to free information.)Important: If you’re trying to access a service running on the same machine as
ssh_server_host, remember to use 127.0.0.1, not localhost. What’s the difference, you say? Well, since IPv6 is here to stay, localhost can map to either 127.0.0.1 (IPv4) or ::1/128 (IPv6). If your applications aren’t all IPv6-compliant, this can cause some headache. Hopefully, we will all be on IPv6 in the near future, but till then, this is a way to make things work. If you’re trying to use IPv6, you need to uselocal_port/service_host/service_port(slashes instead of colons.) -
service_port -
The port number on which the desired service is running. Here are some common port numbers:
Service Port Web: HTTP 80 Web over SSL: HTTPS 443 Outgoing email: SMTP 25 Incoming email: POP3 110 Incoming email: IMAP 143 VNC 5900 iTunes Music Sharing 3689 -
ssh_server_host -
The machine that you’re SSHing into. This is the one that is running sshd, the SSH daemon.
-
ssh_server_port -
The port number on which the SSH daemon is listening on
ssh_server_host. This is most likely 22; you should only use a different value if your sysadmin has told you that the SSH server is running on another port (or if you’re a sysadmin yourself and you set up your SSH server to run on a non-standard port for security through obscurity.) -
ssh_server_username -
The username you would use to connect to
ssh_server_hostin a regular SSH session. This may or may not be the same as the username you currently use on your local machine.
The Entire Command, Line by Line
- Line 1 simply calls the ssh program;
- Line 2 sets up the port forwarding. The
-Lparameter specifies that this is a remote-to-local tunnel. If you wanted to create a local-to-remote tunnel, you’d have used-Rinstead of-L. The next three parameters are from our list above, separated by colons. (Use slashes instead of colons for IPv6.) If you want to set up multiple tunnels from the same host, simply repeat line 2 as many times as you’d like, once for each set oflocal_port:service_host:service_port. - Line 3 selects a port on the
ssh_server_hostto connect to. Omit this line if you’re connecting to the default port 22. - Line 4 specifies the username to use on the
ssh_server_host. It is also possible to use thessh_server_username@ssh_server_hostsyntax instead of the-lparameter. - Line 5 indicates to ssh that no commands be run on the remote system. Since you’re using this SSH connection simply for tunneling, this is a useful option to set.
- Line 6 contains the most basic parameter of this entire process. Please don’t get this wrong.
Common Errors and Solutions
| Problem | Solution |
|---|---|
| Error message: channel 3: open failed: connect failed: Connection refused |
Change localhost to 127.0.0.1 in the ssh -L parameter.
|
| Cannot listen on port X on local machine because of network policies. | Try to use another port locally. Ports such as 3306 (MySQL) may have been left open. These are good to use for SSH tunneling if you aren’t already running MySQL. |
| Error message: Privileged ports can only be forwarded by root. | Use a port above 1024, or try to set up the SSH tunnel as root. |
|
Error message: bind: Address already in use channel_setup_fwd_listener: cannot listen to port: xxxx Could not request local forwarding. |
Some local server process is already listening on the local port you’re trying to forward to. Pick a different local port and configure your program to connect to th at port instead. If your program cannot be configured to listen to a different port, try to find what server process is occupying that port (netstat -a on Linux or lsof -i -P on Mac OS X) and stop it. Retry setting up the tunnel.
|
| I want other hosts on my network to be able to use the tunnel I established. (By default, only local clients can connect to SSH tunnels established this way.) |
Use the -g option when setting up the tunnel. Realize that this is insecure, but it may make sense in certain scenarios.
|
| I don’t know what local port is available for me to use. |
Linux: netstat -a | grep LISTENMac OS X: lsof -i -P | grep LISTENwill show you the ports that are in use. Generally, you can pick any that’s not already taken. To make sure you’re not breaking some other unknown protocol, check the IANA Well-known Port Numbers list and pick one that’s not taken. |
If you’ve not been able to debug this so far, try passing the -v parameter to ssh to see verbose output. Add another -v for more verbose output.
If you’re reading this, and come across any specific source of trouble, please let me know so I can add it to this mini HOWTO.
Thanks Manas,
As you wished in this page, you saved me a lot a work figuring out how SSH could be configured to tunnel connexions with Tiger.
Now, I can VNC home throught our corporate firewall and access applications not available at work.
Really appreciated,
Denis
Denis Frenette — July 10, 2008
I have everithing configured for mail tunneling. However “Mail” (the Mac Mail client) gets a connection refused on localhost:1110, I disabled firewall and I have the same error. I also tried 127.0.0.1:1110
Victor — July 13, 2008
What protocol are you trying to use with Mail.app? For POP3, it’s 110, not 1110. And if you want to tunnel ports below 1024, you will need root access.
Manas — July 14, 2008
Can parameters be passed to SSH via a URL? For example, can :
% ssh host -l user
be encoded as a URL as:
ssh://host%20-l%20user
Thanks.
DevNull — August 9, 2008
Hi Manas,
I am trying to connect through SFTP using FUGU between two Macs. While I can connect from one machine to the other, I can not connect the reverse way. After I feed the usual informations (IP address, User name and then password) on the log in screen of FUGU it just goes back to the log in window without any error message. Both machines use mac os x (10.4).
I will appreciate your help.
Thank you.
RRMohanty — August 14, 2008
The other day I upload the latest security update for my macbook. Today I tried to upload files through Fetch to a host and I keep getting an error message:
Ask the server administrator to allow passive mode data connections through their firewall, or turn off the Mac OS x firewall in the Sharing pane of System Preferences.
- SO I turned off the Mac OS Passive FTP mode (PASV) then the next Error message pops up.
Can not connect to port 1024
Please help,
Thanks
Troy — March 13, 2009
Just wanted to say thanks for the great dissection of ssh port forwarding. You’re explanation and layout was excellent!
Thanks!
Shunil
Shunil — April 15, 2009
Thanks! This really helped me out.
Zach Zolton — July 14, 2009
hi Manas,
in windows i used to set port forwarder using SSH secure FTP like this:
port forwarding local addr 1080 rem host dynamic forward
how to do this in MAC
tks in advance
Dwi Kiansantang — May 19, 2010
You spent all the time to write this, but did not provide one single example.
Frustrating, to say the least.
Joel — July 1, 2011
Joel,
You can type in the following:
“ssh -l joel 192.168.1.11″
Assuming your user name is “joel” and the machine you try to connect to is “192.168.1.11″
Of course, this only work if you are connected on the same network…
Jack Tseng — July 15, 2011
For internet access:
1. You need to setup an dyndns or noip account
2. You then need to set up port forwarding in your router (default port is “22″)
3. Instead use the “192.168.1.11″ LAN address, you would use say “abc.dyndns.org” address where “abc” is what you use as your host name when you setup the dyndns.org account…
Hope this help..
Jack Tseng — July 15, 2011
Got the port forward working on the first try after a quick read. Karma++ for you – many thanks.
shook100 — September 23, 2011
Hi,
could you possibly give me a hand?
I own a Mac OSX Lion and I want to set up a port forwarding (local-to-remote?) in order to enable Click’n'Load kind of access between my computer and my NAS server which is running pyLoad. I just need to make that all the packets coming in on port 9666 will be forwarded to my NAS box. I want to set this up as a service so it is enabled at boot time and I’m not prompted with the password all the time.
This is what I’ve done:
Marcs-MacBook-Air:~ marc$ ssh -L 127.0.0.1:9666:[ServerIP]:8100 -N 192.168.0.2 -l admin -p 24
admin@192.168.0.2′s password:
channel 1: open failed: administratively prohibited: open failed
channel 1: open failed: administratively prohibited: open failed
and I’m following this german guide http://forum.pyload.org/viewtopic.php?f=9&t=452 (the OP seems to have been mixed port numbers but that’s not a big deal).
Help would be very much appreciated. I thank you in advance. Cheers on your post, very very helpful!!!! ;)
Marc — October 12, 2011
Thank you very much. This saved me a lot of time, and worked on the first try.
Two suggestions (trying to build my own positive karma :-) ):
1: If you end the command with &, it will politely run in the background, giving you your Terminal window back.
2: You wrote “The -L parameter specifies that this is a remote-to-local tunnel.” This is backward to my understanding. -L means that I connect to that port locally, and my data is sent off to the remote host, so I would call it a “local-to-remote tunnel.” I say this having a: read the ssh man page, and b: run it and it actually worked. :-) Don’t know if what you wrote was a typo, or just a failure of my understanding, but I thought I’d mention it in case anyone else had the same failure of understanding.
Again, thank you very much for this page.
Greg — November 22, 2011
Excellent post! Now I can finally delete those ugly tunneling apps. This works perfect with the Automator.
Eelco Wiersma — January 16, 2012
[...] RealVNC, and 5900 is the port number of the VNC in Linux. For details about this command, refer to SSH Port Forwarding on Mac OS X. Then start RealVNC, enter “localhost:5901” and your VNC [...]
Connect Mac OS X with Linux Server « Bo Yang's Blog — August 24, 2012
Thanks for the useful post! Save me the hour :)
Mahdi — February 3, 2013