Advanced SSH configuration and tunneling: We don’t need no stinking VPN software

Advanced SSH configuration and tunneling: We don’t need no stinking VPN software

by Noah Gift

In a recent Red Hat Magazine article, Paul Frields gave some examples of how SSH port forwarding can be used
to remotely gain access to resources, or ports, from a remote location.
This article will show a pragmatic implementation of SSH port
forwarding by demonstrating how to use configuration files and
conditional statements to create permanent, yet dynamic, SSH
configurations for your home, office, and any virtual machines you may
have on your systems.


An ad-hoc forward of a specific port or two from the command line
can be very handy, for example forwarding a work-only accessible wiki
to your home machine, or from a local coffee shop so that you can read
it. But there is a better way to architect a permanent solution. Many
people don’t realize that it is completely possible to access at home
every single resource that you have at work by simply creating SSH
configuration files that have comprehensive tunneling instructions.
Contrary to popular belief, this does not require VPN software. It
requires only an open SSH port, which can be listening on port 22 or
4010. It doesn’t matter. While this is bad news for commercial vendors
of VPN software, it is good news for you.

The world has changed, and now people work from home, from the road,
and from the coffee shop. In addition, IT workers often use virtual
machines running on their laptops to simulate production environments.
By creating comprehensive SSH tunneling configurations, it is possible
to make a remote machine, along with virtual machines, completely
integrated into a production environment.

About SSH config files

Although reading a man page for something as big as SSH can be
daunting, I would suggest doing a cursory skim through some of the
options. It is always a good idea to do at least some skimming before
engaging in heavy duty use of a command line tool in ways you have
never used it before. There are two configuration files to be aware of
for this article. The system-wide configuration file lives in /etc/ssh_config , and the user ssh file lives in ~/.ssh/config.

Since this is a more advanced article on SSH, it is important to
know the distinction between the system-wide configuration file and the
user configuration file. If you run a system cron job and would like
SSH forwarding to be involved, it is important to note that the /etc/ssh_config
file needs to be edited. If you need to enable forwarding for a user
shell, which is most typical, then you should edit the user
configuration file. The SSH config files also have a man page (man
ssh_config), and it would be helpful to view that man page as well.

Creating A Basic SSH Config File

Getting basic requirements together

The basics of a creating a customized config file are easy. The
general idea is to create a configuration that forwards local ports
that bind to ports on a remote machine. While you are setting up your
SSH configuration file, it would be a good to keep the list of ports handy. This will help you decide what port IMAP uses, for example.

A work network behind a firewall may consist of the following
resources that are not accessible from outside of the local area

SMTP Server:			Port:  25	DNS Name:  smtp.pretendco.comCorporate Wiki:			Port:  8080    DNS Name:  wiki.pretendco.comIMAP Mail Server:		Port:  143	DNS Name:  imap.pretendco.comSubversion Server:		Port:  22	DNS Name:  svn.pretendco.comNFS Server:			Port:  2049	DNS Name:  nfs.pretendco.comSMB/CIFS Server:		Port:  3020	DNS Name:  smb.pretendco.comSSH Server:			Port: 22	DNS Name.  dev.pretendco.comVNC Server/Dev Machine: 	Port:  5900	DNS Name:

All that is needed to gain access to these resources from elsewhere
is to have a publicly accessible SSH server with one open port inside
of the LAN. Let’s suppose this server is called and that it has sshd (the SSH daemon) listening on port 5001. We can now build an SSH config file based on this information.

Understanding options

Now that we have a list of internal IP addresses, DNS names, and the
ports with the services we would like to access, we can create a
configuration file with a set of cascading configuration options. SSH
has many helpful options that I would recommend perusing in the
ssh_config man page. We are going to focus on the following options:

The most basic of configuration
parameters. This gives you the ability to designate sections of the
config file by hostname and pattern. For example:

Host *  (this means a section applies to every host)Host (this means it only applies to

You can nest multiple host configurations to create custom setups and alias hostnames so that they appear locally like they do at work. For example, a localhost:8080 tunnel could be turned into an alias like:

Host	Hostname localhost	Port 2200

This is handy because it allows you to completely simulate working
inside of a local area network. And if you have scripts or
configuration files that are hard coded to work with names inside of
your LAN, then you will very much enjoy using this configuration.

ServerAliveInterval: This option can be configured
to send a message every N seconds to a remote server so that a
connection will not die. By default it is set to 0 seconds.

Host and Hostname are really the only options you will need for most
configurations, but knowing about other options like
ServerAliveInterval and ServerAliveCountMax can be helpful too. Now
that we have the basic requirements and understand how to use the
options, let’s write a configuration file that will create our VPN to

Writing ~/.ssh/config

Here is a configuration file based on the things we just talked
about. You should be able to use this as a template by plugging in the
names and ports of the devices you would like to connect to.

If you have a config file in ~/.ssh/config, make a backup and move the original file. You can do something like this:

cd ~/.ssh/mv config backup_config_file

Now you can cut and paste this into a new file you call config.

###SSH Port Forwarding Configuration###

####Global Configuration Options###

#Host * will apply to all hostsHost *    ServerAliveCountMax 4       #Note default is 3    ServerAliveInterval 15      #Note default is 0

####Port Forwarding Directives###

#Network Reference, Cheat Sheet:#Refer to for full list of port numbers#SMTP Server:         Port:  25   DNS Name: Wiki:          Port:  8080    DNS Name: Mail Server:        Port:  143  DNS Name: Server:       Port:  22   DNS Name: Server:          Port:  2049 DNS Name: Server:     Port:  3020 DNS Name: Server:          Port: 22    DNS Name. Server/Dev Machine:  Port:  5900 DNS Name:

#(Note we just made up the name workTunnel.)#The workTunnel alias holds both the nested ssh server configuration,#and the actual port forwarding directives.#Note you can forward to either an IP Address or a hostname.

Host workTunnel    #Work SSH Server To Initiate Tunneling From    Host    Port 5001

    # SMTP Server    LocalForward localhost:2525 

    # Corporate Wiki    # Note I am forwarding to an IP address just to show that you can.    LocalForward localhost:8080

    # IMAP Mail Server    LocalForward locahost:1430

    # Subversion Server    LocalForward locahost:2222

    # NFS Server    LocalForward locahost:2049

    # SMB/CIFS Server    LocalForward locahost:3020

    # SSH Server    LocalForward locahost:2220

    # VNC Server    LocalForward locahost:5900

###Hostname alias directives####These allow you to mimic hostnames as they appear at work.#We just take the localhost names from the above section and add alias names.#Note that you don't need to use a FQDN; you can use a short name ,such as smtp instead of

Host    HostName localhost    Port 2525

Host    HostName localhost    Port 8080

Host    HostName localhost    Port 1430

Host    HostName localhost    Port 2222

Host    HostName localhost    Port 2049

Host    HostName localhost    Port 3020

Host    HostName localhost    Port 2220

Host    HostName localhost    Port 5900

#End Config File

Using the SSH Tunnel

Once you customize the ~/.ssh/config file from the
template shown above, you will need to open an SSH connection to the
master alias, which holds the nested port forwarding for everyone. To
do this, I would highly recommend connecting in SSH verbose mode first.
SSH is extremely quiet by default, and it will be a good idea to use a
-v option as shown below:

ssh -v workTunnel

If you configured things correctly, you should see output that looks like this:

....................debug1: Local connections to localhost:2200 forwarded to remote address Local forwarding listening on ::1 port 2200.debug1: channel 0: new [port listener]debug1: Local forwarding listening on port 2200.debug1: channel 1: new [port listener]debug1: Local connections to localhost:2222 forwarded to remote address Local forwarding listening on ::1 port 2222.debug1: channel 2: new [port listener]debug1: Local forwarding listening on port 2222.......................

Something very important to note, is that if you setup a HostName alias
properly, then you can perform an ssh directory to that resource, just
as you would inside of work. For example, if you need to access your
inside the firewall you can type:

svn list svn+ssh://

If you need to access a machine with a protocol other than ssh, say
your internal wiki running on port 8080, then you can quite simply add
an alias to your /etc/hosts file as show below:

# that require network functionality will fail.   localhost.localdomain   localhost wiki::1 localhost6.localdomain6 localhost6

You can always get to the forwarded wiki port by using:


But, with the change to the /etc/hosts file you can also access it this way:


If you are really motivated you can also do port forwarding to a
“privilaged port”, port 80, if you have a server running on port 80
inside of the firewire, and you would then get to the http resource
like you would at work, be slightly changing the ssh configuration
file. Please note you will also need to do tunneling with “sudo”

    # Internal Web Server running on port 80    LocalForward locahost:80

This then allows you to browse to http://web.


Now that you have a sophisticated SSH configuration set up, you can connect to resources in exactly
the same way you connect at work because of the host alias directives
we applied. If you have an internal wiki server at work and you applied
your custom information to the template I have supplied, then you can
just type in wiki:8080 (substituting your actual wiki server), and it
will work. I hope you find this as cool as I do!

Please note that things are not exactly perfect though. When you get
back to work, if you try to SSH into your development box, you will
have a problem, as your configuration file is set up to think you are
at home. There is a simple solution, though. (Remember this only
applies SSH connections to machines you have listed in your config

You can do quite a few things, and I will leave it to you to decide which to use:

1. You could customize your Bash or Z-Shell startup script to detect
whether you are at home or at work, and then source configuration files
based on what IP address your local machine is assigned.
2. You could create an alternate SSH file named remoteConfig and leave your regular config file blank. When you are at home or on the road, you can use ssh -F ~/.ssh/remoteConfig
3. An even easier way would be to make an alias out of option 2.

You can then create an alias in your bashrc file or your .zshenv file, that looks something like this:

alias stunnel='ssh -v -F ~/.ssh/remoteConfig workTunnel'

Now when you are at work, you use SSH like you normally do, but when you are on the road or at home you type in:


With one command, you have access to your complete LAN in exactly
the manner you use it at work, and you don’t need to muck around with
writing conditional statements and sourcing bash config files to do it.


In this article we took ad hoc SSH tunneling and turned it into a
full-blown VPN. I hope this took some of the mystery out of working
from home via SSH tunneling and gave you an idea of how you can
customize SSH tunneling to do just about anything.

I mentioned virtual machines in the beginning of the article, but
then only hinted at how they could be included in this setup. As an
exercise to the reader, I will leave integrating virtual machines to
you. As a hint, look at how we aliased the stunnel command, and that
should give you all the head start you need.

The information provided in this article is for
your information only. The origin of this information may be internal
or external to Red Hat. While Red Hat attempts to verify the validity
of this information before it is posted, Red Hat makes no express or
implied claims to its validity. Please review and comply with any
relevant IT policies at your company.

on Tuesday, November 27th, 2007 at 9:39 am and is filed under technical.
You can follow any responses to this entry through the RSS 2.0 feed.

You can leave a response, or trackback from your own site.