Unless otherwise noted, articles © 2005-2008 Doug Spencer, SecurityBulletins.com. Linking to articles is welcomed. Articles on this site are general information and are NOT GUARANTEED to work for your specific needs. I offer paid professional consulting services and will be happy to develop custom solutions for your specific needs. View the consulting page for more information.


SSH Tunnelling

From SecurityBulletins.com

Jump to: navigation, search

Contents

SSH Tunnelling

Written by Doug Spencer 11/19/2006

Tunnelling in SSH is an incredibly powerful tool. It allows any traffic to be passed over a connection that allows SSH, if you know how to use it. This article will explain a few of the ways SSH tunnelling can be used.

The version of SSH I am using allows the following options:

usage: ssh [-1246AaCfgkMNnqsTtVvXxY] [-b bind_address] [-c cipher_spec]
           [-D port] [-e escape_char] [-F configfile]
           [-i identity_file] [-L [bind_address:]port:host:hostport]
           [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]
           [-R [bind_address:]port:host:hostport] [-S ctl_path]
           [user@]hostname [command]


X Tunnelling

First, a simple scenario. You have a system that you want to tunnel X traffic from to remotely run a graphical program. Since this is a common requirement, SSH has a built-in option that does this. You do have to set "X11Forwarding yes" in your sshd_config file and restart sshd to get it working. Next, just issue a command like the following:

ssh -X remotehost

After logging in successfully, run "export | grep DISPLAY" and verify it is set. Normally, it will come back as something similar to:

declare -x DISPLAY="localhost:10.0"

If it is NOT set, then check that the "xauth" command is available on the system. If it is not, it needs to be to set the X cookies and to allow a remote X server to work. Once you have a DISPLAY environment variable, you can run your X program.

Forward a local port to a remote host

Let's say you have a slightly more difficult scenario. You want to bind a port on your local system and forward traffic that goes to your local port to a remote host. Let's say specifically you have a VMWare system on 192.168.1.12 that you can't directly reach on port 902, due to firewall filters. The command to accomplish this is:

ssh -L 1902:localhost:902 192.168.1.12

ssh -L localport:destination:Remoteport remoteip

In the command shown above, we are binding and forwarding traffic from our port 1902 to destination localhost (127.0.0.1) port 902, relative to 192.168.1.12.

To use this tunnel, we will start VMWare on our local system, say we want to do a remote connection, set the hostname to "localhost:1902" and type in your credentials. You will be connected to 192.168.1.12's VMWare instance, rather than your local copy.

Forward a remote port to your local host

In this scenario, you want to forward a remote port to your local system. This may be needed if, for instance, your firewalls only allow incoming connections to a remote system. If the remote system is still 192.168.1.12, and we want to forward traffic from the remote system's 127.0.0.1 address and port 81 to our localhost port 25, we could use the following command:

ssh -R 81:localhost:25 192.168.1.12

The -R option specifies the first item specified is the remote port that will be forwarded to the items that follow. You can think the syntax on SSH as:

ssh [local|remote forward] source_port:destination_address:destination_port remote_host

Forwarding Multiple Ports

You can specify more than one port forwarding command on the command line, so if you wanted to forward port 1234 and port 1235 to your remote host's localhost bound port 24 and 25, you could specify:

ssh -L 1902:localhost:902 -L 1922:localhost:22 192.168.1.12

Forwarding low ports on UNIX/Linux

If you need to bind a low port on UNIX or Linux systems, you generally have to run as root. Usually ports below 1024 are considered privileged and can only be created by a privileged user. An alternate method is to change the setting for privileged ports.


Advanced SSH forwarding

You can also do much more advanced forwarding using SSH. The destination address shown in the syntax above can specify a different host than the destination system.

Forwarding to a third host

If the remote host, 192.168.1.12, is a gatekeeper and you need to get VMWare traffic to 192.168.2.24, you could do the following:

ssh -L 1902:192.168.2.24:902 192.168.1.12 

This allows you to send traffic to a system that you don't have direct connectivity to.

Forwarding ports on non-localhost addresses

If you want to listen on all interfaces to forward traffic, you use the -g option. This specifies that the system that is doing the port forwarding will use gateway forwarding and remote systems can connect to forwarded ports.

To check what is being allowed after your SSH forwarding command, run "netstat -an | grep LISTEN" on the system that is doing the forwarding and look for the port you are forwarding. If it says "0.0.0.0:PORT" then that forwarding is listening on all interfaces. If it says "127.0.0.1:PORT" then it is only accessible by something running on that system.

Using SSH to build a Virtual Private Network (VPN)

You can also combine SSH with the Point to Point Protocol (PPP) to create a virtual private network. This can be accompished as follows:

/usr/sbin/pppd persist noauth 192.168.100.3:192.168.100.4 pty "/usr/bin/ssh -o 'BatchMode yes' -C -e none REMOTE_IP -l tunnel -i ~/.ssh/identity.vpn /usr/bin/sudo /usr/sbin/pppd notty noauth'"

This command starts with pppd doing a persistent connection between 192.168.100.3 and 192.168.100.4 via SSH. The rest of this is:

-o 'BatchMode yes' == specifies to not require user input
-C == Turns on compression
-e none == Turns off SSH escape characters
REMOTE_IP is the remote system you want to connect to
-l tunnel == specifies the user you want to use to connect, in this case "tunnel"
-i == specifies the private key identity file to use
/usr/bin/sudo allows limited root on the remote system, since PPP needs to run as root.
pppd notty noauth == specifies not to require a terminal and not to authenticate on the PPP layer. 

This is included in the Sockstunnel program I wrote to create a VPN over a SOCKS connection. There are other transports that can be used as well. Basically, anything that will allow communication to take place could be used to create a VPN using this method. For instance, HTTP proxies can pass SSH traffic using [GNU httptunnel].

Using SSH to emulate a SOCKS proxy

SSH now has the ability to emulate a SOCKS proxy and dynamically forward ports. To use this feature, simply specify -D [bind_address:]port on the SSH command line and start your SOCKS aware software, specifying the port you allocated. This is an easy way to tunnel a variety of traffic.

Personal tools