Fortunately, we can totally avoid these two thorny issues
by relying on stateful technology. Stateful technology
recognizes that TCP, UDP, and ICMP packet exchanges are part of
greater logical "connections." Then, we can filter packets
based upon the role they play (if any) in a connection. But
before we can fully understand how stateful firewalls work, we
first need to grasp some stateful terminology:
connection: the stateful netfilter code recognizes
coordinated packet exchanges between two hosts as a single
logical connection. These logical connections can consist of
traditional TCP connections, or more subtle UDP or ICMP packet
exchanges. On a netfilter-enabled Linux system, you can view a
list of all currently recognized connections by typing
"cat/proc/net/ip_conntrack."
Packets that comprise a logical connection are classified into
one of four states:
NEW: NEW packets are those that have been sent out with the
intention of establishing a connection with another host.
Packets are considered NEW as long as the remote host has not
yet replied.
ESTABLISHED: ESTABLISHED packets are part of an existing
connection. A packet is considered ESTABLISHED if it is
"replying" to previously-sent packets. For example, when a
remote host replies to NEW packets, those reply packets are
considered to be in the ESTABLISHED state. In addition, any
packets sent out to reply to ESTABLISHED packets will
themselves be considered ESTABLISHED.
RELATED: RELATED packets are like NEW packets in that they
have been sent out with the intention of establishing a new
connection. However, they are unlike NEW packets in that the
to-be-established connection is an extension of an
already-established data exchange. We can allow
multi-connection protocols like FTP to properly pierce our
firewall by allowing RELATED packets through.
INVALID: INVALID packets are those packets that don't fit into
any of the above categories. From a netfilter perspective, they
consist of packets that just don't "make sense." A default
policy of DENY will ensure that INVALID packets are
discarded.
Now, let's look at how to put this new stateful paradigm into
action. Rather than create two static rules to allow incoming
traffic with a source port of 80, we can use the following
rules to create a "universal" stateful firewall—one that
will handle virtually any type of connection-oriented protocol
in a safe and effective way. Our firewall rules below will
allow our network to connect to any service on the Internet,
while at the same time denying external access to any of our
services:
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j
ACCEPT
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j
ACCEPT
#trust all new connections from our internal LAN, whether for
us or just passing through
iptables -A INPUT -m state --state NEW -i ! eth1 -j
ACCEPT
iptables -A FORWARD -m state --state NEW -i ! eth1 -j
ACCEPT
Let's do a quick walkthrough of how these four stateful
firewall rules work. Our first two rules allow any incoming
packets (whether destined for our box or for another host) to
be accepted as long as they are part of or related to an
already-established connection. Now, what new connections do we
allow through our firewall? In the last two rules, we allow any
new connections to pass through our firewall as long as they
are not coming in from our eth1 interface, which is our
connection to the Internet. This means that any new connections
initiated by our firewall box or by machines on our LAN are
allowed out, and the response to these packets are allowed back
in since they are considered a reply, and thus ESTABLISHED and
accepted by our first two rules.
In one fell swoop, we've prevented Joe Random User on the
Internet from connecting to any services running on our
firewall box or our LAN, while at the same time allowing our
firewall and LAN machines to connect to the Internet as usual.
If you happen to have a bunch of workstations on your private
LAN and are not providing any services to the outside world,
this happens to be an ideal configuration.
Join me in
my next
article as we improve our firewall script and put these new
rules (as well as others) into action. See you then! :)