Paranoid Penguin - Application Proxying with Zorp, Part II

The Zorp proxy server works with the kernel Netfilter to make an application-level proxy that looks transparent to the client.

In my last column, I sang the praises of application-layer proxy firewalls
and introduced Balazs Scheidler's Zorp firewall suite, available in
both commercial and free-of-charge versions. This column continues
where we left off, discussing basic Zorp configuration for a
simple inside-DMZ-outside scenario. We are going to configure only a couple
of services, but this should be enough to help prospective Zorp
users begin building their own intelligent firewall systems.

To review, application-layer proxies broker rather than merely
pass the traffic that flows through them. For example, when a
user on one network initiates an HTTP session on the other side
of a proxying firewall, the firewall intercepts and breaks the
connection, acting both as the server (from the client's viewpoint)
and as the client (from the destination server's standpoint).

Zorp uses transparent proxies, which means that users behind a
Zorp firewall need not be aware that the firewall is there; they
may target foreign addresses and hostnames without configuring
their software to communicate with the proxy. This is an important
mitigator against the ugly fact that proxies are inherently more
complicated than other kinds of firewalls. With Zorp, all the
complexity is in the back end, resulting in much happier end users.

But that doesn't mean Zorp is painful for its administrators,
either. I'd rate its complexity as being higher than iptables but
lower than sendmail.cf. So without further ado, let's configure
ourselves a Zorp firewall.

Assumptions

This article assumes that, per my last column, you've successfully
patched your Linux 2.4 kernel and your iptables binary to support the TPROXY module (see
www.balabit.com/products/oss/tproxy). It also assumes you have compiled
and/or installed packages for libzorpll, zorp and zorp-modules;
source code and deb packages are available at
www.balabit.com/products/zorp_gpl.
My examples further assume you're running Zorp GPL version
2.0, though the examples should apply equally to Zorp Pro 2.0. Zorp
Pro has some proxy modules not included with Zorp GPL, but the
modules common to both behave the same.

The Scenario

Zorp supports many more than three interfaces per firewall, but the
most common firewall architecture nowadays is the three-homed-host
architecture shown in Figure 1. This is the architecture I cover here.

Figure 1. Example Architecture

Similarly, as you can see in Figure 1, we've got only three data flows:
HTTP from the Internet to a DMZed Web server; HTTP from the internal
network to the Internet; and HTTP and SSH from the internal network to
the DMZ. Absent are things like IMAP, NNTP, FTP and other services that
even simple setups commonly use. If you understand how to configure
Zorp to accommodate these, though, you should be able to figure out others.
I do, however, discuss DNS and SMTP, even though I omitted them from
Figure 1.

Configuring a Dummy Interface

The first thing we need to do doesn't directly involve Zorp but rather
the TPROXY kernel module. In transparent proxying, TPROXY needs a dummy
network interface to bind to whenever it splits a data flow in two. This
needs to be an
interface whose IP address is neither Internet-routable nor associated
with any network connected to the firewall.

Linux 2.4 kernels compile with support for dummy network interfaces by
default. You should have one, unless you intentionally compiled your
kernel without dummy driver support. If so, compile a new kernel
with dummy support. All you need to do for TPROXY's purposes,
therefore, is explicitly configure dummy0 with a nonroutable and unused
address. In Debian, you should add the following lines to
/etc/networking/interfaces:

Other distributions handle network configuration differently—Red Hat and
SuSE use ifcfg- files in /etc/sysconfig/network—but hopefully you
get the picture. Notice the 32-bit network mask: I repeat, this address
must not belong to a real network.

iptables Configuration

You may be wondering, isn't this article about Zorp and not
iptables? Yes, but Zorp runs in conjunction with iptables, not in place
of it. TPROXY, in fact, is specifically a Netfilter patch. To use TPROXY,
we need to configure it with the iptables command, as we do for
the rest of Netfilter. (Netfilter is the proper name for Linux 2.4's
firewall code—iptables is its front-end command.)

In addition, it's recommended that you run certain services, namely DNS
and SMTP, on the firewall as self-contained proxies. If you do,
you need to use iptables to configure your firewall to accept those
connections directly. For example, BIND v9 supports split-horizon
DNS, in which external clients are served from different zone files than
are internal clients. Similarly, Postfix is easy to configure to act as
a relay on behalf of internal hosts, but strictly as a local deliverer
when dealing with external hosts. It makes sense to run such proxy-like
services on a firewall, as long as you configure them extremely carefully.

If you're new to Netfilter/iptables, what follows may make little
sense, and space doesn't permit me to explain it all in detail. Zorp is,
after all, an advanced tool. In a nutshell, what we're going to do with
iptables is
run all packets through some simple checks against spoofed IP addresses.
We then are going to intercept packets that need to be proxied
transparently and
process them in custom chains rather than by using the normal FORWARD
chain.
Technically, nothing is forwarded. Finally, we pass some packets that
are destined for the firewall itself.

Zorp Pro includes a group of scripts collectively called iptables-utils, which simplify
iptables management for Zorp. A free version of iptables-utils for Zorp GPL
2.0 is available at
www.balabit.com/downloads/zorp/zorp-os/pool/i/iptables-utils.
I highly recommend iptables-utils, as it makes it much easier to test
a new iptables configuration before actually committing it.

Because it
uses a syntax that I don't have space here to explain, the following
example is instead a conventional iptables startup script. Here are the
most important parts of such a script.
First should come rules for the special tproxy table that the TPROXY
module adds to Netfilter (Listing 1). This is where we define a custom
proxy chain for each of our networks: PRblue for proxied connections
initiated from our internal network; PRpurple for proxied connections
initiated from our DMZ (none, in this scenario); and PRred for proxied
connections originating from the Internet.