Since networks are the source of significant system security problems, there has long been an interest in finding some method to control access to a host at that level. The 2.2.x Linux kernel included a firewall support feature known as ipchains which is very popular. The more recent 2.4.x kernels included the netfilter capability which improves on ipchains in the areas of effectiveness and performance.
While ipchains is still popular, iptables has some significant advantages and will be discussed here. In order to use iptables, you need to have a kernel configured with the following:
After configuring and installing your kernel with netfiltering, you can check the existence with iptables -L. You should see an output indicating that all three default chains are empty.
The packet filtering process takes each incoming IP packet and adds to the processing a series of rules that allow packets to be dropped, forwarded or modified in different ways. A diagram of the process is shown below:
The process begins when any IP packet arrives in the system as Input, it has to undergo some error checking, a Checksum test and a Sanity test, and then it becomes part of the input chain. For the time being, ignore the Routing Decision blocks. From the input chain, a decision is made: does this packet belong here or should it be forwarded to another host. If the answer is the former, it is sent to the local process otherwise it is sent to the forward chain. A packet that is generated internally to the host, or which comes from the forward chain is processed by the output chain.
netfilter allows a system administrator to provide a set of rules that control each of the processing steps - input chain, forward chain and output chain. Routing will be discussed later.
Lets consider what all this means. If a packet reaches the input chain, rules can be formulated that allow the packet in, reject the packet or send it back to the originator. Similarly, packets reaching the output chain can be allowed out, or they can be stopped at that point. Finally, packets that pass through the system on the way somewhere else (this system is acting as a router) can be allowed, dropped or rerouted.
Obviously, this would allow you to protect your system from potential attackers, to hide data, to control the activities of your users and to act on behalf of other hosts to provide unique services.
IP Network Address Translation (NAT) is a process that allows IP addresses to be manipulated in several beneficial ways. It will be discussed later, but it is part of the netfilter process.
The control of netfilter is done through a utility named iptables. This rather simple program provides the only standard interface to controlling netfilter. In the future, there will likely be better tools. There are a few variants on the command itself:
iptables -[ADC] chain rule-specification [extensions] |
iptables -[RI] chain rulenum rule-specification [extensions] |
iptables -D chain rulenum [extensions] |
iptables -[LFZ] chain [extensions] |
iptables -[NX] chain |
iptables -P chain target [extensions] |
iptables -E old-chain-name new-chain-name |
Currently, three tables are defined by netfilter, the filter table, the nat table and the mangle table. In this section, only the filter table will be discussed.
A table consists of several built-in chains and user-defined chains as desired. Each chain consists of a set of rules that can match a packet and specify what should be done with a matched packet (also known as a target).
Commands:
Commands |     | Meaning |
---|---|---|
-A |     | Append a new rule to a chain. |
-C |     | Given a rule specification, return a message describing the handling. |
-D |     | Delete a rule from a chain. |
-E |     | Rename a chain. |
-F |     | Flush the rules in a chain |
-I |     | Insert a rule at the beginning of the chain. |
-L |     | List the rules in a chain. |
-N |     | Create a new chain |
-P |     | Set the default policy for a chain. |
-R |     | Replace a rule in a chain. |
-X |     | Delete a chain |
-Z |     | Zero the counters for a chain. |
Chains:
The predefined chains that are available for filtering are the INPUT, FORWARD and OUTPUT chains. There are two other predefined chains, PREROUTING and POSTROUTING that are related to network address translation and will be discussed in that section.
Policies:
The acceptable policies (or targets) for filtering are
ACCEPT |     | Allow the datagram to pass |
DROP |     | Discard the datagram |
QUEUE |     | Pass the datagram to user space for further processing |
RETURN |     | Return to Chain that called the one containing this rule. |
Rule Specification:
A rule specification has a set of parameters, each of which must be supplied, or its default will be assumed. They are:
Parameter |     | Default |     | Meaning |
---|---|---|---|---|
-p [!] protocol |     | All protocols |     | The datagram protocol, tcp, udp, icmp or a number from the /etc/protocols file. The ! negates the protocol given. |
-s [!] address[/mask] |     | All addresses |     | The source address as a DNS name, IP address or an address/mask pair. Presence of ! negates the specification. |
-d [!] address[/mask] |     | All addresses |     | The destination address as a DNS name, IP address or an address/mask pair. Presence of ! negates the specification. |
-j target |     | No action |     | Specifies what action to take - ACCEPT, DROP, QUEUE or RETURN, a user-defined chain or a target provided by an extension. |
-i [!]interface-name |     | Any interface |     | The interface on which the datagram was received. ! negates. Ending the name with a + matches all that begin with the string; e.g. eth+ matches eth0, eth1 and eth-gb. |
-o [!]interface-name |     | All interfaces |     | The outgoing interface which has the same syntax as the -i option. |
[!]-f |     | All interfaces |     | Indicates that this rule applies only to the second or later fragments. |
Options:
There are a few options that can be applied to iptables commands.
Option |     | Meaning |
---|---|---|
-v |     | Verbose output |
-m ext |     | Enable match extensions for ext. |
-n |     | Use IP addresses without attempting to resolve DNS names. |
-x |     | Expand all counters without rounding to thousands (K's), millions (M's) or billions (B's). |
--line-numbers |     | Causes line numbers to be supplied to show a rules position in the chain. |
Extensions:
iptables is extensible, but there are a few standard extensions. These are related to the specific protocols that might be carried in an IP packet. The use of the extensions is indicated with the -m option or through the -p option.
TCP Extensions
These extensions are valid if -p tcp or --protocol tcp is specified or by using -m tcp.
Option |     | Default |     | Meaning |
---|---|---|---|---|
--sport[!][port[:port]] |     | All ports |     | Specify the source port or range of ports to match. For example, --sport 80, --sport 50:100 or --sport !23. The name of the service from /etc/services may also be used, as in --sport telnet. |
--dport[!][port[:port]] |     | All ports |     | Specify the destination port or range of ports to match. |
--tcp-flags [!] mask comp |     | Ignore flags |     | Specify the TCP flags that should match in the datagram. The format is a list of flags to be examined and the second is a list of flags which must be set. For example, --tcp-flags SYN,ACK,FIN   SYN indicates that the SYN flag must be set and the ACK and FIN flags must be unset |
[!]--syn |     | Ignore |     | Match only connection initiation packets with the SYN bit set and ACK, FIN and RST bits unset. |
UDP Extensions
These extensions are valid if -p udp or --protocol udp is specified.
Option |     | Default |     | Meaning |
---|---|---|---|---|
--sport[!][port[:port]] |     | All ports |     | Specify the source port or range of ports to match. For example, --sport 80, --sport 50:100 or --sport !23. |
--dport[!][port[:port]] |     | All ports |     | Specify the destination port or range of ports to match. |
ICMP Extensions
These extensions are valid if -p icmp or --protocol icmp is specified.
Option |     | Default |     | Meaning |
---|---|---|---|---|
--icmp-type [!] typename |     | All types |     | Specify the type of the icmp message to be matched. The legal types are: echo-request, echo-reply, source-quench, time-exceeded, destination-unreachable, network-unreachable, host-unreachable, protocol-unreachable and port-unreachable. |
State Extensions
These extensions allow rules to be based on the state of a connection.
Option |     | Default |     | Meaning |
---|---|---|---|---|
--state state |     | All states |     | The state is a comma separated list of connection states INVALID, not associated with a know connection, NEW, this packet start a new connection, ESTABLISHED, packet belongs a existing connection, RELATED, a new connection, but related to an existing conn. |
Whew! Now lets see how it works.
Suppose we want to do some simple firewalling on a system connected to the Internet. Assume that our IP address is 172.17.200.4 with an address mask of 255.255.248.0. We want to allow telnet out, but not in; http in both directions, but output is limited to a single site; ftp in, but not out.
# Flush the input and output tables. |
  |
iptables -F INPUT |
iptables -F OUTPUT |
  |
# Set the default policies to allow no input |
  |
iptables -P INPUT DROP |
  |
# Allow all local traffic |
  |
iptables -A INPUT -i lo -j ACCEPT |
iptables -A OUTPUT -o lo -j ACCEPT |
  |
# Control telnet - don't allow telnet connections by |
# by not allowing syn packets, but output is OK. |
  |
iptables -F INPUT -p tcp --sport telnet -j ACCEPT |
iptables -F INPUT -p tcp --syn --sport telnet -j DROP |
iptables -F OUTPUT -p tcp --dport telnet -j ACCEPT |
  |
# HTML is allowed out to a single site, and in from anywhere |
  |
iptables -F OUTPUT -p tcp --dport http -j DROP |
iptables -F OUTPUT -p tcp --dport http -d 172.17.0.0/255.255.0.0 -j ACCEPT |
iptables -F INPUT -p tcp --sport http -j ACCEPT |
  |
# ftp is allowed in, but not out. Of course, ftp connections |
# are bidirectional, so some output has to be allowed. |
# But there are two parts to ftp - the static server |
# part (port 21) and the dynamic ftp data (port 20) |
# Also, you can have passive ftp connections where |
# the endpoints agree on a high (> 1023) port to use. |
  |
iptables -F OUTPUT -p tcp --syn --dport ftp -j DROP |
iptables -F OUTPUT -p tcp -syn --dport ftp-data -j DROP |
iptables -A OUTPUT -p tcp --sport 1024: --dport 1024: -m state |
      --state ESTABLISHED,RELATED -j ACCEPT |
iptables -F INPUT -p tcp --sport ftp -j ACCEPT |
iptables -F INPUT -p tcp --sport ftp-data -j ACCEPT |
iptables -A INPUT -p tcp --sport 1024: --dport 1024: -j ACCEPT |
  |
Suppose that we want to make this more realistic by having a default OUTPUT policy of DROP. This creates a number of problems, because all traffic is stopped, including DNS, NFS and some other things that you would really like to have. You have to explictly open each service as needed. iptables does not have a bidirectional option, so you have to define the input and output rules individually.
So, if we might have to add the following rules to the above rule set.
DNSserver=172.17.1.1 |
# Set the default output policy |
  |
iptables -P OUTPUT DROP |
  |
# For simple client services, DNS uses UDP on port 53 |
# or domain. For providing services, tcp is used. |
  |
iptables -A INPUT -p udp -s $DNSserver --sport 53 -j ACCEPT |
# Allow UDP packets to DNS servers from client. |
iptables -A OUTPUT -p udp -d $DNSserver --dport 53 -j ACCEPT |
  |
# open up ping |
  |
iptables -A INPUT -p icmp -icmp-type echo-reply -j ACCEPT |
iptables -A OUTPUT -p icmp -icmp-type echo-request -j ACCEPT |
  |
# open up ping |
  |
iptables -A INPUT -p icmp -icmp-type echo-reply -j ACCEPT |
iptables -A OUTPUT -p icmp -icmp-type echo-request -j ACCEPT |
ipchains-save > /etc/ipchain-rules
Then you need a script that normally would be put in /etc/rc.d/rcS.d
or /etc/rc.d/rc1.d.
This needs to run early, before the network starts up. For example,
/etc/rc.d/rc1.d/S20packetfilter might be good.
[ -f /etc/ipchain-rules] || exit 0
case $1 in
start)
echo -n "starting packet filtering"
/sbin/ipchains-restore < /etc/ipchains-rules || exit 1
echo 1 > /proc/sys/net/ipv4/ip_forward
echo "."
; ;
stop)
echo -n "Turning off packet filtering"
echo 0 > /proc/sys/net/ipv4/ip_forward
/sbin/ipchains -X
/sbin/ipchains -F
/sbin/ipchains -P input ACCEPT
/sbin/ipchains -P output ACCEPT
/sbin/ipchains -P forward ACCEPT
echo "."
;;
*)
echo "Usage: /etc/init.d/packetfilter {start | stop}
exit 1
; ;
esac
exit 0
Everything except www -p TCP -d 0.0.0.0/0 ! www Only telnet packets from 192.0.21 -p TCP -s 192.0.21.0/255.255.255.0 23 Telnet packets from everyone but 192.0.21 -p TCP -s ! 192.0.21.0/255.255.255.0 telnet Any fragments going to butch -d butch.tweety.com/255.255.248.0 -f Add a rule to the input chain ipchains -A input -s ! 153.90.2.1 telnet -j DENY Add a rule to the input chain for a port set. ipchains -A input -s 0/0 1024:65535
|---------| ........... |---------| |---------| --->| input |---->. routing .---->| forward |---->| output |----> | | chain | | . decision. | chain | ^ | chain | ACCEPT S| |---------| | ........... |---------| | |---------| a| | | | | | | n| | | | | | | i| | | | | | | t| V | V V | V y| DENY/REJECT| Local Process DENY/REJECT | DENY/REJECT | | | | C| | |------------------------| h| |--------------------------------| k| Demasquerade | V DENY
kern.* /var/log/kern.log *.=info /var/log/messages
I want to allow ftp to my local machine from another host.
ipchains -A input -p TCP -s 153.90.192.1/21 ftp -j ACCEPT
ipchains -A output -p TCP -d 153.90.192.1/21 ftp -j ACCEPT
ipchains -A output -p TCP -s 153.90.192.1/21 ftp-data -j ACCEPT
ipchains -A input -p TCP -s 153.90.192.1/21 ftp-data -j ACCEPT
I want to allow telnet, but only from local hosts.
ipchains -A input -p TCP -s ! 153.90.192.0/255.255.248.0 telnet -j DENY
I want to allow UDP for dns for my dns server only.
ipchains -A input -p UDP -s 153.90.192.10/255.255.248.0 dns -j ACCEPT
ipchains -A output -p UDP -s 153.90.192.10/255.255.248.0 dns -j ACCEPT
No NFS. Shutdown the portmapper.
ipchains -A input -s 0.0.0.0/0 -p 111 -j DENY
ipchains -A output -s 0.0.0.0/0 -p 111 -j DENY
I want to get mail from anyone, except from a spam site.
ipchains -A input -p tcp -s 0.0.0.0/0 sendmail -j ACCEPT
ipchains -A input -p tcp -s fui.spam.com sendmail -j DENY
If mail goes out, it has to be through my proxy mail server.
ipchains -A output -p tcp -d ! 153.90.199.199/21 sendmail -j DENY
I don't want anyone to connect a specific host using a browser.
ipchains -A output -y -p tcp -d silly.website.net 80 -j DENY
Don't spoof my address.
ipchains -A input -s 153.90.192.40 -j DENY
I want to log any attempts to connect to wierd ports. Also,
this applies to any protocol or internal users.
ipchains -b -l -p all -s 0.0.0.0/0
I have a modem I use to connect to another network. The interface
is ppp0. I need to set up a chain for it and set policies.
ipchains -N ppp-in
ipchains -A input -i ppp0 -j ppp-in
ipchains -P ppp-in DENY
My machine will be the dns server for this subnet.
ipchains -A input -p UDP -s 199.99.99.0/24 dns -j ACCEPT
ipchains -A output -p UDP -s 199.99.99.0/24 dns -j ACCEPT
My machine will be the dns server for this subnet.
ipchains -A input -p UDP -s 199.99.99.0/24 dns -j ACCEPT
ipchains -A output -p UDP -s 199.99.99.0/24 dns -j ACCEPT