The standard glued linux setup has a firewall but leaves it set wide open. This document describes how to set up and use a firewall on glued linux. It is hoped that some of the scripts will be adopted into the standard glued linux distribution so that set up becomes trivial.
The firewall configuration described to prevent unwanted access to your machine at an early stage. Although the pre-cursors of this have been used successfully in Physics for several years now, including in some atypical scenarios, the above philosophy has been the motivating factor. There is no facility in this firewall configuration to block outgoing traffic, and forwarding of packets is simply denied in all cases. These scenarios did not arise in Physics, and we have little experience with such. However, you should be able to customize for some or all of this if desired, but if so you are going beyond my experiences.
Even if you stay within the blocking unwanted access realm, this configuration is currently beta. Hopefully, it will become standard glue when beta testing is done. But you are also warned that a misconfigured firewall can cause a lot of confusing problems, and some may take a while to be uncovered. So show care when customizing.
The basis of the firewall setup is the iptables
firewall
currently used in linux. The assorted files to be added to glue attempt
to make the exact firewalling software modular, but only iptables
is currently supported.
Iptables
has the nice feature that is can operate in a
stateful mode. This means it remembers a bit about the history of the network
traffic. In particular, we make use of this to have the firewall allow
any network traffic from another machine that is in response to something
our machine sent out. This allows a few simple firewall rules to essentially
shut down all ports to incoming traffic, but still let the web connection I
made to www.somewebpage.com to go through, or to allow me to ssh or telnet
to various hosts. Basically, an user on glued linux box with this firewall
configuration can connect to anyplace he wants with whatever protocol he wants,
and the traffic will be allowed to flow both ways. (Note:
this is really only true if the protocol is either known to
iptables
or does not do wierd things in terms of switching ports.
But it seems to work reasonably well.)
The other side of the firewall is to allow connections for those services
we wish to offer. This configuration makes use of the fact that most services
in Glue are controlled by the hostinfo variables, so we punch holes based on
which services hostinfo says should be running. Generally, the holes are
open to the entire internet, but in some cases for services which are believed
to only be legitimately used locally, the hole might only be open to campus
or the subnet the machine is on. This can be overridden in
rc.machine
if necessary.
The is room for special customization in the rc.machine
file
as well, so the firewall configuration has shown to be fairly flexible in
our experiences.
In keeping with the general Glue philosophy, the firewall is controlled by hostinfo variables set in the hesiod configuration tree. There are three main variables controlling the firewall and its setup at this time:
iptables
firewall.
iptables
, although that behavior may change in
the future.
/etc/glue/config/config_iptables_minimal
gets
called to do the initial setup of the firewall before the
network is set up. If this variable is defined, and the
file it points to exists, that script will be called instead.
This should not normally be needed, and it is suggested even
if used the replacement script call config_iptables_minimal to set the chains up correctly.
/etc/glue/config/config_iptables
gets called
shortly after the network is set up and hesiod variables
read. If this variable is defined and points to an existing
file, it will be called instead. This should not normally be
needed.
Usually, one only needs define the hostinfo variable FIREWALL
to iptables
. If you do not want any firewall (e.g. a wide
open firewall, or you have a custom kernel without firewalling), define
FIREWALL
to NONE
. Other values are not defined,
and this just provides a mechanism to allow for a choice of firewalls if other
alternatives become available in the future.
The IPTABLES_MIN_CONFIG
and IPTABLES_CONFIG
are
specific to the iptables
firewall, and are just hooks in case
extreme customization is needed. They have not been needed in Physics, and
have been only minimally tested. Be aware of the fact that the file referred
to be IPTABLES_MIN_CONFIG
must be local to the system, as the
script that invokes it is generally called before networking is up.
NOTE: In a typical setup, the firewall is configured
before the network interfaces are brought up, so that the
firewall protects the system as soon as the interfaces are up. Because Glue
systems use hostinfo variables through hesiod to determine which services
will be running, we split the firewall configuration into two parts:
an initial minimal configuration which is generally quite restrictive
but will allow us to do what is necessary to be part of Glue (and in particular
to update the hostinfo variables via hesiod), and the full-fledged
configuration that is based on hostinfo variables. The initial, minimal
configuration of the firewall will generally occur before the
hostinfo variables are updated via hesiod, and so will typically be using
stale values. However, since this initial configuration is dependent only on
the FIREWALL
, and in rare cases IPTABLES_MIN_CONFIG
hostinfo variables, and it is expected that these should change very rarely,
this should normally not be a problem. Especially as a change in the actual
firewall being run often requires a kernel modification.
However, if you plan to change the FIREWALL
variable, you
should update the hostinfo variables on disk before the reboot (and after
your changes have propagated through hesiod). You can do this with the
command
/etc/glue/init.d/hostconfig start
at some point before rebooting and after the hostinfo changes have propagated
through hesiod.
Run /etc/glue/init.d/hostconfig start before rebooting after any changes to FIREWALL have propagated through hesiod.
This section describes how the firewall would get started as part of the standard Glue distribution. The files are not currently installed, but hopefully will be once beta testing is finished.
The first step is when S08firewall
is called in the
rc.d
initialization directory for run levels 2, 3, and 5.
This is just before the network
interfaces are brought up, so that any firewall protection is active from
the very beginning. (This would replace the standard S08ipchains
or S08iptables
init.d script.) This script checks the copy
of hostinfo on the disk (which is stale, most likely from the previous boot,
because without a network interface we cannot get the current one). It will
then start up whatever firewall is requested (or none if none requested).
Currently only iptables (and no firewall) are supported.
In the case of NO
firewall, the firewall script in init.d
just exits. This should leave the firewall in the kernel in a wide
open position.
In the case the variable FIREWALL
is iptables
,
the command /etc/init.d/iptables start
is run, and then either
the script pointed to by IPTABLES_MIN_CONFIG
(if it is defined
and exists) or /etc/glue/config/config_iptables_minimal
is called.
In the former case, it is recommended that config_iptables_minimal
be called from the user defined script, or that it otherwise makes sure that
the standard chains are created.
config_iptables_minimal
first deletes anything in the
iptables rules, and then builds the basic structure of the r
ulesets. This includes setting the policies on the default chains,
creating the Glue standard chains existing-connections
,
glue-required
, glue-optional
, and
machine-optional
. These are then linked into the standard
INPUT
chain, and the chains existing-connections
and glue-required
are populated. The other two are left empty,
as their contents depends on hostinfo variables, and we want to wait until
fresh values are available.
The next step in the process is to fill in the glue-optional
chain. This step is delayed until after the hostinfo variables are refreshed
from the hesiod database, but preferably should occur before any
network services
are started (not absolutely required, but any services started before this
are not really up because not visible from other machines on the network).
Typically this would be done in S40setup
(NOTE: current glue
rc5.d has the setup script at 57, after the inetsvc script at 50. Probably
need to push back hostconfig and setup to before 50?).
The S480setup
init.d script should check the hostinfo variable
IPTABLES_CONFIG
, and if defined and pointing to a valid script,
execute that script. Otherwise, it should execute
/etc/glue/config/config_iptables
. This script should open up
all the the ports needed to access servers started up in the standard Glue
init.d sequence, i. e. those servers started up based on hostinfo variables.
The final step is /etc/rc.machine
. This script can do any
additional customization of the firewall needed (and indeed, all customizations
needed by physics in past couple of years were able to be done here, without
needing custom IPTABLES_MIN_CONFIG
or IPTABLES_CONFIG
scripts). If necessary, you can delete firewall rules defined earlier from
here. But more commonly, you will add holes for any additional services
started. Since these services are typically started in this file, it is
quite natural. E. g., if your linux box is to be a foo server, just before
the line in /etc/rc.machine
that starts up the foo daemon, just
punch holes for the ports that it will be accessed by in the firewall.
At this point in time, the firewalling stuff is not part of the standard Glue linux distribution. It is currently undergoing beta testing (and hopefully will be part of the standard distribution after successful beta testing). If you wish to beta test, or otherwise want to use it before it is part of the standard package, here's where we tell you how.
The first step is to set the FIREWALL
hostinfo variable,
and wait until it propagates through hesiod and your local hostinfo scripts
are current. (Or if you are impatient, just hand edit it into
/etc/glue/hostinfo/hostinfo.sh
, only the Bourne shell version
is used for firewalling currently).
Next, you need to run the following two scripts, in order:
/dept/phys/software/linux/OIT-linux/firewall/glue-config/config_iptables_minimal
/dept/phys/software/linux/OIT-linux/firewall/glue-config/config_iptables
/etc/rc.machine
for my machine, though
it is safest to run them manually first, and hold off on entering into
rc.machine
until satisfied nothing is broken (this way a reboot
will set things straight).
If you need to turn firewalling off (i.e., make the firewall wide open),
the commands iptables -P INPUT ACCEPT
followed
by iptables -F
should do it.
Note that if the machine is running any services that are not part of the standard Glue set (i. e. are not controlled by hostinfo variables and started in standard init.d files), they are almost certainly not going to work after the firewall is turned on. You will need to punch holes for these explicitly. See the section on customization.
Hopefully standard Glue services (controlled by hostinfo variables and started in standard init.d files) will continue to work.
The firewall should allow for your machine to access almost any service as a client; as long as your machine initiates the conversation with the remote host, and nothing too funky is going on with changing the ports it should just work.
Starting the firewall this way means that the network interface is up for a little while before the firewall is tightened down. That is why becoming part of the standard init.d process is desired. But late is better than never.
This section discusses the innards of the firewall ruleset. You probably want to at least skim it before making any customizations.
Built into iptables are three standard chains:
INPUT
chain. The OUTPUT
chain is left wide open, so nothing is blocking traffic leaving this machine.
The FORWARD
chain is left tightly closed because unless we really
know what we are doing we probably should not be routing.
We create four Glue-defined chains, and have the INPUT
chain
call them one by one. If a rule in any of these chains accepts a packet, it
is allowed in, otherwise go to the next rule, then the next chain, etc. When
we run out of rules and chains, the packet gets dropped.
The configuration takes the policy to simply drop unaccepted packets, that is act like it never happened. This is the most secure option, because a potential hacker would have no idea from that whether or not there is even a machine there. This likely can also be quite confusing to a legitimate sysadmin who tries something and gets no response back. I tried using somewhat more sysadmin friendly actions instead of simply dropping the packet (like returning some sort of ICMP host unreachable packet), but I am not entirely sure what response makes the most sense, and some of these odd ICMP responses confuse scanning software generating as much if not more sysadmin confusion. If you really want to get a different response, just add a rule to the end of INPUT that rejects the packet in the desired manner.
The four Glue-defined chains are, in order of calling:
existing-connections
glue-required
glue-optional
machine-optional
existing-connections
is the chain that is responsible for
accepting the remote half of any conversations you initiated. It accepts
any packet received on the loopback interface (very nasty things happen if
you prevent the system from talking to itself), and also makes use of the
statefulness of iptables to accept ESTABLISHED
or
RELATED
packets on all interfaces. ESTABLISHED
connections are those that have seen packets in both directions. This means
if your machine starts a conversation with machine B (e. g. makes a http
request), and machine B replies (e. g. sends a web page back), it is allowed.
RELATED
is for some protocols like ftp wherein the server starts
a new connection back to the client. Iptables knows about the more common of
those sort of oddities, and can handle it. Stateful firewalls are
nice. This chain is set up in config_iptables_minimal
glue-required
is the chain that makes sure there are enough
holes in the firewall for your box to function as a Glue machine. The
absolute minimum needed for functioning; the sort of thing that if you block
this, what's the point of being in Glue. It opens up the ports needed for:
config_iptables_minimal
.
glue-optional
is the chain that pokes holes in the firewall
for any standard Glue services that might be running on the box. By standard
Glue service, I mean a service which is started/controlled according to
hostinfo variables, and is started in standard Glue init.d scripts. Because
the presence of the service on a particular machine depends on hostinfo
variables, we use the same variables to poke holes for the service. This
chain is created as empty in config_iptables_minimal
, and
filled in config_iptables
. The delay in filling is that it
depends on a lot of hostinfo variables, and we want to make sure we are using
fresh values. As the name implies, the stuff in here is optional, in that
someone, somewhere might want a system without any one item. Also included
in here are a few other optional holes not associated with a service, like
whether or not the machine should respond to pings.
machine-optional
is created as empty in
config_iptables_minimal
, and nothing is put into it in general.
It exists for per machine customizations of the firewall, typically from
rc.machine
script. E. g., if your machine should be running
a foo server on port 666, just before you start the foo server in
rc.machine
you should poke a hole in the firewall for it.
This is discussed in more detail in the next section.
Naturally, for certain machines the standard configuration will not suffice. The initialization scripts provide plenty of places for customization to occur:
config_iptables_minimal
script. This is done by defining the hostinfo variable
IPTABLES_MIN_CONFIG
to point to a replacement script. Remember, it may take a second
reboot to take effect because the hostinfo variables used at that
point of the boot process are stale. Also, the named script must
be on a local filesystem because networking is not yet up. It is
advised that your script call the standard
config_iptables_minimal
script and then modify the
rules as needed.
config_iptables
script. This
is done if the hostinfo variable IPTABLES_CONFIG
is
defined and points to a script. You may wish to call the standard
version within your version in this case as well.
machine-optional
in
your rc.machine
script. This is the preferred way, and
is actually fairly nice because most services for which additional
firewall rules would be needed would started up there anyhow.
Method 3 is the preferred way, and despite having some rather non-standard
configurations, all customization for Physics in the past couple of years
has been done in /etc/rc.machine
.
The difficult step in customizing is to figure out what ports need to have
holes punched in the firewall. If you know the protocol, that is usually
fairly straight forward. In other cases, you may need run a packet sniffer
while the protocol is going on to see where things are being blocked. If
you run into difficulties in determining whether the firewall is blocking
things or the daemon is just not working, you can issue the command
/sbin/iptables -F
which will clear all the firewall rules (leaving
you completely exposed, but that can be useful for testing a new service).
The firewall rules can be re-enabled by rebooting or running the configuration
scripts /etc/glue/config/config_iptables_minimal
and
/etc/glue/config/config_iptables
. (NOTE: these
expect to be run in a Bourne shell, so you may need to run as sh
script.
When adding rules in your /etc/rc.machine
script, you may
find it helpful to source /etc/glue/config/iptable_utilities.sh
.
These have some helpful routines for enabling a service to the world,
just to campus, just to your subnet, or just to a few specified hosts. These
are described in more detail in an
appendix.