7. Appendix

7.1 Tunneling though Squid

So you have finally configured your proxy server, allowing only requests to a few standard ports, blocking blacklisted sites, ads and viruses. The HTTP CONNECT method is restricted to the standard HTTPS port. Your LAN firewalls rules are very strict and block everything but requests to port 3128 of the proxy. Therefore, you feel pretty confident that users won't be able to do anything on the Internet you didn't explicitly allow.

But Squid is an ugly beast, and if you don't pay very close attention to its configuration (and log files), your users could end up getting around most of your blocking rules. Let's have a look at a practical example.

Stunnel is a program that allows you to encrypt arbitrary TCP connections inside SSL. It is mainly used to secure non-SSL aware daemons and protocols (like POP, IMAP, LDAP, etc) by having Stunnel provide the encryption, requiring no changes to the daemon's code.

Basically, Stunnel establishes an encrypted and persistent connection between two separate machines. One machine acts as the server and forwards any connection Stunnel receives to a user-defined port. The other machine acts as the client, binding to an arbitrary port and forwarding any connection it receives on that port to the server machine.

We will use Stunnel and Squid to bypass firewall rules and ssh(1) to a remote server (e.g. your home computer) from a local computer in the corporate LAN. The OpenBSD ports and packages archives include a few similar tools for tunneling network traffic through proxy servers, such as:

However, Stunnel is probably the most versatile and comprehensive tunneling solution, since it can forward any type of network traffic (not only ssh(1)) and provides an additional SSL cryptography layer, thus protecting clear text protocols such as telnet(1) or ftp(1).

7.1.1 Server-side configuration

The remote computer will necessarily have to act as the server. Install Stunnel from the packages and create the SSL certificate:

remote# pkg_add stunnel-x.xx.tgz
[...]
remote# openssl req -x509 -newkey rsa:2048 -keyout /etc/ssl/private/stunnel.key \
> -out /etc/ssl/stunnel.crt -days 365 -nodes
[...]
remote# chmod 600 /etc/ssl/private/stunnel.key

Then configure Stunnel to bind to port 443 (HTTPS) and forward incoming connections to port 22 (ssh). The configuration file is /etc/stunnel/stunnel.conf:

/etc/stunnel/stunnel.conf
cert = /etc/ssl/stunnel.crt
key = /etc/ssl/private/stunnel.key
sslVersion = SSLv3

chroot = /var/stunnel/
setuid = _stunnel
setgid = _stunnel
pid = /var/run/stunnel.pid

socket = l:TCP_NODELAY=1
socket = r:TCP_NODELAY=1

[https]
accept  = 443
connect = 22
TIMEOUTclose = 0

Now we can start it and go to work to have some fun with our tunnel:

remote# /usr/local/sbin/stunnel

7.1.2 Client-side configuration

So now we come to the local computer, which will act as the client. The SSL tunnel needs to go through Squid to get around the firewall rules but, by default, Stunnel doesn't support web proxies. Fortunately, a few patches are available that add SSL-proxy support to Stunnel. The most recent available applies to Stunnel version 4.05, so I suggest that you download and install this version on the client machine.

local$ tar -zxvf stunnel-4.05.tar.gz
[...]
local$ patch -p0 < connect-proxy.mwald.patch
[...]
local$ cd stunnel-4.05
local$ ./configure
[...]
local$ ln -s /usr/sbin/openssl /usr/bin/openssl
local$ make
[...]
local$ su
Password:
local# make install
[...]
local#

The patch introduces two additional configuration parameters: httpsproxy_dest (name or address of the Stunnel server) and httpsproxy_auth (proxy authentication credentials). We will configure the client to accept connections on an arbitrary port (e.g. 1443) and forward them to port 443 of the remote Stunnel server (which, in turn, will forward them to port 22). In other words, when you will connect to port 1443 on the local computer, you will actually get connected to port 22 on the remote computer.

The client configuration file looks like:

/etc/stunnel/stunnel.conf
chroot = /var/stunnel
setuid = _stunnel
setgid = _stunnel
pid = /var/run/stunnel.pid

client = yes

[https]
accept = 1443
connect = web-proxy:3128
httpsproxy_dest = stunnel-server:443
httpsproxy_auth = username:password

Ok, everything is ready, let's give it a try:

local# /usr/local/sbin/stunnel
local# ssh localhost -p 1443
root@localhost's password:
remote#

As you can see, despite firewall rules and Squid ACLs, we have successfully connected to the remote computer. Once the tunnel is up, you could even do the opposite and connect from the remote server to the local client by simply opening a reverse ssh from the local client:

local# ssh -NR 2443:localhost:22 -p 1443

This way, every connection received by the remote server on port 2443 will be forwarded to port 22 of the local client:

remote# ssh localhost -p 2443
root@localhost's password:
local#

You could even allow X11 forwarding on the remote server and have your whole remote graphical environment available on the local machine (for instance to surf the web with no proxy filters).

Anyway, this paragraph only meant to point out how much careful Squid configuration must be. Usually, however, the stricter your corporate policy, the more determined your users will be to evade it.

By the way, using whitelists is probably the best solution to prevent tunneling, but, if they are too restrictive, get ready to get your car keyed by a crowd of angry users!

7.2 References

7.3 Bibliography