Step by Step Linux Guide
Step by Step Linux Guide
Step Linux
Guide
by
M. B. G. Suranga De Silva
Step by Step Linux Guide, describes the system administration aspects of using Linux.
It is intended for people who know nothing about system administration. This book
Step by StepTM Linux Guide. Page 1
doesn’t tell you how to install Linux since it is very straight forward but it gives you
real world mail, DNS, proxy, web, messaging etc… server installations and
configurations.
System administration is all the things that one has to do to keep a computer system in a
useable shape. It
Includes things like backing up files and restoring , installing new programs, creating
accounts for users, making certain that the filesystem is not corrupted, and so on.
There is no one official Linux distribution, so different people have different setups,
and many people
have a setup they have built up themselves. This book is not targeted at any one
distribution, even though
I use Red Hat Linux 8 and 9 the contents can be applied to any distribution.
Many people have helped me with this book, directly or indirectly. I would like to
especially thank my own brother Dilan Kalpa De Silva, Luckshika Jayadeva for her
excellent type-setting, my ever loving mother, two sisters and my aunt Mallika
Vitharana.
2. Stable
4. Administrators can build their own systems, from that they can take
the full control over the system. When company relies on the system,
administrators will feel more job security.
6. High Security
4. Type cd /path/to/jabber/
7. Type cd jabber-1.4.2/
8. Type ./configure
9 Type make
12. Type ./jabberd/jabberd to start the Jabber daemon. This will run
the server using the default hostname of localhost. You should see
13. Open a separate console window on the same machine and type
telnet localhost 5222 to connect to your server (yes, you can
connect using simple old telnet!). You should see the following:
Trying 127.0.0.1...
Connected to your-machine-name.
Escape character is '^]'.
14. Now open an XML stream to your server by pasting the full text of
the following XML snippet into your telnet window:
<stream:stream
to='localhost'
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'>
15. Close the stream properly by pasting the following XML snippet
into your telnet window: </stream:stream>
16. Stop the server by killing the process or simply typing ^C in the
window where you started the server deamon.
<host><jabberd:cmdline flag="h">localhost</jabberd:cmdline></host>
Ex.
<host><jabberd:cmdline flag="h">192.168.200.8</jabberd:cmdline></host>
or
<host><jabberd:cmdline flag="h">im.jic.com</jabberd:cmdline></host>
Note:
Make sure to create a folder and name it as the name you put in the
above line that is 192.168.200.8 or im.jic.com in
/path/to/jabber/jabber-1.4.2/spool/
Ex:
or
Ex:
<ip port=”5222”>192.168.200.8</ip>
<ip port=”5269”>192.168.200.8</ip>
or
Click “yes” and proceed. You need to add another user like this and add
contact between the other user and start messaging. Following
screenshots show how to add a new contact.
3. Add the following lines to the sendmail.mc file using the text editor.
FEATURE(always_add_domain)dnl
FEATURE(`masquerade_entire_domain’)
FEATURE(`masquerade_envelope’)
FEATURE(`allmasquerade’)
MASQUERADE_AS(`slts.lk.’)
MASQUERADE_DOMAIN(`slts.lk.’)
MASQUERADE_AS(slts.lk)
Note:
Replace slts.lk by the domain name of your organization
DAEMON_OPTIONS(`port=smtp, ……..)
localhost.localdomain RELAY
localhost RELAY
192.168.1 RELAY
slts.lk RELAY
Note:
Add the network id of your domain and domain name instead of the
values given here.
slts.lk
eng.slts.lk
Note:
Add the names of your domains or sub-domains
Note:
These are aliases for the local server. Replace the entries with your
own domain info.
NETWORKING = YES
HOSTNAME = mail.slts.lk
Note:
Replace with your own domain info.
HOSTNAME = mail.slts.lk
telnet localhost 25
gunzip qpopper4.0.5.tar.gz
then type:
./configure
Then type:
make
mkdir /usr/local/man/
mkdir /usr/local/man/man8
make install
6. Open the file “/etc/xinetd.conf” and add the following lines to the
file and save:
(A similar configuration is available in the following file:
/qpopper/qpopper4.0.5/samples/qpopper.xinetd
You can copy it to the destination and do the necessary changes)
service pop3s
{
flags = REUSE NAMEINARGS
socket_type = stream
wait = no
user = root
server = /usr/local/sbin/popper
server_args = popper –f /etc/qpopper110.cfg –s
instances = 50
disable = no
per_source = 10
}
1. Start the IMAP server and httpd in Red Hat services and put
squirrelmail-1.4.2.tar.gz to /var/www/html/ directory
2. Unpack SquirrelMail in
cd /var/www/html/squirrelmail-1.4.2/config/
4. make a new file called “config.php” in that directory and copy the
contents of “config_default.php” to “config.php”
(“config_default.php” is in the same directory that is
/var/www/html/squirrelmail-1.4.2/config/ )
12. choose option 8 and add the compatibility plugin.save and exit
19. choose option 8 and add the change_passwd plugin.save and exit.
3. # cd samba-***
4. # ./configure
5. # make
6. # make install
Note :
The users you need to add into samaba should be already created in Linux.
Start Samba
# /usr/local/samba/sbin/smbd -D
# /usr/local/samba/sbin/nmbd -D
If you want to have start samba on bootup, put the above lines into the
etc/rc.d/rc.local file.
Stop Samba
# killall -9 smbd
# killall -9 nmbd
DHCP Server
These are the steps of setting up DHCP server in eth0 interface
ddns-update-style interim;
ignore client-update;
default-lease-time 600;
max-lease-time 7200;
option subnet-mask 255.255.255.0;
option brodcat-address 192.168.1.255;
option roters 192.168.1.1;
option domain-name-servers 203.115.0.1
subnet 192.168.1.0 netmask 255.255.255.0 {
range 192.168.1.100 192.168.1.200
}
Step by StepTM Linux Guide. Page 18
Make sure to give the interface that the DHCP drags in
/etc/sysconfig/dhcpd as follows
#command line option here
DHCPDRAGS = eth0
Say Yes to over write the file and restart the dhcpd.
service dhcpd restart
PHP/MySQL
<?
phpinfo();
?>
If you have PHP installed you will see a huge page with all the details of
your PHP installation on it. Next, scroll down through all this information.
If you find a section about MySQL then you will know that MySQL is
installed. These are pre installed in RH8 and RH9.
Now type again mysql –u root –p and come to the mysql prompt
Then you should be able to see the database you have just created
“database1”
<?
$user="root";
$password="suranga";
$database="database";
mysql_connect(localhost,$user,$password);
@mysql_select_db($database) or die( "Unable to select database");
$query="CREATE TABLE contacts (id int(6) NOT NULL
auto_increment,first varchar(15) NOT NULL,last varchar(15) NOT
NULL,phone varchar(20) NOT NULL,mobile varchar(20) NOT
NULL,fax varchar(20) NOT NULL,email varchar(30) NOT NULL,web
varchar(30) NOT NULL,PRIMARY KEY (id),UNIQUE id (id),KEY
id_2 (id))";
mysql_query($query);
mysql_close();
?>
Step by StepTM Linux Guide. Page 20
save this in /var/www/html/ and type http://localhost/createtable.php
in your browser
again come to mysql prompt and type use database1; and show tables;
then you should see the newly created contacts table
<?
$user="root";
$password="suranga";
$database="database";
mysql_connect(localhost,$user,$password);
@mysql_select_db($database) or die( "Unable to select database");
$query = "INSERT INTO contacts VALUES ('','John','Smith','01234
567890','00112 334455','01234
567891','johnsmith@gowansnet.com','http://www.gowansnet.com')";
mysql_query($query);
mysql_close();
?>
<html>
<head>
<title></title>
<style>
</style>
</head>
<body bgcolor=#ffcc00>
<div class=text2>
<form action="add.php" method="post">
<p>First Name:<br />
<input class=text type="text" name="first_name" size=40 /><br />
Age:<br />
<input class=text type="text" name="age" size=4 /><br /><br />
<html>
<head>
<title></title>
<style>
</style>
</head>
<body class=text bgcolor=#ffcc00>
<?php
if (! @mysql_select_db('kalpadb') ) {
die( '<p>Unable to locate the joke ' . 'database at this time.</p>' );
}
if (isset($_POST['submitjoke'])) {
$fname = $_POST['first_name'];
$age = $_POST['age'];
$sql = "INSERT INTO kalpa SET fname='$fname',age='$age' ";
if (@mysql_query($sql)) {
echo('<p>Successfully added.</p>');
echo('<a href=add.html>Back</a>');
} else {
echo('<p>Error adding to the database: ' .
mysql_error() . '</p>');
}
?>
</body>
</html>
This is show.php where you can see the contents of the table via your
browser. Save this also in /var/www/html/
Step by StepTM Linux Guide. Page 23
<html>
<head>
<title></title>
<META HTTP-EQUIV="Expires" CONTENT="0">
<meta http-equiv="pragma" content="no-cache">
<style>
</style>
</head>
<body>
<?php
if (! @mysql_select_db('kalpadb') ) {
die( '<p>Unable to locate the ' . 'database at this time.</p>' );
}
echo('<tr>');
Step by StepTM Linux Guide. Page 24
echo('<td>' . $row['fname'] . '</td>');
echo('<td>' . $row['age'] . '</td>');
echo('</tr>');
}
echo('</table>');
?>
</body>
</html>
Java SDK
Change to the directory where you downloaded the SDK and make the
self-extracting binary executable (/usr/local/java)
chmod +x j2sdk-1_4_1_06-linux-i586.bin
./j2sdk-1_4_1_06-linux-i586.bin
JAVA_HOME="/usr/local/java/j2sdk1.4.2"
export JAVA_HOME
CATALINA_HOME=”/usr/local/tomcat/jakarta-tomcat-4.1.29”
export CATALINA_HOME
groupadd tomcat
useradd -g tomcat tomcat
Tomcat Standalone
Unzip Tomcat by issuing the following command from your download
directory:
ln -s jakarta-tomcat-4.1.29 jakarta-tomcat
You should now be able to start and stop Tomcat from the
CATALINA_HOME/bin directory by typing ./startup.sh and
./shutdown.sh respectively. Test that Tomcat is working by starting it
and typing http://localhost:8080 into your browser. You should see the
Tomcat welcome page with links to documentation and sample code.
Verify Tomcat is working by clicking on some of the examples links.
/var/log/process-name.log {
rotate 12
monthly
errors root@localhost
missingok
postrotate
/usr/bin/killall -HUP process-name 2> /dev/null || true
endscript
}
The configuration file lists the log file to be rotated, the process kill
command to momentarily shut down and restart the process, and some
configuration parameters listed in the logrotate man page.
Ex.
• Search and list all files from current directory and down for the string
ABC:
find ./ -name "*" -exec grep -H ABC {} \;
find ./ -type f -print | xargs grep -H "ABC" /dev/null
egrep -r ABC *
• Find all files created or updated in the last five minutes: (Great for
finding effects of make install)
find / -cmin -5
• Find all users in group 20 and change them to group 102: (execute as root)
find / -group 20 -exec chown :102 {} \;
Note:
Suid executable binaries are programs which switch to root
privaleges to perform their tasks. These are created by applying a
"stickey" bit: chmod +s. These programs should be watched as they
are often the first point of entry for hackers. Thus it is prudent to
run this command and remove the "stickey" bits from executables
Step by StepTM Linux Guide. Page 33
which either won't be used or are not required by users. chmod -s
filename
Directive Description
-name Find files whose name matches given pattern
-print Display path of matching files
-user Searches for files belonging to a specific user
-exec
Execute Unix/Linux command for each matching
command {}
file.
\;
-atime (+t,- Find files accessed more that +t days ago, less than
t,t) -t or precisely t days ago.
-ctime (+t,-
Find files changed ...
t,t)
-perm Find files set with specified permissions.
-type Locate files of a specified type:
c: character device files
b: blocked device
d: directories
Also see:
Finding/Locating files:
Find location/list of files which contain a given
locate/slocate
partial name
Find executable file location of command given.
which
Command must be in path.
Find executable file location of command given
whereis
and related files
Display name of RPM package from which the file
rpm -qf file
was installed.
File Information/Status/Ownership/Security:
ls List directory contents. List file information
chmod Change file access permissions
chmod ugo+rwx file-name :Change file security so that the
user, group and all others have read, write and execute
privileges.
chmod go-wx file-name :Remove file access so that the group
and all others have write and execute privileges
revoked/removed.
chown Change file owner and group
chown root.root file-name :Make file owned by root. Group
Step by StepTM Linux Guide. Page 35
assignment is also root.
fuser Identify processes using files or sockets
If you ever get the message: error: cannot get exclusive lock
then you may need to kill a process that has the file
locked. Either terminate the process through the
application interface or using the fuser command: fuser -k
file-name
file Identify file type.
file file-name
Uses /usr/share/magic, /usr/share/magic.mime for
file signatures
to identify file type. The file extention is NOT used.
• Automatically: (preferred)
This will backup the files, directories and all it's subdirectories and files
of the directories /home and /opt to the first SCSI tape device. (/dev/st0)
Step by StepTM Linux Guide. Page 37
Restoring files from backup:
#!/bin/bash
tar -cz -f /mnt/BackupServer/user-id/backup-weekly-`date +%F`.tar.gz -
C /home/user-id dir-to-back-up
Be sure to allow execute permission on the script: chmod ugo+x
/etc/cron.weekly/backup-weekly.sh
Notes:
• Backup using compression to put more on SCSI tape device: tar -z -
cvf /dev/st0 /home /opt
IPTABLES
When a packet first enters the firewall, it hits the hardware and then gets
passed on to the proper device driver in the kernel. Then the packet starts
to go through a series of steps in the kernel, before it is either sent to the
correct application (locally), or forwarded to another host - or whatever
happens to it.
First, let us have a look at a packet that is destined for our own local
host. It would pass through the following steps before actually being
delivered to our application that receives it:
8 Local process/application
(i.e., server/client program)
Note that this time the packet was passed through the INPUT chain
instead of the FORWARD chain. Quite logical. Most probably the only
thing that's really logical about the traversing of tables and chains in your
eyes in the beginning, but if you continue to think about it, you'll find it
will get clearer in time.
In this example, we're assuming that the packet is destined for another
host on another network. The packet goes through the different steps in
the following fashion:
As you can see, there are quite a lot of steps to pass through. The packet
can be stopped at any of the iptables chains, or anywhere else if it is
malformed; however, we are mainly interested in the iptables aspect of
this lot. Do note that there are no specific chains or tables for different
interfaces or anything like that. FORWARD is always passed by all
packets that are forwarded over this firewall/router.
We have now seen how the different chains are traversed in three
separate scenarios. If we were to figure out a good map of all this, it
would look something like this:
If you feel that you want more information, you could use the
rc.test-iptables.txt script. This test script should give you the
necessary rules to test how the tables and chains are traversed.
You are strongly advised not to use this table for any filtering;
nor will any DNAT, SNAT or Masquerading work in this
table.
• TOS
• TTL
• MARK
The TTL target is used to change the TTL (Time To Live) field of the
packet. We could tell packets to only have a specific TTL and so on. One
good reason for this could be that we don't want to give ourself away to
nosy Internet Service Providers. Some Internet Service Providers do not
like users running multiple computers on one single connection, and
there are some Internet Service Providers known to look for a single host
generating different TTL values, and take this as one of many signs of
multiple computers connected to a single connection.
The MARK target is used to set special mark values to the packet. These
marks could then be recognized by the iproute2 programs to do different
routing on the packet depending on what mark they have, or if they don't
have any. We could also do bandwidth limiting and Class Based
Queuing based on these marks.
• DNAT
• SNAT
• MASQUERADE
The DNAT target is mainly used in cases where you have a public IP
and want to redirect accesses to the firewall to some other host (on a
Step by StepTM Linux Guide. Page 47
DMZ for example). In other words, we change the destination address of
the packet and reroute it to the host.
SNAT is mainly used for changing the source address of packets. For the
most part you'll hide your local networks or DMZ, etc. A very good
example would be that of a firewall of which we know outside IP
address, but need to substitute our local network's IP numbers with that
of our firewall. With this target the firewall will automatically SNAT
and De-SNAT the packets, hence making it possible to make
connections from the LAN to the Internet. If your network uses
192.168.0.0/netmask for example, the packets would never get back
from the Internet, because IANA has regulated these networks (among
others) as private and only for use in isolated LANs.
4.1. Introduction
The state machine is a special part within iptables that should really not
be called the state machine at all, since it is really a connection tracking
machine. However, most people recognize it under the first name.
Throughout this chapter i will use this names more or less as if they
where synonymous. This should not be overly confusing. Connection
tracking is done to let the Netfilter framework know the state of a
specific connection. Firewalls that implement this are generally called
stateful firewalls. A stateful firewall is generally much more secure than
non-stateful firewalls since it allows us to write much tighter rule-sets.
State Explanation
NEW The NEW state tells us that the packet is the first
packet that we see. This means that the first packet that
the conntrack module sees, within a specific
connection, will be matched. For example, if we see a
SYN packet and it is the first packet in a connection
that we see, it will match. However, the packet may as
well not be a SYN packet and still be considered
NEW. This may lead to certain problems in some
instances, but it may also be extremely helpful when
we need to pick up lost connections from other
firewalls, or when a connection has already timed out,
but in reality is not closed.
INVALID The INVALID state means that the packet can not be
identified or that it does not have any state. This may
be due to several reasons, such as the system running
out of memory or ICMP error messages that do not
respond to any known connections. Generally, it is a
good idea to DROP everything in this state.
These states can be used together with the --state match to match packets
based on their connection tracking state. This is what makes the state
machine so incredibly strong and efficient for our firewall. Previously,
we often had to open up all ports above 1024 to let all traffic back into
our local networks again. With the state machine in place this is not
necessary any longer, since we can now just open up the firewall for
return traffic and not for all kinds of other traffic.
As you can see from the above entry, we have a precise state in which a
SYN packet has been sent, (the SYN_SENT flag is set), and to which as yet
no reply has been sent (witness the [UNREPLIED] flag). The next internal
state will be reached when we see another packet in the other direction.
In the last example, we have gotten the final ACK in the 3-way
handshake and the connection has entered the ESTABLISHED state, as
far as the internal mechanisms of iptables are aware. After a few more
packets, the connection will also become [ASSURED], as shown in the
introduction section of this chapter.
When the TCP connection has been closed down, the connection enters
the TIME_WAIT state, which is per default set to 2 minutes. This is used
so that all packets that have gotten out of order can still get through our
rule-set, even after the connection has already closed. This is used as a
kind of buffer time so that packets that have gotten stuck in one or
another congested router can still get to the firewall, or to the other end
of the connection.
These values are most definitely not absolute. They may change with
kernel revisions, and they may also be changed via the proc file-system
in the /proc/sys/net/ipv4/netfilter/ip_ct_tcp_* variables. The default
values should, however, be fairly well established in practice. These
values are set in jiffies (or 1/100th parts of seconds), so 3000 means 30
seconds.
As you can see from the first and second values, this is an UDP packet.
The first is the protocol name, and the second is protocol number. This is
just the same as for TCP connections. The third value marks how many
seconds this state entry has to live. After this, we get the values of the
packet that we have seen and the future expectations of packets over this
connection reaching us from the initiating packet sender. These are the
source, destination, source port and destination port. At this point, the
[UNREPLIED] flag tells us that there's so far been no response to the
packet. Finally, we get a brief list of the expectations for returning
packets. Do note that the latter entries are in reverse order to the first
values. The timeout at this point is set to 30 seconds, as per default.
At this point the server has seen a reply to the first packet sent out and
the connection is now considered as ESTABLISHED. This is not shown
in the connection tracking, as you can see. The main difference is that
the [UNREPLIED] flag has now gone. Moreover, the default timeout has
changed to 180 seconds - but in this example that's by now been
decremented to 170 seconds - in 10 seconds' time, it will be 160 seconds.
There's one thing that's missing, though, and can change a bit, and that is
the [ASSURED] flag described above. For the [ASSURED] flag to be set on
a tracked connection, there must have been a small amount of traffic
over that connection.
At this point, the connection has become assured. The connection looks
exactly the same as the previous example, except for the [ASSURED] flag.
If this connection is not used for 180 seconds, it times out. 180 Seconds
is a comparatively low value, but should be sufficient for most use. This
value is reset to its full value for each packet that matches the same entry
and passes through the firewall, just the same as for all of the internal
states.
This entry looks a little bit different from the standard states for TCP and
UDP as you can see. The protocol is there, and the timeout, as well as
source and destination addresses. The problem comes after that however.
We now have 3 new fields called type, code and id. They are not special
in any way, the type field contains the ICMP type and the code field
contains the ICMP code. These are all available in ICMP types appendix.
The final id field, contains the ICMP ID. Each ICMP packet gets an ID
set to it when it is sent, and when the receiver gets the ICMP message, it
sets the same ID within the new ICMP message so that the sender will
recognize the reply and will be able to connect it with the correct ICMP
request.
Note that this means that the reply packet must match the
criterion given by the connection tracking entry to be considered
as established, just as with all other traffic types.
Let's take the FTP protocol as the first example. The FTP protocol first
opens up a single connection that is called the FTP control session.
When we issue commands through this session, other ports are opened to
carry the rest of the data related to that specific command. These
connections can be done in two ways, either actively or passively. When
a connection is done actively, the FTP client sends the server a port and
IP address to connect to. After this, the FTP client opens up the port and
the server connects to that specified port from its own port 20 (known as
FTP-Data) and sends the data over it.
The problem here is that the firewall will not know about these extra
connections, since they where negotiated within the actual payload of the
protocol data. Because of this, the firewall will be unable to know that it
should let the server connect to the client over these specific ports.
Passive FTP works the opposite way. The FTP client tells the server that
it wants some specific data, upon which the server replies with an IP
address to connect to and at what port. The client will, upon receipt of
this data, connect to that specific port, from its own port 20(the FTP-data
port), and get the data in question. If you have an FTP server behind your
firewall, you will in other words require this module in addition to your
standard iptables modules to let clients on the Internet connect to the
FTP server properly. The same goes if you are extremely restrictive to
your users, and only want to let them reach HTTP and FTP servers on
the Internet and block all other ports. Consider the following image and
its bearing on Passive FTP.
As you can understand, these tools are definitely something for you if
you are working on a huge set of rules that needs to be inserted.
However, they do have drawbacks that we will discuss more in the next
section.
One possibility to get around this is to make a small script which grabs
the values you would like to use in the script, then sed the iptables-
restore file for specific keywords and replace them with the values
collected via the small script. At this point, you could save it to a
temporary file, and then use iptables-restore to load the new values.
This causes a lot of problems however, and you will be unable to use
iptables-save properly since it would probably erase your manually
added keywords in the restore script. It is in other words a clumsy
solution.
Step by StepTM Linux Guide. Page 72
Another solution is to load the iptables-restore scripts first, and then
load a specific shell script that inserts more dynamic rules in their proper
places. Of course, as you can understand, this is just as clumsy as the
first solution. iptables-restore is simply not very well suited for
configurations where IP addresses are dynamically assigned to your
firewall or where you want different behaviors depending on
configuration options and so on.
5.3. iptables-save
The iptables-save command is, as we have already explained, a tool to
save the current rule-set into a file that iptables-restore can use. This
command is quite simple really, and takes only two arguments. Take a
look at the following example to understand the syntax of the command.
As you can see, each command has now been prefixed with the byte and
packet counters since we used the -c argument. Except for this, the
command-line is quite intact from the script. The only problem now, is
how to save the output to a file. Quite simple, and you should already
know how to do this if you have used linux at all before. It is only a
Step by StepTM Linux Guide. Page 75
matter of piping the command output on to the file that you would like to
save it as. This could look like the following:
The above command will in other words save the whole rule-set to a file
called /etc/iptables-save with byte and packet counters still intact.
5.4. iptables-restore
The iptables-restore command is used to restore the iptables rule-set
that was saved with the iptables-save command. It takes all the input
from standard input and can not load from files as of writing this,
unfortunately. This is the command syntax for iptables-restore:
The -c argument restores the byte and packet counters and must be used
if you want to restore counters that was previously saved with iptables-
save. This argument may also be written in its long form --counters.
This would cat the rule-set located within the /etc/iptables-save file and
then pipe it to iptables-restore which takes the rule-set on the standard
input and then restores it, including byte and packet counters. It is that
simple to begin with. This command could be varied until oblivion and
we could show different piping possibilities, however, this is a bit out of
Step by StepTM Linux Guide. Page 76
the scope of this chapter, and hence we will skip that part and leave it as
an exercise for the reader to experiment with.
6.1. Basics
As we have already explained, each rule is a line that the kernel looks at
to find out what to do with a packet. If all the criteria - or matches - are
met, we perform the target - or jump - instruction. Normally we would
write our rules in a syntax that looks something like this:
There is nothing that says that the target instruction has to be last
function in the line. However, you would usually adhere to this syntax to
get the best readability. Anyway, most of the rules you'll see are written
in this way. Hence, if you read someone else's script, you'll most likely
recognize the syntax and easily understand the rule.
One thing to think about though: The command should always come
first, or alternatively directly after the table specification. We use
'command' to tell the program what to do, for example to insert a rule or
to add a rule to the end of the chain, or to delete a rule. We shall take a
further look at this below.
The match is the part of the rule that we send to the kernel that details the
specific character of the packet, what makes it different from all other
packets. Here we could specify what IP address the packet comes from,
from which network interface, the intended IP address, port, protocol or
whatever. There is a heap of different matches that we can use that we
will look closer at further on in this chapter.
Finally we have the target of the packet. If all the matches are met for a
packet, we tell the kernel what to do with it. We could, for example, tell
the kernel to send the packet to another chain that we've created
ourselves, and which is part of this particular table. We could tell the
kernel to drop the packet dead and do no further processing, or we could
tell the kernel to send a specified reply to the sender. As with the rest of
the content in this section, we'll look closer at it further on in the chapter.
6.2. Tables
The -t option specifies which table to use. Per default, the filter table is
used. We may specify one of the following tables with the -t option. Do
note that this is an extremely brief summary of some of the contents of
the Traversing of tables and chains chapter.
Table Explanation
nat The nat table is used mainly for Network Address
Translation. "NAT"ed packets get their IP addresses altered,
according to our rules. Packets in a stream only traverse this
table once. We assume that the first packet of a stream is
allowed. The rest of the packets in the same stream are
automatically "NAT"ed or Masqueraded etc, and will be
subject to the same actions as the first packet. These will, in
other words, not go through this table again, but will
nevertheless be treated like the first packet in the stream.
This is the main reason why you should not do any filtering
in this table, which we will discuss at greater length further
on. The PREROUTING chain is used to alter packets as
soon as they get in to the firewall. The OUTPUT chain is
used for altering locally generated packets (i.e., on the
firewall) before they get to the routing decision. Finally we
have the POSTROUTING chain which is used to alter
packets just as they are about to leave the firewall.
The above details should have explained the basics about the three
different tables that are available. They should be used for totally
different purposes, and you should know what to use each chain for. If
you do not understand their usage, you may well dig a pit for yourself in
your firewall, into which you will fall as soon as someone finds it and
pushes you into it. We have already discussed the requisite tables and
chains in more detail within the Traversing of tables and chains chapter.
If you do not understand this fully, I advise you to go back and read
through it again.
6.3. Commands
In this section we will cover all the different commands and what can be
done with them. The command tells iptables what to do with the rest of
the rule that we send to the parser. Normally we would want either to
add or delete something in some table or another. The following
commands are available to iptables:
You should always enter a complete command line, unless you just want
to list the built-in help for iptables or get the version of the command.
To get the version, use the -v option and to get the help message, use the
-h option. As usual, in other words. Next comes a few options that can
be used with various different commands. Note that we tell you with
which commands the options can be used and what effect they will have.
Also note that we do not include any options here that affect rules or
matches. Instead, we'll take a look at matches and targets in a later
section of this chapter.
These matches are protocol specific and are only available when working
with TCP packets and streams. To use these matches, you need to
specify --protocol tcp on the command line before trying to use them.
Note that the --protocol tcp match must be to the left of the protocol
specific matches. These matches are loaded implicitly in a sense, just as
the UDP and ICMP matches are loaded implicitly. The other matches
will be looked over in the continuation of this section, after the TCP
match section.
Match --tcp-flags
Example iptables -p tcp --tcp-flags SYN,FIN,ACK SYN
Explanation This match is used to match on the TCP flags in a packet.
First of all, the match takes a list of flags to compare (a
mask) and secondly it takes list of flags that should be set to
1, or turned on. Both lists should be comma-delimited. The
match knows about the SYN, ACK, FIN, RST, URG, PSH
flags, and it also recognizes the words ALL and NONE.
ALL and NONE is pretty much self describing: ALL means
to use all flags and NONE means to use no flags for the
option. --tcp-flags ALL NONE would in other words mean
to check all of the TCP flags and match if none of the flags
are set. This option can also be inverted with the ! sign. For
example, if we specify ! SYN,FIN,ACK SYN, we would
get a match that would match packets that had the ACK and
FIN bits set, but not the SYN bit. Also note that the comma
delimitation should not include spaces. You can see the
correct syntax in the example above.
Match --syn
Example iptables -p tcp --syn
Explanation The --syn match is more or less an old relic from the
ipchains days and is still there for backward compatibility
and for and to make transition one to the other easier. It is
used to match packets if they have the SYN bit set and the
ACK and RST bits unset. This command would in other
words be exactly the same as the --tcp-flags
SYN,RST,ACK SYN match. Such packets are mainly used
to request new TCP connections from a server. If you block
these packets, you should have effectively blocked all
incoming connection attempts. However, you will not have
blocked the outgoing connections, which a lot of exploits
today use (for example, hacking a legitimate service and
then installing a program or suchlike that enables initiating
an existing connection to your host, instead of opening up a
TM
Step by Step Linux Guide. Page 92
new port on it). This match can also be inverted with the !
sign in this, ! --syn, way. This would match all packets with
the RST or the ACK bits set, in other words packets in an
already established connection.
Match --tcp-option
Example iptables -p tcp --tcp-option 16
Explanation This match is used to match packets depending on their
TCP options. A TCP Option is a specific part of the header.
This part consists of 3 different fields. The first one is 8 bits
long and tells us which Options are used in this stream, the
second one is also 8 bits long and tells us how long the
options field is. The reason for this length field is that TCP
options are, well, optional. To be compliant with the
standards, we do not need to implement all options, but
instead we can just look at what kind of option it is, and if
we do not support it, we just look at the length field and can
then jump over this data. This match is used to match
different TCP options depending on their decimal values. It
may also be inverted with the ! flag, so that the match
matches all TCP options but the option given to the match.
For a complete list of all options, take a closer look at the
Internet Engineering Task Force who maintains a list of all
the standard numbers used on the Internet.
This section describes matches that will only work together with UDP
packets. These matches are implicitly loaded when you specify the --
protocol UDP match and will be available after this specification. Note
that UDP packets are not connection oriented, and hence there is no such
thing as different flags to set in the packet to give data on what the
datagram is supposed to do, such as open or closing a connection, or if
they are just simply supposed to send data. UDP packets do not require
any kind of acknowledgment either. If they are lost, they are simply lost
(Not taking ICMP error messaging etc into account). This means that
there are quite a lot less matches to work with on a UDP packet than
Step by StepTM Linux Guide. Page 93
there is on TCP packets. Note that the state machine will work on all
kinds of packets even though UDP or ICMP packets are counted as
connectionless protocols. The state machine works pretty much the same
on UDP packets as on TCP packets.
These are the ICMP matches. These packets are even more ephemeral,
that is to say short lived, than UDP packets, in the sense that they are
connectionless. The ICMP protocol is mainly used for error reporting
and for connection controlling and suchlike. ICMP is not a protocol
subordinated to the IP protocol, but more of a protocol that augments the
IP protocol and helps in handling errors. The headers of ICMP packets
are very similar to those of the IP headers, but differ in a number of
ways. The main feature of this protocol is the type header, that tells us
what the packet is for. One example is, if we try to access an
unaccessible IP address, we would normally get an ICMP host
unreachable in return. For a complete listing of ICMP types, see the
ICMP types appendix. There is only one ICMP specific match available
for ICMP packets, and hopefully this should suffice. This match is
implicitly loaded when we use the --protocol ICMP match and we get
access to it automatically. Note that all the generic matches can also be
used, so that among other things we can match on the source and
destination addresses.
Match --icmp-type
Example iptables -A INPUT -p icmp --icmp-type 8
Explanation This match is used to specify the ICMP type to match.
ICMP types can be specified either by their numeric values
or by their names. Numerical values are specified in RFC
792. To find a complete listing of the ICMP name values,
Step by StepTM Linux Guide. Page 95
do an iptables --protocol icmp --help, or check the ICMP
types appendix. This match can also be inverted with the !
sign in this, --icmp-type ! 8, fashion. Note that some ICMP
types are obsolete, and others again may be "dangerous" for
an unprotected host since they may, among other things,
redirect packets to the wrong places.
The limit match extension must be loaded explicitly with the -m limit
option. This match can, for example, be used to advantage to give
limited logging of specific rules etc. For example, you could use this to
match all packets that does not exceed a given value, and after this value
Step by StepTM Linux Guide. Page 96
has been exceeded, limit logging of the event in question. Think of a
time limit : You could limit how many times a certain rule may be
matched in a certain time frame, for example to lessen the effects of DoS
syn flood attacks. This is its main usage, but there are more usages, of
course. The limit match may also be inverted by adding a ! flag in front
of the limit match. It would then be expressed as -m limit ! --limit
5/s.This means that all packets will be matched after they have broken
thelimit.
Consider the example below for further explanation of how this may look.
3. The token bucket is now empty. Once the token bucket is empty, the
packets that qualify for the rule otherwise no longer match the rule
and proceed to the next rule if any, or hit the chain policy.
4. For each 1/5 s without a matching packet, the token count goes up by
1, upto a maximum of 10. 1 second after receiving the 10 packets, we
will once again have 5 tokens left.
5. And of course, the bucket will be emptied by 1 token for each packet
it receives.
Match --limit
Example iptables -A INPUT -m limit --limit 3/hour
Explanation This sets the maximum average match rate for the limit
match. You specify it with a number and an optional time
unit. The following time units are currently recognized:
/second /minute /hour /day. The default value here is 3 per
hour, or 3/hour. This tells the limit match how many times
to allow the match to occur per time unit (e.g. per minute).
Match --limit-burst
Example iptables -A INPUT -m limit --limit-burst 5
Explanation This is the setting for the burst limit of the limit match. It
tells iptables the maximum number of packets to match
within the given time unit. This number gets decremented
by one for every time unit (specified by the --limit option)
in which the event does not occur, back down to the lowest
possible value, 1. If the event is repeated, the counter is
again incremented, until the count reaches the burst limit.
And so on. The default --limit-burst value is 5. For a
simple way of checking out how this works, you can use the
example Limit-match.txt one-rule-script. Using this script,
you can see for yourself how the limit rule works, by simply
sending ping packets at different intervals and in different
burst numbers. All echo replies will be blocked until the
threshold for the burst limit has again been reached.
The MAC (Ethernet Media Access Control) match can be used to match
packets based on their MAC source address. As of writing this
documentation, this match is a little bit limited, however, in the future
this may be more evolved and may be more useful. This match can be
Match --mac-source
Example iptables -A INPUT -m mac --mac-source
00:00:00:00:00:01
Explanation This match is used to match packets based on their MAC
source address. The MAC address specified must be in the
form XX:XX:XX:XX:XX:XX, else it will not be legal. The
match may be reversed with an ! sign and would look like --
mac-source ! 00:00:00:00:00:01. This would in other
words reverse the meaning of the match, so that all packets
except packets from this MAC address would be matched.
Note that since MAC addresses are only used on Ethernet
type networks, this match will only be possible to use for
Ethernet interfaces. The MAC match is only valid in the
PREROUTING, FORWARD and INPUT chains and
nowhere else.
The mark match extension is used to match packets based on the marks
they have set. A mark is a special field, only maintained within the
kernel, that is associated with the packets as they travel through the
computer. Marks may be used by different kernel routines for such tasks
as traffic shaping and filtering. As of today, there is only one way of
setting a mark in Linux, namely the MARK target in iptables. This was
previously done with the FWMARK target in ipchains, and this is why
people still refer to FWMARK in advanced routing areas. The mark
Step by StepTM Linux Guide. Page 99
field is currently set to an unsigned integer, or 4294967296 possible
values on a 32 bit system. In other words, you are probably not going to
run into this limit for quite some time.
Match --mark
Example iptables -t mangle -A INPUT -m mark --mark 1
Explanation This match is used to match packets that have previously
been marked. Marks can be set with the MARK target
which we will discuss in the next section. All packets
traveling through Netfilter get a special mark field
associated with them. Note that this mark field is not in any
way propagated, within or outside the packet. It stays inside
the computer that made it. If the mark field matches the
mark, it is a match. The mark field is an unsigned integer,
hence there can be a maximum of 4294967296 different
marks. You may also use a mask with the mark. The mark
specification would then look like, for example, --mark 1/1.
If a mask is specified, it is logically AND ed with the mark
specified before the actual comparison.
You can not use both standard port matching and multiport
matching at the same time, for example you can't write: --sport
1024:63353 -m multiport --dport 21,23,80. This will simply
not work. What in fact happens, if you do, is that iptables honors
the first element in the rule, and ignores the multiport
instruction.
Step by StepTM Linux Guide. Page 100
Table 6-11. Multiport match options
Match --source-port
Example iptables -A INPUT -p tcp -m multiport --source-port
22,53,80,110
Explanation This match matches multiple source ports. A maximum of
15 separate ports may be specified. The ports must be
comma delimited, as in the above example. The match may
only be used in conjunction with the -p tcp or -p udp
matches. It is mainly an enhanced version of the normal --
source-port match.
Match --destination-port
Example iptables -A INPUT -p tcp -m multiport --destination-
port 22,53,80,110
Explanation This match is used to match multiple destination ports. It
works exactly the same way as the above mentioned source
port match, except that it matches destination ports. It too
has a limit of 15 ports and may only be used in conjunction
with -p tcp and -p udp.
Match --port
Example iptables -A INPUT -p tcp -m multiport --port
22,53,80,110
Explanation This match extension can be used to match packets based
both on their destination port and their source port. It works
the same way as the --source-port and --destination-port
matches above. It can take a maximum of 15 ports and can
only be used in conjunction with -p tcp and -p udp. Note
that the --port match will only match packets coming in
from and going to the same port, for example, port 80 to
port 80, port 110 to port 110 and so on.
Match --uid-owner
Example iptables -A OUTPUT -m owner --uid-owner 500
Explanation This packet match will match if the packet was created by
the given User ID (UID). This could be used to match
outgoing packets based on who created them. One possible
use would be to block any other user than root from opening
new connections outside your firewall. Another possible use
could be to block everyone but the http user from sending
packets from the HTTP port.
Match --gid-owner
Example iptables -A OUTPUT -m owner --gid-owner 0
Explanation This match is used to match all packets based on their
Group ID (GID). This means that we match all packets
based on what group the user creating the packets are in.
This could be used to block all but the users in the network
group from getting out onto the Internet or, as described
above, only to allow members of the http group to create
packets going out from the HTTP port.
Match --sid-owner
Example iptables -A OUTPUT -m owner --sid-owner 100
Explanation This match is used to match packets based on the Session
ID used by the program in question. The value of the SID,
or Session ID of a process, is that of the process itself and
all processes resulting from the originating process. These
latter could be threads, or a child of the original process. So,
for example, all of our HTTPD processes should have the
same SID as their parent process (the originating HTTPD
process), if our HTTPD is threaded (most HTTPDs are,
Apache and Roxen for instance). To show this in example,
we have created a small script called Sid-owner.txt. This
script could possibly be run every hour or so together with
some extra code to check if the HTTPD is actually running
and start it again if necessary, then flush and re-enter our
OUTPUT chain if needed.
Match --state
Example iptables -A INPUT -m state --state
RELATED,ESTABLISHED
Explanation This match option tells the state match what states the
packets must be in to be matched. There are currently 4
states that can be used. INVALID, ESTABLISHED, NEW
and RELATED. INVALID means that the packet is
associated with no known stream or connection and that it
may contain faulty data or headers. ESTABLISHED means
that the packet is part of an already established connection
that has seen packets in both directions and is fully valid.
NEW means that the packet has or will start a new
connection, or that it is associated with a connection that
has not seen packets in both directions. Finally, RELATED
means that the packet is starting a new connection and is
associated with an already established connection. This
could for example mean an FTP data transfer, or an ICMP
error associated with an TCP or UDP connection. Note that
the NEW state does not look for SYN bits in TCP packets
trying to start a new connection and should, hence, not be
used unmodified in cases where we have only one firewall
and no load balancing between different firewalls.
However, there may be times where this could be useful.
For more information on how this could be used, read the
The state machine chapter.
The TOS match can be used to match packets based on their TOS field.
TOS stands for Type Of Service, consists of 8 bits, and is located in the
IP header. This match is loaded explicitly by adding -m tos to the rule.
TOS is normally used to inform intermediate hosts of the precedence of
the stream and its content (it doesn't really, but it informs of any specific
requirements for the stream, such as it having to be sent as fast as
possible, or it needing to be able to send as much payload as possible).
How different routers and administrators deal with these values depends.
Most do not care at all, while others try their best to do something good
with the packets in question and the data they provide.
Match --tos
Example iptables -A INPUT -p tcp -m tos --tos 0x16
Explanation This match is used as described above. It can match packets
based on their TOS field and their value. This could be
used, among other things together with the iproute2 and
advanced routing functions in Linux, to mark packets for
later usage. The match takes an hex or numeric value as an
option, or possibly one of the names resulting from
'iptables -m tos -h'. At the time of writing it contained the
following named values: Minimize-Delay 16 (0x10) ,
Maximize-Throughput 8 (0x08) , Maximize-
Reliability 4 (0x04) , Minimize-Cost 2 (0x02) , and
Normal-Service 0 (0x00) . Minimize-Delay means to
minimize the delay in putting the packets through - example
of standard services that would require this include telnet,
SSH and FTP-control. Maximize-Throughput means to
find a path that allows as big a throughput as possible - a
standard protocol would be FTP-data. Maximize-
Reliability means to maximize the reliability of the
connection and to use lines that are as reliable as possible -
a couple of typical examples are BOOTP and TFTP.
Step by StepTM Linux Guide. Page 105
Minimize-Cost means minimizing the cost of packets
getting through each link to the client or server; for example
finding the route that costs the least to travel along.
Examples of normal protocols that would use this would be
RTSP (Real Time Stream Control Protocol) and other
streaming video/radio protocols. Finally, Normal-Service
would mean any normal protocol that has no special needs.
The TTL match is used to match packets based on their TTL (Time To
Live) field residing in the IP headers. The TTL field contains 8 bits of
data and is decremented once every time it is processed by an
intermediate host between the client and recipient host. If the TTL
reaches 0, an ICMP type 11 code 0 (TTL equals 0 during transit) or code
1 (TTL equals 0 during reassembly) is transmitted to the party sending
the packet and informing it of the problem. This match is only used to
match packets based on their TTL, and not to change anything. The
latter, incidentally, applies to all kinds of matches. To load this match,
you need to add an -m ttl to the rule.
Match --ttl
Example iptables -A OUTPUT -m ttl --ttl 60
Explanation This match option is used to specify the TTL value to
match. It takes a numeric value and matches this value
within the packet. There is no inversion and there are no
other specifics to match. It could, for example, be used for
debugging your local network - e.g. LAN hosts that seem to
have problems connecting to hosts on the Internet - or to
find possible ingress by Trojans etc. The usage is relatively
limited, however; its usefulness really depends on your
imagination. One example would be to find hosts with bad
default TTL values (could be due to a badly implemented
6.5. Targets/Jumps
The target/jumps tells the rule what to do with a packet that is a perfect
match with the match section of the rule. There are a couple of basic
targets, the ACCEPT and DROP targets, which we will deal with first.
However, before we do that, let us have a brief look at how a jump is
done.
The jump specification is done in exactly the same way as in the target
definition, except that it requires a chain within the same table to jump
to. To jump to a specific chain, it is of course a prerequisite that that
chain exists. As we have already explained, a user-defined chain is
created with the -N command. For example, let's say we create a chain in
the filter table called tcp_packets, like this:
iptables -N tcp_packets
We would then jump from the INPUT chain to the tcp_packets chain
and start traversing that chain. When/If we reach the end of that chain,
Note that the DNAT target is only available within the PREROUTING
and OUTPUT chains in the nat table, and any of the chains called upon
from any of those listed chains. Note that chains containing DNAT
targets may not be used from any other chains, such as the
POSTROUTING chain.
Option --to-destination
Example iptables -t nat -A PREROUTING -p tcp -d 15.45.23.67 --
dport 80 -j DNAT --to-destination 192.168.1.1-
192.168.1.10
Explanation The --to-destination option tells the DNAT mechanism
which Destination IP to set in the IP header, and where to
send packets that are matched. The above example would
send on all packets destined for IP address 15.45.23.67 to a
range of LAN IP's, namely 192.168.1.1 through 10. Note, as
described previously, that a single stream will always use
Now, all packets from the Internet going to port 80 on our firewall are
redirected (or DNAT'ed) to our internal HTTP server. If you test this
from the Internet, everything should work just perfect. So, what happens
if you try connecting from a host on the same local network as the HTTP
server? It will simply not work. This is a problem with routing really.
We start out by dissect what happens in a normal case. The external box
has IP address $EXT_BOX, to maintain readability.
5. Packet reaches the HTTP server, and the HTTP box replies back
through the firewall, if that is the box that the routing database has
entered as the gateway for $EXT_BOX. Normally, this would be the
default gateway of the HTTP server.
Now, we will consider what happens if the packet was instead generated
by a client on the same network as the HTTP server itself. The client has
the IP address $LAN_BOX, while the rest of the machines maintain the
same settings.
3. The packet gets DNAT'ed, and all other required actions are taken,
however, the packet is not SNAT'ed, so the same source IP address is
used on the packet.
4. The packet leaves the firewall and reaches the HTTP server.
5. The HTTP server tries to respond to the packet, and sees in the
routing databases that the packet came from a local box on the same
network, and hence tries to send the packet directly to the original
source IP address (which now becomes the destination IP address).
6. The packet reaches the client, and the client gets confused since the
return packet does not come from the host that it sent the original
request to. Hence, the client drops the reply packet, and waits for the
"real" reply.
Step by StepTM Linux Guide. Page 111
The simple solution to this problem is to SNAT all packets entering the
firewall and leaving for a host or IP that we know we do DNAT to. For
example, consider the above rule. We SNAT the packets entering our
firewall that are destined for $HTTP_IP port 80 so that they look as if
they came from $LAN_IP. This will force the HTTP server to send the
packets back to our firewall, which Un-DNAT's the packets and sends
them on to the client. The rule would look something like this:
This can also have even more severe implications. Take a SMTP
server on the LAN, that allows requests from the internal
network, and you have your firewall set up to forward SMTP
traffic to it. You have now effectively created an open relay
SMTP server, with horrenduously bad logging!
Adding this final rule should get everything up and running. All separate
networks that do not sit on the same net as the HTTP server will run
smoothly, all hosts on the same network as the HTTP server will be able
to connect and finally, the firewall will be able to do proper connections
as well. Now everything works and no problems should arise.
Everyone should realize that these rules only effects how the
packet is DNAT'ed and SNAT'ed properly. In addition to these
rules, you may also need extra rules in the filter table
(FORWARD chain) to allow the packets to traverse through
those chains as well. Don't forget that all packets have already
gone through the PREROUTING chain, and should hence have
their destination addresses rewritten already by DNAT.
The LOG target currently takes five options that could be of interest if
you have specific information needs, or want to set different options to
specific values. They are all listed below.
Option --log-level
Example iptables -A FORWARD -p tcp -j LOG --log-level debug
Explanation This is the option to tell iptables and syslog which log level
to use. For a complete list of log levels read the
syslog.conf manual. Normally there are the following log
levels, or priorities as they are normally referred to: debug,
info, notice, warning, warn, err, error, crit, alert, emerg and
panic. The keyword error is the same as err, warn is the
same as warning and panic is the same as emerg. Note that
all three of these are deprecated, in other words do not use
error, warn and panic. The priority defines the severity of
the message being logged. All messages are logged through
the kernel facility. In other words, setting kern.=info
/var/log/iptables in your syslog.conf file and then letting
all your LOG messages in iptables use log level info,
would make all messages appear in the
/var/log/iptables file. Note that there may be other
messages here as well from other parts of the kernel that
uses the info priority. For more information on logging I
recommend you to read the syslog and syslog.conf man-
pages as well as other HOWTOs etc.
Option --log-prefix
Example iptables -A INPUT -p tcp -j LOG --log-prefix "INPUT
packets"
Explanation This option tells iptables to prefix all log messages with a
specific prefix, which can the easily be combined with grep
or other tools to track specific problems and output from
different rules. The prefix may be up to 29 letters long,
including white-spaces and other special symbols.
Option --log-tcp-sequence
Step by StepTM Linux Guide. Page 115
Example iptables -A INPUT -p tcp -j LOG --log-tcp-sequence
Explanation This option will log the TCP Sequence numbers, together
with the log message. The TCP Sequence number are
special numbers that identify each packet and where it fits
into a TCP sequence, as well as how the stream should be
reassembled. Note that this option constitutes a security risk
if the logs are readable by unauthorized users, or by the
world for that matter. As does any log that contains output
from iptables.
Option --log-tcp-options
Example iptables -A FORWARD -p tcp -j LOG --log-tcp-options
Explanation The --log-tcp-options option logs the different options from
the TCP packet headers and can be valuable when trying to
debug what could go wrong, or what has actually gone
wrong. This option does not take any variable fields or
anything like that, just as most of the LOG options don't.
Option --log-ip-options
Example iptables -A FORWARD -p tcp -j LOG --log-ip-options
Explanation The --log-ip-options option will log most of the IP packet
header options. This works exactly the same as the --log-
tcp-options option, but instead works on the IP options.
These logging messages may be valuable when trying to
debug or track specific culprits, as well as for debugging -
in just the same way as the previous option.
Option --set-mark
Example iptables -t mangle -A PREROUTING -p tcp --dport 22 -j
MARK --set-mark 2
Explanation The --set-mark option is required to set a mark. The --set-
mark match takes an integer value. For example, we may
set mark 2 on a specific stream of packets, or on all packets
from a specific host and then do advanced routing on that
host, to decrease or increase the network bandwidth, etc.
Option --to-ports
Example iptables -t nat -A POSTROUTING -p TCP -j
MASQUERADE --to-ports 1024-31000
Explanation The --to-ports option is used to set the source port or ports
to use on outgoing packets. Either you can specify a single
port like --to-ports 1025 or you may specify a port range as
--to-ports 1024-3000. In other words, the lower port range
delimiter and the upper port range delimiter separated with
a hyphen. This alters the default SNAT port-selection as
described in the SNAT target section. The --to-ports option
is only valid if the rule match section specifies the TCP or
UDP protocols with the --protocol match.
Note that the MIRROR target is only valid within the INPUT,
FORWARD and PREROUTING chains, and any user-defined chains
which are called from those chains. Also note that outgoing packets
resulting from the MIRROR target are not seen by any of the normal
chains in the filter, nat or mangle tables, which could give rise to loops
and other problems. This could make the target the cause of unforeseen
headaches. For example, a host might send a spoofed packet to another
host that uses the MIRROR command with a TTL of 255, at the same
time spoofing its own packet, so as to seem as if it comes from a third
host that uses the MIRROR command. The packet will then bounce
back and forth incessantly, for the number of hops there are to be
completed. If there is only 1 hop, the packet will jump back and forth
240-255 times. Not bad for a cracker, in other words, to send 1500 bytes
of data and eat up 380 kbyte of your connection. Note that this is a best
case scenario for the cracker or script kiddie, whatever we want to call
them.
Note that the REDIRECT target is only valid within the PREROUTING
and OUTPUT chains of the nat table. It is also valid within user-defined
chains that are only called from those chains, and nowhere else. The
REDIRECT target takes only one option, as described below.
Option --to-ports
Example iptables -t nat -A PREROUTING -p tcp --dport 80 -j
REDIRECT --to-ports 8080
Explanation The --to-ports option specifies the destination port, or port
range, to use. Without the --to-ports option, the destination
port is never altered. This is specified, as above, --to-ports
8080 in case we only want to specify one port. If we would
want to specify an port range, we would do it like --to-ports
8080-8090, which tells the REDIRECT target to redirect
Step by StepTM Linux Guide. Page 120
the packets to the ports 8080 through 8090. Note that this
option is only available in rules specifying the TCP or UDP
protocol with the --protocol matcher, since it wouldn't
make any sense anywhere else.
Option --reject-with
Example iptables -A FORWARD -p TCP --dport 22 -j REJECT --
reject-with tcp-reset
The SNAT target is only valid within the nat table, within the
POSTROUTING chain. This is in other words the only chain in which
you may use SNAT. Only the first packet in a connection is mangled by
SNAT, and after that all future packets using the same connection will
also be SNATted. Furthermore, the initial rules in the POSTROUTING
chain will be applied to all the packets in the same stream.
Option --to-source
Example iptables -t nat -A POSTROUTING -p tcp -o eth0 -j
SNAT --to-source 194.236.50.155-194.236.50.160:1024-
32000
There are currently a lot of routers on the Internet which do a pretty bad
job at this, so as of now it may prove to be a bit useless to attempt TOS
mangling before sending the packets on to the Internet. At best the
routers will not pay any attention to the TOS field. At worst, they will
look at the TOS field and do the wrong thing. However, as stated above,
the TOS field can most definitely be put to good use if you have a large
WAN or LAN with multiple routers. You then in fact have the
possibility of giving packets different routes and preferences, based on
their TOS value - even though this might be confined to your own
network.
Note that this target is only valid within the mangle table and
can not be used outside it.
Option --set-tos
Example iptables -t mangle -A PREROUTING -p TCP --dport 22
-j TOS --set-tos 0x10
Explanation The --set-tos option tells the TOS mangler what TOS value
to set on packets that are matched. The option takes a
numeric value, either in hex or in decimal value. As the
TOS value consists of 8 bits, the value may be 0-255, or in
hex 0x00-0xFF. Note that in the standard TOS target you
are limited to using the named values available (which
should be more or less standardized), as mentioned in the
previous warning. These values are Minimize-Delay
(decimal value 16, hex value 0x10), Maximize-Throughput
(decimal value 8, hex value 0x08), Maximize-Reliability
(decimal value 4, hex value 0x04), Minimize-Cost (decimal
value 2, hex 0x02) or Normal-Service (decimal value 0, hex
value 0x00). The default value on most packets is Normal-
Service, or 0. Note that you can, of course, use the actual
names instead of the actual hex values to set the TOS value;
in fact this is generally to be recommended, since the values
associated with the names may be changed in future. For a
complete listing of the "descriptive values", do an iptables -
j TOS -h. This listing is complete as of iptables 1.2.5 and
should hopefully remain so for a while.
This patch requires the TTL patch from the patch-o-matic tree
available im the base directory from
http://www.netfilter.org/documentation/index.html#FAQ - The
official Netfilter Frequently Asked Questions. Also a good place
to start at when wondering what iptables and Netfilter is about..
For more information on how to set the default value used in Linux, read
the ip-sysctl.txt, which you may find within the Other resources and
links appendix.
The TTL target is only valid within the mangle table, and nowhere else.
It takes 3 options as of writing this, all of them described below in the
table.
Option --ttl-set
Example iptables -t mangle -A PREROUTING -i eth0 -j TTL --
ttl-set 64
Explanation The --ttl-set option tells the TTL target which TTL value to
set on the packet in question. A good value would be
around 64 somewhere. It's not too long, and it is not too
short. Do not set this value too high, since it may affect
your network and it is a bit immoral to set this value to
high, since the packet may start bouncing back and forth
between two mis-configured routers, and the higher the
TTL, the more bandwidth will be eaten unnecessary in such
a case. This target could be used to limit how far away our
clients are. A good case of this could be DNS servers,
where we don't want the clients to be too far away.
Option --ttl-dec
Example iptables -t mangle -A PREROUTING -i eth0 -j TTL --
ttl-dec 1
Option --ttl-inc
Example iptables -t mangle -A PREROUTING -i eth0 -j TTL --
ttl-inc 1
Explanation The --ttl-inc option tells the TTL target to increment the
Time To Live value with the value specified to the --ttl-inc
option. This means that we should raise the TTL value with
the value specified in the --ttl-inc option, and if we
specified --ttl-inc 4, a packet entering with a TTL of 53
would leave the host with TTL 56. Note that the same thing
goes here, as for the previous example of the --ttl-dec
option, where the network code will automatically
decrement the TTL value by 1, which it always does. This
may be used to make our firewall a bit more stealthy to
trace-routes among other things. By setting the TTL one
value higher for all incoming packets, we effectively make
the firewall hidden from trace-routes. Trace-routes are a
loved and hated thing, since they provide excellent
information on problems with connections and where it
happens, but at the same time, it gives the hacker/cracker
some good information about your upstreams if they have
targeted you. For a good example on how this could be
used, see the Ttl-inc.txt script.
Option --ulog-nlgroup
Example iptables -A INPUT -p TCP --dport 22 -j ULOG --ulog-
nlgroup 2
Explanation The --ulog-nlgroup option tells the ULOG target which
netlink group to send the packet to. There are 32 netlink
groups, which are simply specified as 1-32. If we would
like to reach netlink group 5, we would simply write --ulog-
nlgroup 5. The default netlink group used is 1.
Option --ulog-prefix
Example iptables -A INPUT -p TCP --dport 22 -j ULOG --ulog-
prefix "SSH connection attempt: "
Explanation The --ulog-prefix option works just the same as the prefix
value for the standard LOG target. This option prefixes all
log entries with a user-specified log prefix. It can be 32
characters long, and is definitely most useful to distinguish
different log-messages and where they came from.
Option --ulog-qthreshold
Example iptables -A INPUT -p TCP --dport 22 -j ULOG --ulog-
qthreshold 10
Explanation The --ulog-qthreshold option tells the ULOG target how
many packets to queue inside the kernel before actually
sending the data to user-space. For example, if we set the
threshold to 10 as above, the kernel would first accumulate
10 packets inside the kernel, and then transmit it outside to
the user-space as one single netlink multi part message. The
default value here is 1 because of backward compatibility,
the user-space daemon did not know how to handle multi-
part messages previously.
note that there might be more efficient ways of making the rule-
set, however, the script has been written for readability so that
everyone can understand it without having to know too much
BASH scripting before reading this
Next is the option to load ipt_owner module, which could for example be
used to only allow certain users to make certain connections, etc. I will
not use that module in this example but basically, you could allow only
root to do FTP and HTTP connections to redhat.com and DROP all the
others. You could also disallow all users but your own user and root to
connect from your box to the Internet, might be boring for others, but
you will be a bit more secure to bouncing hacker attacks and attacks
where the hacker will only use your host as an intermediate host. For
more information about the ipt_owner match, look at the Owner match
section within the How a rule is built chapter.
We may also load extra modules for the state matching code here. All
modules that extend the state matching code and connection tracking
code are called ip_conntrack_* and ip_nat_*. Connection tracking
helpers are special modules that tells the kernel how to properly track the
specific connections. Without these so called helpers, the kernel would
not know what to look for when it tries to track specific connections. The
NAT helpers on the other hand, are extensions of the connection tracking
helpers that tells the kernel what to look for in specific packets and how
to translate these so the connections will actually work. For example,
FTP is a complex protocol by definition, and it sends connection
information within the actual payload of the packet. So, if one of your
NATed boxes connect to a FTP server on the Internet, it will send its
own local network IP address within the payload of the packet, and tells
the FTP server to connect to that IP address. Since this local network
address is not valid outside your own network, the FTP server will not
know what to do with it and hence the connection will break down. The
Step by StepTM Linux Guide. Page 133
FTP NAT helpers do all of the translations within these connections so
the FTP server will actually know where to connect. The same thing
applies for DCC file transfers (sends) and chats. Creating these kind of
connections requires the IP address and ports to be sent within the IRC
protocol, which in turn requires some translation to be done. Without
these helpers, some FTP and IRC stuff will work no doubt, however,
some other things will not work. For example, you may be able to
receive files over DCC, but not be able to send files. This is due to how
the DCC starts a connection. First off, you tell the receiver that you want
to send a file and where he should connect to. Without the helpers, the
DCC connection will look as if it wants the receiver to connect to some
host on the receivers own local network. In other words, the whole
connection will be broken. However, the other way around, it will work
flawlessly since the sender will (most probably) give you the correct
address to connect to.
As of this writing, there is only the option to load modules which add
support for the FTP and IRC protocols. For a long explanation of these
conntrack and nat modules, read the Common problems and questions
appendix. There are also H.323 conntrack helpers within the patch-o-
matic, as well as some other conntrack as well as NAT helpers. To be
able to use these helpers, you need to use the patch-o-matic and compile
your own kernel. For a better explanation on how this is done, read the
Preparations chapter.
Note that you need to load the ip_nat_irc and ip_nat_ftp if you
want Network Address Translation to work properly on any of
the FTP and IRC protocols. You will also need to load the
ip_conntrack_irc and ip_conntrack_ftp modules before actually
loading the NAT modules. They are used the same way as the
conntrack modules, but it will make it possible for the computer
to do NAT on these two protocols.
In case you need dynamic IP support, for example if you use SLIP, PPP
or DHCP you may enable the next option, ip_dynaddr by doing the
following :
If there is any other options you might need to turn on you should follow
that style, there's other documentations on how to do these things and
this is out of the scope of this documentation. There is a good but rather
brief document about the proc system available within the kernel, which
is also available within the Other resources and links appendix. The
Other resources and links appendix is generally a good place to start
looking when you have specific areas that you are looking for
information on, that you do not find here.
I have displaced all the different user-chains in the fashion I have to save
as much CPU as possible but at the same time put the main weight on
security and readability. Instead of letting a TCP packet traverse ICMP,
UDP and TCP rules, I simply match all TCP packets and then let the
TCP packets traverse an user specified chain. This way we do not get too
much overhead out of it all. The following picture will try to explain the
basics of how an incoming packet traverses Netfilter. With these pictures
and explanations, I wish to explain and clarify the goals of this script.
We will not discuss any specific details yet, but instead further on in the
chapter. This is a really trivial picture in comparison to the one in the
Traversing of tables and chains chapter where we discussed the whole
traversal of chains and tables in depth.
In the case of this scenario, we would also like to let our local network
do connections to the Internet. Since the local network is fully trusted,
we want to allow all kind of traffic from the local network to the
Internet. However, the Internet is most definitely not a trusted network
and hence we want to block them from getting to our local network.
Based upon these general assumptions, let's look at what we need to do
and what we do not need and want to do.
Since we have an FTP server running on the server, as well as the fact
we want to traverse as few rules as possible, we add a rule which lets all
established and related traffic through at the top of the INPUT chain. For
the same reason, we want to split the rules down into sub-chains. By
doing this, our packets will hopefully only need to traverse as few rules
as possible. By traversing less rules, we make the rule-set less time
consuming for each packet, and reduce redundancy within the network.
Since we are running on a relatively small network, this box is also used
as a secondary workstation and to give some extra levy for this, we want
to allow certain specific protocols to make contact with the firewall
itself, such as speak freely and ICQ.
The default policy is used every time the packets do not match a rule in
the chain. For example, let's say we get a packet that match no single rule
in our whole rule-set. If this happens, we must decide what should
happen to the packet in question, and this is where the default policy
comes into the picture. The default policy is used on all packets that does
not match with any other rule in our rule-set.
After this, we create the different special chains that we want to use with
the -N command. The new chains are created and set up with no rules
inside of them. The chains we will use are, as previously described,
icmp_packets, tcp_packets, udp_packets and the allowed chain, which is
used by the tcp_packets chain. Incoming packets on $INET_IFACE, of
ICMP type, will be redirected to the chain icmp_packets. Packets of TCP
type, will be redirected to the tcp_packets chain and incoming packets of
UDP type from $INET_IFACE go to udp_packets chain. All of this will
be explained more in detail in the INPUT chain section below. To create
a chain is quite simple and only consists of a short declaration of the
chain as this:
In the upcoming sections we will have a closer look at each and one of
the user defined chains that we have by now created. Let us have a closer
look at how they look and what rules they contain and what we will
accomplish within them.
If you want to fully understand the NEW not SYN, you need to look at
the State NEW packets but no SYN bit set section in the Common
problems and questions appendix regarding state NEW and non-SYN
packets getting through other rules. These packets could be allowed
under certain circumstances but in 99% of the cases we wouldn't want
these packets to get through. Hence, we log them to our logs and then we
DROP them.
The tcp_packets chain specifies what ports that are allowed to use on the
firewall from the Internet. There is, however, even more checks to do,
hence we send each and one of the packets on to the allowed chain,
which we described previously.
-A tcp_packets tells iptables in which chain to add the new rule, the
rule will be added to the end of the chain. -p TCP tells it to match TCP
packets and -s 0/0 matches all source addresses from 0.0.0.0 with
netmask 0.0.0.0, in other words all source addresses. This is actually the
default behavior but I am using it just to make everything as clear as
possible. --dport 21 means destination port 21, in other words if the
packet is destined for port 21 they also match. If all the criteria are
matched, then the packet will be targeted for the allowed chain. If it
doesn't match any of the rules, they will be passed back to the original
chain that sent the packet to the tcp_packets chain.
As it is now, I allow TCP port 21, or FTP control port, which is used to
control FTP connections and later on I also allow all RELATED
connections, and that way we allow PASSIVE and ACTIVE connections
since the ip_conntrack_ftp module is, hopefully, loaded. If we do not
want to allow FTP at all, we can unload the ip_conntrack_ftp module
Step by StepTM Linux Guide. Page 143
and delete the $IPTABLES -A tcp_packets -p TCP -s 0/0 --dport 21 -j
allowed line from the rc.firewall.txt file.
Port 80 is HTTP, in other words your web server, delete it if you do not
want to run a web server directly on your firewall.
If you feel like adding more open ports with this script, well, it should be
quite obvious how to do that by now. Just cut and paste one of the other
lines in the tcp_packets chain and change it to the port you want to open.
I personally also allow port 123, which is NTP or network time protocol.
This protocol is used to set your computer clock to the same time as
certain other time servers which have very accurate clocks. Most of you
probably do not use this protocol and hence I am not allowing it per
default. The same thing applies here however, the rule is there and it is
simple to uncomment to get it working.
Port 4000 is the ICQ protocol. This should be an extremely well known
protocol that is used by the Mirabilis application named ICQ. There is at
least 2-3 different ICQ clones for Linux and it is one of the most widely
used chat programs in the world. I doubt there is any further need to
explain what it is.
At this point, two extra rules are available if you are experiencing a lot of
log entries due to different circumstances. The first rule will block
broadcast packets to destination ports 135 through 139. These are used
by NetBIOS, or SMB for most Microsoft users. This will block all log
entries we may get from Microsoft Networks on our outside otherwise.
The second rule was also created to take care of excessive logging
problems, but instead takes care of DHCP queries from the outside. This
is specifically true if your outside network consists of a non-switched
Ethernet type of network, where the clients receive their IP addresses by
DHCP. During these circumstances, you could wind up with a lot of logs
from just that.
Do note that the last two rules are specifically opted out since
some people may be interested in these kind of logs. If you are
experiencing problems with excessive legit logging, try to drop
these types of packages at this point. There are also more rules
of this type just before the log rules in the INPUT chain.
The reason that I allow these ICMP packets are as follows, Echo
Requests are used to request an echo reply, which in turn is used to
mainly ping other hosts to see if they are available on any of the
networks. Without this rule, other hosts will not be able to ping us to see
if we are available on any network connection. Do note that some people
would tend to erase this rule, since they simple do not want to be seen on
the Internet. Deleting this rule will effectively render any pings to our
firewall totally useless from the Internet since the firewall will simply
not respond to them.
Time Exceeded (i.e., TTL equals 0 during transit and TTL equals 0
during reassembly), is allowed in the case we want to trace-route some
host or if a packet gets its Time To Live set to 0, we will get a reply
about this. For example, when you trace-route someone, you start out
with TTL = 1, and it gets down to 0 at the first hop on the way out, and a
Time Exceeded is sent back from the first gateway en route to the host
we are trying to trace-route, then TTL = 2 and the second gateway sends
Time Exceeded, and so on until we get an actual reply from the host we
finally want to get to. This way, we will get a reply from each host on
our way to the actual host we want to reach, and we can see every host in
between and find out what host is broken.
First of all we do certain checks for bad packets. This is done by sending
all TCP packets to the bad_tcp_packets chain. This chain contains a few
rules that will check for badly formed packets or other anomalies that we
do not want to accept. For a full explanation of the The bad_tcp_packets
chain section in this chapter.
At this point we start looking for traffic from generally trusted networks.
These include the local network adapter and all traffic coming from
there, all traffic to and from our loopback interface, including all our
currently assigned IP addresses (this means all of them, including our
Internet IP address). As it is, we have chosen to put the rule that allows
LAN activity to the firewall at the top, since our local network generates
more traffic than the Internet connection. This allows for less overhead
used to try and match each packet with each rule and it is always a good
Before we start touching the "real" rules which decides what we allow
from the Internet interface and not, we have a related rule set up to
reduce our overhead. This is a state rule which allows all packets part of
an already ESTABLISHED or RELATED stream to the Internet IP
address. This rule has an equivalent rule in the allowed chain, which are
made rather redundant by this rule, which will be evaluated before the
allowed ones are. However, the --state ESTABLISHED,RELATED
rule in the allowed chain has been retained for several reasons, such as
people wanting to cut and pasting the function.
After this, We match all TCP packets in the INPUT chain that comes in
on the $INET_IFACE interface, and send those to the tcp_packets,
which was previously described. Now we do the same match for UDP
packets on the $INET_IFACE and send those to the udp_packets chain,
and after this all ICMP packets are sent to the icmp_packets chain.
Normally, a firewall would be hardest hit by TCP packets, then UDP and
last of them all ICMP packets. This is in normal case, mind you, and it
may be wrong for you. The absolute same thing should be looked upon
here, as with the network specific rules. Which causes the most traffic?
Should the rules be thrown around to generate less overhead? On
networks sending huge amounts of data, this is an absolute necessity
since a Pentium III equivalent machine may be brought to its knees by a
simple rule-set containing 100 rules and a single 100mbit Ethernet card
running at full capacity if the rule-set is badly written. This is an
important piece to look at when writing a rule-set for your own local
network.
At this point we have one extra rule, that is per default opted out, that
can be used to get rid of some excessive logging in case we have some
Microsoft network on the outside of our Linux firewall. Microsoft clients
have a bad habit of sending out tons of multicast packets to the
224.0.0.0/8 range, and hence we have the opportunity to block those
packets here so we don't fill our logs with them. There are also two more
rules doing something similar tasks in the udp_packets chain described
in the The UDP chain.
Everything that has not yet been caught will be DROPed by the default
policy on the INPUT chain. The default policy was set quite some time
back, in the Setting up default policies section, in this chapter.
After this first check for bad TCP packets, we have the main rules in the
FORWARD chain. The first rule will allow all traffic from our
$LAN_IFACE to any other interface to flow freely, without restrictions.
This rule will in other words allow all traffic from our LAN to the
Internet. The second rule will allow ESTABLISHED and RELATED
traffic back through the firewall. This will in other words allow packets
belonging to connections that was initiated from our internal network to
flow freely back to our local network. These rules are required for our
local network to be able to access the Internet, since the default policy of
the FORWARD chain was previously set to DROP. This is quite clever,
since it will allow hosts on our local network to connect to hosts on the
Internet, but at the same time block hosts on the Internet from connecting
to the hosts on our internal network.
Even though this is the structure I have chosen, do note that this
may not be the best structure for your scripts. It is only a
structure that I have chosen to use since it fits the need of being
easy to read and follow the best according to my logic.
4.I. Filter table - First of all we go through the filter table and
its content. First of all we should set up all the policies in
the table.
4.I.a.) Set policies - Set up all the default policies for the
system chains. Normally I will set DROP policies
on the chains in the filter table, and specifically
ACCEPT services and streams that I want to allow
inside. This way we will get rid of all ports that we
do not want to let people use.
5. nat table - After the filter table we take care of the nat table. This is
done after the filter table because of a number of reasons within these
scripts. First of all we do not want to turn the whole forwarding
mechanism and NAT function on at a too early stage, which could
possibly lead to packets getting through the firewall at just the wrong
time point (i.e., when the NAT has been turned on, but none of the
filter rules has been run). Also, I look upon the nat table as a sort of
layer that lies just outside the filter table and kind of surrounds it.
The filter table would hence be the core, while the nat table acts as a
layer lying around the filter table, and finally the mangle table lies
around the nat table as a second layer. This may be wrong in some
perspectives, but not too far from reality.
6.I. Set policies - Set the default policies within the chain. The
same thing goes here as for the nat table pretty much. The
table was not made for filtering, and hence you should
avoid it all together. I have not set any policies in any of
the scripts in the mangle table one way or the other, and
you are encouraged not to do so either.
6.II. Create user specified chains - Create all the user specified
chains. Since I have barely used the mangle table at all in
the scripts, I have neither created any chains here since it
is fairly unusable without any data to use within it.
However, this section was added just in case someone, or
I, would have the need for it in the future.
Hopefully this should explain more in detail how each script is structured
and why they are structured in such a way.
The rc.firewall.txt script is the main core on which the rest of the scripts
are based upon. The rc.firewall file chapter should explain every detail in
the script most thoroughly. Mainly it was written for a dual homed
network. For example, where you have one LAN and one Internet
Connection. This script also makes the assumption that you have a static
IP to the Internet, and hence don't use DHCP, PPP, SLIP or some other
protocol that assigns you an IP automatically. If you are looking for a
script that will work with those setups, please take a closer look at the
rc.DHCP.firewall.txt script.
CONFIG_NETFILTER
CONFIG_IP_NF_CONNTRACK
CONFIG_IP_NF_IPTABLES
CONFIG_IP_NF_MATCH_LIMIT
CONFIG_IP_NF_MATCH_STATE
CONFIG_IP_NF_FILTER
CONFIG_IP_NF_NAT
CONFIG_IP_NF_TARGET_LOG
The rc.DMZ.firewall.txt script was written for those people out there that
have one Trusted Internal Network, one De-Militarized Zone and one
Internet Connection. The De-Militarized Zone is in this case 1-to-1
NATed and requires you to do some IP aliasing on your firewall, i.e.,
you must make the box recognize packets for more than one IP. There
are several ways to get this to work, one is to set 1-to-1 NAT, another
one if you have a whole subnet is to create a subnetwork, giving the
firewall one IP both internally and externally. You could then set the IP's
to the DMZed boxes as you wish. Do note that this will "steal" two IP's
for you, one for the broadcast address and one for the network address.
CONFIG_NETFILTER
CONFIG_IP_NF_CONNTRACK
CONFIG_IP_NF_IPTABLES
CONFIG_IP_NF_MATCH_LIMIT
CONFIG_IP_NF_MATCH_STATE
CONFIG_IP_NF_FILTER
CONFIG_IP_NF_NAT
CONFIG_IP_NF_TARGET_LOG
You need to have two internal networks with this script as you can see
from the picture. One uses IP range 192.168.0.0/24 and consists of a
Trusted Internal Network. The other one uses IP range 192.168.1.0/24
and consists of the De-Militarized Zone which we will do 1-to-1 NAT to.
For example, if someone from the Internet sends a packet to our DNS_IP,
then we use DNAT, to send the packet on to our DNS on the DMZ
network. When the DNS sees our packet, the packet will be destined for
the actual DNS internal network IP, and not to our external DNS IP. If
the packet would not have been translated, the DNS wouldn't have
answered the packet. We will show a short example of how the DNAT
code looks:
8.4. rc.DHCP.firewall.txt
The main changes done to the script consists of erasing the STATIC_IP
variable as I already said and deleting all references to this variable.
Instead of using this variable the script now does its main filtering on the
variable INET_IFACE. In other words -d $STATIC_IP has been changed
to -i $INET_IFACE. This is pretty much the only changes made and
that's all that's needed really.
There are some more things to think about though. We can no longer
filter in the INPUT chain depending on, for example, --in-interface
$LAN_IFACE --dst $INET_IP. This in turn forces us to filter only
based on interfaces in such cases where the internal machines must
access the Internet addressable IP. One great example is if we are
running an HTTP on our firewall. If we go to the main page, which
contains static links back to the same host, which could be some dyndns
solution, we would get a real hard trouble. The NATed box would ask
the DNS for the IP of the HTTP server, then try to access that IP. In case
we filter based on interface and IP, the NATed box would be unable to
get to the HTTP because the INPUT chain would DROP the packets flat
Step by StepTM Linux Guide. Page 165
to the ground. This also applies in a sense to the case where we got a
static IP, but in such cases it could be gotten around by adding rules
which check the LAN interface packets for our INET_IP, and if so
ACCEPT them.
As you may read from above, it may be a good idea to get a script, or
write one, that handles dynamic IP in a better sense. We could for
example make a script that grabs the IP from ifconfig and adds it to a
variable, upon boot-up of the Internet connection. A good way to do this,
would be to use for example the ip-up scripts provided with pppd and
some other programs. For a good site, check out the linuxguruz.org
iptables site which has a huge collection of scripts available to download.
You will find a link to the linuxguruz.org site from the Other resources
and links appendix.
Also, there is the possibility to add something like this to your scripts:
INET_IP=`ifconfig $INET_IFACE | grep inet | cut -d : -f 2 | \
cut -d ' ' -f 1`
8.5. rc.UTIN.firewall.txt
• CONFIG_NETFILTER
• CONFIG_IP_NF_CONNTRACK
• CONFIG_IP_NF_IPTABLES
• CONFIG_IP_NF_MATCH_LIMIT
• CONFIG_IP_NF_MATCH_STATE
• CONFIG_IP_NF_FILTER
• CONFIG_IP_NF_NAT
• CONFIG_IP_NF_TARGET_LOG
This script follows the golden rule to not trust anyone, not even our own
employees. This is a sad fact, but a large part of the hacks and cracks that
a company gets hit by is a matter of people from their own staff
perpetrating the hit. This script will hopefully give you some clues as to
what you can do with your firewall to strengthen it up. It's not very
different from the original rc.firewall.txt script, but it does give a
few hints at what we would normally let through etc.
ping -c 1 host.on.the.internet
This script was written for testing purposes only. In other words,
it's not a good idea to have rules like this that logs everything of
one sort since your log partitions might get filled up quickly and
it would be an effective Denial of Service attack against you and
might lead to real attacks on you that would be unlogged after
the initial Denial of Service attack.
8.7. rc.flush-iptables.txt
The rc.flush-iptables.txt script should not really be called a script in
itself. The rc.flush-iptables.txt script will reset and flush all your tables
and chains. The script starts by setting the default policies to ACCEPT
on the INPUT, OUTPUT and FORWARD chains of the filter table.
After this we reset the default policies of the PREROUTING,
POSTROUTING and OUTPUT chains of the nat table. We do this first
so we won't have to bother about closed connections and packets not
getting through. This script is intended for actually setting up and
Step by StepTM Linux Guide. Page 169
troubleshooting your firewall, and hence we only care about opening the
whole thing up and reset it to default values.
After this we flush all chains first in the filter table and then in the NAT
table. This way we know there is no redundant rules lying around
anywhere. When all of this is done, we jump down to the next section
where we erase all the user specified chains in the NAT and filter tables.
When this step is done, we consider the script done. You may consider
adding rules to flush your mangle table if you use it.
8.8. Limit-match.txt
The limit-match.txt script is a minor test script which will let you test the
limit match and see how it works. Load the script up, and then send ping
packets at different intervals to see which gets through, and how often
they get through. All echo replies will be blocked until the threshold for
the burst limit has again been reached.
8.10. Sid-owner.txt
The sid-owner.txt is a small example script that shows how we could use
the SID owner match. It does nothing real, but you should be able to run
the script, and then from the output of iptables -L -v be able to tell that
the rule actually matches.
8.11. Ttl-inc.txt
A small example ttl-inc.txt script. This script shows how we could make
the firewall/router invisible to traceroutes, which would otherwise reveal
much information to possible attackers.
##########################################################
#################
#
# 1. Configuration options.
#
#
# 1.1 Internet Configuration.
#
#
# 1.1.1 DHCP
#
#
# 1.1.2 PPPoE
#
#
# 1.2 Local Area Network configuration.
#
# your LAN's IP range and localhost IP. /24 means to only
use the first 24
# bits of the 32 bit IP address. the same as netmask
255.255.255.0
#
LAN_IP="192.168.0.2"
LAN_IP_RANGE="192.168.0.0/16"
LAN_IFACE="eth1"
#
# 1.3 DMZ Configuration.
#
#
# 1.4 Localhost Configuration.
#
LO_IFACE="lo"
LO_IP="127.0.0.1"
#
# 1.5 IPTables Configuration.
#
IPTABLES="/usr/sbin/iptables"
#
# 1.6 Other Configuration.
#
##########################################################
#################
#
# 2. Module loading.
#
/sbin/depmod -a
#
# 2.1 Required modules
#
/sbin/modprobe ip_tables
/sbin/modprobe ip_conntrack
/sbin/modprobe iptable_filter
/sbin/modprobe iptable_mangle
/sbin/modprobe iptable_nat
/sbin/modprobe ipt_LOG
/sbin/modprobe ipt_limit
/sbin/modprobe ipt_state
#
# 2.2 Non-Required modules
#
#/sbin/modprobe ipt_owner
#/sbin/modprobe ipt_REJECT
#/sbin/modprobe ipt_MASQUERADE
#/sbin/modprobe ip_conntrack_ftp
#/sbin/modprobe ip_conntrack_irc
#/sbin/modprobe ip_nat_ftp
#/sbin/modprobe ip_nat_irc
##########################################################
#################
#
# 3. /proc set up.
#
#
# 3.1 Required proc configuration
#
#
# 3.2 Non-Required proc configuration
#
######
# 4.1 Filter table
#
#
# 4.1.1 Set policies
#
#
# 4.1.2 Create userspecified chains
#
#
# Create chain for bad tcp packets
#
$IPTABLES -N bad_tcp_packets
#
# Create separate chains for ICMP, TCP and UDP to traverse
#
$IPTABLES -N allowed
$IPTABLES -N tcp_packets
$IPTABLES -N udp_packets
$IPTABLES -N icmp_packets
#
# 4.1.3 Create content in userspecified chains
#
#
# bad_tcp_packets chain
#
#
# allowed chain
#
#
# TCP rules
#
#
# UDP ports
#
#
# In Microsoft Networks you will be swamped by broadcasts.
These lines
# will prevent them from showing up in the logs.
#
#
# ICMP rules
#
#
# 4.1.4 INPUT chain
#
#
# Bad TCP packets we don't want.
#
#
# Rules for special networks not part of the Internet
#
#
# Special rule for DHCP requests from LAN, which are not
caught properly
# otherwise.
#
#
# If you have a Microsoft Network on the outside of your
firewall, you may
# also get flooded by Multicasts. We drop them so we do
not get flooded by
# logs
#
#
# Log weird packets that don't match the above.
#
#
# 4.1.5 FORWARD chain
#
#
# Bad TCP packets we don't want
#
#
# Accept the packets we actually want to forward
#
#
# Log weird packets that don't match the above.
#
#
# 4.1.6 OUTPUT chain
#
#
# Bad TCP packets we don't want.
#
#
# Special OUTPUT rules to decide which IP's to allow.
#
#
# Log weird packets that don't match the above.
#
######
# 4.2 nat table
#
#
# 4.2.1 Set policies
#
#
# 4.2.2 Create user specified chains
#
#
# 4.2.3 Create content in user specified chains
#
#
# 4.2.4 PREROUTING chain
#
#
# Enable simple IP Forwarding and Network Address
Translation
#
#
# 4.2.6 OUTPUT chain
#
######
# 4.3 mangle table
#
#
# 4.3.1 Set policies
#
#
# 4.3.2 Create user specified chains
#
#
# 4.3.3 Create content in user specified chains
#
#
# 4.3.4 PREROUTING chain
#
#
# 4.3.5 INPUT chain
#
#
# 4.3.6 FORWARD chain
#
#
# 4.3.7 OUTPUT chain
#
#
# 4.3.8 POSTROUTING chain
#
##########################################################
#################
#
# 1. Configuration options.
#
#
# 1.1 Internet Configuration.
#
INET_IP="194.236.50.152"
HTTP_IP="194.236.50.153"
DNS_IP="194.236.50.154"
INET_IFACE="eth0"
#
# 1.1.2 PPPoE
#
#
# 1.2 Local Area Network configuration.
#
# your LAN's IP range and localhost IP. /24 means to only
use the first 24
# bits of the 32 bit IP address. the same as netmask
255.255.255.0
#
LAN_IP="192.168.0.1"
LAN_IFACE="eth1"
#
# 1.3 DMZ Configuration.
#
DMZ_HTTP_IP="192.168.1.2"
DMZ_DNS_IP="192.168.1.3"
DMZ_IP="192.168.1.1"
DMZ_IFACE="eth2"
#
# 1.4 Localhost Configuration.
#
LO_IFACE="lo"
LO_IP="127.0.0.1"
#
# 1.5 IPTables Configuration.
#
IPTABLES="/usr/sbin/iptables"
#
# 1.6 Other Configuration.
#
##########################################################
#################
#
# 2. Module loading.
#
# Needed to initially load modules
#
/sbin/depmod -a
#
# 2.1 Required modules
#
/sbin/modprobe ip_tables
/sbin/modprobe ip_conntrack
/sbin/modprobe iptable_filter
/sbin/modprobe iptable_mangle
/sbin/modprobe iptable_nat
/sbin/modprobe ipt_LOG
/sbin/modprobe ipt_limit
/sbin/modprobe ipt_state
#
# 2.2 Non-Required modules
#
#/sbin/modprobe ipt_owner
#/sbin/modprobe ipt_REJECT
#/sbin/modprobe ipt_MASQUERADE
#/sbin/modprobe ip_conntrack_ftp
#/sbin/modprobe ip_conntrack_irc
#/sbin/modprobe ip_nat_ftp
#/sbin/modprobe ip_nat_irc
##########################################################
#################
#
# 3. /proc set up.
#
#
# 3.1 Required proc configuration
#
#
# 3.2 Non-Required proc configuration
#
##########################################################
#################
#
# 4. rules set up.
#
######
# 4.1 Filter table
#
#
# 4.1.1 Set policies
#
#
# 4.1.2 Create userspecified chains
#
#
# Create chain for bad tcp packets
#
$IPTABLES -N bad_tcp_packets
#
# Create separate chains for ICMP, TCP and UDP to traverse
#
$IPTABLES -N allowed
$IPTABLES -N icmp_packets
#
# 4.1.3 Create content in userspecified chains
#
#
# bad_tcp_packets chain
#
#
# allowed chain
#
#
# ICMP rules
#
#
# 4.1.4 INPUT chain
#
#
# Bad TCP packets we don't want
#
#
# Packets from the Internet to this box
#
#
# Packets from LAN, DMZ or LOCALHOST
#
#
# From DMZ Interface to DMZ firewall IP
#
#
# From Localhost interface to Localhost IP's
#
#
# Special rule for DHCP requests from LAN, which are not
caught properly
# otherwise.
#
#
# All established and related packets incoming from the
internet to the
# firewall
#
#
# In Microsoft Networks you will be swamped by broadcasts.
These lines
# will prevent them from showing up in the logs.
#
#
# If we get DHCP requests from the Outside of our network,
our logs will
# be swamped as well. This rule will block them from
getting logged.
#
#
# If you have a Microsoft Network on the outside of your
firewall, you may
# also get flooded by Multicasts. We drop them so we do
not get flooded by
# logs
#
#
# Log weird packets that don't match the above.
#
#
# 4.1.5 FORWARD chain
#
#
# Bad TCP packets we don't want
#
#
# DMZ section
#
# General rules
#
#
# DNS server
#
#
# LAN section
#
#
# Log weird packets that don't match the above.
#
#
# 4.1.6 OUTPUT chain
#
#
# Bad TCP packets we don't want.
#
#
# Log weird packets that don't match the above.
#
######
# 4.2 nat table
#
#
# 4.2.1 Set policies
#
#
# 4.2.2 Create user specified chains
#
#
# 4.2.3 Create content in user specified chains
#
#
# 4.2.4 PREROUTING chain
#
#
# 4.2.5 POSTROUTING chain
#
#
# 4.2.6 OUTPUT chain
#
######
# 4.3 mangle table
#
#
# 4.3.1 Set policies
#
#
# 4.3.2 Create user specified chains
#
#
# 4.3.3 Create content in user specified chains
#
#
# 4.3.4 PREROUTING chain
#
#
# 4.3.5 INPUT chain
#
#
# 4.3.6 FORWARD chain
#
#
# 4.3.7 OUTPUT chain
#
#
# 4.3.8 POSTROUTING chain
#
##########################################################
#################
#
# 1. Configuration options.
#
#
# 1.1 Internet Configuration.
#
INET_IP="194.236.50.155"
INET_IFACE="eth0"
INET_BROADCAST="194.236.50.255"
#
# 1.1.2 PPPoE
#
#
# 1.2 Local Area Network configuration.
#
# your LAN's IP range and localhost IP. /24 means to only
use the first 24
# bits of the 32 bit IP address. the same as netmask
255.255.255.0
#
LAN_IP="192.168.0.2"
LAN_IP_RANGE="192.168.0.0/16"
LAN_IFACE="eth1"
#
# 1.3 DMZ Configuration.
#
#
# 1.4 Localhost Configuration.
#
LO_IFACE="lo"
LO_IP="127.0.0.1"
#
# 1.5 IPTables Configuration.
#
IPTABLES="/usr/sbin/iptables"
#
# 1.6 Other Configuration.
#
##########################################################
#################
#
# 2. Module loading.
#
#
# Needed to initially load modules
#
#
# 2.1 Required modules
#
/sbin/modprobe ip_tables
/sbin/modprobe ip_conntrack
/sbin/modprobe iptable_filter
/sbin/modprobe iptable_mangle
/sbin/modprobe iptable_nat
/sbin/modprobe ipt_LOG
/sbin/modprobe ipt_limit
/sbin/modprobe ipt_state
#
# 2.2 Non-Required modules
#
#/sbin/modprobe ipt_owner
#/sbin/modprobe ipt_REJECT
#/sbin/modprobe ipt_MASQUERADE
#/sbin/modprobe ip_conntrack_ftp
#/sbin/modprobe ip_conntrack_irc
#/sbin/modprobe ip_nat_ftp
#/sbin/modprobe ip_nat_irc
##########################################################
#################
#
# 3. /proc set up.
#
#
# 3.1 Required proc configuration
#
#
# 3.2 Non-Required proc configuration
#
##########################################################
#################
#
######
# 4.1 Filter table
#
#
# 4.1.1 Set policies
#
#
# 4.1.2 Create userspecified chains
#
#
# Create chain for bad tcp packets
#
$IPTABLES -N bad_tcp_packets
#
# Create separate chains for ICMP, TCP and UDP to traverse
#
$IPTABLES -N allowed
$IPTABLES -N tcp_packets
$IPTABLES -N udp_packets
$IPTABLES -N icmp_packets
#
# 4.1.3 Create content in userspecified chains
#
#
# bad_tcp_packets chain
#
#
# TCP rules
#
#
# UDP ports
#
#
# In Microsoft Networks you will be swamped by broadcasts.
These lines
# will prevent them from showing up in the logs.
#
#
# If we get DHCP requests from the Outside of our network,
our logs will
# be swamped as well. This rule will block them from
getting logged.
#
#
# ICMP rules
#
#
# 4.1.4 INPUT chain
#
#
# Bad TCP packets we don't want.
#
#
# Rules for special networks not part of the Internet
#
#
# Rules for incoming packets from anywhere.
#
#
# If you have a Microsoft Network on the outside of your
firewall, you may
# also get flooded by Multicasts. We drop them so we do
not get flooded by
# logs
#
# Log weird packets that don't match the above.
#
#
# 4.1.5 FORWARD chain
#
#
# Bad TCP packets we don't want
#
#
# Accept the packets we actually want to forward
#
#
# Log weird packets that don't match the above.
#
#
# 4.1.6 OUTPUT chain
#
#
# Bad TCP packets we don't want.
#
#
# Special OUTPUT rules to decide which IP's to allow.
#
#
# Log weird packets that don't match the above.
#
######
# 4.2 nat table
#
#
# 4.2.1 Set policies
#
#
# 4.2.2 Create user specified chains
#
#
# 4.2.3 Create content in user specified chains
#
#
# 4.2.4 PREROUTING chain
#
#
# 4.2.5 POSTROUTING chain
#
#
# Enable simple IP Forwarding and Network Address
Translation
#
######
# 4.3 mangle table
#
#
# 4.3.1 Set policies
#
#
# 4.3.2 Create user specified chains
#
#
# 4.3.3 Create content in user specified chains
#
#
# 4.3.4 PREROUTING chain
#
#
# 4.3.5 INPUT chain
#
#
# 4.3.6 FORWARD chain
#
#
# 4.3.7 OUTPUT chain
#
#
# 4.3.8 POSTROUTING chain
#
##########################################################
#################
#
# 1. Configuration options.
#
#
# 1.1 Internet Configuration.
#
INET_IFACE="eth0"
#
# 1.1.1 DHCP
#
# Information pertaining to DHCP over the Internet, if
needed.
#
# Set DHCP variable to no if you don't get IP from DHCP.
If you get DHCP
# over the Internet set this variable to yes, and set up
the proper IP
# address for the DHCP server in the DHCP_SERVER variable.
#
DHCP="no"
DHCP_SERVER="195.22.90.65"
#
# 1.1.2 PPPoE
#
PPPOE_PMTU="no"
#
# 1.2 Local Area Network configuration.
#
# your LAN's IP range and localhost IP. /24 means to only
use the first 24
# bits of the 32 bit IP address. the same as netmask
255.255.255.0
#
LAN_IP="192.168.0.2"
LAN_IP_RANGE="192.168.0.0/16"
#
# 1.3 DMZ Configuration.
#
#
# 1.4 Localhost Configuration.
#
LO_IFACE="lo"
LO_IP="127.0.0.1"
#
# 1.5 IPTables Configuration.
#
IPTABLES="/usr/sbin/iptables"
#
# 1.6 Other Configuration.
#
##########################################################
#################
#
# 2. Module loading.
#
#
# Needed to initially load modules
#
/sbin/depmod -a
#
# 2.1 Required modules
#
/sbin/modprobe ip_conntrack
/sbin/modprobe ip_tables
/sbin/modprobe iptable_filter
/sbin/modprobe iptable_mangle
/sbin/modprobe iptable_nat
/sbin/modprobe ipt_LOG
/sbin/modprobe ipt_limit
/sbin/modprobe ipt_MASQUERADE
#
# 2.2 Non-Required modules
#
##########################################################
#################
#
# 3. /proc set up.
#
#
# 3.1 Required proc configuration
#
#
# 3.2 Non-Required proc configuration
#
##########################################################
#################
#
# 4. rules set up.
#
######
# 4.1 Filter table
#
#
# 4.1.1 Set policies
#
#
# 4.1.2 Create userspecified chains
#
$IPTABLES -N bad_tcp_packets
#
# Create separate chains for ICMP, TCP and UDP to traverse
#
$IPTABLES -N allowed
$IPTABLES -N tcp_packets
$IPTABLES -N udp_packets
$IPTABLES -N icmp_packets
#
# 4.1.3 Create content in userspecified chains
#
#
# bad_tcp_packets chain
#
#
# allowed chain
#
#
# TCP rules
#
#
# UDP ports
#
#
# In Microsoft Networks you will be swamped by broadcasts.
These lines
# will prevent them from showing up in the logs.
#
#
# If we get DHCP requests from the Outside of our network,
our logs will
# be swamped as well. This rule will block them from
getting logged.
#
#
# ICMP rules
#
#
# 4.1.4 INPUT chain
#
#
# Bad TCP packets we don't want.
#
#
# Rules for special networks not part of the Internet
#
#
# Special rule for DHCP requests from LAN, which are not
caught properly
# otherwise.
#
#
# Rules for incoming packets from the internet.
#
#
# If you have a Microsoft Network on the outside of your
firewall, you may
# also get flooded by Multicasts. We drop them so we do
not get flooded by
# logs
#
#
# 4.1.5 FORWARD chain
#
#
# Bad TCP packets we don't want
#
#
# Accept the packets we actually want to forward
#
#
# Log weird packets that don't match the above.
#
#
# 4.1.6 OUTPUT chain
#
#
# Bad TCP packets we don't want.
#
#
# Special OUTPUT rules to decide which IP's to allow.
#
######
# 4.2 nat table
#
#
# 4.2.1 Set policies
#
#
# 4.2.2 Create user specified chains
#
#
# 4.2.3 Create content in user specified chains
#
#
# 4.2.4 PREROUTING chain
#
#
# 4.2.5 POSTROUTING chain
#
#
# 4.2.6 OUTPUT chain
#
######
# 4.3 mangle table
#
#
# 4.3.1 Set policies
#
# 4.3.2 Create user specified chains
#
#
# 4.3.3 Create content in user specified chains
#
#
# 4.3.4 PREROUTING chain
#
#
# 4.3.5 INPUT chain
#
#
# 4.3.6 FORWARD chain
#
#
# 4.3.7 OUTPUT chain
#
#
# 4.3.8 POSTROUTING chain
#
#
# Configurations
#
IPTABLES="/usr/sbin/iptables"
#
# reset the default policies in the filter table.
#
$IPTABLES -P INPUT ACCEPT
$IPTABLES -P FORWARD ACCEPT
$IPTABLES -P OUTPUT ACCEPT
#
# reset the default policies in the nat table.
#
$IPTABLES -t nat -P PREROUTING ACCEPT
$IPTABLES -t nat -P POSTROUTING ACCEPT
$IPTABLES -t nat -P OUTPUT ACCEPT
#
# reset the default policies in the mangle table.
#
$IPTABLES -t mangle -P PREROUTING ACCEPT
$IPTABLES -t mangle -P OUTPUT ACCEPT
#
# flush all the rules in the filter and nat tables.
#
$IPTABLES -F
$IPTABLES -t nat -F
$IPTABLES -t mangle -F
#
# erase all chains that's not default in filter and nat
table.
#
$IPTABLES -X
$IPTABLES -t nat -X
$IPTABLES -t mangle -X
Step by StepTM Linux Guide. Page 210
I.6. Example rc.test-iptables script
#!/bin/bash
#
# rc.test-iptables - test script for iptables chains and
tables.
#
# Copyright (C) 2001 Oskar Andreasson
<bluefluxATkoffeinDOTnet>
#
# 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; version 2 of the License.
#
# 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 or from the site that you
downloaded it
# from; if not, write to the Free Software Foundation,
Inc., 59 Temple
# Place, Suite 330, Boston, MA 02111-1307 USA
#
#
# Filter table, all chains
#
iptables -t filter -A INPUT -p icmp --icmp-type echo-
request \
-j LOG --log-prefix="filter INPUT:"
iptables -t filter -A INPUT -p icmp --icmp-type echo-reply
\
-j LOG --log-prefix="filter INPUT:"
iptables -t filter -A OUTPUT -p icmp --icmp-type echo-
request \
-j LOG --log-prefix="filter OUTPUT:"
#
# NAT table, all chains except OUTPUT which don't work.
#
iptables -t nat -A PREROUTING -p icmp --icmp-type echo-
request \
-j LOG --log-prefix="nat PREROUTING:"
iptables -t nat -A PREROUTING -p icmp --icmp-type echo-
reply \
-j LOG --log-prefix="nat PREROUTING:"
iptables -t nat -A POSTROUTING -p icmp --icmp-type echo-
request \
-j LOG --log-prefix="nat POSTROUTING:"
iptables -t nat -A POSTROUTING -p icmp --icmp-type echo-
reply \
-j LOG --log-prefix="nat POSTROUTING:"
iptables -t nat -A OUTPUT -p icmp --icmp-type echo-request
\
-j LOG --log-prefix="nat OUTPUT:"
iptables -t nat -A OUTPUT -p icmp --icmp-type echo-reply \
-j LOG --log-prefix="nat OUTPUT:"
#
# Mangle table, all chains
#
iptables -t mangle -A PREROUTING -p icmp --icmp-type echo-
request \
-j LOG --log-prefix="mangle PREROUTING:"
iptables -t mangle -A PREROUTING -p icmp --icmp-type echo-
reply \
-j LOG --log-prefix="mangle PREROUTING:"
iptables -t mangle -I FORWARD 1 -p icmp --icmp-type echo-
request \
-j LOG --log-prefix="mangle FORWARD:"
iptables -t mangle -I FORWARD 1 -p icmp --icmp-type echo-
reply \
-j LOG --log-prefix="mangle FORWARD:"
iptables -t mangle -I INPUT 1 -p icmp --icmp-type echo-
request \
-j LOG --log-prefix="mangle INPUT:"
iptables -t mangle -I INPUT 1 -p icmp --icmp-type echo-
reply \
First do this lab and read the DNS concepts after this lab. Good Luck
options {
directory "/var/named";
// query-source address * port 53;
};
zone "." IN { //The zone '.' is shorthand for the root domain which translates to 'any
//domain not defined as either a master or slave in this named.conf file'.
type hint; // If a server is going to provide caching services then it must provide
//recursive queries and recursive queries need access to the root servers which is
//provided via the 'type hint' statement.
file "named.ca"; //named.ca file has the list of root servers
};
zone "localhost" IN {
type master;
file "localhost.zone";
allow-update { none; };
};
zone "0.0.127.in-addr.arpa" IN {
type master;
file "named.local";
allow-update { none; };
};
zone "suranga.com" IN {
type master;
zone "200.168.192.in-addr.arpa" IN {
type master;
allow-update { none; };
};
1. 0.0.127.in-addr.arpa.zone
2. 200.168.192.in-addr.arpa.zone
3. suranga.com.zone
4. localhost.zone
5 . named.local
$TTL 86400
@ IN SOA localhost. root.localhost (
1 ; serial
28800 ; refresh
7200 ; retry
604800 ; expire
86400 ; ttk
)
@ IN NS localhost.
1 IN PTR localhost.
$TTL 86400
@ IN SOA 192.168.200.8. root.localhost (
1 ; serial
28800 ; refresh
7200 ; retry
604800 ; expire
86400 ; ttk
)
@ IN NS localhost.
1 IN PTR localhost.
2 IN PTR im3.
suranga.com.zone file
$TTL 86400
@ IN SOA @ root.suranga.com (
1 ; serial
28800 ; refresh
7200 ; retry
604800 ; expire
86400 ; ttl
)
IN NS suranga.com.
@ IN A 192.168.200.8
im3 IN A 192.168.200.250
IN NS localhost.
@ IN A 127.0.0.1
named.localhost file
$TTL 86400
@ IN SOA localhost. root.localhost. (
1997022700 ; Serial
28800 ; Refresh
14400 ; Retry
3600000 ; Expire
86400 ) ; Minimum
IN NS localhost.
1 IN PTR localhost.
Now go to the prompt and type service named start and type nslookup
commands to verify your domain as follows.
Name: suranga.com
Address: 192.168.200.8
>im3.suranga.com
Server: 192.168.200.8
Address: 192.168.200.8#53
Name: im3.suranga.com
Address: 192.168.200.250
Zone:
Basically a zone that keeps the information about the domain database.
1800;retry: This particular line refers to the retry cycle which in turn
means that the slave server should wait before asking the master server
again in case master server doesn’t respond.
Before begin just skim the following definitions you will understand all
later
A 'zone' is convenient short-hand for that part of the domain name for
which we are configuring the DNS server (e.g. BIND) and is always an
entity for which we are authoritative.
suranga.com.zone file
$TTL 86400
@ IN SOA @ root.suranga.com (
1 ; serial
28800 ; refresh
7200 ; retry
604800 ; expire
86400 ; ttl
)
IN NS suranga.com.
@ IN A 192.168.200.8
im3 IN A 192.168.200.250
Resource Records(RR)
Resource Records are defined by RFC 1035. Resource Records describe
global properties of a zone and the hosts or services that are part of the
zone. Resource Records have a binary format, used internally by DNS
software and when sent across a network e.g. zone updates, and a text
format which is used in zone files.
Step by StepTM Linux Guide. Page 220
Resource Records include SOA Record, NS Records, A Records,
CNAME Records, PTR Records, MX Records.
Format
name ttl class rr name-server mail-address (se ref ret ex min)
suranga.com. IN SOA ns.suranga.com. root.suranga.com. (
2003080800 ; se = serial number
18000 ; ref = refresh
900 ; ret = update retry
259200 ; ex = expiry
10800 ; min = minimum
)
Format
name ttl class rr name
suranga.com. IN NS ns1.suranga.com.
The name servers also need an A record if they are in the same zone.
While only one name server is defined in the SOA record any number of
NS records may be defined. Name servers are not required to be in the
same zone and in most cases probably are not.
If multiple address are defined with either the same name or without a
name then BIND will respond to queries with all the addresses defined
but the order will change The same IP may be defined with different
names (beware: in this case a reverse lookup may not give the result you
want). IP addresses do not have to be in the same class or range.
You can map other CNAME records to a CNAME record but this
considered bad practice since 'queries' will look for the A record and this
will involve additional DNS transactions.
Format
name ttl class rr name
15 IN PTR www.suranga.com.
The number '15' (the base IP address) is actually a name and because
there is no 'dot' BIND adds the $ORIGIN. The example below which
defines a reverse map zone file for the Class C address 192.168.23.0
should make this clearer:
Step by StepTM Linux Guide. Page 225
$TTL 12h
$ORIGIN 23.168.192.IN-ADDR.ARPA.
@ IN SOA ns1.suranga.com. root.suranga.com. (
2003080800 ; serial number
3h ; refresh
15m ; update retry
3w ; expiry
3h ; minimum
)
IN NS ns1.suranga.com.
IN NS ns2.suranga.com.
2 IN PTR web.suranga.com. ; qualified names
....
15 IN PTR www.suranga.com.
....
17 IN PTR mail.suranga.com.
....
74 IN PTR im.suranga.com.
....
Format
name ttl class rr pref name
suranga.com. IN MX 10 mail.suranga.com.
The Preference field is relative to any other MX record for the zone
(value 0 to 65535). Low values are more preferred. The preferred value
10 you see all over the place is just a convention. Any number of MX
records may be defined. If the host is in the domain it requires an A
record. MX records do not need to point to a host in this zone.
There are a number of ways your system can resolve a name and the
actual order will vary based on your configuration:
1. If you are using a linux system with the GNU glibc libraries the
order of lookup is determined by the 'hosts' entry in the
/etc/nsswitch.conf file which will read something like:
order hosts,bind
The Domain Name System uses a tree (or hierarchical) name structure.
At the top of the tree is the root followed by the Top Level Domains
(TLDs) then the domain-name and any number of lower levels each
separated with a dot.
NOTE:
domain-name.tld e.g.
suranga.com
So What is www.suranga.com
A host name must be unique within the 'Domain Name' but can be
anything the owner of 'suranga.com' wants.
www.mail.suranga.com
The Authority and therefore the responsibility for the User (or 'Domain
Name') DNS servers lies with the owner of the domain. In the majority
of cases this responsibility is delegated by the owner of the Domain to
an ISP, Web Hosting company or increasingly a registrar.
When any DNS cannot answer (resolve) a request for a domain name
from a host e.g. suranga.com the query is passed to a Root-Server which
will direct the query to the appropriate TLD DNS server which will in
turn direct it to the appropriate Domain (User) DNS server.
A single DNS server may support many domains. The data for each
domain describes global properties of the domain and its hosts (or
services). This data is defined in the form of textual Resource Records
organized in Zone Files. The format of Zone files is defined in RFC
1035 and is supported by most DNS software.
The zone file formats which constitute the majority of the work
(depending on how many sites you operate) is standard and is typically
supported by all the DNS suppliers.
DNS Queries
The major task carried out by a DNS server is to respond to queries
(questions) from a local or remote resolver or other DNS acting on
behalf of a resolver. A query would be something like 'what is the IP
address of host=mail in domain=suranga.com'.
A DNS server may receive such a query for any domain. DNS servers
may be configured to be authoritative for some (if any) domains, slaves,
caching, forwarding or many other combination.
Most of the queries that a DNS server will receive will be for domains
for which it has no knowledge that is outside its own domain for which
it has no local zone files. The DNS system allows the name server to
respond in different ways to queries about which it has no knowledge.
Recursive Queries
A recursive query is one where the DNS server will fully answer the
query (or give an error). DNS servers are not required to support
recursive queries.
Inverse Queries
An Inverse query maps a resource record to a domain. An example
Inverse query would be 'what is the domain name for this MX record'.
Inverse query support is optional and it is permitted from the DNS
server to return a response 'Not Implemented'.
Inverse queries are NOT used to find a host name given an IP address.
This process is called Reverse Mapping (Look-up) uses recursive and
Iterative (non-recursive) queries with the special domain name IN-
ADDR.ARPA.
The process works as for AXFR. The 'slave' sends a query for the
domain's SOA Resource Record every REFRESH interval. If the
SERIAL value of the SOA record has changed the 'slave' requests a
Zone Transfer and indicates whether or not it is capable of accepting an
Incremental Transfer (IXFR). If both 'master' and 'slave' support the
feature and incremental transfer takes place. Incremental Zone transfers
use TCP on port 53.
The default mode for BIND when acting as a 'slave' is to use IXFR.
Notify (NOTIFY)
RFC 1912 recommends a REFRESH interval of up to 12 hours on the
REFRESH interval of an SOA Resource Record. This means that
changes to the 'master' DNS may not be visible at the 'slave' DNS for up
to 12 hours. In a dynamic environment this is unacceptable. RFC 1996
introduced a scheme whereby the 'master' will send a NOTIFY message
to the 'slave' DNS systems that a change MAY have occurred in the
domain records. The 'slave' on receipt of the NOTIFY will request the
latest SOA Resource Record and if the SERIAL value is different will
attempt a Zone Transfer using either a full Zone Transfer (AXFR) or an
Incremental Transfer (IXFR).
Dynamic Update
The classic method of updating Zone Resource Records is to manually
edit the zone file and then stop and start the name server to propagate the
changes. When the volume of changes reaches a certain level this can
become operationally unacceptable - especially considering that in an
organization which handle large numbers of Zone Files, such as service
provider, BIND itself can take a long time to restart at it plows through
very large numbers of zone statements.
RFC 2136 takes the first approach and defines a process where zone
records can be updated from an external source. The key limitation in
this specification is that a new domain cannot be added dynamically. All
other records within an existing zone can be added, changed or deleted.
In fact this limitation is also true for both of BIND's APIs as well.
DNS Security is a huge and complex topic. The critical point is to first
understand what you want to secure - or rather what threat level you
want to secure against. This will be very different if you run a root
server vs running a modest in-house DNS serving a couple of low
volume web sites.
Security Threats
To begin we must first understand the normal data flows in a DNS
system. Diagram below shows this flow.
Security Types
We classify each threat type below. This classification simply allows us
select appropriate remedies and strategies for avoiding or securing our
system. The numbering used below relates to the above diagram.
Security – Local
Normal system administration practices such as ensuring that files
(configuration and zone files) are securely backed-up, proper read and
write permissions applied and sensible physical access control to servers
may be sufficient.
TSIG and TKEY implementations are messy but not too complicated -
simply because of the scope of the problem. With Server-Server
transactions there is a finite and normally small number of hosts
involved. The protocols depend on a shared secret between the master
and the slave(s) or updater(s). It is further assumed that you can get the
shared secret securely to the peer server by some means not covered in
the protocol itself. This process, known as key exchange.
///////////////////////////////////////////////////////chap3
The solution is to reverse the order of the address and place the result
under the special domain IN-ADDR.ARPA (you will see this also
written as in-addr.arpa which is OK since domains are case insensitive
but the case should be preserved so we will use IN-ADDR.ARPA).
Finally the last part of the IPv4 Address (17) is the host address and
hosts, from our previous reading, are typically defined inside a zone file
so we will ignore it and only use the Class C address base. The result of
our manipulations are:
IP address =192.168.23.17
Class C base = 192.168.23 ; omits the host address = 17
Reversed Class C base = 23.168.192
Added to IN-ADDR.ARPA domain = 23.168.192.IN-
ADDR.ARPA
Step by StepTM Linux Guide. Page 246
This is show in figure 3.0 below.
$ORIGIN 23.168.192.IN-ADDR.ARPA.
@ IN SOA ns1.foo.com.
root.foo.com. (
2003080800 ; serial
number
3h ; refresh
15m ; update
retry
3w ; expiry
3h ; minimum
)
IN NS ns1.foo.com.
IN NS ns2.foo.com.
1 IN PTR www.foo.com. ;
qualified name
2 IN PTR joe.foo.com.
.....
17 IN PTR bill.foo.com.
.....
74 IN PTR fred.foo.com.
....
Normal domain name mapping as we have seen maps the domain name
to an IP address. This process is independent of the ISP or other
authority that allocated the IP name space. If the addresses were to
change then the owner of the domain that maps these addresses would
be able to make the necessary changes directly with either the relevant
registrar i.e. change the IP address of DNS's for the domain or change
the zone file(s) that describe the domain.
The rule is that entities can be delegated only once in the domain name
tree this includes IN-ADDR.ARPA. When a Class C subnet is assigned
by an ISP or other authority e.g. 192.168.23.64/27 (a 32 IP address
subnet) the responsibility for reverse mapping for the whole Class C
address has already been assigned to the ISP or Authority. If you want to
change the host names in the assigned subnet they must be notified to
the authority for that Class C address. Generally this is unacceptable
since such requests may encounter indifference, cost or questions. It is
most desirable that responsibility for reverse mapping be delegated when
the IP address subnet is assigned.
The technique defined in RFC 2317 provides for such delegation to take
place using CNAME Resource Records (rather than the more normal
PTR Resource Records) in an expanded IN-ADDR.ARPA name space.
$ORIGIN 23.168.192.IN-ADDR.ARPA.
@ IN SOA ns1.isp.com. root.isp.com.
(
2003080800 ; serial
number
3h ; refresh
15m ; update
retry
3w ; expiry
3h ; minimum
)
IN NS ns1.isp.com.
IN NS ns2.isp.com.
; definition of other IP address 0 - 63
....
$ORIGIN 64/27.23.168.192.IN-ADDR.ARPA.
@ IN SOA ns1.mydomain.com.
root.mydomain.com. (
2003080800 ; serial number
3h ; refresh
15m ; update retry
3w ; expiry
3h ; minimum
)
IN NS ns1.mydomain.com.
IN NS ns2.mydomain.com.
; IPs addresses in the subnet - all need to be defined
; except 64 and 95 since they are the subnets
; broadcast and multicast addresses not hosts/nodes
65 IN PTR fred.mydomain.com. ;qualified
66 IN PTR joe.mydomain.com.
67 IN PTR bill.mydomain.com.
....
93 IN PTR web.mydomain.com.
94 IN PTR ftp.mydomain.com.
; end of 192.168.23.64/27 subnet
Now you have to change your reverse map zone names in the name.conf
file to reflect the above change. The following examples shows the
reverse map declaration before and after the change to reflect the
configuration above:
The above configuration will only resolve by querying the master zone
for 23.168.192.IN-ADDR.ARPA and following down the delegation
back to itself. If changes are not made at the ISP or issuing Authority or
have not yet propagated then this configuration will generate 'nslookup'
and 'dig' errors.
A Master DNS contains one or more zone files for which this DNS is
Authoritative ('type master'). The zone has been delegated (via an NS
Resource Record) to this DNS.
The term 'master' was introduced in BIND 8.x and replaced the term
'primary'.
If you are running Stealth Servers and wish them to be notified you will
have to add an also-notify parameter as shown in the BIND
named.conf file fragment below:
You can turn off all NOTIFY operations by specifying 'notify no' in the
zone declaration.
The term 'slave' was introduced in BIND 8.x and replaced the term
'secondary'.
The master DNS for each zone is defined in the 'masters' zone section
and allows slaves to refresh their zone record when the 'expiry'
parameter of the SOA Record is reached. If a slave cannot reach the
master DNS when the 'expiry' time has been reached it will stop
responding to requests for the zone. It will NOT use time-expired data.
The file parameter is optional and allows the slave to write the
transferred zone to disc and hence if BIND is restarted before the 'expiry'
time the server will use the saved data. In large DNS systems this can
save a considerable amount of network traffic.
Assuming NOTIFY is allowed in the master DNS for the zone (the
default behaviour) then zone changes are propagated to all the slave
servers defined with NS Records in the master zone file. There can be
any number of slave DNS's for any given 'master' zone. The NOTIFY
process is open to abuse. BIND's default behaviour is to only allow
NOTIFY from the 'master' DNS. Other acceptable NOTIFY sources can
be defined using the allow-notify parameter in named.conf.
Step by StepTM Linux Guide. Page 254
Example configuration files for a slave DNS are provided.
If the caching server obtains its data directly from a zone master it will
respond as 'authoritative', if the data is supplied from its cache the
response is 'non-authoritative'.
The default BIND behaviour is to cache and this is associated with the
recursion parameter (the default is 'recursion yes'). There are many
configuration examples which show caching behaviour being defined
using a 'type hint' statement in a zone declaration. These configurations
confuse two distinct but related functions. If a server is going to provide
caching services then it must provide recursive queries and recursive
queries need access to the root servers which is provided via the 'type
hint' statement. A caching server will typically have a named.conf file
which includes the following fragment:
For general usage the breadth of BIND functionality typically offsets any
performance concerns. However if the DNS is being 'hit' thousands of
times per second performance is a major factor. There are now a number
of alternate Open Source DNS servers some of which stress
performance. These servers typically do NOT provide caching services
(they are said to be 'Authoritative only' servers).
Where dial-up links are used with DNS forwarding servers BIND's
general purpose nature and strict standards adherence may not make it
an optimal solution. A number of the Alternate DNS solutions
specifically target support for such links. BIND provides two parameters
dialup and heartbeat-interval (neither of which is currently supported by
BIND 9) as well as a number of others which can be used to minimise
connection time.
A stealth server is defined as being a name server which does not appear
in any publicly visible NS Records for the domain. The stealth server is
normally used in a configuration called Split Severs which can be
roughly defined as having the following characteristics:
There are a number of articles which suggest that the view statement
may be used to provide similar functionality using a single server but
this does not address the problem of the DNS host system being
compromised and by simple inspection of the named.conf file additional
data about the organisation could be discovered. In our opinion 'view'
does not provide adequate security in a 'Split DNS' solution.
Using BIND 9's view statement can provide different services to internal
and external requests can reduce further the Stealth server's visibility e.g.
forwarding all DNS internal requests to the external server.
You cannot completely turn off caching in BIND but you can control it
and provide the functionality described above by simply turning off
recursion in the 'option' section of named.conf as shown in the example
below.
All the configuration files are deliberately kept simple - links are
provided to the various sections that will describe more 'advanced'
parameters as appropriate. Comments are included in the files to
describe functionality. The configuration used throughout is:
Here is a convention that is in daily use. Its sole merits are that it
is a convention and makes sense to its authors.
Note:
For most Linux distributions you have a small overhead at the beginning
to rename the supplied files but the author considers it worthwhile in the
long run to avaoid confusion.
When BIND loads it uses this file (defined in a special zone 'type
hint') to contact a server to update its list of root-servers. If the
root.servers files has not been defined BIND has its own compiled list
of servers for class IN only.
This file will get out of data but as long as there is one operation
server, BIND will find what it is looking for. Unless you need very
quick load times you can leave this file alone. The root.servers file
tells you where to get an updated copy or you can get one fron
ICANN.
pri/pri.mydomain.com
This file supplied with the standard distributions (this file is typically
called localhost.zone in BIND distributions) is a model of brevity and
very cryptic! Comments have been added to clarify the definitions.
This file should not need modification.
$TTL 86400 ;
; could use $ORIGIN 0.0.127.IN-ADDR.ARPA.
@ IN SOA localhost. root.localhost. (
1997022700 ; Serial
3h ; Refresh
15 ; Retry
1w ; Expire
3h ) ; Minimum
IN NS localhost.
1 IN PTR localhost.
192.168.0.rev
This file (192.168.0.rev) is the sample reverse map zone file used
throughout this Chapter and has the following characteristics.
Note:
Notes:
Notes:
1. The Caching only name server contains no zones (other
than 'localhost') with 'master' or 'slave' types.
2. The reverse map zone has been omitted since it assumed
that an external body (ISP etc) has the master domain
DNS and is therefore also responsible for the reverse
map. It could be added if required for local operational
reasons.
Step by StepTM Linux Guide. Page 275
6.5 Forwarding (a.k.a. Proxy, Client, Remote)
DNS Server
The functionality of the Forwarding name server was
previously described.
Notes:
1. The Forwarding name server typically contains no zones
(other than 'localhost') with 'master' or 'slave' types.
2. The reverse map zone has been omitted since it assumed
that an external body (ISP etc) has the master domain
DNS and is therefore also responsible for the reverse
map. It could be added if required for local operational
reasons.
3. The forward option must be used in conjunction with a
forwarders option. The value 'only' will override
'recursive query' behaviour.
4. Since all queries are forwarded the root servers zone
('type hint') can be omitted.
5. Forwarding can be done on a zone basis in which case the
values defined override the global options.
1. The zone file for the 'Stealth' server will contain both
public and private hosts, whereas the 'Public' server's
master zone file will contain only public hosts.
Notes:
1. The reverse mapping zone would typically not be present
on a performance oriented server and has been omitted.
Notes:
1. All the required zones must be declared in each view.
2. The 'goodguys' view contains the root.servers, 'localhost'
and reverse mapping file.
3. The 'badguys' view contains only the required zone files
for which we will answer authoritatively.
4. The 'badguys' view may contain an edited version of the
reverse map file.
This chapter describes the BIND 9.x named.conf file which controls the
behaviour and functionality of BIND. named.conf is the only file which
is used by BIND - confusingly there are still many references to
boot.conf which was used by BIND 4 - ignore them.
controls
include Allows inclusion of external files into named.conf for
administrative convenience or security reasons.
key
logging Configures the location, level and type of logging that
BIND performs. Unless you are using syslogd you
need a logging statement for BIND.
server
trusted-keys
The above example shows a very simple but fairly normal zone file. The
following notes apply to zone files:
Note:
The record format shown below is as defined in the RFCs and is
used internally or when transferring information across a
network e.g. during a DNS XFER. Do not confuse this with the
format you use to define an entry in a zone source file.
Where:
NAME The name of the node to which this record belongs
TYPE The resource record type which determines the value(s)
of the RDATA field. Type takes one of the values below.
CLASS A 16 bit value which defines the protocol family or an
instance of the protocol. The normal value is IN =
Internet protocol (other values are HS and CH both
historic MIT protocols).
TTL 32 bit value. The time to Live in seconds (range is 1 to
x). The value zero indicates the data should not be
cached.
RDLENGTH The total length of the RDATA records.
RDATA Data content of each record is defined by the TYPE and
CLASS values.
Note:
The value field shown below is used internally in the DNS application
e.g. BIND or when transferring data between DNS's and does not appear
in any textual zone file definition. There are a number of other record
types which were defined over the years and are no longer actively
supported these include MD, MF, MG, MINFO, MR, NULL. A full list
of DNS Record Types may be obtained from IANA DNS Parameters.
RR Type Value
Security Overview
DNS Security is a huge and complex topic. It is made worse by the fact
that almost all the documentation dives right in and you fail to see the
forest for all the d@!mned trees.
Security Threats
To begin we must first understand the normal data flows in a DNS
system. Diagram 1-3 below shows this flow.
Every data flow (each RED line above) is a potential source of threat!.
Using the numbers from the above diagram here is what can happen at
each flow (beware you may not sleep tonight):
Security Types
We classify each threat type below. This classification simply allows us
select appropriate remedies and strategies for avoiding or securing our
system. The numbering used below relates to diagram 1-3.
Security – Local
Normal system administration practices such as ensuring that files
(configuration and zone files) are securely backed-up, proper read and
write permissions applied and sensible physical access control to servers
may be sufficient.
TSIG and TKEY implementations are messy but not too complicated -
simply because of the scope of the problem. With Server-Server
transactions there is a finite and normally small number of hosts
involved. The protocols depend on a shared secret between the master
and the slave(s) or updater(s). It is further assumed that you can get the
shared secret securely to the peer server by some means not covered in
the protocol itself. This process, known as key exchange, may not be
trivial (typically long random strings of base64 characters are involved)
but you can use the telephone(!), mail, fax or PGP email amongst other
methods.
Server-Client (DNSSEC)
The classic Remote Poisoned cache problem is not trivial to solve
simply because there may an infinitely large number of Remote Caches
involved. It is not reasonable to assume that you can use a shared
secret. Instead the mechanism relies on public/private key
authentication. The DNSSEC specifications (RFC 2535 augmented
with others) attempt to answer three questions:
allow-notify
[ allow-notify { address_match_list }; ]
allow-notify applies to slave zones only and defines a match list e.g. IP
address(es) that are allowed to update the zone in addition to those IPs
defined in the masters option for the zone. The default behaviour is to
allow zone updates only from the 'masters' IP(s). This option may be
specified in a zone statement or in a 'global' options statement.
allow-transfer
[ allow-transfer { address_match_list }; ]
allow-transfer ("none");
allow-update
[ allow-update { address_match_list }; ]
Step by StepTM Linux Guide. Page 300
allow-update defines a match list e.g. IP address(es) that are allowed to
submit dynamic updates for 'master' zones. The default in BIND 9 is to
disallow updates from all hosts. This option may be specified in a zone
statement or in a 'global' options statement. Mutually exclusive with
update-policy and applies to master zones only.
allow-update-forwarding
[ allow-update-forwarding { address_match_list }; ]
also-notify
[ also-notify { ip_addr [port ip_port] ; [ ip_addr [port ip_port] ; ... ] }; ]
dialup
[ dialup dialup_option; ]
max-refresh-time, min-refresh-time
[ max-refresh-time number ; ]
[ min-refresh-time number ; ]
Only valid for 'type slave' zones. The refresh time is normally defined by
the SOA record 'refresh' parameter. This allows the slave server
administrator to override the definition and substitute the values defined.
The values may take the normal time short-cuts. This option may be
specified in a zone statement or in a 'global' options statement.
max-retry-time, min-retry-time
[ max-retry-time number ; ]
[ min-retry-time number ; ]
Only valid for 'type slave' zones. The retry time is normally defined by
the SOA record 'update retry' parameter. This allows the slave server
administrator to override the definition and substitute the values defined.
The values may take the normal time short-cuts. This option may be
specified in a zone statement or in a 'global' options statement.
max-transfer-idle-in
[ max-transfer-idle-in number ; ]
Only valid for 'type slave' zones. Inbound zone transfers making no
progress in this many minutes will be terminated. The default is 60
minutes (1 hour). The maximum value is 28 days (40320 minutes). This
option may be specified in a zone statement or in a 'global' options
statement.
Only valid for 'type master' zones. Outbound zone transfers running
longer than this many minutes will be terminated. The default is 120
minutes (2 hours). The maximum value is 28 days (40320 minutes). This
option may be specified in a zone statement or in a 'global' options
statement.
max-transfer-time-in
[ max-transfer-time-in number ; ]
Only valid for 'type slave' zones. Inbound zone transfers running longer
than this many minutes will be terminated. The default is 120 minutes (2
hours). The maximum value is 28 days (40320 minutes). This option
may be specified in a zone statement or in a 'global' options statement.
max-transfer-time-out
[ max-transfer-time-out number ; ]
Only valid for 'type master' zones. Outbound zone transfers running
longer than this many minutes will be terminated. The default is 120
minutes (2 hours). The maximum value is 28 days (40320 minutes). This
option may be specified in a zone statement or in a 'global' options
statement.
Notify
[ notify yes | no | explicit; ]
notify behaviour is only applicable to zones with 'type master' and if set
to 'yes' then, when zone information changes, NOTIFY messages are
sent from zone masters to the slaves defined in the NS records for the
zone (with the exception of the 'Primary Master' name server defined in
the SOA record) and to any IPs listed in also-notify options.
notify-source
[ notify-source (ip4_addr | *) [port ip_port] ; ]
Only valid for 'type master' zones. notify-source defines the IPv4
address (and optionally port) to be used for outgoing NOTIFY
operations. The value '*' means the IP of this server (default). This IPv4
address must appear in the masters or also-notify option for the
receiving slave name servers. This option may be specified in a zone
statement or in a 'global' options statement.
notify-source-v6
[ notify-source-v6 (ip6_addr | *) [port ip_port] ; ]
provide-ixfr
[ provide-ixfr yes|no ; ]
request-ixfr
[ request-ixfr yes|no ; ]
transfers
[ transfers number ; ]
Limits the number of concurrent zone transfers from any given server. If
not present the default for transfers-per-ns is used. This option may be
specified only in a server statement.
transfer-format
[ transfer-format ( one-answer | many-answers ); ]
transfer-in
[ transfer-in number ; ]
transfers-per-ns
[ transfer-per-ns number ; ]
transfer-source
[ transfer-source (ip4_addr | *) [port ip_port] ; ]]
transfer-source-v6
[ transfer-source-v6 (ip6_addr | *) [port ip_port] ; ]]
update-policy
[ update-policy { update_policy_rule [...] }; ]
Incomplete - to be supplied
Where:
Parameter Description
name To be supplied
subdomain
self To be supplied
wildcard To be supplied
acl's define a match list e.g. IP address(es), which are then referenced
(used) in a number of options statements and the view statement(s). acl's
MUST be defined before they are referenced in any other statement. For
this reason they are usually defined first in the named.conf file. 'acl-
name' is an arbitrary (but unique) quoted string defining the specific list.
The 'acl-name' is the method used to reference the particular list. Any
number of acl's may be defined. The following special 'acl-name' values
are built into BIND:
//defining acl's
// using acl's
zone "somedomain.com" {
type master;
file "pri.somedomain.com";
also-notify {"moreips"};
};
zone "mydomain.com" {
type slave;
masters ("someips"};
file "sec.mydomain.com;
allow-transfer {"none"}; // this is a 'special' acl
};
DNS
Primary DNS 203.115.0.1
Secondary DNS 203.115.0.18
ddns-update-style interim;
ignore client-update;
default-lease-time 600;
max-lease-time 7200;
option subnet-mask 255.255.255.0;
option brodcat-address 192.168.1.255;
option roters 192.168.1.1;
option domain-name-servers 203.115.0.1
subnet 192.168.1.0 netmask 255.255.255.0 {
range 192.168.1.100 192.168.1.200
}
mv dhcpd.leases~ dhcpd.leases
Say Yes to over write the file and restart the dhcpd.
service dhcpd restart
/nocat/NoCatAuth-0.82.tar.gz
cd /nocat
tar zvxf NoCatAuth-x.xx.tar.gz
cd NoCatAuth-x.xx
make gateway
Note:
The radius port of gateway is 1646 and radius port of authserver is
1645, because 1645 is the port that free radius work and 1646 is the
port for accounting.
IP Address 172.22.4.1
Subnet mask 255.255.255.0
Default gateway 172.22.4.245
AuthServer Installation
Download the NoCatAuth and put in this directory
/nocat/NoCatAuth-0.82.tar.gz
# cd /nocat
# tar zvxf NoCatAuth-x.xx.tar.gz
# cd NoCatAuth-x.xx
# make authserv
Your selection ? 1
Keysize ? 1024 bits
Key is valid for ? 0
(Y/N) ? y
Real Name:? suranga
Emailad : suranga@slts.lk
Comments : good
Step by StepTM Linux Guide. Page 316
(N)(C)(E)(O)(Q) ? O
Enter passphrase : 8
Repeat passphrase : 8
(IMPORTANT – do not enter passprase)
httpd.conf
ServerTokens OS
ServerRoot "/etc/httpd"
PidFile run/httpd.pid
Timeout 300
KeepAlive Off
MaxKeepAliveRequests 100
KeepAliveTimeout 15
<IfModule prefork.c>
StartServers 8
MinSpareServers 5
MaxSpareServers 20
MaxClients 150
MaxRequestsPerChild 1000
</IfModule>
<IfModule worker.c>
StartServers 2
MaxClients 150
MinSpareThreads 25
MaxSpareThreads 75
ThreadsPerChild 25
MaxRequestsPerChild 0
</IfModule>
<IfModule perchild.c>
NumServers 5
StartThreads 5
MinSpareThreads 5
Step by StepTM Linux Guide. Page 317
MaxSpareThreads 10
MaxThreadsPerChild 20
MaxRequestsPerChild 0
</IfModule>
Listen 80
Include conf.d/*.conf
LoadModule access_module modules/mod_access.so
LoadModule auth_module modules/mod_auth.so
LoadModule auth_anon_module modules/mod_auth_anon.so
LoadModule auth_dbm_module modules/mod_auth_dbm.so
LoadModule auth_digest_module modules/mod_auth_digest.so
LoadModule include_module modules/mod_include.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule env_module modules/mod_env.so
LoadModule mime_magic_module modules/mod_mime_magic.so
LoadModule cern_meta_module modules/mod_cern_meta.so
LoadModule expires_module modules/mod_expires.so
LoadModule headers_module modules/mod_headers.so
LoadModule usertrack_module modules/mod_usertrack.so
LoadModule unique_id_module modules/mod_unique_id.so
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule mime_module modules/mod_mime.so
LoadModule dav_module modules/mod_dav.so
LoadModule status_module modules/mod_status.so
LoadModule autoindex_module modules/mod_autoindex.so
LoadModule asis_module modules/mod_asis.so
LoadModule info_module modules/mod_info.so
LoadModule cgi_module modules/mod_cgi.so
LoadModule dav_fs_module modules/mod_dav_fs.so
LoadModule vhost_alias_module modules/mod_vhost_alias.so
LoadModule negotiation_module modules/mod_negotiation.so
LoadModule dir_module modules/mod_dir.so
LoadModule imap_module modules/mod_imap.so
LoadModule actions_module modules/mod_actions.so
LoadModule speling_module modules/mod_speling.so
LoadModule userdir_module modules/mod_userdir.so
LoadModule alias_module modules/mod_alias.so
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so
Step by StepTM Linux Guide. Page 318
User nobody
Group nobody
ServerAdmin root@localhost
UseCanonicalName Off
DocumentRoot "/var/www/html"
<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>
<Directory "/var/www/html">
Options Indexes FollowSymLinks
AllowOverride Options
Order allow,deny
Allow from all
</Directory>
<LocationMatch "^/$>
Options -Indexes
ErrorDocument 403 /error/noindex.html
</LocationMatch>
<IfModule mod_userdir.c>
UserDir disable
</IfModule>
DirectoryIndex index.html index.html.var
AccessFileName .htaccess
<Files ~ "^\.ht">
Order allow,deny
Deny from all
</Files>
TypesConfig /etc/mime.types
DefaultType text/plain
<IfModule mod_mime_magic.c>
MIMEMagicFile conf/magic
</IfModule>
HostnameLookups Off
ErrorLog logs/error_log
LogLevel warn
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-
Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b" common
LogFormat "%{Referer}i -> %U" referer
LogFormat "%{User-agent}i" agent
CustomLog logs/access_log combined
Step by StepTM Linux Guide. Page 319
ServerSignature On
Alias /icons/ "/var/www/icons/"
<Directory "/var/www/icons">
Options Indexes MultiViews
AllowOverride None
Order allow,deny
Allow from all
</Directory>
Alias /manual "/var/www/manual"
<Directory "/var/www/manual">
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
Allow from all
</Directory>
<IfModule mod_dav_fs.c>
DAVLockDB /var/lib/dav/lockdb
</IfModule>
ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
<IfModule mod_cgid.c>
</IfModule>
<Directory "/var/www/cgi-bin">
AllowOverride None
Options None
Order allow,deny
Allow from all
</Directory>
<Directory "/usr/local/nocat/cgi-bin">
Options +ExecCGI
</Directory>
IndexOptions FancyIndexing VersionSort NameWidth=*
AddIconByEncoding (CMP,/icons/compressed.gif) x-compress x-gzip
AddIcon /icons/back.gif ..
AddIcon /icons/hand.right.gif README
AddIcon /icons/folder.gif ^^DIRECTORY^^
AddIcon /icons/blank.gif ^^BLANKICON^^
DefaultIcon /icons/unknown.gif
ReadmeName README.html
HeaderName HEADER.html
IndexIgnore .??* *~ *# HEADER* README* RCS CVS *,v *,t
AddEncoding x-compress Z
AddEncoding x-gzip gz tgz
AddLanguage da .dk
AddLanguage nl .nl
AddLanguage en .en
AddLanguage et .et
AddLanguage fr .fr
AddLanguage de .de
AddLanguage he .he
AddLanguage el .el
AddLanguage it .it
AddLanguage ja .ja
AddLanguage pl .po
AddLanguage kr .kr
AddLanguage pt .pt
AddLanguage nn .nn
Step by StepTM Linux Guide. Page 321
AddLanguage no .no
AddLanguage pt-br .pt-br
AddLanguage ltz .ltz
AddLanguage ca .ca
AddLanguage es .es
AddLanguage sv .se
AddLanguage cz .cz
AddLanguage ru .ru
AddLanguage tw .tw
AddLanguage zh-tw .tw
AddLanguage hr .hr
LanguagePriority en da nl et fr de el it ja kr no pl pt pt-br ltz ca es sv tw
ForceLanguagePriority Prefer Fallback
AddDefaultCharset ISO-8859-1
AddCharset ISO-8859-1 .iso8859-1 .latin1
AddCharset ISO-8859-2 .iso8859-2 .latin2 .cen
AddCharset ISO-8859-3 .iso8859-3 .latin3
AddCharset ISO-8859-4 .iso8859-4 .latin4
AddCharset ISO-8859-5 .iso8859-5 .latin5 .cyr .iso-ru
AddCharset ISO-8859-6 .iso8859-6 .latin6 .arb
AddCharset ISO-8859-7 .iso8859-7 .latin7 .grk
AddCharset ISO-8859-8 .iso8859-8 .latin8 .heb
AddCharset ISO-8859-9 .iso8859-9 .latin9 .trk
AddCharset ISO-2022-JP .iso2022-jp .jis
AddCharset ISO-2022-KR .iso2022-kr .kis
AddCharset ISO-2022-CN .iso2022-cn .cis
AddCharset Big5 .Big5 .big5
AddCharset WINDOWS-1251 .cp-1251 .win-1251
AddCharset CP866 .cp866
AddCharset KOI8-r .koi8-r .koi8-ru
AddCharset KOI8-ru .koi8-uk .ua
AddCharset ISO-10646-UCS-2 .ucs2
AddCharset ISO-10646-UCS-4 .ucs4
AddCharset UTF-8 .utf8
AddCharset GB2312 .gb2312 .gb
AddCharset utf-7 .utf7
AddCharset utf-8 .utf8
AddCharset big5 .big5 .b5
AddCharset EUC-TW .euc-tw
AddCharset EUC-JP .euc-jp
AddCharset EUC-KR .euc-kr
AddCharset shift_jis .sjis
Step by StepTM Linux Guide. Page 322
AddType application/x-tar .tgz
AddHandler cgi-script .cgi .pl
AddHandler imap-file map
AddHandler type-map var
AddOutputFilter INCLUDES .shtml
Alias /error/ "/var/www/error/"
<IfModule mod_negotiation.c>
<IfModule mod_include.c>
<Directory "/var/www/error">
AllowOverride None
Options IncludesNoExec
AddOutputFilter Includes html
AddHandler type-map var
Order allow,deny
Allow from all
LanguagePriority en es de fr
ForceLanguagePriority Prefer Fallback
</Directory>
</IfModule>
</IfModule>
BrowserMatch "Mozilla/2" nokeepalive
BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-
response-1.0
BrowserMatch "RealPlayer 4\.0" force-response-1.0
BrowserMatch "Java/1\.0" force-response-1.0
BrowserMatch "JDK/1\.0" force-response-1.0
BrowserMatch "Microsoft Data Access Internet Publishing Provider"
redirect-carefully
BrowserMatch "^WebDrive" redirect-carefully
ssl.conf
LoadModule ssl_module modules/mod_ssl.so
Listen 443
AddType application/x-x509-ca-cert .crt
AddType application/x-pkcs7-crl .crl
SSLPassPhraseDialog builtin
SSLSessionCache dbm:/var/cache/mod_ssl/scache
SSLSessionCacheTimeout 300
SSLMutex file:logs/ssl_mutex
SSLRandomSeed startup builtin
SSLRandomSeed connect builtin
<VirtualHost _default_:443>
DocumentRoot "/var/www/html"
ServerName 203.94.84.205:443
ServerAdmin you@your.address
ErrorLog logs/ssl_error_log
TransferLog logs/ssl_access_log
SSLEngine on
SSLCipherSuite
ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv
2:+EXP:+eNULL
CustomLog logs/ssl_request_log \
"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
</VirtualHost>
<Directory /usr/local/nocat/cgi-bin>
SetEnv PERL5LIB /usr/local/nocat/lib
SetEnv NOCAT /usr/local/nocat/nocat.conf
</Directory>
SetEnvIf User-Agent ".*MSIE.*" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
DataSource Passwd
UserFile /usr/local/nocat/etc/passwd
GroupUserFile /usr/local/nocat/etc/group
GroupAdminFile /usr/local/nocat/etc/groupadm
• Assign permissions
mysql > grant all on nocat.* to nocat@localhost identified by
“nocatauth”;
mysql > flush privileges;
mysql> quit
##
# Auth service database settings.
#
# If you select DataSource DBI, then Database, DB_User,
and DB_Password
# are required.
#
# Database is a DBI-style data source specification.
#
# For postgres support:
# Database dbi:Pg:dbname=nocat
#
# For mysql support:
Database dbi:mysql:database=nocat
DB_User nocat
DB_Passwd nocatauth
• We add users to our new nocat data base with admintool NoCatAuth utility.
# usr/local/nocat/bin/admintool –c toni password
# usr/local/nocat/bin/admintool –a toni members
• We can verify that we have added the user correctly to members tables.
# mysql –u nocat –pnocatauth
mysql > use nocat;
mysql > select * from member;
mysql > exit
• Then you have to modify the etc/raddb/clients file. This file lists
the hosts authorized to hit the FreeRADIUS server with requests
and secret key those will use in their requests. Also, add the IP
address of a desktop console machine with which you can test
your setup using RADIUS ping utility. (This can refer to our
gateway that is 172.22.4.234)
Eg:
# Client Name Key
#---------------- ----------------------
#portmaster1.isp.com testing123
#portmaster2.isp.com testing123
#proxyradius.isp2.com TheirKey
localhost testing123
172.22.4.238 testing123
tc-clt.hasselltech.net oreilly
• Next you have to add the IP address of the gateway into the
etc/raddb/naslist file.
Eg:
# NAS Name Short Name Type
#--------------- ----------- ----
#portmaster1.isp.com pm1.NY livingston
localhost local portslave
172.22.4.238 local portslave
tc-clt.hasselltech.net tc.char tc
• The end of your radiusd.conf should then look something like this:
authorize {
preprocess
chap
mschap
#counter
#attr_filter
#eap
Suffix
Sql
#files
#etc_smbpasswd
}
authenticate {
authtype PAP {
pap
}
authtype CHAP {
chap
}
authtype MS-CHAP {
ms chap
}
#pam
#unix
#authtype LDAP {
# ldap
#}
}
preact {
preprocess
suffix
#files
}
session {
radutmp
}
DataSource RADIUS
RADIUS_Host localhost:1645
RADIUS_Secret testing123
RADIUS_TimeOut 5
Note:
The radius port of gateway is 1646 and radius port of authserver is
1645, because 1645 is the port that free radius work and 1646 is the
port for accounting.
Populating MySQL
You should now create some dummy data in the database to test against.
It goes something like this:
Here's a dump of tables from the 'radius' database from mysql on my test
box (edited slightly for clarity). This example includes three users, one
with a dynamically assigned IP by the NAS (fredf), one assigned a static
IP (barney), and one representing a dial-up routed connection
(dialrouter):
mysql>
Enter FreeRADIUS.
Introduction to FreeRADIUS
The developers of FreeRADIUS speak on their product and its
development, from the FreeRADIUS Web site:
• More than one DEFAULT entry, with each being capable of "falling
through" to the next
• Permitting and denying access to users based on the huntgroup
to which they are connected
• Vendor-specific attributes
• 3Com/USR NetServer
• 3Com/USR TotalControl
• Cistron PortSlave
• Computone PowerRack
• Cyclades PathRAS
• Livingston PortMaster
Installing FreeRADIUS
At present, the FreeRADIUS team doesn't offer precompiled binaries.
The best way to start off is to grab the latest source code, compressed
using tar and gzip, from the FreeRADIUS Web site. Once the file is on
your computer, execute the following command to uncompress the file:
--with-logdir=DIR
Specifies the directory for LOCALSTATEDIR/log
log files.
--with- Specifies the directory for LOGDIR/radacct
radacctdir=DIR detail files.
--with-raddbdir=DIR
Specifies the directory for SYSCONFDIR/raddb
configuration files.
Makes the dictionary case
--with-dict-nocase Yes
insensitive.
Includes support for
--with-ascend-binary attributes provided with Yes
the Ascend binary filter.
Uses threads if they're
--with-threads Yes
supported and available.
Compiles SNMP support
--with-snmp Yes
into the binaries.
Specifies where the
--with-mysql-
include-dir=DIR include files for MySQL Not applicable
can be found.
Specifies where the
--with-mysql-lib-
dur=DIR dictionary files for MySQL Not applicable
can be found.
Specifies where MySQL is
--with-mysql-dir-DIR installed on the local Not applicable
system.
--disable-ltdl-
install Does not install libltdl. Not applicable
--with-static-
Compiles the list of
modules=QUOTED- Not applicable
MODULE-LIST modules statically.
Turns on extra developer
--enable-developer Not applicable
warnings in the compiler.
The programs will then be configured to compile. The rest of this chapter
will assume that you installed FreeRADIUS in these locations.
Next, type make. This will compile the binaries. Finally, type make
install. This will place all of the files in the appropriate locations. It will
also install configuration files if this server has not had a RADIUS server
installed before. Otherwise, the procedure will not overwrite your
existing configuration and will report to you on what files it did not
install.
radius:/etc/raddb # ls -al
total 396
drwxr-xr-x 2 root root 4096 Apr 10 10:39 .
drwxr-xr-x 3 root root 4096 Apr 10 10:18 ..
-rw-r--r-- 1 root root 635 Apr 10 10:18 acct_users
-rw-r--r-- 1 root root 3431 Apr 10 10:18 attrs
-rw-r--r-- 1 root root 595 Apr 10 11:02 clients
-rw-r--r-- 1 root root 2235 Apr 10 10:39 clients.conf
-rw-r--r-- 1 root root 12041 Apr 10 10:18 dictionary
-rw-r--r-- 1 root root 10046 Apr 10 10:39 dictionary.acc
-rw-r--r-- 1 root root 1320 Apr 10 10:39 dictionary.aptis
While it may seem obvious, change the shared secrets from the defaults
in the file or the samples listed previously. Failing to do so presents a
significant security risk to your implementation and network.
3Com/USR TotalControl Tc
Progressing along with the FreeRADIUS setup you will come to the
/etc/raddb/hints file. This file can be used to provide "hints" to the
Step by StepTM Linux Guide. Page 341
RADIUS server about how to provision services for a specific user based
on how his login name is constructed. For example, when you've
configured your default service to be a SLIP connection, then a SLIP
connection will be set up if a user logs in with her standard username
(e.g., meis). However, if that same user wanted a PPP connection, she
could alter her username to be Prneis, and the RADIUS server (knowing
about that convention from the /etc/raddb/hints file) would set up a PPP
connection for her. Suffixes on the end of the username work in the same
way. More on the hints file will be provided later in the chapter. You
shouldn't need to edit this file initially since we're just testing, but if
you'd like to check it out, a sample /etc/raddb/hints file looks like this:
You can filter these defined huntgroups to restrict their access to certain
users and groups and match a username/password to a specific
huntgroup, possibly to assign a static IP address. You define huntgroups
based on the IP address of the NAS and a port range. (Keep in mind that
a range can be anywhere from 1 to the maximum number of ports you
have.) To configure this file, you first specify the terminal servers in
each POP. Then, you configure a stanza that defines the restriction and
the criteria that a potential user must satisfy to pass the restriction. That
criteria is most likely a Unix username or groupname.
Again, you shouldn't have to configure this file to get basic functionality
enabled for testing; if you would like to peruse the file and its features,
however, I've provided a sample /etc/raddb/huntgroups file. It's for an
ISP with a POP in Raleigh, North Carolina that wants to restrict the first
five ports on its second of three terminal servers in that POP to only
premium customers:
Since we won't add any users to the users file for our testing purposes,
FreeRADIUS will fall back to accounts configured locally on the Unix
machine. However, if you want to add a user to the users file to test that
functionality, a sample /etc/raddb/users file looks like this:
There will be much more about the users file later in this chapter.
The radiusd.conf File
This file is much like Apache's httpd.conf file in that it lists nearly every
directive and option for the basic functionality of the FreeRADIUS
Step by StepTM Linux Guide. Page 344
product. You will need to edit the Unix section of this file to make sure
that the locations of the passwd, shadow, and group files are not
commented out and are correct. FreeRADIUS needs these locations to
start up. The appropriate section looks like this:
unix {
(some content removed)
# Define the locations of the normal passwd, shadow,
and group files.
#
# 'shadow' is commented out by default, because not
all
# systems have shadow passwords.
#
# To force the module to use the system passwd
fnctns,
# instead of reading the files, comment out the
'passwd'
# and 'shadow' configuration entries. This is
required
# for some systems, like FreeBSD.
#
passwd = /etc/passwd
shadow = /etc/shadow
group = /etc/group
(some content removed)
}
I will cover the radiusd.conf file in more detail later in this chapter.
With that done, it's now time to launch the radiusd daemon and test
your setup. Execute radiusd from the command line; it should look
similar to this:
radius:/etc/raddb # radiusd
radiusd: Starting - reading configuration files ...
radius:/etc/raddb #
Once you have FreeRADIUS running, you need to test the configuration
to make sure it is responding to requests. FreeRADIUS starts up
5. Click Send.
------------------attribute dump----------------------
------------------attribute dump----------------------
Next, you'll need to test accounting packets. The old standard for
RADIUS accounting used port 1646. Change the port number in
NTRadPing accordingly, and select Accounting Start from the Request
Type drop-down list box. Make sure the root password is correct again,
and send your request along. The response should be similar to the
following:
------------------attribute dump----------------------
Finally, stop that accounting process by changing the Request Type box
selection to Accounting Stop and resending the request. You should
receive a response like this:
------------------attribute dump----------------------
radiusd -p 1645
• Are you using the correct secret key? This as well is configured
in the /etc/raddb/clients file.
To assist in diagnosing your problem, you may want to try running the
server in debugging mode. While operating in this mode, FreeRADIUS
outputs just about everything it does, and by simply sifting through all of
the messages it prints while running, you can identify most problems.
radiusd -c
This command checks the configuration of the RADIUS server and alerts
you to any syntax errors in the files. It prints the status and exits with
either a zero, if everything is correct, or a one if errors were present. This
command is also useful when you're updating a production server that
cannot be down: if there were a syntax error in the files, radiusd would
fail to load correctly, and downtime would obviously ensue. With the
check capability, this situation can be avoided.
In-depth Configuration
At this point, you've compiled, installed, configured, started, and tested a
simple FreeRADIUS implementation that is functional. However, 99.5%
Step by StepTM Linux Guide. Page 350
of the RADIUS/AAA implementations around the world are just not that
simple. In this section, I'll delve into the two major configuration files
and discuss how to tweak, tune, customize, and effect change to the
default FreeRADIUS installation.
Configuring radiusd.conf
Pidfile
This file contains the process identification number for the radiusd
daemon. You can use this file from the command line to perform any
action to a running instance of FreeRADIUS. For example, to shut
FreeRADIUS down without any protests, issue:
Usage:
pidfile = [path]
Suggestion:
pidfile = ${run_dir}/radiusd.pid
user and group
Step by StepTM Linux Guide. Page 351
These options dictate under what user and group radiusd runs. It is not
prudent to allow FreeRADIUS to run under a user and group with
excessive permissions. In fact, to minimize the permissions granted to
FreeRADIUS, use the user and group "nobody." However, on systems
configured to use shadow passwords, you may need to set the user to
"nobody" and the group to "shadow" so that radiusd can read the
shadow file. This is not a desirable idea. On some systems, you may
need to set both the user and group to "root," although it's clear why that
is an even worse idea.
Usage:
Suggestion:
Usage:
max_request_time = 30
Suggestion:
max_request_time = 60
delete_blocked_requests
This directive is paired with the max_request_time directive in that it
controls when requests that exceed the time threshold should be killed.
Most of the time, this value should be set to "no."
Usage:
delete_blocked_requests = [yes/no]
Suggestion:
delete_blocked_requests = no
Step by StepTM Linux Guide. Page 352
cleanup_delay
Usage:
cleanup_delay = [value]
Suggestion:
cleanup_delay = 6
max_requests
Usage:
max_requests = [value]
Suggestion:
This directive specifies the address under which radiusd will accept
requests and reply to them. The "address" can be an IP address, fully
Step by StepTM Linux Guide. Page 353
qualified domain name, or the * wildcard character (to instruct the
daemon to listen on all interfaces).
Usage:
bind_address = [value]
Suggestion:
bind_address = *
port
Usage:
port = [value]
Suggestion:
port = 1645
hostname_lookups
Usage:
Suggestion:
hostname_lookups = no
allow_core_dumps
Usage:
allow_core_dumps = [yes/no]
Suggestion:
allow_core_dumps = no
regular and extended expressions
Usage:
Suggestion:
regular_expressions = yes; extended_expressions = yes
log
Usage:
Suggestion:
Clearly setting the lower_user directive to after makes the most sense:
it adds processing time to each request, but unless this particular machine
normally carries a high load, the reduced troubleshooting time is worth
the extra performance cost. However, a secure password often makes use
of a combination of uppercase and lowercase letters, so security dictates
leaving the password attribute alone.
Usage:
Suggestion:
Usage:
nospace_user = [before/after/no]; nospace_password =
[before/after/no]
Suggestion:
nospace_user = after; nospace_password = before
1. The first field is the username for each user, up to 253 characters.
FreeRADIUS processes this file in the order in which the entries are
listed. When information received from the RADIUS client equipment
matches an entry in the users file, FreeRADIUS stops processing and
sets the service up based on that users file entry. However, you can alter
If you don't want to issue a password for each user via their entry in the
users file, then simply set Auth-Type := System on the first line for each
user. FreeRADIUS will then query the system password database for the
correct password, which saves some administrative headache.
Next, here's a complete entry for the user Anna Watson. She has a space
in her user-name and she also has a password specified in her entry. She
also gets a positive fall-through so that she can use some of the DEFAULT
user's attributes with her connection:
These DEFAULT user configurations match with all usernames that can get
to them (i.e., the individual users must have a positive Fall-Through
attribute). Recall from the earlier discussion that DEFAULT entries may
also have Fall-Through attributes.
First, let's make sure that all users are checked against the system
password file unless they have a password explicitly assigned in the
entry.
Now, include a DEFAULT entry for all users connecting via a framed
protocol, such as PPP or SLIP. Note that I tell the RADIUS client to
assign the IP address via the Framed-IP-Address attribute's value.
Finally, set the DEFAULT entry for PPP users. I've already told
FreeRADIUS to assign framed protocol users with a dynamic IP address,
so all I need to do is set the compression method and explicitly designate
PPP as the framed protocol for this default.
Similarly, you can set up an entry in the users file where if a user
connects with a prefix of "s.", then you can provision SLIP service for
him. FreeRADIUS can authenticate him against the system passwords,
and then fall through to pick up the SLIP attributes from another
DEFAULT entry. Here is an example:
It means that some shared libraries on the server are not available. There
are a couple of possible causes from this.
First, the libraries that are needed by the module listed in the error
messages couldn't be found when FreeRADIUS was being compiled.
However, if a static version of the module was available, it was built at
The other cause is that the dynamic linker on your server is not
configured correctly. This would result in the libraries that are required
being found at compile time, but not run time. FreeRADIUS makes use
of standard calls to link to these shared libraries, so if these calls fail, the
system is misconfigured. This can be fixed by telling the linker where
these libraries are on your system, which can be done in one of the
following ways:
• If your system allows it, edit the /etc/ld.so.conf file and add the
directory containing the shared libraries to the list.
• Set the path to these libraries inside radiusd.conf using the libdir
configuration directive. The radiusd.conf file has more details on
this.
The gibberish may also result from a shared secret that is too long.
FreeRADIUS limits the secret length to 16 characters, since some NAS
Some people may say using CHAP is much more secure, since the user
passwords are not transmitted in plain text over the connection between
the user and the NAS. This is simply not true in practice. While hiding
the password during transmission is beneficial, the CHAP protocol
requires you to leave plain text passwords sitting in a file on a server,
completely unencrypted. Obviously, it's much more likely that a cracker
will gain access to your RADIUS server, grab the users file with all of
these plainly available passwords, and wreak havoc and harm on your
network than it is that the same cracker would intercept one user's
password during the establishment of the connection.
Introduction
• MySQL administration
I'm not going to describe any of the above stuff, especially the latter as
I'm far from an expert on it. This document focuses on getting
FreeRadius running with MySQL. It does NOT describe a basic
FreeRadius installation in detail (e.g. getting it up and running with a
'users' text file or other FreeRadius configurations), nor does it cover
using multiple authentication methods, fall-through's or any of that stuff.
Just plain-old-MySQL-only. If you don't know about RADIUS itself, go
Please note: This isn't official documentation. It's not even UNofficial
documentation. It's not documentation of any type by any stretch of the
imagination. So far, it's just my own personal notes, written on the fly.
Little editing, little detail. You takes your chances. I will try to improve
when I can, or have additional information - don't hold your breath
though, as life can get busy around here. The notes focus on the SQL
element, NOT generally on getting FreeRadius installed and configured
and operational with text files (maybe later!) although there is a little bit
on that.
Also note: I'm not a programmer - editing low-level code and compiling
stuff is not something I'm particularly familiar with. Ask me to read C
code and I'll probably panic. My background and experience on Linux
(and other stuff) puts me in the system admin/networking bracket (I'm a
network builder and web app developer by day), so please bear that in
mind here. Feel free to mail me, especially with suggestions and any info
useful to add here, but please don't ask me 'how to I compile' stuff.
Thanks.
Lastly for this bit : a big thank you to all those that helped, emailed and
generally contributed to me getting this up and going, and thus to the
creation of these notes.
System
I did my original testing on SuSe Linux 7.0 on Intel with FreeRadius 0.2
and MySQL 3.23.42 using a Cisco 3640 acting as a test NAS unit. The
final deployment was to RedHat 7.1. Today I'm running FreeRadius
0.8.1. If you're running an older version you are strongly recommended
to upgrade.
aaa new-model
aaa authentication ppp default if-needed group radius local
aaa authorization network default group radius
aaa accounting update newinfo
aaa accounting exec default start-stop group radius
aaa accounting network default wait-start group radius
aaa accounting connection default start-stop group radius
[a.b.c.d and e.f.g.h are the IP's of your primary and secondary RADIUS
servers. YOUR-RADIUS-KEY is your RADIUS secret key as defined in
clients.conf (see below). ]
Getting Started
First off, you should get FreeRadius compiled, installed and running in a
basic text file configuration (e.g. using the 'users' file) on your box. This
2. Unpack the tarball and install it. On my own system the basic
steps were all that was needed, and everything got dumped in the
standard places:
Note that you might need to add options to ./configure if you installed
MySQL to a non-standard place, or want FreeRadius to a non-standard
place, or want or need any other odd bits and pieces. I was keeping it
simple and didn't need to.
/usr/local/sbin/radiusd -X
Lots of stuff will scroll to the screen, and it should tell you it's ready to
accept requests. If you get an error, READ THE DEBUG, then check the
docs, check the above and try again.
You should now be able to use FreeRadius. You can use radtest to test an
account from the command line:
So, if your example user is 'fred' with password 'wilma', your server is
called 'radius.domain.com', is using port 1645, and you put localhost (or
You should get an 'Access Accept' response. If you don't, do not pass
Go, do not collect £200. Go back and check everything. Read the docs,
READ THE DEBUG!!
Next up, you need to create the schema for the database. There is a file
which describes this and is actually a SQL script file. It can be found at
/src/modules/rlm_sql/drivers/rlm_sql_mysql/db_mysql.sql where you
untar'd FreeRadius. This is the bit that, at least at the time I originally
wrote these notes, wasn't really documented anywhere and was the thing
most people seemed to be asking.
How you run that script is up to you and how you like to admin MySQL.
The easiest way is to:
...where 'root' and 'rootpass' are your mysql root name and password
respectively.
If you're stripping all realm names (i.e. you want user joe@domain.com
to authenticate as just 'joe'), then in sql.conf, under the 'query config:
username' section, you MAY need to adjust the line(s) referring to
sql_user_name = '%{Stripped-User-Name}'
...and comment out the following line referring to just User-Name. If you
want to see what's happening here, switch on all the logging options in
radiusd.conf and run radiusd in debug mode (-X) to see what's happening
: you'll see " user@domain" being passed to MySQL when using User-
Name, but just "user" when using Stripped-User-Name. Using the latter,
realms worked for me (basically, I strip everything, as all user names are
unique on the server anyway). Of course, set all your other SQL options
as needed (database login details, etc)
Also add a line saying 'sql' to the accounting{} section too between 'unix'
and 'radutmp'. FreeRadius will now do accounting to MySQL as well.
The end of your radiusd.conf should then look something like this:
authorise {
preprocess
chap
mschap
#counter
#attr_filter
#eap
suffix
sql
#files
#etc_smbpasswd
}
authenticate {
authtype PAP {
pap
Step by StepTM Linux Guide. Page 371
}
authtype CHAP {
chap
}
authtype MS-CHAP{
mschap
}
#pam
#unix
#authtype LDAP {
# ldap
#}
}
preacct {
preprocess
suffix
#files
}
accounting {
acct_unique
detail
#counter
unix
sql
radutmp
#sradutmp
}
session {
radutmp
}
Populating MySQL
Here's a dump of tables from the 'radius' database from mysql on my test
box (edited slightly for clarity). This example includes three users, one
with a dynamically assigned IP by the NAS (fredf), one assigned a static
IP (barney), and one representing a dial-up routed connection
(dialrouter):
mysql>
Note the operator ('op') values used in the various tables. The password
check attribute should use ==. Most return attributes should have a :=
operator, although if you're returning multiple attributes of the same type
(e.g. multiple Cisco- AVpair's) you should use the += operator instead
otherwise only the first one will be returned. Read the docs for more
details on operators.
If you're stripping all domain name elements from usernames via realms,
remember NOT to include the domain name elements in the usernames
you put in the MySQL tables - they should get stripped BEFORE the
database is checked, so name@domain will NEVER match if you're
realm stripping (assuming you follow point 2 above) – you should just
have 'name' as a user in the database. Once it's working without, and if
you want more complex realm handling, go back to work out not
stripping (and keeping name@domain in the db) if you really want to.
Fire up radiusd again in debug mode. The debug output should show it
connecting to the MySQL database. Use radtest (or NTradPing) to test
again - the user should authenticate and the debug output should show
FreeRadius talking to MySQL.
You're done!
Additional Snippets:
To use encrypted passwords in radcheck use the attribute 'Crypt-
Password', instead of 'Password', and just put the encrypted password in
the value field. ( i.e. UNIX crypt'd password).
group {
sql1 {
fail = 1
notfound = return
noop = 2
ok = return
updated = 3
reject = return
userlock = 4
invalid = 5
handled = 6
}
sql2 {
fail = 1
notfound = return
noop = 2
ok = return
updated = 3
reject = return
userlock = 4
invalid = 5
handled = 6
}
}
Note that if FreeRadius fails over to the second MySQL server and tries
to update the accounting table (radacct), nasty things might possibly
happen to your replication setup and database integrity as the first
MySQL server won't have got the updates...
Installing PhpMyAdmin
2. Open the file config.inc.php in your favorite editor and change the values
for host, user, password and authentication mode to fit your environment.
Here, "host" means the MySQL server. Also insert the correct value for
$cfg['PmaAbsoluteUri']. Have a look at Configuration section for an
explanation of all values.
Under export select all databases or the databases you want to export.
Select the following options.
Importing
Nagios
"Nagios is a system and network monitoring application. It watches hosts
and services that you specify, alerting you when things go bad and when
they get better" (from nagios.org <http://www.nagios.org>). This is the
same tool that used to be called NetSaint until recently. Although the
NetSaint site is still up, all future development will be done on Nagios.
Nagios runs on Unix and its variants and optionally requires a Web
server to be installed (for the Web interface).
Download the latest Nagios package and the latest Nagios plugins to a
temporary location. For this article we will be using ~/tmp/nagios.
Step by StepTM Linux Guide. Page 380
root@ducati:~/tmp/nagios# ls
nagios-1.0b5.tar.gz nagiosplug-1.3-beta1.tar.gz
First we will install the main Nagios application. Start by decompressing
the tar.gz archive.
root@ducati:~/tmp/nagios# tar xfvz nagios-1.0b5.tar.gz
This will decompress the archive and we will end up with a nagios-1.0b5
directory. (The filename and the name of the directory created will
differ, depending on when and which version you download.) Go into
this new directory:
root@ducati:~/tmp/nagios# cd nagios-1.0b5
root@ducati:~/tmp/nagios/nagios-1.0b5#
At this point, we need to decide where on our system we want to install
Nagios. You can install Nagios anywhere, but the best approach to
selecting the location is to stick with the default installation directory
(/usr/local/nagios), because the documentation always refers to this
directory. This will make it easier to solve problems that we might have.
Create the directory where you would like to install Nagios.
root@ducati:~/tmp/nagios/nagios-1.0b5# mkdir /usr/local/nagios
At this point, we need to create a user and a group that our Nagios
application will run as. You can use "root" for this purpose, but since it's
not required, we might as well not use it, for better security. In order to
make maintaining Nagios easier, we will dedicate a new username and
group to it. The user and the group that we will create are both called
"nagios."
root@ducati:~/tmp/nagios/nagios-1.0b5# useradd nagios
If you don't have the useradd command on your system, try the adduser
command. On some systems, adduser is an interactive command that
expects you to answer a few questions before creating the account.
Please refer to the man page for the command you're using for more
information.
root@ducati:~/tmp/nagios/nagios-1.0b5# groupadd nagios
On some systems, adduser will create the matching group; on other
systems you will need to edit the /etc/group file to add the group by
hand. Please refer to the documentation on your system for more
information.
Once we have created the user and the group, we can now start the actual
installation process. First we need to specify some parameters and create
the Makefile that will be used to compile and install the software.
Type the following script on a single line without line breaks:
root@ducati:~/tmp/nagios/nagios-1.0b5# ./configure --
prefix=/usr/local/nagios
Plugins Installation
Download the latest Nagios Plugins package and decompress it. You will
need to run the configure script that is provided in order to prepare the
package for compilation on your system. You will find that that the
plugins are installed in a fashion similar to the actual Nagios program.
root@ducati:~/tmp/nagios/nagiosplug-1.3-beta1# ./configure
--prefix=/usr/local/nagios --with-nagios-user=nagios --with-nagios-
group=nagios
You might get notifications about missing programs or Perl modules
while configure is running. These are mostly OK, unless you specifically
need the mentioned application to monitor a service.
Once configure is complete, compile all of the plugins.
root@ducati:~/tmp/nagios/nagiosplug-1.3-beta1# make all
If no errors were reported, you are ready to install the plugins.
root@ducati:~/tmp/nagios/nagiosplug-1.3-beta1# make install
The plugins will be installed in the libexec directory of your Nagios base
directory (/usr/local/nagios/libexec, in my case).
root@ducati:~/tmp/nagios/nagiosplug-1.3-beta1# cd
/usr/local/nagios/libexec/
There are a few rules that all Nagios plugins should implement, making
them suitable for use by Nagios. All plugins provide a --help option that
displays information about the plugin and how it works. This feature
helps a lot when you're trying to monitor a new service using a plugin
you haven't used before.
For instance, to learn how the check_ssh plugin works, run the following
command.
root@ducati:/usr/local/nagios/libexec# ./check_ssh -h
check_ssh (nagios-plugins 1.3.0-alpha1) 1.1.1.1
The nagios plugins come with ABSOLUTELY NO WARRANTY. You
may redistribute
copies of the plugins under the terms of the GNU General Public
License.
For more information about these matters, see the file named COPYING.
Copyright (c) 1999 Remi Paulmier (remi@sinfomic.fr)
Usage:
check_ssh -t [timeout] -p [port] <host> check_ssh -V prints version info
check_ssh -h prints more detailed help
by default, port is 22
root@ducati:/usr/local/nagios/libexec#
This shows us that the check_ssh plugin accepts one required parameter
host, and two optional paramters, timeout and port.
Step by StepTM Linux Guide. Page 384
There's nothing especially complicated about the plugins. In fact, you
can run the plugins manually to check services on the console.
root@ducati:/usr/local/nagios/libexec# ./check_ssh www.freelinuxcd.org
SSH ok - protocol version 1.99- - server version
Now that both Nagios and the plugins are installed, we are almost ready
to start monitoring our servers. However, Nagios will not even start
before we configure it properly.
Let's start by taking a look the sample configuration files.
root@ducati:~/tmp/nagios# cd /usr/local/nagios/etc
root@ducati:/usr/local/nagios/etc# ls -1
cgi.cfg-sample
checkcommands.cfg-sample
contactgroups.cfg-sample
contacts.cfg-sample
dependencies.cfg-sample
escalations.cfg-sample
hostgroups.cfg-sample
hosts.cfg-sample
misccommands.cfg-sample
nagios.cfg-sample
resource.cfg-sample
services.cfg-sample
timeperiods.cfg-sample
Since these are sample files, the Nagios authors added a .cfg-sample
suffix to each file. First, we need to copy or rename each one to *.cfg, so
that the software can use them properly. (If you don't change the
configuration filenames, Nagios will still try to access them with the .cgi
extension, and not be able to find them. The authors must have wanted to
ensure that everyone create their own custom configuration files.)
Before renaming the sample files, I like to take a backup of them, just in
case I need to refer to them later.
The following is what you should end up with in the etc directory.
root@ducati:/usr/local/nagios/etc# ls -1
cgi.cfg
checkcommands.cfg
contactgroups.cfg
contacts.cfg
dependencies.cfg
escalations.cfg
hostgroups.cfg
hosts.cfg
misccommands.cfg
nagios.cfg
resource.cfg
sample/
services.cfg
timeperiods.cfg
First we will start with the main configuration file, nagios.cfg. You can
pretty much leave everything as is, becasue the Nagios installation
process will make sure the file paths used in the configuration file are
correct. There's one option, however, that you might want to change. The
check_external_commands is set to 0 by default. If you would like to
be able to change the way Nagios works, or directly run commands
through the Web interface, you might want to set this to 1. There are still
some other options you need to set in cgi.cfg to configure which
usernames are allowed to run external commands.
In order to get Nagios running, you will need to modify all but a few of
the sample configuration files. Configuring Nagios to monitor your
servers is not as difficult as it looks; I have found that the best approach
to configuring Nagios properly the first time is to use the debugging
mode of the Nagios binary. You can run Nagios in this mode by running:
root@ducati:/usr/local/nagios/etc#../bin/nagios-v
nagios.cfg
This command will go through the configuration files and report any
errors that were found. Start fixing the errors one by one, and run the
command again to find the next error. For our purposes, I will disable all
Step by StepTM Linux Guide. Page 386
hosts and services definitions that come with the sample configuration
files and merely use the files as templates for our own hosts and services.
We will keep most of the files as is, and remove the following (we will
create them from scratch):
hosts.cfg
services.cfg
contacts.cfg
contactgroups.cfg
hostgroups.cfg
dependencies.cfg
escalations.cfg
We will not be going into the more advanced configuration that requires
using dependencies.cfg and escalations.cfg , so just remove these
two files so that the sample configuration in these do not stop Nagios
from starting up. Still, Nagios requires that these files are present in the
etc directory, so create two empty files and name them
dependencies.cfg and escalations.cfg by running the following as
root.
root@ducati:/usr/local/nagios/etc# touch dependencies.cfg
root@ducati:/usr/local/nagios/etc# touch escalations.cfg
We now have all of the configuration files we need and are ready to start
configuring them to suit our monitoring needs. In my next article
</pub/a/onlamp/2002/09/26/nagios.html>, I will cover the configuration
file basics, how to define services to be monitored, how to configure
Nagios to notify people when a service is down, and how to configure
and use the Web interface that comes with Nagios.
Until then, Happy Hacking.
Now we will take a look at each configuration file one by one and
configure one host 'freelinuxcd.org' and two services on it 'http' and
'ping' to be monitored. If something goes wrong with these services, two
users 'oktay' and 'verty' will be notified.
Step by StepTM Linux Guide. Page 387
Configuring Monitoring
We first need to add our host definition and configure some options for
that host. You can add as many hosts as you like, but we will stick with
one host for simplicity.
Contents of hosts.cfg
# Host Definition
define host{
# Name of host template to use
use generic-host
host_name freelinuxcd.org
alias Free Linux CD Project Server
address www.freelinuxcd.org
Step by StepTM Linux Guide. Page 388
check_command check-host-alive
max_check_attempts 10
notification_interval 120
notification_period 24x7
notification_options d,u,r
}
The first host defined is not a real host but a template which other host
definitions are derived from. This mechanism can be seen in other
configuration files also and makes configuration based on a predefined
set of defaults a breeze.
Now we need to add this host to a hostgroup. Even though we will keep
the configuration simple by defining a single host, we still have to
associate it with a group so that the application knows which contact
group (see below) to send notifications to.
Contents of hostgroups.cfg
define hostgroup{
hostgroup_name flcd-servers
alias The Free Linux CD Project Servers
contact_groups flcd-admins
members freelinuxcd.org
}
Above, we have defined a new hostgroup and associate the 'flcd-
admins' contact group with it. Now let's look into the contactgroup
settings.
Contents of contactgroups.cfg
define contactgroup{
contactgroup_name flcd-admins
Step by StepTM Linux Guide. Page 389
alias FreeLinuxCD.org Admins
members oktay, verty
}
We have defined the contact group 'flcd-admins ' and added two
members 'oktay' and 'verty' to this group. This configuration ensures
that both users will be notified when something goes wrong with a server
that 'flcd-admins ' is responsible for. (Individual notification
preferences can override this). The next step is to set the contact
information and notification preferences for these users.
Contents of contacts.cfg
define contact{
contact_name oktay
alias Oktay Altunergil
service_notification_period 24x7
host_notification_period 24x7
service_notification_options w,u,c,r
host_notification_options d,u,r
service_notification_commands notify-by-email,notify-
by-epager
host_notification_commands host-notify-by-
email,host-notify-by-epager
email oktay@freelinuxcd.org
pager dummypagenagios-
admin@localhost.localdomain
}
define contact{
contact_name Verty
alias David 'Verty' Ky
service_notification_period 24x7
host_notification_period 24x7
service_notification_options w,u,c,r
host_notification_options d,u,r
service_notification_commands notify-by-email,notify-
by-epager
host_notification_commands host-notify-by-email
email verty@flcd.org
}
Contents of services.cfg
# Generic service definition template
define service{
# The 'name' of this service template, referenced in
other service definitions
name generic-service
# Active service checks are enabled
active_checks_enabled 1
# Passive service checks are enabled/accepted
passive_checks_enabled 1
# Active service checks should be parallelized
# (disabling this can lead to major performance problems)
parallelize_check 1
# We should obsess over this service (if necessary)
obsess_over_service 1
# Default is to NOT check service 'freshness'
check_freshness 0
# Service notifications are enabled
notifications_enabled 1
# Service event handler is enabled
event_handler_enabled 1
# Flap detection is enabled
flap_detection_enabled 1
# Process performance data
process_perf_data 1
# Retain status information across program restarts
retain_status_information 1
# Retain non-status information across program restarts
retain_nonstatus_information 1
# DONT REGISTER THIS DEFINITION - ITS NOT A REAL SERVICE,
JUST A TEMPLATE!
register 0
}
# Service definition
define service{
# Name of service template to use
host_name freelinuxcd.org
service_description HTTP
is_volatile 0
check_period 24x7
max_check_attempts 3
normal_check_interval 5
retry_check_interval 1
contact_groups flcd-admins
notification_interval 120
notification_period 24x7
notification_options w,u,c,r
check_command check_http
}
# Service definition
define service{
# Name of service template to use
use generic-service
host_name freelinuxcd.org
service_description PING
is_volatile 0
check_period 24x7
max_check_attempts 3
normal_check_interval 5
retry_check_interval 1
contact_groups flcd-admins
notification_interval 120
notification_period 24x7
notification_options c,r
check_command check_ping!100.0,20%!500.0,60%
}
Starting Nagios
Now that we have configured the hosts and the services to monitor, we
are ready to fire up Nagios and start monitoring. We will start Nagios
using the init script that we had installed earlier.
If you receive the above error message, it means the 'su' command
installed on your server does not support the '-l' option. To fix it, open up
/etc/rc.d/rc.nagios (or its equivalent on your system) and remove the 'l'
where it says 'su -l'. You will end up with 'su -' which means the same
thing. After making the change, run the above startup command again. If
you receive 'permission denied' errors. Just reset the ownership
information on your Nagios installation directory and it will be resolved.
Addition to httpd.conf
When you're adding your first user, the password file that .htaccess refers
to will not be present. You need to run the 'htpasswd' command with the
-c option to create the file.