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
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.
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.
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.
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 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.
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
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.
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.
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".
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!
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.
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".
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.
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.
TBD