Firewall bypassing kit

We're talking here about the problem of being within a firewalled organization and wanting to access a computer that you control that is on the outside, roaming free on the Internet. Many firewalls allow only ports 80 (HTTP) and 443 (HTTPS) through, and can inspect the contents of the former (allowing them to say no if they dislike the contents of your traffic), but not the latter. The best way to achieve decent communication with your machine through a firewall is to get SSH running (because then you can tunnel anything else, such as VNC, through SSH). So our goal then becomes to establish an SSH connection over HTTPS.

We'll label the machines firewalled (where you're sitting, frustrated with your inability to get any work done) and yourserver (out there, with useful stuff on it and proper access). This summary will assume that yourserver runs UNIX/Linux.

A pretty good way of achieving our aim is to set up Apache on yourserver and use mod_proxy and mod_proxy_connect to allow HTTP(S) CONNECT commands through to port 22 (yourserver's local SSH server).

Client side (Windows)

On the client side, assuming a Windows client, run an SSH client such as PuTTY, and have it communicate through a tool like Proxytunnel.

Here's a local copy of stuff you might need:

Put them all in the same directory. To test the proxytunnel configuration, from a command prompt, run one of these (note :80 for HTTP, and -E for encryption with :443 for HTTPS):

proxytunnel -v -p yourserver:80 -d localhost:22 -H "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Win32)"
proxytunnel -v -E -p yourserver:443 -d localhost:22 -H "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Win32)"

To test in a Linux/Ubuntu environment:

sudo apt-get install libssl-dev proxytunnel

proxytunnel -v -p yourserver:80 -d localhost:22 -H "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Win32)"
proxytunnel -v -E -p yourserver:443 -d localhost:22 -H "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Win32)"

To run with Putty, set up Putty as usual (usual i.e. genuine remote host name, and port 22 as usual) but in the Connection > Proxy settings, choose proxy type "local", and in the "Telnet command or local proxy command" box, enter one of these (note :80 for HTTP, -E for encryption with :443 for HTTPS):

proxytunnel -q -p %host:80 -d localhost:22 -H "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Win32)"
proxytunnel -q -E -p %host:443 -d localhost:22 -H "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Win32)"

If your proxy is fussy about the browser you use (!), amend the user agent string. See this list of common user agent strings.

Having done this, you can then configure PuTTY (Connection > SSH > Tunnels) to create tunnels - for example, from firewalled:5900 ("L5900") to yourserver:5900 ("yourserver:5900"). Having logged in via PuTTY to yourserver, this would allow you to run a VNC viewer on firewalled and have the VNC viewer connect to localhost:5900, which would be tunnelled by PuTTY to yourserver's VNC server.

Let's illustrate with three scenarios, using the notations "machine(software)" and "machine:port" (>>||>> denotes the position of the firewall):

Typically, "sshclient" means PuTTY on Windows machines; "webserver" means Apache on Linux machines; "sshserver" means OpenSSH.

If your site's restrictions are such that you can't run even this (e.g. you can't run .EXE files), you'd have to look at Java client implementations of SSH and proxytunnel.

More specifically on PuTTY

This configuration:

... gives an open port at the client's localhost:22 (suitable for X2Go connections), tunnelling via PuTTY, itself travelling via the HTTPS proxy on the remote host's port 443 to its port 22. Note that the proxytunnel "-d" switch is relative to the remote computer, not the local.

Client side (Linux)

Download http-proxy-tunnel (local copy); extract Configure .ssh/config as follows:

host myserver
    HostName myserver.mydomain
    User myuser
    ProtocolKeepAlives 5
    ProxyCommand "http://%h" "localhost:%p"
    # ... or "https://%h"
    # LogLevel DEBUG3

Then you can ssh in. (Note then also the possibility of tunnelling other things via SSH.)

Server side

I'll assume you already have a basic SSH server running on port 22, and have Apache up and running for both HTTP (80) and SSL/HTTPS (443).

  1. Enable necessary bits in Apache:
    sudo a2enmod proxy
    sudo a2enmod proxy_connect
  2. Edit the relevant site configuration file (e.g. in an OS with the "Debian layout", such as Ubuntu, edit /etc/apache2/sites-available/default for HTTP, and /etc/apache2/sites-available/default-ssl for HTTPS). Make sure you get the security right; open proxies cause significant Internet problems. The following allows CONNECT commands to "localhost:22" (exactly, case-sensitive) only, from anywhere, and denies everything else.
    ProxyRequests On
    AllowCONNECT 22
            Order deny,allow
            Deny from all
    <ProxyMatch ^(?=localhost:22$)>
            Allow from all
  3. Patch Apache; as of v2.2.9 there's a bug relating to CONNECT commands over HTTPS (though not plain HTTP). To do this from a shell prompt (assuming a basic Ubuntu and apache2 installation):
    # prerequisites
    sudo apt-get install apache2-src build-essential libpcre3-dev libcrypt-ssleay-perl libcurl4-openssl-dev
    # unpack the Apache source
    cd /usr/src
    sudo tar xvfz apache2.tar.gz
    # get the patch; apply the patch
    cd /usr/src/apache2/
    lwp-request > /tmp/httpd-2.2.9-proxytunnel.patch
    cat /tmp/httpd-2.2.9-proxytunnel.patch | patch -p1
    # install zlib
    cd /usr/src
    sudo wget
    sudo tar xvfz zlib-1.2.3.tar.gz
    cd zlib-1.2.3/
    sudo ./configure --prefix=/usr/local
    sudo make
    sudo make install
    # build (some of) Apache
    cd /usr/src/apache2
    sudo ./configure --enable-modules=all --enable-mods-shared=all --enable-proxy --enable-proxy-connect --enable-proxy-ftp --enable-proxy-http --enable-ssl
    sudo make all
    # copy the libraries we've just built into the live version
    sudo find -name "*proxy*.so" | sudo xargs cp -t /usr/lib/apache2/modules
  4. Restart Apache.
    sudo apache2ctl configtest
    sudo apache2ctl restart

Primary sources for this page:

Valid HTML 4.01 Transitional
Valid CSS