Firewall Tunneling with HttpTunnel

Version 1.2, August 19, 2010

The sons of Hermes love to play,
And only do their best when they
Are told they oughtn't;

Apollo's children never shrink
From boring jobs but have to think
Their work important.

-- W.H. Auden

Introduction

You are at work and want to check the mail on your computer at home. Running an email client, you discover that outgoing requests for mail are blocked by the corporate firewall.

During your lunch break, you decide to catch up with "Swimsuit of the day" for the last six years. An ominous warning from your network administrator fills the screen instead.

Firewalls are properly used to keep outsiders from accessing information inside a corporate or private LAN. Correctly configured, they work very well and have become an absolute necessity for any LAN connected to the internet.

Appealing as it may seem to power-mad network administrators and authoritarian political-correctness goobs, trying to prevent people inside the firewall from reaching forbidden outside information is very nearly impossible.

Unfortunately, it is not impossible for authorities to inspect the content flowing through your network connection and exact revenge if they disapprove. After showing how to get through the firewall, we will demonstrate the use of cryptographic counter-measures to foil this snooping.

We will cover a particular type of firewall-piercing known as tunneling. A tunneling protocol is used to hide one kind of tcp/ip stream inside another.

In order to use the technique described here, you must be the administrator (root) of a computer outside the firewall that is continuously connected to the internet. This machine we call the "server" with the ip name: "www.server.com". The computer you use inside the restrictive firewall we call the "client" with the ip name "localhost".

The methods described here will work for both Linux and Windows clients. It is assumed that the server is running Linux, although it should be possible to deal with a Windows server by using Cygwin or some other ssh server for Windows.

The software packages described here are HttpTunnel and ssh.

HttpTunnel for Linux is available from the creator's site or as an RPM package. The windows version must be downloaded directly because it has no parent link on the owner's site.

This article will assume you have installed the RPM version of HttpTunnel on your server. If you prefer to work with the tgz version, you will have to deal with creating the start/stop init scripts yourself.

Nearly all Linux systems have the SSH package. You will need to have the sshd daemon configured and running on your server. This topic is beyond the scope of this article.

For a Windows client, I suggest using the excellent Putty program, Alternatively, if you already have Cygwin, everything will work as described for Linux.

If you want to use a Windows machine as your outside server, running Cygwin is probably the path of least resistance. I found several slightly out-of-date binaries for HttpTunnel on the web. For best results, I would suggest building it from the source using Cygwin.

How it works

Restrictive firewalls always allow inmates some access to external services. Usually they allow web browsing, always monitored and restricted in various ways.

The HttpTunnel software lets us hijack one of the web browser ports (http or https) and use it as a raw data channel to an outside server. Unrestricted access to anything can be achieved using this outside server.

The HttpTunnel package has two programs: hts and htc. You run hts on the server outside the firewall and htc on the client inside the firewall.

As an example, we will assume that you'd like to use telnet to reach computers on the internet, but the telnet protocol is blocked by the firewall when you're at work.

When the tunneling programs are properly configured, here's what happens when you send out a keystroke using a telnet client inside the firewall:

The telnet program sends a tcp packet to the htc program. It wraps the packet so it looks like a browser GET request and forwards it out to to the outside web server. The firewall allows this because it looks like any other browser request.

The "web server" on our outside machine is actually the hts program. It gets the phony http packet, strips off the http wrapper, and forwards the packet to the local telnet server. You log into this server and use the server's shell to access any text-based service on the internet.

Reverse traffic from the telnet server goes back though hts where it is wrapped as a phoney http reply and returned to the firewall. The firewall allows it through to the client machine where the htc program removes the http wrapper and sends the packet back to the telnet client.

Choosing a port to pierce the firewall

All the examples will use port 443 (https) to pierce the firewall. We choose this port because most restrictive firewalls allow access to secure web sites using SSL. Another reason to prefer this port is that network administrators expect the traffic to be encrypted, so they many not bother to examine the content.

If you serve web pages with your outside machine, the web server will normally bind and listen on port 80 for http and port 443 for https. To disable https on the Apache server, remove the file /etc/httpd/conf.d/ssl.conf and restart. Other web servers will have a similar configuation option.

Obtaining secure shell (SSH) access

On your server:

	hts -F localhost:22 443 

On the client:

	htc -F 10022 www.server.com:443 

The client can now do:

	ssh -p 10022 localhost 

This process takes a while, but you should soon see a login prompt. Sometimes, I find that I have to press <enter> once to get things moving.

You may find it painful and tiring to type your username and password every time you want to make a remote connection. To elminate this annoyance, you need to configure ssh to use RSA authentication. This process is somewhat involved, but you can read all about it at SSH Access with RSA Keys.

Using ssh to forward other protocols

Using ssh is a very good idea because the data stream cannot be captured and examined. In addition to supporting shell sessions, ssh has the ability to forward other protocols.

Using this capability completely defeats efforts to determine what you're doing on the internet. The authorities can only know that you're connected to a particular web server via https.

Of course, if this goes on for 8 hours a day, you may be in trouble on more general grounds.

We assume you have run htc to set up a tunnel to the remote ssh:

	htc -F 10022 www.server.com:443 

The general form of the ssh command for forwarding through a tunnel is:

	ssh -L localPort:hostName:hostPort -p 10022 localhost 

The varaibles in the "-L" expression refer to these values:

	localPort	A free local port you will use to access the service.
	hostName	A host that offers the service.
	hostPort	The port number of the service. 

A tricky point about the host name parameter between the colons: The name is evaluated on the server side. In all of the examples that follow, we will be using "localhost" for this host name. Because it's evaluated on the server, it refers to the server machine. The "localhost" at the end of command line refers to the client machine (where you're running ssh.)

The following sections present examples of forwarding specific protocols.

Incoming mail on port IMAP

As a first example, we will connect to a remote IMAP server:

	ssh -L 10143:localhost:143 -p 10022 localhost 

At this point, you can configure your email client program to use the imap server on localhost at port 10143.

In case you are using "Outlook Express", the alternative IMAP port number can be specified on the "Advanced" tab of the account properties window.

If you are the administrator/root on the client machine and don't run a local imap server, you can use the standard imap port as the local port as well:

	ssh -L 143:localhost:143 -p 10022 localhost 

This is nice because you simply configure your email client to use IMAP with "localhost" as the server. There's no need to specify a special port number.

If your client machine runs Linux, the imap server will normally bind and listen on port 143. To free the port, you must stop this server. On old Redhat and Fedora systems, this is done by editing /etc/xinetd.d/imap and setting "enable = no" in the configuration script. You must then restart xinetd using:

	service xinetd restart 

On newer Fedora systems, imap is handled by the "dovecot" server. You stop this process using:

	service dovecot stop 

Outgoing mail on port SMTP

Of course, no evil-doer would be satisfied with simply reading mail. The ssh command line can have multiple "-L" sections. The following command configures your tunnel to handle both incoming (IMAP port 143) and outgoing (SMTP port 25) mail:

	ssh -L 143:localhost:143 -L 25:localhost:25 -p 10022 localhost 

Your email client can then use "localhost" as the outgoing server.

In the example shown above you must find some way to free smtp port 25 on your client machine. If you client runs Linux, this would be done by stopping the sendmail service:

	service sendmail stop 

The does not prevent you from sending mail with sendmail, but it will stop the client from being a mail server. This is not usually a problem for clients inside a corporate filewall.

Samba file sharing

Suppose your server at home has samba shares and you want mount them at work. You would tunnel ports 137, 138 and 139:

	ssh -L 137:localhost:137 -L 138:localhost:138 -L 139:localhost:139 -p 10022 locahost 

If you have a share called "archive" on your server at home, you must now mount it as if it was local to your client machine:

	mount -t smbfs //localhost/archive /mnt/temp -o username=goop,password=gleep 

To make this work, you must not be running a samba server on your localhost because it would bind the ports first. To stop the local server:

	service smb stop 

On Windows clients, the "samba" server is enabled when you have installed "File and Printer Sharing for Microsoft Windows". I have not investigated the effects of disabling this server.

USENET News

News is an essential service. You don't need proxies or any other special equipment. Remember that the forwarding host expression is evaluated on the host: All you need to do is forward directly to the news server you would use at home:

	ssh -L 119:news.someserver.com:119 -p 10022 localhost 

On your client machine, simply configure the news server to be "localhost".

Surf the web in peace

For this feat, you will need to configure a proxy server. I run a separate Apache process for this function. To do this, make a copy of your original "httpd.conf" file called "proxy.conf". Edit "proxy.conf" to make the server listen on a different port. The default setting is 80. For this example, I'll use 8090. You also need to add directives that enable the proxy and restrict access.

Changes/additions to proxy.conf:

	Listen 8090
	ProxyRequests on
	<Proxy *>
		Order deny,allow
		Deny from all
		Allow from 127.0.0.1
	</Proxy> 

Search through "proxy.conf" to make sure that mod_proxy.so gets loaded. The expression will look something like:

	LoadModule mod_proxy.so 

To start the new server, execute:

	httpd -f conf/proxy.conf 

Note the odd syntax for the file path: It is relative to /etc/httpd no matter where you run the command.

Add the following port forwarding to your ssh command line:

	-L 8090:localhost:8090 

Finally, you must configure your web browser. For Microsoft Internet Explorer, the setting is buried at:

	Menu:		Tools
	Item:		Internet Options
	Button:		LAN Settings
	Check Box: 	Use a proxy server...
	Button: 	Advanced 

In the configuration window, add these entries:

	Type	Proxy address	Port
	----------------------------
	HTTP:	localhost	8090
	FTP:	localhost	8090 

For Netscape/Mozilla browser, the path is:

	Menu:		Edit
	Item:		Preferences
	Category:	Advanced
	Selection:	Proxies 

In the configuration window, add the same entries shown above for Internet Exploader.
You are ready to rock-n-roll!

Using ssh for reverse tunneling

The ssh command can also create reverse tunnels that allow you to go home and access services normally visible only inside the corporate LAN. This is really too terrible to contemplate so I will simply show you how to do it:

Let's assume your workplace has an internal website "goodstuff" you need to access from home. Before you go home from work, run the commands:

	htc -F 10022 www.server.com:443
	ssh -R 10080:goodstuff:80 -p 10022 localhost 

When you get home, use the web browser on your server to access:

	http://locahost:10080 

You can now travel around the corporate LAN following links from the "goodstuff" page.

	MwooHaHaHaHa! 

If the network administrators at work figure out what you're doing, you will be fired, sued, and beaten with a rubber hose.
I never use reverse tunneling.

Configuring HttpTunnel for automatic operation

The httpTunnel rpm installs a number of configuration files that 1) enable automatic startup as a system service and 2) handle requests using xinetd.

The default setup will use port 443 (https) as the externally visible port and port 22 (ssh) as the internal server. This is a highly desireable setup and I recommend that you use it as it comes out of the box.

Programs and configuration files:

	/usr/bin/htc		The client program
	/usr/bin/hts		The server program
	/etc/syconfig/hts	Configuration parameters for the init scripts:
	/etc/rc.d/init.d/hts	The init script to start the server
	/etc/xinetd.d/hts 	Configure xinetd to use hts (optional) 

Select the external port:
This depends on the firewall you're behind and also which port you're willing to tie up on your server. The default is 443, which is nice unless your server needs this port for severing secure pages.

To use an alternative external port, edit /etc/xinetd.d/hts and specify the port on the "port=" line and verify that "enable = yes" is present.

The /etc/xinetd.d/hts file that comes with HttpTunnel wouldn't start hts on my Redhat system. I needed to add a line for "server=/usr/bin/hts". This should not be necessary because we are qsimply forwarding one port to another.

After editing /etc/xinetd.d/hts, perform: "service xinetd reload".

Select the internal port:
This determines the service you want to make available. The value is set in /etc/sysconfig/hts. The assignment for HTS_OPTS is near the top of the file. The default setting is for SSH (port 22), which I highly recommend.

Now you can start the server using "service hts start"
To make the service autostart at boot time, use "chkconfig --add hts".

Keeping the connection alive

Holes in firewalls like to close by themselves. This can be caused by timeouts configured in the firewall, in your ssh server or even bad weather. I've never figured this out to my satisfaction. The following sections outline some methods that have helped me. Trial-and-error is often necessary.

HttpTunnel parameters

Here are the options I currently use with hts and htc. I fiddle with these values constantly. I don't think the documentation is perfectly accurate, but I haven't started reading the source code yet...

	-S		Use strict content length
	-M 3000		Maximum connect time 50 minutes
	-c 100M		Limit get/put requests to 100 Megs.
	-k 10		Send a keep-alive message every 10 seconds

Keep alives (-k) can be sent too quickly. If you have a slow or unresponsive connection, you may need to slow them down using the -k option. The default is 5 seconds.

My experiments indicate that the -c option sets an upper size limit on get/put requests, not the size of each transfer as the documentation suggests. Bigger seems to work better.

Using autossh

The autossh program is a very simple program available as an rpm or tgz. It spawns ssh along with your normal ssh command line parameters and then monitors the connection. When autossh sees that your connection isn't working, it kills the stalled ssh and restarts a new one with the same parameters.
The command syntax:

	autossh -M testPort <your usual ssh command-line parameters> 

	Example:

	autossh -M 20000 -L 143:localhost:143 25:localhost:25 -p 10022 localhost 

The "-M testPort" specifies a port (and port+1) where autossh creates a port-forwarded loop for testing the connection. You can pick any unused port. By default, the connection is tested every 10 minutes. See the autossh homepage for details.

You have a Windows client

There are those who believe that the vast unwashed should not have access to powers like these. Some companies even mandate Windows to subjugate the minds of their employes. Even for the 3L33T like you.

The windows version of HttpTunnel works exactly like the Linux version. If you need this, I suggest you act quickly: The program is on a student site with no parent links.

For the Windows ssh client, there is a wonderful program, Putty, that saves the day. This free program gives you telnet, rlogin, and ssh. It has a nice configuration GUI with support for port forwarding and ssl authorization. A sample configuration for the antics described above may be found here.

References

TBD