User's Guide

sf Firewall Software--a TCP/IP packet filtering firewall for Linux

Robert Muchsel and Roland Schmid

Version 0.2.9, last edited on November 7th, 1996

[Logo]

Table of Contents

---

Introduction

Charlie Kaufman says:

"Firewalls are the wrong approach. They don't solve the general problem, and they make it very difficult or impossible to do many things. On the other hand, if I were in charge of a corporate network, I'd never consider hooking into the Internet without one. And if I were looking for a likely financially successful security product to invest in, I'd pick firewalls."

It's free

We want to give you the opportunity to protect your network without boosting someone else's fortune.

The firewall software was written by Robert Muchsel and Roland Schmid, two students from the Swiss Federal Institute of Technology Zurich, Switzerland, with input from Dr. Hannes Lubich. Dr. Lubich is a former employee of SWITCH, the Swiss Academic and Research Network. We also wish to thank arago GmbH, Frankfurt, for their thorough testing.

Target group

If you have medium volume traffic to the Internet and only a single entry point into the net, the software is designed for you. A Linux PC must be able to route all your traffic, therefore you shouldn't use your trashiest 386 machine for this purpose (unless it is a 14.4K modem link, where even a 386 might suffice).

We have successfully tested the software

It is documented

A tutorial, a description of the most important software design decisions and an installation guide will direct you to the installation and operation of the firewall.

We suggest you first print a copy of Chapman's article, since our firewall implements many of his concepts. If you are unfamiliar with firewalling and TCP/IP related threats, it might be wise to get Cheswick's and Bellovin's book also.

It comes with all the source code

We don't believe in security by obscurity. The source is yours to poke around, tailor it to your needs and eliminate all the bugs you can get hold of. We request, however, that you do not make publicly available modified versions of the source code. And it would be nice if you informed us of bugs and if you sent us any useful additions.

It has nifty features

You might have noticed the firewall is called "sf firewall" and not "yasbf" (yet another silly boring firewall). The sf firewall is an experimental firewall. In addition to a human-readable configuration language, we implemented dynamic rules, variables and time-outs, extensive logging, alerting and counter intelligence, RIP, FTP, ICMP, IGMP, UDP and TCP filtering and offer control of all IP fields. The firewall also prevents packet address spoofing and oversized IP packets.

And... It works

There's no such thing as bug-free software. However, we have enough faith in our software to let it protect a few networks in the banking industry.

Please don't try to hack our networks.
Please don't try to show us how to circumvent our firewall.

Since we (the software authors) are not directly connected to the Internet, you will only harass some innocent people somewhere else.

How to contact us

Please address all correspondence to firewall-bugs@switch.ch. This is not a distribution list, so please do not send subscription requests.

We appreciate your feedback, your suggestions and bug reports and we'd like some example configurations for inclusion with the next version of the software.

Copyright

Copyright © 1996 Robert Muchsel and Roland Schmid

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

Bibliography

A few papers and books you should have read before trying to configure the sf firewall:

Essential readings

Chapman, D.B. 1992:
Network (In)Security Through IP Packet Filtering.
Great Circle Associates, Mountain View, California.
Available for ftp from ftp.greatcircle.com.

Recommended readings

Bellovin, S.M. 1989:
Security Problems in the TCP/IP Protocol Suite.
AT&T Bell Laboratories, Murray Hill, New Jersey.
Available for ftp from ftp.research.att.com.

Cheswick, W.R. and Bellovin, S.M. 1994:
Firewalls and Internet Security--Repelling the Wily Hacker.
Addison-Wesley, Reading, Massachusetts.

Kaufman, C., Perlman, R., Speciner, M. 1995:
Network Security--PRIVATE Communication in a PUBLIC World.
Prentice Hall, Eaglewood Cliffs, New Jersey.

Stevens, W.R. 1994:
TCP/IP Illustrated, Volume 1--The Protocols.
Addison-Wesley, Reading, Massachusetts.

---

Installation

This chapter describes how to install the sf firewall on a Linux 2.0.x system.

Unpack the archive in a directory, for example /usr/local/src. The files will be written into ./sf-0.2.9 (you have probably already done that).

We recommend to use Linux kernel version 2.0.24, which is the latest version the firewall has been tested against (early 2.0.x kernels occasionally drop TCP connections; kernels 2.0.23 and earlier are vulnerable to oversized IP packets). There is a version of the sf firewall for kernels 1.2.x, please get the archive sf-0.1.tar.gz.

There is no need to patch the 2.0.24 kernel, however you should fix the bugs in your Linux distribution (e.g. sendmail). To minimize the impact of TCP SYN flooding attacks, it might be wise to install a patch.

If your current kernel configuration does not include "Loadable module support", "Networks firewall support" and "IP routing", you must recompile the kernel. To recompile the kernel, change to the /usr/src/linux directory (note: if your kernel tree is somewhere else, you must edit make.options in the sf directory). First run make menuconfig and select the appropriate options. Then compile by executing

make clean; make dep; make zImage.

For further information about compiling a Linux kernel, please refer to the Linux kernel HOWTO.

While the kernel is being compiled, you can continue with the firewall setup. Change to the sf-0.2.9 directory and type

./configure

View the file sf_custom.h and check if the information is appropriate for your system configuration. Do not change anything you are not sure about!

Now type

make clean; make dep; make

to generate the files sfc, sfident and sf.o.

Create a new user called firewall by adding the following line to your /etc/passwd file (you can use any unused user and group id):

firewall:x:888:888::/dev/null:/bin/false

Create a new group firewall by adding the following line to your /etc/group file:

firewall:x:888:

Now, type

make install

This command creates the firewall device, the firewall pipe and copies the executable files to their final destinations.

Create the firewall configuration file /etc/firewall.conf. You should use an example file included in this package and change it for your needs.

When the kernel compilation has succeeded, install the new kernel (copy zImage to /vmlinuz, run lilo and reboot).

Now you can insert the module (insmod sf) and start the firewall daemon (sfc start). For automatic startup at boot time, insert these two statements into a file in /sbin/init.d/ (or /etc/rc.d/, depending on your init style). Be sure to start the firewall daemon before the routing daemon. If your firewall configuration does not allow ICMP routing redirects, you should check your routing tables after the start of the firewall daemon for dynamically generated routes and delete them.

We recommend the following changes to your Linux system:

---

Setting up the Firewall Configuration

The packet filter is set up by a configuration file specifying all rules and actions. This chapter describes all possible configuration options.

For details concerning the syntax and the available options of the statements, please refer to the overview at the end of this chapter. It is recommended to use an example file provided with the firewall package as a starting point for your own configuration.

The configuration file is divided into three parts:

Any line in the configuration file starting with a #-sign is treated as a comment. C style comments are also allowed; they are normally used for comments covering multiple lines or not starting at the beginning of a line. (A C style comment is any text starting with /* and ending with */).

Note that you may only use lower case letters in the configuration file (strings can also contain upper case letters).

Specifying IP Addresses

IP addresses are used at several places in the configuration file. You can either use the dotted decimal notation or hostnames. In the latter case, the hostname is translated into IP addresses when parsing the configuration file using the resolver. All addresses returned by the resolver for the specified hostname are inserted. It is strongly recommended not to use hostnames for the following reasons:

You can specify a mask after the address or hostname. Note that this is normally not the netmask! Two addresses match if all bits are equal that are set to one in the mask. Thus if you want the complete address to be equal, the mask is 255.255.255.255. This mask is normally used to compare host addresses.

Examples:

129.132.1.18   mask 255.255.255.255   matches exactly one host
193.135.255.0  mask 255.255.255.0     matches all addresses in the class C net
129.132.20.0   mask 255.255.255.0     matches all addresses in the class B net
                                      129.132.20.0 using subnetting
You do not have to specify the mask if the address is either a host address or a net address without subnetting. The following examples show what mask is calculated automatically: 
129.132.1.18   = 129.132.1.18  mask 255.255.255.255
129.132.0.0    = 129.132.0.0   mask 255.255.0.0
193.135.255.0  = 193.135.255.0 mask 255.255.255.0

Note that the address 129.132.20.0 without mask is treated as a host address, because the host part of the class B net is not zero! To specify a subnet address, you always have to give the netmask as mask.

The Setup Section

The configuration file starts with the setup keyword. The optional internalnets statement is used to inform the firewall about the IP addresses of the nets (and/or hosts) that are "behind" the firewall. Normally these are the IP addresses allocated by your organization. The list of addresses is separated by commas and terminated by a semicolon. This information is used by the filter to prevent IP address spoofing. It determines if a packet arrived on the correct interface (a packet containing a source address out of the address space allocated by the organization must not arrive on the interface connected to the internet). It is assumed that there is only one connection to the internet within the organization.

You must specify a default mail address using the mail_default statement. This address is used, if no other address is given in a mail statement or if a severe event occurs (e.g. disk full). You may also specify a list of mail addresses separated by spaces within the string.

The Configuration Section

The configuration section starts with the keyword rules. Each rule in the configuration section starts with one of the keywords accept, block or reject. An accept rule causes the filter to let packets matching the rule pass through. Packets matching a block rule are dropped silently, i.e. no ICMP error messages are generated. Using a reject rule, the matching packet is dropped, but an ICMP error message is sent back to the source address. The default error message is host unreachable, however it is possible to specify a different message in the form reject with icmp_..._unreachable.

Next you may optionally provide a list of IP options using the keyword options. A packet matches the rule if it has set at least one of the listed options. A special case is the time to live field, which is not really an option but is treated like one here. Its value can be compared with a constant, a packet matches the rule only if the comparison is true, regardless of other options listed.

Information about the protocol is provided with one of the keywords tcp, udp, icmp, igmp, rip or all, where all matches packets regardless of their protocol. Another possibility is to give the protocol number used in the IP header, for example 9 for IGP. Using icmp or igmp, the rule may be restricted to a list of message types. rip is a special case of udp where all packets directed to port 520 are investigated. A RIP packet matches the rule if all announced destinations are listed. The following is an example for a RIP rule:

accept rip outside      /* matches all external addresses */
from 194.40.243.5       /* next router in the internet */
to 194.40.243.4;        /* own address */

A packet matches a rule if the source address is one of the addresses given after the from keyword and the destination address is one of the addresses given after the to keyword. If the from list or the to list is omitted, the packet matches regardless of the source and destination address respectively. Instead of the address list you may specify the inside keyword, which denotes all addresses provided in the internalnets statement (see above) or the outside keyword, which denotes all addresses not listed in the internalnets statement.

If the protocol of the rule is tcp or udp, you can also specify a port or a range of ports giving either the port number or the service name. The latter is translated to the number using the /etc/services file. Specifying a port with a protocol other than tcp or udp does not have an effect.

Here is an example for the from and to part of a rule:

from inside port telnet           /* all inside addresses with source port 23 */
to 129.132.0.0,                   /* all packets directed to this net */
port 2700,                        /* all packets directed to port 2700 */
130.103.24.0 mask 255.255.255.0
port 3000..4000;                  /* all packets to the specified subnet with
                                     3000 <= destination port <= 4000 */

At last you must specify the notification level, which tells the firewall what to do if the rule matches (apart from accept, block or reject the packet). A level of zero means that the firewall daemon is not informed about the event. If the level is greater than zero, the firewall daemon makes an entry in the firewall log file and performs all actions as specified in the notification section (see below).

The order of the rules in the file is very important. If two rules overlap, the priority of the first one is higher than of the second one. The consequence of this is that you should start with specific rules and put general rules at the end of the section. For example if you wanted to block all UDP packets except from the host 194.40.236.34, you would have to write two rules in the following order:

accept udp from 194.40.236.34 notification_level 0;
block  udp notification_level 1;

The Notification Section

The notification section starts with the notification keyword followed by a paragraph for each used notification level. Each paragraph starts with the keyword level followed by the level number and a colon. You can specify a list of actions in each paragraph. The following actions are possible:

message
defines additional text that is written to the log file and into mail messages. If the message covers multiple lines, you have to terminate the string with a double quote (") and restart it in the next line. Note that you must specify separate messages within if statements.
syslog
uses the syslog daemon to make a log entry in addition to the entry into the firewall log file.
report
copies log entry to the firewall.report log file in addition to the default log file.
mail
sends an E-mail to the specified address(es). If no address is specified, the mail is sent to the address given in the mail_default statement.
spy
starts counter intelligence, for example a back finger. You should use spy together with mail to receive the spy results as E-mail.
relevel
changes the notification level for the rule that caused the action. The next time a packet matches that rule, the actions specified in the "new" level are executed.
exec
executes an arbitrary shell command. For example it can be used to shut down an interface or the whole system, to trigger the pager of the system administrator, etc. This is a very powerful command, use it with care!
call
calls another notification level and executes it.
let
assigns or changes the value of a variable. A time-out value (in seconds) can be specified at the end of the let statement. If a variable is to be updated or accessed and the time since its last update or access is greater than the time-out value, the variable is reset to zero before updating or accessing it.
A filter rule
can be specified that is added to the filter configuration dynamically. In addition to the options described above there are some special features for dynamic rules. If you give the keyword currentprotocol instead of one of the protocol names, the protocol of the packet that triggered the action is used for the dynamic rule. Similarly you can use the keywords sourcehost, sourcenet, desthost, destnet after to and from to insert the appropriate information into the dynamic rule. Finally it is possible to specify a time-out value (in seconds) at the end of the rule. The rule will be deleted automatically after the specified time. Be aware that it can be dangerous to use dynamic rules, because you never know which rules are active at the moment. It is also difficult to determine how different dynamic rules can influence each other, because the priorities of the rules depend on the order in which the events occur.

You can use an if statement to specify a list of actions that are to be executed only if the given condition is true.

Variables are declared implicitly, the initial value is set to zero. They can hold only integer values. If you access or update variables, you can optionally specify one of the qualifiers sourcehost and desthost after the variable name, separated by a colon. A special instance of the variable is accessed or created using the source or destination address of the packet that triggered the action as identification. If a variable is updated using a qualifier, both the variable itself and the instance are updated. This feature can be used to count the number of occurrences of an event both in total and separately for each distinct source or destination address.

In the following example, the qualified variables and the time-out mechanism for variables and dynamic rules are used. If a host pings your net 100 times in sequence with a maximum time of 2 seconds between two pings, all packets from that host are blocked for 10 minutes. The notification level of the dynamic rule is set to zero to reduce the amount of data transferred from the filter to the firewall daemon.

accept icmp icmp_echo to inside notification_level 10;

notification

level 10:

  let pingcount:sourcehost := pingcount:sourcehost + 1 timeout 2;
  if pingcount:sourcehost > 100 then
    block all from sourcehost notification_level 0 timeout 600
  endif;

Writing Filter Rules

In this chapter we will discuss the topics that are specific to our packet filter. We strongly recommend to read the book "Firewalls and Internet Security" of Cheswick and Bellovin (Addison-Wesley, 1994) to get an idea about security problems with TCP/IP and how to configure a packet filter appropriately.

Block or Reject Packets?

It is often difficult to decide whether to block or to reject packets. If you block a packet, it is treated by the sender as if it got lost during transmission. So normally a protocol or application inherent time-out mechanism will cause the packet to be retransmitted several times. If you send an ICMP error message back, the sender will immediately be informed, that the packet cannot be delivered and will normally not retransmit it anymore.

You should never reject packets if the protocol or the sending application ignores ICMP error messages (like for example some DNS implementations), because this would cause a flood of error messages to be generated. TCP does not ignore the ICMP error messages, but keeps retransmitting the packet anyway, because the unreachable error may be due to a temporary failure of an intermediate router. To reject TCP packets, a reset packet should be generated (reject with tcp_reset and reject with best both do this).

Many programs do not distinguish between the different ICMP unreachable messages, so if you send back a port unreachable message, it may have the same effect as a host unreachable message. That way a host may become completely unreachable which is in most cases not the intended effect.

You should not try to reject any ICMP error messages, as this would not work anyway due to the kernel implementation.

If you use the reject with best option, TCP packets are bounced with a reset; an ICMP port unreachable message is generated for UDP packets and all other packets are rejected with ICMP host unreachable.

Filtering TCP Circuits

If you write rules for TCP, the from address specifies the originator of the connection. Return packets are automatically allowed for established connections. If the notification level is not zero, the logging information is passed to the firewall daemon only once at connection establishment time.

The FTP protocol requires a special treatment as the data connection is initiated by the server. However you don't have to allow the incoming data connection explicitly. Each control connection is filtered for PORT commands, which announce the establishment of a data connection to a specific port. For each PORT command found, the specified data connection is allowed automatically.

Inbound and Outbound Packets

The packet filter is called each time an IP packet is sent or received. A forwarded packet is examined only at receive time, at send time only the interface is checked (for address spoofing). Local packets (i.e. packets that are not going to leave the host) are examined only at send time.

Address Spoofing

An address spoofing alarm is set off in one of the following cases:

  1. The source address is "inside" and the receiving interface is "outside" (or vice versa). This means that some exterior host may be trying to gain access to an interior host.
  2. The destination address and the sending interface do not match. This means that the routing table is probably corrupt, because it is sending the packets via the wrong interface.
  3. The loopback address is used on any interface other than the loopback interface.

Note that class D (multicasting) and class E addresses are not checked against address spoofing.

Fragmented IP Packets

Only the first fragment of an IP packet is examined and the result of the examination is stored. All subsequent packets are silently discarded if the first fragment was not accepted. If the fragments do not arrive in order, all fragments that arrive before the first one are blocked.

Syntax of the Configuration File

configuration    = setup_section
                   rules_section
                   [ notification_section ]
                   "end.".
setup_section    = "setup"
                   [ internal_statement ]
                   mail_statement.
rules_section    = "rules" { (  block_statement
                              | accept_statement
                              | reject_statement ) }.
setup_statement  = "internalnets" address { "," address } ";".
mail_statement   = "mail_default" """ mailaddress(es) """ ";".
block_statement  = "block" rule ";".
accept_statement = "accept" rule ";".
reject_statement = "reject" [ "with" (  "icmp_net_unreachable"
                                      | "icmp_host_unreachable"
                                      | "icmp_protocol_unreachable"
                                      | "icmp_port_unreachable"
                                      | "tcp_reset"
                                      | "best"
                                      | "echo_reply" ) ]
                    rule ";".
rule = [ "options" ip_option { "," ip_option } ]
     (  "all"
      | protocol_number
      | "icmp" [ icmp_type { "," icmp_type } ]
      | "igmp" [ igmp_type { "," igmp_type } ]
      | "tcp"
      | "udp"
      | "rip" [ ( address { "," address } | inside | outside ) ] )
     [ "from" ( fulladdr { "," fulladdr }
               | "inside" [ "port" port [ ".." port ] ]
               | "outside" [ "port" port [ ".." port ] ] ) ]
     [ "to"   ( fulladdr { "," fulladdr }
               | "inside" [ "port" port [ ".." port ] ]
               | "outside" [ "port" port [ ".." port ] ] ) ]
     "notification_level" value.
ip_option = (  "record_route"
             | "timestamp"
             | "security"
             | "loose_source_route"
             | "strict_source_route"
             | "sat_id"
             | "time_to_live" ( "<" | "=" | ">" | "!=" ) value ).
icmp_type = (  "icmp_echo_reply"
             | "icmp_destination_unreachable"
             | "icmp_source_quench"
             | "icmp_redirect"
             | "icmp_echo_request"
             | "icmp_time_exceeded"
             | "icmp_parameter_problem"
             | "icmp_timestamp"
             | "icmp_timestamp_reply"
             | "icmp_info_request"
             | "icmp_info_reply"
             | "icmp_address"
             | "icmp_address_reply" ).
igmp_type = (  "igmp_host_membership_query"
             | "igmp_host_membership_report"
             | "igmp_host_leave_message" ).
fulladdr  = (  address [ "port" port [ ".." port ] ]
             | "port" port [ ".." port ] ).
address   = ( ip_address | """ name """ ) [ "mask" mask ].
port      = ( port_no | name ).
notification_section = "notification"
                "level" ( value | "spoof" | "oversized" ) ":" ( { entry ";" } | ";" )
              { "level" ( value | "spoof" | "oversized" ) ":" ( { entry ";" } | ";" ) }.
entry     = (  "message" """ text """ { """ text """ }
             | "syslog"
             | "report"
             | "mail" [ """ mailaddress(es) """ ]
             | "spy"
             | "exec" """ command """
             | "relevel" value
             | "call" value
             | "if" ( variable | value ) ( "<" | "=" | ">" | "!=" )
                    ( variable | value ) "then"
                { entry ";" } "endif"
             | "let" variable ":="
               ( value | "destport" | variable
                                      [ ( "+" | "-" ) ( value | variable ) ] )
                [ "timeout" seconds ]
             | dynamic_rule [ "timeout" seconds ]
            ).
variable  = name [ ":" qualifier ].
qualifier = ( "sourcehost" | "desthost" ).
[ special keywords allowed in dynamic_rule:
  "currentprotocol"  uses protocol of actual packet
  "sourcehost"       uses source host address
  "sourcenet"        uses source net address
  "desthost"         uses destination host address
  "destnet"          uses destination net address     ]

---

Examples, Please!

First, please carefully read the syntax description. In this section we'll describe a working (though not very useful) example making use of "notifications". For your convenience, this example is included with the distribution in source form (including some statements left out below for brevity).

In the following example, the text is printed in a monospaced font. Important keywords are printed in bold, and comments are italic.

# Sample configuration for the sf firewall

setup

internalnets 193.194.195.0;
mail_default "adm@x.y.z";

rules

# Some simple alarming rules to detect hackers

block tcp to port 87, /* link */
             port 95  /* supdup */
             notification_level 99;

block options loose_source_route, strict_source_route all
             notification_level 13;

# ...omit some more RIP statements

# detect secondary routes to the internet

block rip from inside notification_level 12;

# ...omit some more statements having notification level 0

# Permit incoming FTP requests to our FTP server only

accept tcp to 130.59.4.16 port 21 notification_level 1;

# Permit incoming Telnet requests to our Telnet/Login Server only

accept tcp to 130.59.4.16 port 23 notification_level 2;
accept all from 127.0.0.1 to 127.0.0.1 notification_level 0;

# block all other TCP connection requests and trigger the alarm

block tcp notification_level 99;

notification

level 1: /* log all permitted incoming FTP connection requests */
  message "FTP connection request.";

level 2: /* log all permitted incoming Telnet connection requests */
  message "Telnet connection request.";

level 3: /* log all permitted incoming WWW connection requests */
  message "WWW connection request.";

level 11:
  message "ICMP redirect received.";

level 12:
  message "There may be a secondary route to the internet.";

level 13:
  message "IP packet with source route option detected";
  let sr:sourcehost := sr:sourcehost + 1 timeout 300;
  if sr:sourcehost = 1 then
    message "IP packet with source route option detected";
    spy;
  endif;

level 99:
  message "Illegal TCP connection.";
  syslog;
  let illtcp:sourcehost := illtcp:sourcehost + 1 timeout 600;
  if illtcp:sourcehost = 1 then
    message "Illegal TCP connection.";
    mail;
    spy;
  endif;

end.

The above example shows the use of all possible statements in the "notification" section except relevel, exec and dynamic rules. While the use of exec is pretty straight forward (e.g. exec "ifconfig eth0 down" shuts down the network interface and could be used in a real emergency), relevel and dynamic rules are more complicated.

Releveling a rule is permanent--in contrast to temporary dynamic rules, which override static rules. In general, releveling is not a very good idea and should be substituted by temporary dynamic rules.

Suppose level 100 was the notification level triggered when the host is pinged. The log file would grow too fast if we logged every single ping.

The first idea is to relevel the rule:

...
notification

level 100:
  message "We have been pinged";
  relevel 0;
...

However, this is a bad idea. A single ping suffices to disable the "ping detection" for the whole future. To detect the first ping and be silent thereafter, we'd rather avoid relevel and use:

...
notification

level 100:
  let pings:sourcehost := pings:sourcehost + 1 timeout 600; /* 10 minutes */
  if pings:sourcehost = 1 then
    message "We have been pinged";
  endif;
...

If we are concerned of a denial-of-service attack, we might want to use a dynamic rule and block subsequent pings (after a certain threshold):

  if pings:sourcehost > 1000 then
    message "Possible denial-of-service attack";
    spy;
    block all from sourcehost notification_level 0 timeout 600;
  endif;

Of course, a real denial-of-service attack would probably make use of excessive ftp connects, not pings.

---

Starting and Controlling the Firewall

Once you have installed and configured the firewall, you might wonder how to get it up and running, how to stop it and how to display the current configuration.

This section describes the sfc program, which provides a command line interface to the firewall daemon and the kernel filter module.

Starting the Firewall

First, ensure that the kernel filter module sf.o has been inserted (the lsmod command will help you). If sf.o is not inserted, please consult the Installation Guide--and add the line insmod /the/path/to/sf.o to the startup file of your choice and reboot.

The sfc start command starts the firewall daemon. The default configuration resides in the file /etc/firewall.conf, but you can specify any other file as a third parameter to sfc, e.g. sfc start myconfig.

The start command first parses the configuration file. It then checks that the daemon is not running, opens the log files, forks a daemon process and gives up its root privileges.

Stopping the Firewall

To stop the daemon process, invoke sfc stop, which signals the firewall daemon to exit.

Warning: When the firewall daemon has exited, all network traffic will be blocked. You must remove the kernel filter module sf.o to restore network functionality (rmmod sf.o). Alternatively, you can start a new daemon process (sfc start).

Reason: Suppose there was a bug in the operating system and some evil hacker managed to send a SIGKILL signal to the firewall daemon. The daemon would exit and leave the system unprotected. For example, there was a bug in the Linux 1.2.11 kernel which would allow any user to kill any process. This is one more reason to never allow users on the firewall machine.

Reconfiguring the Firewall

In some cases, it might be desired to automatically switch between different firewall configurations. Imagine an organization where nobody works on Sundays (I've been told such organizations exist). Therefore, network traffic should be monitored much more strictly on Sundays than on normal work days.

If you want to switch configurations, you could tell cron to do a sfc stop; sfc start newconfig. However, there's a better way built into sfc: sfc reconfig newconfig (the newconfig parameter is optional and will be substituted by /etc/firewall.conf if you omit it).

The reconfig command ensures seamless switching of configurations, i.e. existing TCP connections are allowed to continue. To modify this behavior, there are two optional parameters:

flush: The "flush" parameter ends all existing TCP connections which are not allowed under the new configuration. Other TCP connections are allowed to continue.

flush_all: "flush_all" ends all TCP connections (essentially the same as the stop; start sequence).

Checking a Configuration File

To check a configuration file for syntactic errors, you can run sfc checkconfig myconfig (once again, myconfig is optional and will be substituted by /etc/firewall.conf if omitted).

In case of an error, the line number will be displayed. Please check the syntax description for more information.

Displaying the Current Configuration

sfc show shows all active rules and variables.

Active rules:
The active rules are fetched from the kernel filter module and displayed in the same order as checked by the filter:
  Active rules:
  -------------

  1 (line  27) dynamic, timeout Aug 03 15:15:03
    block, notification level 0
    from 193.194.195.196 mask 255.255.255.255

  2 (line  10) static
    block, notification level 7
    protocol RIP

In the first column, the sequential number of the rule will be displayed, in the same order as checked by the kernel. Next, the line number in the configuration file and the type of the rule are given. If the rule is a dynamic rule, the time-out is also shown.

The second line shows what the filter will do if the rule is triggered (block or accept a packet, etc.) and the corresponding notification level.

All following lines are optional. Where applicable, the protocol type and packet origin or destination will be displayed.

Variables:
The variables are read from the firewall daemon.
  Variables:
  ----------

  mails = 0

  pings = 5, timeout Aug 03 15:13:53
      host 193.194.195.196 = 3, timeout Aug 03 15:13:53

  alerts = 3

The output shows the name of the variable and its total value. If the variable is to forget its value (i.e. it is a dynamic variable), the time-out is also displayed.

If the variable is subdivided into different hosts, each host is listed with IP address, value and time-out (where applicable).

---

Counter Intelligence

Some words about the counter intelligence built into the sf firewall daemon:

Some people consider "spying" on other hosts unethical, even if a hosts might be the source of an attack. To pacify those people, the sf firewall will only fall back upon counter intelligence if told so by the spy keyword. Thus the decision is left to you.

The intention of "spying" on foreign hosts is to learn both the foreign host's name and the name of the user on the foreign host who is responsible for triggering a firewall notification.

Actions of the spy Process

Please refer to the implementation guide for a description of the precautions the "spy" process takes when using the protocols presented below.

To learn the host name, the DNS (domain name system) is queried. The result is then reverse translated into an IP address and compared with the original address. If the IP address doesn't match, a special warning is generated--someone might have tampered with the DNS.

The next step, to find out the user name, is much harder. There is no standard way of doing so, and in fact many hosts reject all attempts of the firewall daemon aimed at learning a user name. Worse yet, some hosts even return outright lies. Please keep this in mind when reading the "spy" output.

The first attempt is the ident protocol. This protocol can only be used if the action which triggered the firewall notification is a TCP connection to the firewall host (this is a restriction of the protocol). If everything works as intended, you'll get the user name. If not, you'll either see a "no such user" error message or "connection refused".

The second try is to finger the foreign host. If the host allows finger requests, a list of all users currently logged into the system will be returned. This list contains all sorts of more or less interesting information like login names, real names, online times, and the users' .plan files (control sequences are removed from the output). Some hosts only return a short message equivalent to "To send mail to someone at ..., address your mail using the following format: ...". Other hosts refuse finger requests altogether.

The last try is the rusers command. I have yet to see a host where rusers requests are served, but if it works you'll get a list of user names, the host the user logged in from and online and idle times.

Where the Output is Written to

If you don't do anything special, the output is appended to the firewall.spy file in the log file directory. If you put the mail keyword in the same notification section as the spy keyword, the results will also be E-mailed.

Example Output

The output might look similar to the following example (in real life, there will be more than two users logged in):

FIREWALL COUNTER INTELLIGENCE REPORT, Aug 09 12:20:02

Triggered by: (s 13) accept TCP 1.2.3.4:1065->193.194.195.196:telnet

  Host address: 1.2.3.4
  Host name:    oval.office.gov

identd information:
  User ID: unabom.

finger information:
  [1.2.3.4]
  Login: unabom                   Name: John F. Doe
  Directory: /home/unabom         Shell: /bin/csh
  On since Wed Aug  9 10:27 (EST) on tty1
  No Mail.
  No Plan.

  Login: bclinton                 Name: Bill Clinton
  Directory: /home/bclinton       Shell: /bin/bash
  On since Wed Aug  9  9:32 (EST) on tty2, idle 0:22
  New mail received Wed Aug  9 12:18 1995 (EST)
       Unread since Tue Aug  8 20:03 1995 (EST)
  Plan:
    We are using PGP to encrypt our E-mail here at the office.

rusers information:
  unabom     localhost:tty1   Aug  9 10:27
  bclinton   localhost:tty2   Aug  9  9:32    :22

---

The Log Output Explained

Depending on your configuration, the firewall daemon generates from little to huge amounts of log information (you'll receive an E-mail if the disk space gets low on the log device). This section is intended to help you understanding the output.

Where Output is Written to

All output is written to the firewall log file. If you specify the syslog keyword, an entry will be made in the system log file, too. The report keyword copies the entry to the firewall.report file (intended for a daily summary). And if you use the mail keyword, the log entry will be E-mailed (this might be useful in case a system gets broken in--no matter what the hacker tries, he will not be able to delete the E-mail which could have traveled half way around the globe already).

Abbreviations Explained

Because of the abbreviations, the log output looks a bit cryptic for the beginner. This is a trade-off; we are trying to provide as much information as possible on one line (the line will be wrapped automatically if needed).

[Image of a Log Entry]

The following is a listing of possible abbreviations (for details of the configuration, please refer to the complete description):

Rule Types:
s = static rule
d = dynamic rule
SPOOF = implicit spoof rule (includes interface name)
XSIZE = implicit oversized packets rule (includes interface name)

Filter Actions:
accept
block
reject
(includes reject type)

Protocols (excerpt):
RIP
TCP
UDP
ICMP

The Packet Source and Destination will include ports if the protocol supports them.

Other Log Entries

The other log entries should be self-explanatory.

---

Limits

This section deals with the limits of a our firewall system.

Present

Presently, most systems are completely unprotected. Many organizations don't even bother to replace buggy client software. For example, stone aged sendmails are still working on some neglected print servers in the basement, which are often retired work stations not powerful enough for modern software.

Any firewall software, be it buggy or unsafe itself, will therefore improve the situation. IP v6 will improve the situation, too. But even when IP v6 will really be used some years from now, you will most likely be unable to get the IP v6 implementation for some of your more antique machines.

Protection by the sf Firewall System

We'd really like to tell you that you don't have to worry no more. But that's untrue. The sf firewall system will prevent most attacks, but not all attacks. Similar to a locked door, the software puts obstacles into the way of the evil. But if the wicked man keeps trying, he might succeed in smashing the window or breaking open the door.

In doing so, he will most probably make tremendous noise, which our software will aid you detecting. Thus, your chances are increasing of being smarter and faster than he is.

Keep in mind the software is experimental and we are taking no guarantees.

Remaining Loopholes

A packet filter, even if beefed up like ours, cannot protect you against the hijacking of TCP sessions, modifying, intercepting and monitoring packet data somewhere along the route.

You will not be protected against password monitoring (even if you encrypt your passwords, the packets can be replayed). For this reason, you should install one time passwords.

The system provides no means to aid you in authentication. To really know who the "other side" is, you will need dedicated software, e.g. Kerberos.

And lastly, do read the documentation--if you misconfigure the software, there's no one to help you...


Copyright © 1996 Robert Muchsel and Roland Schmid.

Click here to mail your comments and suggestions.

Table of Contents