LDP/LDP/retired/IPTables.sgml

630 lines
27 KiB
Plaintext

<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook V3.1//EN">
<article>
<artheader>
<title>IPTables HOWTO</title>
<author>
<firstname>Matt</firstname>
<surname>Wright</surname>
<affiliation>
<orgname><ulink url="http://www.consultmatt.co.uk">Matt Wright Consulting</ulink></orgname>
<address>
<email>matt@consultmatt.co.uk</email>
</address>
</affiliation>
</author>
<pubdate>2001-11-21</pubdate>
<revhistory>
<revision>
<revnumber>v0.1</revnumber>
<date>2001-11-21</date>
<authorinitials>mww</authorinitials>
<revremark>
Initial writing began.
</revremark>
</revision>
</revhistory>
<abstract>
<para>
This document describes the main functions of the Netfilter Packet
filter (IPTables) included in the 2.4.x series kernels.
</para>
</abstract>
</artheader>
<sect1 id="intro">
<title>Introduction</title>
<para>
I felt the need to write this HOWTO because of, what I thought, is the poor
level of documentation on implementing Packet Filtering firewalls using the 2.4.x Netfilter packet filter. The HOWTO covers using native IPTables commands (ie. not using the ipchains.o) to implement a packet-filter based firewall and the various supported types of NAT.
</para>
<sect2 id="copyright">
<title>Copyright and License</title>
<para>
This document is Copyright 2001 by Matt Wright. Permission is granted
to copy, distribute and/or modify this document under the terms of
the GNU Free Documentation License, Version 1.1 or any later version
published by the Free Software Foundation; with no Invariant
Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A
copy of the license is available at
<ulink url="http://www.gnu.org/copyleft/fdl.html">http://www.gnu.org/copyleft/fdl.html</ulink>
</para>
<para>Send feedback to
<ulink url="mailto:matt@consultmatt.co.uk"><citetitle>matt@consultmatt.co.uk</citetitle></ulink>.
</para>
</sect2>
<sect2 id="author">
<title>About the author</title>
<para> My name is Matt Wright. I'm 16 year-old student in Blackburn,
Lancashire. I'm a freelance Linux consultant. I am the proud owner of
a Duron 950Mhz (all I could easily afford) with 256MB SDRAM, Voodoo 4
Video Card, ATI All-in-Wonder Pro Video Card. I also have a 266Mhz Cyrix
that runs my USB ADSL connection, of which if you are reading this from
<ulink url="http://www.consultmatt.co.uk">http://www.consultmatt.co.uk</ulink>
you will be using. </para>
<para>
You can find me at <ulink url="http://www.consultmatt.co.uk">www.consultmatt.co.uk</ulink>. Or at <ulink url="mailto:matt@consultmatt.co.uk">matt@consultmatt.co.uk</ulink>.
</para>
</sect2>
<sect2 id="greetz">
<title>Acknowledgements</title>
<para><emphasis>TODO: Insert greetz here</emphasis></para>
</sect2>
</sect1>
<sect1 id="whatis">
<title>What is IPTables</title>
<para>IPtables (known as Netfilter) was written by Paul Russell and the other
members of the <ulink url="http://netfilter.samba.org">Netfiler Project
Team</ulink>. It was meant as a replacement for IPChains that was implemented
in the 2.2.x series kernels. It offers true 1:1 NAT capabilities, Packet
filtering and connection tracking.</para>
<para>One major upshot of this is that due to the implementation of connection
tracking you can allow incoming connections by whether or not they relate to
an established connection. There is still some need for helper modules for
some connection types. (FTP and IRC at the moment)</para>
</sect1>
<sect1 id="req">
<title>Requirements</title>
<para>You only need a couple of things to get IPTables going, these include:</para>
<itemizedlist>
<listitem><para>A 2.4.x series kernel with the Netfilter modules compiled.
(I will deal with the Netfilter code as modules but feel free to compile
them in and ignore the module information.)</para></listitem>
<listitem><para>The IPTables source code, get it from <ulink
url="http://netfilter.samba.org">The Netfilter Project</ulink>
</para></listitem>
<listitem><para>This HOWTO <emphasis role="strong">does not</emphasis>
cover compiling and/or installing IPTables. Usually this is pre-installed
with a 2.4.x distro and if not then please consult the Netfilter website
for more information.</para></listitem>
<listitem><para>Basic knowledge about networking; ports, packets, etc.
</para></listitem>
</itemizedlist>
</sect1>
<sect1 id="commands">
<title>Essential IPTables commands</title>
<para>IPTables has a veritable feast of switches and parameters so this section
covers the most useful and most used of IPTables' switches.
They are listed below:</para>
<itemizedlist>
<listitem><para>-t &lt;table&gt;: This specifies the table to work on. If
-t is ommited then the "filter" table is specified.</para></listitem>
<listitem><para>-L &lt;chain&gt;: List all rules in the specified chain.
If the chain is not specified it lists all chains and rules in the
current table.</para></listitem>
<listitem><para>-F &lt;chain&gt;: Flushes the specified chain of all
rules. Again, if no chain is specified it flushes all rules in all chains
in the current table.</para></listitem>
<listitem><para>-X &lt;chain&gt;: This removes the specified user-defined
chain. If no chain is specified it deletes all user-defined chains in the
current table. (Note: You cannot delete a chain referenced to by another
rule.)</para></listitem>
<listitem><para>-N &lt;chain&gt;: This creates a new user-defined chain
for you to add rules to.</para></listitem>
<listitem><para>-A &lt;chain&gt &lt;rule&gt;: This appends a rule to the
end of the specified chain. Rules are explained later.</para></listitem>
<listitem><para>-D &lt;chain&gt; &lt;number&gt;: Deletes the rule at
position "number" in the specified chain.</para></listitem>
<listitem><para>-P &lt;chain&gt; &lt;policy&gt;: Changes the policy for
"chain" to "policy".</para></listitem>
</itemizedlist>
<para>That is the main commands outlined, the rest of the commands are
well documented in the man page IPTABLES(8). It also contains the flags
for useage in rules. I won't list them here because there are too many.
</para>
</sect1>
<sect1 id="tables">
<title>Tables, Chains and the like</title>
<para>There are two main definitons that need to be set out here. The first
is a table. Tables contain a set of chains, either built-in or user-defined.
The main two tables you will encounter are the "filter" table and the "nat"
table.</para>
<para>Chains are lists of rules that a packet traverses. When a packet enters
a chain the packet is checked against each criteria, if it is met then the
packet's fate is determined by the "target" flag. (Explained later in detail).
</para>
<sect2>
<title>The Filter Table</title>
<para>I am going to explain each table and chain before I show a diagram of the
overall system. This is so you can understand what each part does without
having to refer back to this section while looking at the diagram.</para>
<para>The first table we meet is the filter table. This is the table you
encounter if you type <command>iptables -L</command> (-L means list). If you
actually enter this command you will encounter a display similar to this:
</para>
<screen>
[root@enterprise matt]# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
</screen>
<sect3>
<title>The INPUT chain</title>
<para>We'll start with the INPUT chain first. When packets enter the system
they are checked for routing, if the packet is inbound to the local machine
(in this case to <emphasis>enterprise</emphasis>) then the packet is sent
down the INPUT chain.</para>
<para>In its current state the chain is wide open. This is due to the policy.
When the Tables are initalised each policy is set to ACCEPT, the policy defines
what happens when a packet meets none of the rules in the chain. To use an
analogy it is what happens if it drops off the end of the chain.</para>
<para>The case in question has the policy ACCEPT. This is in fact a target that
can be used in a rule, so as not to repeat myself targets are explain in a
later section.</para>
<para>The INPUT chain is the chain that you will most want to secure on your
machine. This is the rule to use to block (or open) ports on the local machine.
Anything accepted in the chain will make it to your network server daemons,
anything dropped will not.</para>
</sect3>
<sect3>
<title>The FORWARD chain</title>
<para>The FORWARD chain is also an important chain, especially if you plan on
masquerading or NAT'ing your conenctions. As with the INPUT chain the packets
appear here after routing but when the routing specifies that the packet is
bound for a machine on the network other than itself.</para>
<para>For instance, if you are using Masquerading and a incoming packet from
the internet enters the network interface the packet would be processed by the
routing information and enter the FORWARD chain as it is bound for another
machine. If the packet is accepted (or is accpeted by policy) then it proceeds
to the destination (and possibly into its INPUT chain if its running Linux), if
however it is dropped then it proceeds no further and it is dumped into the
nearest blackhole.</para>
</sect3>
<sect3>
<title>The OUTPUT chain</title>
<para>The OUTPUT chain is the final built-in chain in the filter table. It
governs the outgoing packets once they have been transmitted into the network
layer by the computer daemons. As with the other chains anything accepted will
be allowed passage out to the big-wide-world and dropped packets appear
alongside their rejected brothers (or sisters).</para>
</sect3>
</sect2>
<sect2>
<title>The NAT table</title>
<para>The NAT (Network Address Translation) table is not accessible by default.
Firstly, if you have the netfilter code compiled as modules then you may have
to do a <command>modprobe iptable_nat</command>. Secondly to access any of the
chains in the NAT table iptables must be invoked with the <command>-t
nat</command> option. Eg:</para>
<para><command>iptables -t nat -L</command></para>
<para>This table is the other super-handy table that we will use. All packets
traverse the chains in here before entering the filter table and before the
packets from the filter table leave the computer. I think a little more
explanation here is in order. The typical default NAT tables output is listed
below:</para>
<screen>
[root@enterprise matt]# iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
</screen>
<para>I shall concentrate on the PREROUTING and POSTROUTING chains in this
table (as I'm not yet sure on what the OUTPUT is for, please mail me if you
can help).</para>
<sect3>
<title>The PREROUTING chain</title>
<para>The PREROUTING chain....you remember where I said before that all the
packets are routed then enter the FORWARD/INPUT/OUTPUT chains?? Well the
PREROUTING chain is where the packets traverse <emphasis role="strong">BEFORE
</emphasis> they get routed. If for instance you wanted to make all packets
destined for port 80 on the local machine (10.0.0.1) actually appear on port
81 of 10.0.0.2 then you would insert the DNAT rule here.</para>
<para>This is also the best place to check for simple spoofing, things like
local, private IP addresses (10.0.0.x, 192.0.0.x, etc) appearing on the
internet side of your machine are obviously wrong and can be dropped quicker
than you can say "distributed denial-of-service attack".</para>
<para>Finally, this is the ONLY place that incoming NAT (Destination NAT, DNAT)
can be performed. This is so the packets can be mangled to force then down the
FORWARD chain instead of the INPUT where they would be lost.</para>
</sect3>
<sect3>
<title>The POSTROUTING chain</title>
<para>This chain is also very important (else why would I mention it!!) it
governs the handling of packets after they have been routed and are about to be
spat out of an network adapter.</para>
<para>The major use for this chain is to allow IP masquerading or Source NAT.
There is a slight difference. IP Masquerading is made specially for all us
people with Dynamic IP address. When the interface is taken down the IP Masq
tries to make sure all connections are closed, this is logical is it is
unlikely you will have the same IP when the adapter comes up again.</para>
<para>Source NAT is different, it leave ports open. This is made for Static IP
based conenctions, if for some reason your interface dies then when it goes
live again it will have to same IP. So, if there have been no timeouts and all
applications still _assume_ they are connected they carry on as usual.</para>
</sect3>
</sect2>
<sect2>
<title>The Diagram!!</title>
<screen>
________ _____ _________
Incoming / \ / \ / \ Outgoing
-->|PREROUTING|--->|FORWARD|-------|POSTROUTING|----->
\________/ \_____/ \_________/
| |
v ____
___ / \
/ \ |OUTPUT|
|INPUT| \____/
\___/ ^
| |
-------> Local Process -------->
</screen>
</sect2>
</sect1>
<sect1>
<title>Packet Filtering</title>
<para>This is where you find out how to firewall off you local machine. It will
involved some of the theory from above to I adive reading it before proceeding.
</para>
<sect2>
<title>Target (-j) ACCEPT,DROP,REJECT,etc</title>
<para>When I was talking above about accepting, dropping and the like I wasn't
just using a phrase. The -j flag in rules specifies what target the rule has,
in layman speak (I know I needed it) it's what happens when the packet matches
the rule concerned. If you had the following command:</para>
<para><command>iptables -A INPUT -p tcp --dport 80 -j ACCEPT</command></para>
<para>This would instruct any packet that has made it to that rule and that is
on port 80 to be accepted.</para>
<sect3>
<title>Target: ACCEPT</title>
<para>This is what is says, it allows a matching packet to continue unhindered.
Also, once a packet has been accpeted it no longer traverses the chain. So if
the above chain allows a packet it is universally allowed. A moral is in this
tale!! If you have any mission critical filters to be tested on all packets
before any are allowed then put them at the top of the chain</para>
</sect3>
<sect3>
<title>Target: DROP</title>
<para>This is the exact opposite of ACCEPT, if the packet matches a filter that
targets to a DROP then the packet is dumped into oblivion and is never seen
again. Please beware, DROP is a stealth DROP. If a packet is DROPed then NO
response is returned to say it failed, you program will just sit around till it
times out.</para>
</sect3>
<sect3>
<title>Target: REJECT</title>
<para>This is similar to DROP, firstly in the netfilter code it is created as
a seperate module (ipt_REJECT.o) and as such needs to be at the very least
compiled if not modprobe'd. Compared to DROP the only difference it a REJECTed
packet has a response sent to the originator saying that it failed. I tend to
use DROP as its stealthy but REJECT has its uses.</para>
</sect3>
</sect2>
<sect2>
<title>Default Policies</title>
<para>Policies, Policies!! This could be a major security hole on you machine.
The default policies come set to ACCEPT andif you've read the above stuff then
you will find that this means ANY packet can get in, out or through your
network.</para>
<para>The most secure action to take is to set all policies to DROP, this has
its problems. Firstly, you can't get in to you machine, soo if like me you
administer your box via SSH you've just cut yourself off. Secondly, no one can
get out either, so the machine itself is unable to get on the internet. Yes,
you can't get through either, if your DROPing all your packets you can't
forward them as well.</para>
<para>To change policies you would do the following:</para>
<para><command>iptables -P INPUT DROP</command></para>
<para>If you are making a ruleset for running at startup then you may want to
policiy all of these off. However, if you are experimenting I suggest caution
(or at least to use a local console).</para>
</sect2>
<sect2>
<title>Matching by Protocol (Ports, etc)</title>
<para>In IPTables, if you examine the man page, there is a switch called
<command>-p, --protocol [!] &lt;protocol&gt;</command> this allows you to
specify rule matches against the protocol. An extension that is provided by
suppliing a <command>-p</command> tag allows matching of ports.</para>
<para>The two flags <command>--source-port</command> and <command>
--destination-port</command> (these can aliased to <command>--sport</command>
and <command>--dport</command>) they are mainly used in to different ways.
</para>
<para>The <command>--source-port</command> can be used anywhere, however, this
matches packets based on the port of the orgininating machine. So if this is
matched on the INPUT chain a <command>--sport</command> would match the port
on the remote machine. In this sense it is more useful in the OUTPUT chains
as the source in this case is the local machine. <command>--sport</command>
would allow you to match say all outgoing port 80 transmissions to allow
you webserver to operate if you've change the OUTPUT policy.</para>
<para>The <command>--destination-port</command> can be used in the opposite
way, allowing you to match the port to which the packet is destined to go to.
So on the INPUT chain it matches the local port while on the OUTPUT chain
it matches the remote port. So then, to allow traffic into your machien via
the input filter you could match packets destined for port 80 on your
local machine and ACCEPT them.</para>
<para><emphasis role="strong">Syntax:</emphasis></para>
<itemizedlist>
<listitem><para>-p [!] &lt;protocol&gt;: Protocol is reqiured. Can be a
builtin (such as www, ftp, etc), port number or any service from
<filename>/etc/services</filename>. ! can be specified to negate the
parameter, or more easily put using ! will watch everything but the
protocol.</para></listitem>
<listitem><para>--sport [!] &lt;port/range&gt;: The port or range must be
specified. The port can be expressed as a number (eg. 80), a service name
(eg. www, ftp, etc) or a range in the form <command>start:end</command>
(eg. 80:110). Again th ! will negate the selection matching the opposite
of what was specified.</para></listitem>
<listitem><para>--dport [!] &lt;port/range&gt;: The port or range must be
specified. The port can be expressed as a number (eg. 80), a service name
(eg. www, ftp, etc) or a range in the form <command>start:end</command>
(eg. 80:110). Again th ! will negate the selection matching the opposite
of what was specified.</para></listitem>
</itemizedlist>
</sect2>
<sect2>
<title>Matching by Source IP and Destination IP</title>
<para>Another useful filter is to be able to filter the connections by their
Source IP, Destination IP, both or ranges. To put a practical side on it, this
enables us to test for easy spoofing checks, allow any machine on our internet
networks different access than that of an internet client.</para>
<para>This is achieved by two commands, the <command>-s</command> (for source
IP) and <command>-d</command> (for Destination IP). As with the port matching
the INPUT and OUTPUT have different definitions of destination and source.
In the INPUT chain the source refers to the remtoe machine and the destination
refers to the local machine. Of course, in the OUTPUT chain the source is the
local machine and the destination is the remote machine.</para>
<para><emphasis role="strong">Syntax:</emphasis></para>
<itemizedlist>
<listitem><para>-s [!] &lt;IP Address&gt;: IP Address is required, can be
expressed as a dotted decimal IP Address (eg. 10.0.0.1) or an IP Class
(or classless) range (eg. 10.0.0.0/16).</para></listitem>
<listitem><para>-d [!] &lt;IP Address&gt;: IP Address is required, can be
expressed as a dotted decimal IP Address (eg. 10.0.0.1) or an IP Class
(or classless) range (eg. 10.0.0.0/16).</para></listitem>
</itemizedlist>
</sect2>
<sect2>
<title>Adapter Matching</title>
<para>A very, very useful two switches here. The two switches in this section
allow you to make a rule match a particular adapter. Say you have an eth0
(local network) and a ppp0 (internet). You could force Masq request to come
only from your internal adapter.</para>
<para>The switches are:</para>
<itemizedlist>
<listitem><para>-i &lt;adapter&gt;: This switch matches the incoming adapter.
Use it in the INPUT, PREROUTING tables to match where the packet has come in
from.</para></listitem>
<listitem><para>-o &lt;adapter&gt;: This switch matches the outgoing adapter.
Use it in the OUTPUT and POSTROUTING tables to match the adapter the packet
will go out through.</para></listitem>
</itemizedlist>
</sect2>
<sect2>
<title>Connection Tracking and States</title>
<para>Final bit of info before I tell you how to set up a good firewall (at
least I think it's good). Connection tracking is a friend and a foe to your
nice secure firewall. It allows the Netfilter code to detect which packets
are for which machine and allows full 1:1 NAT. The states (I think) sort of
merge into the same area. They allow you to set rules to match by the TCP
connection state.</para>
<para>Put more usefully; State checking also you to drop packets that are not
part of an already established connection, or to drop new connections not
originating from your network (use it in Masq'ing).</para>
<para>There are four main states:</para>
<itemizedlist>
<listitem><para>INVALID, when the packet is not related to any connection.
</para></listitem>
<listitem><parA>NEW, a packet that is attempting to create a new connection.
</para></listitem>
<listitem><para>ESTABLISHED, a packet that is part of an already established
TCP conversation.</para></listitem>
<listitem><para>RELEATED, when a packet is starting a new connection but is
in some way related to an existing connection.</para></listitem>
</itemizedlist>
<para>These are extremely useful for only allowing NEW Masq connections out
from the internal network or to allow create connections in and out of the
INPUT chain. To use them you have to specify the <command>-m state --state
</command> switches. The <command>-m state</command> tells IPTables to use
the state checking module and then the <command>--state</command> allows
you to supply states.</para>
<para>I'll come back to using states when I explain the parts you need to your
firewall.</para>
</sect2>
</sect1>
<sect1>
<title>Now to try and design a firewall</title>
<para>This is where all that reading will hopefully come in useful. This won't
tell you the exact commands to type in but it should give you an idea on how
arrange you rulesets and how things tie together.</para>
<sect2>
<title>What do you need in a firewall?</title>
<para>Why do you want a firewall? With the rise in broadband connecitons with
more permanent IP address (not always static though) it is much easier to
conduct attacks on certain people as the IP's stay pointing to the same machine
for longer. Do you run a webserver? Do you want to stop any chance of easily
hacking you new Linux box?</para>
<para>In which case this is the right place to be. <emphasis role="strong">
Note:</emphasis> A firewall CANNOT stop all attacks, nor can it stop people
with valid passwords from gaining entry and trying to find weaknesses.</para>
</sect2>
<sect2>
<title>Note before you start</title>
<sect3>
<title>A note about rc.firewall</title>
<para>On most RedHat derived distributions there is the <filename>/etc/rc.d
</filename>. In here there is usually a <filename>rc.firewall</filename>. This
is executed at startup, so when you have got a good rule/ruleset add the
iptables commands to this and it will run whenever you reboot.</para>
</sect3>
<sect3>
<title>A note about IP Forwarding</title>
<para>The IP Forwarding code (known as Masquerading or NAT) is enabled by
setting the file at <filename>/proc/sys/net/ipv4/ip_forward</filename> to
contain a 1. Be warned: I have had trouble with getting Linux to enable this
value in the rc.firewall so you may have to add it to a SysV init script to
get it to work.</para>
</sect3>
</sect2>
<sect2>
<title>Sealing you machine</title>
<para>I work on the principle of making it airtight (ie. nothing allowed in and
nothing allowed out) and then open up the ports we need.</para>
<para>To seal the machine off the best way is to reset all the policies to
DROP. In that way nothing works (you need to be sat at the console to do this)
and nothign can get in. To seal off the policies use this command:</para>
<para><command>iptables -P INPUT DROP</command></para>
<para><command>iptables -t nat -P PREROUTING DROP</command></para>
<para>This shows one policy set on the filter table and one on the NAT table,
you would need to set each three chains on each table following that style to
secure the machine.</para>
</sect2>
<sect2>
<title>Opening ports for incoming connections</title>
<para>
Now that you have blocked all access into your computer we need to let some
people back in. This is done by specifically allowing ports to be opened. Out
of ease I usually leave the OUTPUT chain open so once you've opened ports
you should see soem immediate action when you try and open a connection, say
to test your web server. </para>
<para>The following commands are used to open a port, or in-fact close on if
you specify DROP.</para>
<para><command>iptables -A INPUT -p tcp --dport 80 -j ACCEPT</command></para>
<para><command>iptables -A INPUT -p udp --dport 53 -j DROP</command></para>
<para>In the above examples, the first one matches any TCP port 80 connections
(you _must_ specify a protocol if you want to use a port. Legal protocols are
tcp, udp, icmp.) The second command matches any UDP based DNS traffic (port 53)
and DROPs it.</para>
<para>All the type of matching commands can be combined with source and
destination IP checking or state checking or any other match criteria you
can have due to your module configuration.</para>
</sect2>
</sect1>
</article>