Creating A Linux Firewall Using the TIS Firewall Toolkit

By Benjamin J. Ewy

Reprinted with permission from the

Linux Journal


As more and more companies try to develop a presence on the Internet, establishing a secure network perimeter has become a very important topic. There are many varieties of what are loosely referred to as Firewalls. The general principle behind a firewall is that it serves as a choke point between an internal network and the outside world. The choke point only allows traffic through that is deemed safe.

IP-based filters are one common form of firewall that rely on the source and destination addresses to decide which kind of traffic to pass through. They have the advantage of flexibility in that they can easily be adapted to different types of traffic as needed. The primary disadvantage of IP-based filters is that they rely on IP addresses as the principle form of authentication, and that they also do not have the ability to look higher into the protocol layer to determine exactly what kind of traffic is being sent.

Application-level gateways are another form of firewall that often consist of a computer called a bastion host. The bastion host runs a set of firewall software which implements the policy "that which is not expressly permitted is prohibited". This policy is implemented at the application level, which allows the bastion host to more completely control the traffic that passes through it.

Implementing the interface between the internal and external networks at the application level allows much more control over the authentication for particular services, and in particular allows for many forms of strong authentication. The main disadvantage of application-level firewalls is that they require interfaces for every specific application that is to pass through the gateway. If a new application interface is desired either custom software must be written or the service must be done without. The Trusted Information Systems Firewall Toolkit (fwtk) is a very useful kit for creating bastion hosts.

The fwtk supports the functions of a bastion host by providing several small programs that can be pieced together as a site desires while simplifying management with a common configuration file. For each service that the security policy allows to pass through the firewall, a specific application level proxy is required. The fwtk comes with proxies for telnet, rlogin, SMTP mail, ftp, http, X window, and a generic TCP plug-board server that works as a transparent pass-through proxy for many other services.

Additionally, the fwtk comes with a tool called netacl which implements network level access control, and authsrv which implements a network authentication service. This article will focus on preparing a generic Linux host to be a bastion host, obtaining and compiling the fwtk, and configuring its services to support a secure network environment.

Preparing Your Bastion Host

The first step is to prepare the Linux host to be a functional and secure bastion host. There are several principles that firewall builders should adhere to. The ideal bastion host should only provide proxy services and should not be a general purpose machine. Only administrative accounts should be allowed, and if possible, logins to the bastion host should be restricted to the console, although allowing strongly authenticated remote access for remote maintenance will be discussed. The bastion host should not rely on any network services such as NIS or any form of remote file access such as NFS. Allowing either of these opens up numerous holes that can compromise your bastion host.

Next, it is necessary to verify that the required functionality is available with the Linux host. Every bastion host has at least two network interfaces, one connected to the internal network, and the other connected to the external network access point. These interfaces should be configured and tested prior to any further modifications, and you should verify the accessibility of your bastion host from both the internal and external networks. Refer to the Linux NET2 HOWTO, and the Linux Multiple Ethernet mini-HOWTO as necessary.

The kernel should be rebuilt, ensuring that IP forwarding (CONFIG_IP_FORWARD) is disabled when you do

make config.
If IP forwarding were enabled, the kernel would automatically forward packets from one interface to the other interface if a route has been established. Controlling this forwarding is what building a bastion host is all about. Finally, if you want to provide a secure mechanism for SMTP mail service, it is necessary to first configure and test sendmail. Refer to the Linux Kernel HOWTO and the Linux Electronic Mail HOWTO as appropriate.

The next task is to secure the bastion host so that only the proxy services are available. Begin by removing all unneeded services from the inetd configuration file, /etc/inetd.conf. Simply put a

#
in front of each unneeded service line, and when done editing the file issue a
kill -HUP
to the process id of inetd. Remove ftp, telnet, SMTP, nntp, shell, login, talk, stalk, pop, uucp, ftp, bootp, finger, systat, netstat and every other service you are not expressly sure you want to provide. We will be defining our proxy services in this file later.

Finally, prevent the startup of any stand-alone daemons by cleaning out the boot files in /etc/rc.d, removing unneeded programs. In particular, check the rc.inet2 file and comment out rpc.portmap, rwhod, rpc.mountd, rpc.nfsd, rpc.ugidd, and ypbind. After you are done removing services, reboot your bastion host and then carefully examine the output from a

ps aux
and check that you didn't miss any unnecessary programs. It is also a good idea to run
rpcinfo -p
and the port scanner that comes with the fwtk in the tools directory to verify that all unnecessary services are dead.

Compiling the Firewall Toolkit

Obtain the toolkit, Linux patches, and, if desired, the S/Key package, as detailed in Obtaining Firewall Resources. Bellcore's S/Key provides one-time password support for network authentication if built into the toolkit. A number of commercial one-time password systems are also supported by the fwtk, but there use is not detailed in this article.

Put the fwtk archive in /usr/src/, and run

tar xfz fwtk-v1.3.tar.Z
to unpack it. If you prefer to build in a different place, modify the Makefile.config as appropriate. The Linux patches that we will be applying assume /usr/src/fwtk is the source code directory.

These patches are based on the work of Marco Pauck (pauck@wmd.de) and the firewall-users mailing list, and have some modifications and additions done by the author to allow the x-gw proxy to work, and to support the S/Key authentication mechanism. Most of the patches work around Linux's select() function. Put the fwtkpatches.tgz file into /usr/src/fwtk. Then run

tar xfz fwtkpatches.tgz
which will create a patches directory. Go into the patches directory and run the INSTALL script or apply the patches by hand. If you do not want S/Key support, run the INSTALL.noskey script instead.

Assuming you want S/Key, put the S/Key archive in /usr/src and run

tar xfz skey-2.2.tar.gz
to unarchive it. It is necessary to compile S/Key first so that its libraries can be linked into the authentication service when we compile the fwtk. This S/Key has been already ported to Linux, so all that is necessary to build it is to run
make
inside the /usr/src/skey-2.2 directory.

When the patches have been installed, and S/Key has been compiled, you can modify the Makefile.config if you want to change any of the defaults, but the rest of this article will assume you have left the Makefile.config as patched. Go to /usr/src/fwtk/ and run

make
and
make install
The firewall components will be installed in /usr/local/etc/ by default.

Configuring the Network Access Control Lists

The firewall toolkit is made up of three main components: netacl, authsrv, and the various service proxies. Netacl is similar to the tcp wrapper, tcpd, that is common on many Linux systems. Netacl is used to check rules on a per-service basis and then to take the defined action. You edit your /etc/inetd.conf file to call netacl passing the normal service to netacl as its first parameter. An example entry for the finger service might look like Listing 1. inetd will invoke netacl when a connection is made on the finger port.

Netacl looks in the common configuration file to see what action to take. The common configuration file is called the netperm-table and is found in /usr/local/etc/netperm-table. A default netperm-table that has many examples in addition to the ones presented in this article is installed automatically. Netacl looks in the netperm-table and reads entries that start with netacl. Netacl understands the permit-hosts and deny-hosts options for defining access lists and requires -exec to be defined for each line as well, as shown in Listing 2.

# Example Inetd Config using netacl
finger  stream  tcp  nowait  daemon  /usr/local/etc/netacl  in.fingerd

# Netacl configuration example
netacl-service: permit-hosts address -exec program name
netacl-service: deny-hosts address -exec program name
A given service can have multiple lines of both the permit and deny varieties. Address can be a list of hosts addresses, and wildcards such as *.my.domain or 129.17.* are supported. The keyword unknown matches hosts that cannot be resolved using DNS. The first rule that matches is the one performed. Lines may not be broken.

In the examples given in this article the following conventions will be used: .internal.net will represent your internal network. ftp.server.internal.net will represent a ftp server internal to your network. www.server.internal.net will represent a www server internal to your network. compute.server.internal.net is a compute server internal to your network. trusted.external.net is a external network that you trust. bastion.host.internal.network will represent your bastion host's IP address.

An important point is that these rules are not associated with a network interface. If you write rules for a service to allow your internal private network to have special access rights, you must ensure that those IP addresses could only have been received from your internal network. IP spoofing can be used to pretend to be a host on your internal network and take advantage of your rules. This can be prevented by using screening routers to block packets claiming to be from the internal network when they arrive on the external network connection. Often your Internet provider can implement this type of rule in the router that feeds your site.

# Example finger service rules
netacl-in.fingerd : permit-hosts .trusted.external.net -exec /usr/sbin/in.fingerd<\n>
netacl-in.fingerd : permit-hosts * -exec /bin/cat /usr/local/etc/dummyfingeroutput
The first line of Listing 3 will exec in.fingerd if the requesting host is a member of .trusted.external.network. The second line will match all others and cat a message of your choice. This might be a ``fake'' finger output to mislead attackers, or a simple explanation that the service is unavailable. Netacl is often used for permissions on services that you are not proxying but can also be used to switch among the proxy or the real service based on the origin of the connection. This feature will be discussed in more detail later.

The netperm-table also contains configuration information for all of the proxies, as shown in Listing 4. The format is similar to the netacl format, and each rule can contain multiple lines. These options will be discussed in more detail for each proxy later.

# Example proxy config line
# format is  : option
ftp-gw: welcome-msg /usr/local/etc/ftp-welcome.txt

Providing a Network Authentication Service

Authsrv is the authentication server for the firewall toolkit. The authentication server is optional but allows multiple types of authentication to be managed in a consistent manner. Support for the authsrv daemon's authentication by is built into all of the proxies in the firewall toolkit, and can be selectively enabled in the netperm-table on a per-proxy or even per-permit-hosts basis

Authsrv has support for many different type of authentication including internal plain-text passwords, and several forms of strong authentication using one time passwords compatible with Bellcore's S/Key, Security Dynamic's SecurID, Enigma Logics' Silver Card, and Digital Pathways' SNK004 Secure Net Key. In our example we have compiled S/Key and its support into authsrv, but the other mechanisms are similar and their details can be found by looking in the /usr/src/fwtk/auth directory. S/Key is a challenge-response one-time password system that will present you with a sequence number and a key at login time. You must give the sequence number, key, and your own private pass-phrase to an S/Key calculator and it will return a 6 word password. That password will only be valid for that particular sequence number, and it has the property that it was created using a nonreversable algorithm, so it is not possible to easily calculate the next password even if the current one is known. This type of strong authentication is one of the best features of using the fwtk.

To configure the authsrv it must be added into the inetd.conf so that inetd will start it, as shown in Listing 5.

# Example inetd configuration for authsrv
authsrv stream tcp nowait root /usr/local/etc/authsrv authsrv
Since authsrv is not a well known service, an unused port must be selected and added to the /etc/services file. The fwtk configuration manual suggests port 7777. The corresponding /etc/services entry would then be:
# Example services entry
authsrv	7777/tcp
As before, when you change the /etc/inetd.conf file, you must send a
-HUP
signal to inetd to cause it to read in the changes.

Configure authsrv itself by setting up its options in the netperm-table. Authsrv recognizes the database, permit-hosts, nobugus, userid, and badsleep options. The database option tells authsrv where to find its database, and the permit-hosts can be used to restrict which hosts can query the authsrv. It is recommended that authsrv be run on the bastion host so that the database is protected from misuse. An example config might include the entries shown in Listing 6 in the netperm-table.

# Example netperm-table entry for authsrv
authsrv: database /usr/local/etc/authsrv.db
authsrv: permit-hosts localhost bastion.host.internal.net
In our example, the bastion host is running the authsrv daemon, and the bastion host is the only host with proxies requiring authentication by our server. We restrict the authsrv requests to come only from the bastion host to prevent unauthorized probing of the database.

Next, we set up a S/Key-based admin account on our bastion host. First, the auth database needs to be initialized. The best way to do this is to run authsrv as root. Then add a admin user and enable logins for that user by entering the following at the authsrv prompt:

authsrv# adduser admin
authsrv# enable admin
Set the protocol to skey, and give the the user wizard privileges:
authsrv# proto admin skey
authsrv# superwiz admin
Then you need to set the admin password. S/Key allows your password to be several words long. Enter your phrase between quotes:
authsrv# password admin "my neat password phrase"
ID admin s/key is 664 wa56038
authsrv# exit
The output returned by authsrv after your pass-phrase is the next sequence number it will use for a challenge, and its key. You can use them to generate one-time passwords as needed using the key program (read its man page, found in /usr/src/skey-2.2/key). For example, if you are challenged with
S/Key Challenge: s/key 663 wa56038
run
key 663 wa56038
and enter in your pass-phrase. It will respond with a six-word phrase that you can enter to authenticate yourself. If you are going to be traveling, there are Macintosh and DOS versions of the S/Key calculator, or you can have key print out a list of your next passwords by running
key -n number 663 wa56038
and it will print out your next number passwords and their appropriate sequence numbers.

There is another program called authmgr which can be used to remotely administer the authentication database. There are many features in addition to those shown here, such as groups and group permissions for users, and the ability to specify authentication on a per-user, per-time basis. These additional features can be found in the authd man pages. Finally, there are two utilities called authdump and authload which allow you to take snapshots of the current database for archival or administrative purposes, and then reload the database.

Configuring and Using the Proxy Services

This section will focus on the configuration and use of the service proxies for telnet, ftp, http, and SMTP mail. Common methods for configuring these services will be discussed, but each of them has many options and are very flexible. The man pages for each of the services should be reviewed to determine if other configurations might suit your installation better. The proxies for rlogin and X-windows are configured similarly to the telnet proxy. The Generic TCP plug-through proxy can be used for NNTP news transfers, talk sessions, or any other TCP service that a site wishes to pass through the firewall.

The telnet proxy is called tn-gw. The tn-gw has many options including the permit-hosts and deny-hosts lines as seen on other services, and a number of message options. The fwtk configuration manual discusses how to use netacl to allow both telnet service to the bastion host and the telnet proxy to coexist on the bastion host, although this is just one of many possible configurations.

First, use netacl to switch the service based on the origin, as shown in Listing 7, which shows an /etc/inetd.conf entry, and Listing 8, which shows the additions to the netperm-table.

# Telnet netacl example
telnet  stream  tcp  nowait  root  /usr/local/etc/netacl  in.telnetd

# Example using netacl to switch telnet service
netacl-in.telnetd: permit-hosts 127.0.0.1 -exec /usr/sbin/in.telnetd
netacl-in.telnetd: permit-hosts bastion.host.internal.net -exec /usr/sbin/in.telnetd
netacl-in.telnetd: permit-hosts * -exec /usr/local/etc/tn-gw

# Example tn-gw config
tn-gw: deny-hosts unknown
tn-gw: permit-hosts .trusted.external.net -dest compute.server.internal.net
tn-gw: permit-hosts .internal.net -passok
tn-gw: permit-hosts * -auth -dest !bastion.host !127.0.0.1
tn-gw: authserver localhost 7777
tn-gw: denial-msg /usr/local/etc/telnet-deny.txt
tn-gw: welcome-msg /usr/local/etc/telnet-welcome.txt
tn-gw: help-msg /usr/local/etc/telnet-help.txt

When a telnet connection is started, inetd calls netacl. Netacl looks at the source IP address, and if it is not from the bastion host it calls the tn-gw proxy. The tn-gw proxy prints a denial message and closes if the source address is unknown, and will allow a non-authenticated connection to compute.server.internal.net only from .trusted.external.net. Connections from the internal net have no restrictions (the default) on their destinations, and users are allowed to change their bastion host passwords if they are coming from the internal network. Additionally, connections from the internal net to the bastion host itself are allowed. Finally, all other hosts are allowed to go to any destination other than the bastion host itself, after they authenticate with the specified authserver. You might not want to use this setup (for example, allowing unauthenticated access from any external site is not a good idea) but it presents many of the options that the toolkit offers.

If a user is on the internal network and wants to have telnet access to the external network, they

telnet
bastion.host
and then type
c external.host
to connect to the external host.

If a user was on the external network and wanted to connect to an internal host then they would have to

telnet bastion.host
enter their userid and authentication as required by specific authentication type, and then
c internal.host
.

Finally, if an administrator wants to connect to the bastion host from the internal network, they

telnet bastion host
then
c bastion.host
and netacl will start the real telnet service on the bastion host.

Next, we will configure the ftp proxy system. We will assume that your site does not want to provide anonymous ftp service from the bastion host to the external network. The TIS configuration guide discusses in more detail how to configure a site that supports anonymous ftp and the ftp proxy on the same host. Our example will only have the ftp proxy on the bastion host.

The inetd.conf file will need to be modified to call the ftp-gw proxy. Netacl is not used since we are not switching the service being provided as we were in the telnet example. The inetd.conf line is shown in Listing 9. Then establish the permissions in the netperm-table, as shown in Listing 10.


# FTP proxy inetd.conf config
ftp  stream  tcp  nowait  root  /usr/local/etc/ftp-gw  ftp-gw

#ftp-gw config example
ftp-gw: authserver localhost 7777
ftp-gw: deny-hosts unknown
ftp-gw: permit-hosts internal.network -log (retr stor)
ftp-gw: permit-hosts * -authall -log (retr stor) -dest ftp.server.internal.net
ftp-gw: denial-msg /usr/local/etc/ftp-deny.txt
ftp-gw: welcome-msg /usr/local/etc/ftp-welcome.txt
ftp-gw: help-msg /usr/local/etc/ftp-help.txt
These lines will print the ftp-deny.txt file and close the connection if the reverse name lookup fails, and will allow internal nodes to ftp through the gateway without authentication, but will log RETR and STOR transactions. Additionally, it will allow external nodes to connect to the internal ftp server after authentication with the authserver, and will again log RETR and STOR transactions.

Users on the internal network will ftp to the bastion host and then enter their destination at the username prompt. To be forwarded to the site big.archive as user bob, they need to enter bob@big.archive at the bastion host's username prompt, and it will forward the connection through. Users on the external network will have to authenticate themselves first and then enter their destination. This is discussed in more detail in the ftp-gw man page.

Now, configure the proxy for http. This is similar to the other proxies and can have a relatively simple configuration. First add the line in Listing 11 to the /etc/inetd.conf file, and then set up the netperm-table configuration entries shown in Listing 12.


# http proxy example in inetd.conf
www  stream  tcp  nowait  root  /usr/local/etc/http-gw http-gw

# http config in netperm-table
http-gw: deny-hosts unknown
http-gw: permit-hosts .internal.net
http-gw: permit-hosts * -httpd www.server.internal.net
This configuration will allow internal hosts to go out to wherever they want without authentication, and allow external hosts to connect to the www.server.internal.net host without authentication. Check the http-gw man page for options involving specific authentication of particular http actions.

For users on the internal network we can configure their proxy-aware web browser to transparently pass through the firewall http proxy. We will use the Netscape browser as our example. Find the Network Preferences menu under the Options menu. Under that, there is a section on proxy configuration. Select manual proxy configuration and enter the IP address of your bastion host for each of the proxied services, and their respective ports. Now you can again use normal http addresses and the browser will do all necessary requests automatically through the bastion host.

Our final service to be proxied will be SMTP mail. The fwtk comes with two programs, smap and smapd, which serve to reduce problems with sendmail and insulate it from some attacks. They do use sendmail, however, so this section will assume that the sendmail configuration for the bastion host has already been setup and debugged. Sendmail configuration is well outside the scope of this document. The Linux Electronic Mail HOWTO can be consulted as necessary.

Smap is a minimal SMTP client that is invoked by inetd, accepts SMTP mail messages, and writes them to a special spool directory. Smapd is a daemon that is replaces sendmail in rc.M (or whichever boot script starts sendmail in your distribution). Smapd will look at the spool directory and deliver messages using sendmail periodically. This time, three changes need to be made. Listing 13 shows an /etc/inetd.conf entry to smap, Listing 14 shows how to start smapd from a boot script, and Listing 15 shows the netperm-table entries.

# inetd.conf for smap example
smtp  stream  tcp  nowait  uucp  /usr/local/etc/smap smap

# rc.M example for starting smapd
if [ -x /usr/local/etc/smapd ]; then
        echo "Starting sendmail proxy"
        /usr/local/etc/smapd
fi


#netperm-table example for smap and smapd
smap, smapd:    userid uucp
smap, smapd:    directory /var/spool/inspool
smapd:          executable /usr/local/etc/smapd

Next, create the /var/spool/inspool directory and make it owned by uucp. Run
mkdir /var/spool/inspool; chown uccp
/var/spool/inspool
. Finally, run sendmail from a cron job so that it can process any entries that were unable to be delivered. A line like
0,30 * * * * /usr/lib/sendmail -q >/dev/null 2>&1
should be added to root's crontab.

Final Points and Additional Resources

The TIS Firewall Toolkit is a very flexible and useful collection of programs for creating bastion hosts. A collection of examples of how to configure a Linux based bastion host have been presented. Many of these programs have additional features and the documentation that comes with the toolkit should be read to get the most out of these programs. Several additional tools, such as a portscanner and several log summary generators, come with the fwtk.

Some final steps before completing your bastion host include removing any unnecessary programs that may have been installed. In general new holes are found every day, so the fewer programs installed, the better. This includes gcc! Without a compiler, many hackers are limited in what they can do if they should break in. It is a good idea to run Tripwire on your system after it is configured, to provide a safeguard against unauthorized modifications to the system. Tripwire checksums files and alerts you to their modification. Finally, make a complete backup of your bastion host so that you have a ``Day 1 copy'' to revert to in case of emergency.

There are many useful references for information on firewalls. First, the fwtk comes with an overview, an installation and configuration guide, a user manual that shows users how to access services through the firewall, and man pages for all of the programs associated with the fwtk.

Several excellent books on firewalls are: Firewalls and Internet Security, Cheswick & Bellovin, Addison Wesley. Building Internet Firewalls, Chapman & Zwicky, O'Reilly & Associates Internet Firewalls and Network Security, Siyan & Hare, New Riders Publishing.

Firewall Resources

The TIS Firewall Toolkit

The TIS Firewall Toolkit Documentation.

The Linux Patches for the fwtk.

The TIS Firewall Toolkit Users Archive.

S/Key version 2.2 for Linux.

Tripwire is a file integrity checker.


The Official Internet Firewall FAQ.

Commercial Firewall Vendors.

Firewall Mailing List Archive.


Linux NET-2 HOWTO

Linux Firewall HOWTO

Linux Kernel HOWTO

Linux Multiple Ethernet mini-HOWTO


The author can be reached at bewy@tisl.ukans.edu