IPTables Tutorial Part 2
Hello and welcome.
This is part 2 of the IPTables tutorial. If you are new to iptables it
is highly recommended that you start with part I. Please see the link to
that video in the description. If you check the description of the
video, you will also see a link to the firewall script as it looked at
the end of part 1 and part two, for your convenience. Also, there were
some requests for transcripts, and I have provided links to transcipts
of part 1 and part 2 as well.
Last week we covered setting up default targets for the 3 main chains,
those being input, output, and forward of course, as well as poking
holes through the filewall to allow specific services in. This week we
are going to cover setting up custom chains, filtering by IP address and
protocol, and port redirection.
IPTables scripts really are little programs, and style is as important
in these scripts as it is when working in any other programming
language. The scripts should be logical and human readable. In this
spirit, the first thing we are going to do is improve the flow of our
firewall, even though it will not change its functionality at all. We
are going to create our own custom chain and direct all the services we
want to allow through it.
First, we are going to declare the new chain. This is done with the -N
switch, and we will insert this line towards the top of the script. We
can name the new chain SERVICES.
$IPT -N SERVICES
Now, we are going to separate the lines allowing services from the
others. We are going to changes the target chain of these rules from
INPUT to SERVICES. Finally, we need to decide where in the INPUT chain
we want to branch off to redirect the packet through the SERVICES
chain. We will insert this branch after the rule to accept packets from
loopback. The command to branch to the new chain is simply:
$IPT -A INPUT -j SERVICES
Whenever you jump to a custom chain, the packet will pass though the
rules in the custom chain, then continue down the original chain as
shown in this diagram. We do no need to put a special rule to jump back
to the built-in chain.
Now that our script is a little better organized, let's consider a
slightly different situation than we have previously. Let's say that
this computer is running a print server, and we want to allow local
network access to the print server but restrict it from the internet.
The local network is behind a router that is set to distribute addresses
to local machines between 192.168.1.1-192.168.1.254.
What we need to do is add a rule that will match a certain port only if
the source IP is one that would be given out by our network. Let's
append a new line to our SERVICES chain.
$IPT -A SERVICES -m iprange --src-range 192.168.1.1-192.168.1.254 -p
tcp --dport 631 -j ACCEPT
This line we will match packets based on their ip range, since we want
to allow packets arriving from machines with local ip addresses. The -p
tcp switch means that will we accept packets from the tcp protocol. And
finally the -dport switch means that we will match packets destined for
port 631, which is the standard port for a cups server. To also allow
udp access, we need to make a new rule, exactly the same except with udp
instead of tcp.
Now we have allowed local access to the printer, and disallowed
internet users.
Let's consider one more possibility for today. This scenerio is going
to delve into some principles that we won't be convering in depth until
part 3, but let's have a quick look. Let's say that we have a web
service on our machine that doesn't start as root, so it can't bind to
the standard port 80. However, we still want other to be able to reach
our service on the standard port so that people won't have to remember
an awkward url with a port override. Because we want to change packet
data and redirect it from one port to another, we can't use the filter
table. We are going to have to use the Netword Address Translation
table, or nat for short. Once these packets have been altered, they will
then pass though the forward chain, because they are considered to be
routed even if only the port has been changed. Finally we need to allow
the service on the SERVICES chain.
I know this is a lot to swallow at once, but bear with me because there
will be many details filled in next time.
First, we need to get rid of our rule about accepting traffic on port
80 because out webserver is no longer bound to port 80.
Next, we need to set the default targets for the three chains on the
nat table. They are OUTPUT, PREROUTING, and POSTROUTING. We do this with
the following lines:
$IPT -t nat -P OUTPUT ACCEPT
$IPT -t nat -P PREROUTING ACCEPT
$IPT -t nat -P POSTROUTING ACCEPT
Next, we are going to add the rule that actually redirects the packet.
Let's say our webserver is bound to port 8080. We will redirect it to
port 80 with the following line:
$IPT -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports
8080
This is simple enough. Now, since this packet will next be passing
through the FORWARD chain, we need to add a rule that these packets are
OK.
$IPT -A FORWARD -p tcp --dport 8080 -j ACCEPT
Finally, the packet will pass though the standard INPUT chain like any
other. So we need to add this line to our services chain:
$IPT -A SERVICES -p tcp --dport 8080 -j ACCEPT
Now, when we run our firewall, all traffic directed at port 80 will
arrive on our machine on port 8080. Tune in in two weeks for part 3 of
the IPTABLES tutorial.