Tải bản đầy đủ (.pdf) (29 trang)

Designing and Implementing Linux Firewalls and QoS using netfilter, iproute2, NAT, and filter phần 5 pps

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (651.63 KB, 29 trang )

NAT and Packet Mangling with iptables
[ 104 ]
computers in 192.168.1.0/24 that are not in 192.168.1.0/27 pass through the Linux
router and get SNATed. To solve this problem, we have two alternatives.
The rst would be not to SNAT 192.168.1.0/24 when the destination is another
computer in 192.168.1.0/24:
iptables –t nat –A POSTROUTING –s 192.168.1.0/24 –d ! 192.168.1.0/24
–j SNAT –-to 1.2.4.0-1.2.4.32 –-to 1.2.3.1
The second choice we have is to SNAT only the packets that go out on Eth1:
iptables –t nat –A POSTROUTING –s 192.168.1.0/24 –o eth1 –j SNAT –-to
1.2.4.0-1.2.4.32 –-to 1.2.3.1
Our provider connected another location of our company to the same equipment,
and since we are in the same VLAN, we don't have to build a tunnel between the
routers at each location, but just route the networks through the Linux router at
that location. On the other site, we have the network 192.168.2.0/24. We need to let
computers in our network access computers in the 192.168.2.0/24 network without
SNATing them:
iptables –t nat –I POSTROUTING –s 192.168.1.0/24 –d 192.168.2.0/24 –j
ACCEPT
This command will insert the rule before the NAT rule; so if any packet from
192.168.1.0/24 is destined to any IP in the 192.168.2.0/24 network, this rule will
match and the chain will not be analyzed further, so SNAT will not take place.
Jane, our secretary, is famous for her good coffee, but since she got the IRC fever,
she's not doing anything anymore. The manager is angry about this but she doesn't
want to re Jane because she's addicted to her famous coffee; so she comes to ask
us to do something about it. There are many things we can do in this matter, for
instance drop packets from Jane (192.168.1.31) when trying to access ports 6666 to
6669 in the POSTROUTING chain:
iptables –t nat –I POSTROUTING –s 192.168.1.31 –p tcp –-dport
6666:6669 –j DROP
We might want to ask the manager what Jane is allowed to do. For instance, if the


manager wants to allow Jane only web access, we can do the following:
iptables –t nat –I POSTROUTING –s 192.168.1.31 –p tcp –-dport ! 80 –j
DROP
This rule will not SNAT Jane's IP address when trying to access something other
than port 80 TCP, but it will SNAT her IP address when accessing any UDP services
because UDP packets will not match this rule; so she will be able to access any DNS
server outside our network.
Chapter 4
[ 105 ]
DNAT with iptables
We will continue with the previous scenario for DNAT as well. One day, the
manager calls us telling she needs to access her computer from home. Of course she
can't do that because of her private IP address 192.168.1.50. We decide to allocate
one of the public IP addresses that we have for her ofce computer, but if we were
to create an alias on Eth0 for that, we would not only lose some IP addresses, but she
also won't be in the same network as the others. The best solution is to map a public
IP address (let's say 1.2.4.1) to her ofce computer's private IP address (192.168.1.50).
This is, of course, DNAT:
iptables –t nat –A PREROUTING –d 1.2.4.1 –j DNAT –-to 192.168.1.50
So the next thing to do is to call her and tell him that whenever she tries to connect to
her ofce computer from home, she must connect to 1.2.4.1.
Our intranet server has the IP address 192.168.1.100. One guy from the nancial
department has a broadband connection and asks us if he can access the intranet
server from home. He gives us his public IP address as 1.2.5.17. We tell him that from
his home he should try the IP address 1.2.4.2 in his web browser, and we execute:
iptables –t nat –A PREROUTING –s 1.2.5.17 –d 1.2.4.2 –p tcp –-dport 80
–j DNAT -–to 192.168.1.100
We think we might want to SSH to the intranet server from anywhere. It would not
be a very wise idea to map one IP address to the intranet server as it is vital for our
company, and if an SSH bug is discovered, we don't want that server to be hacked.

A good idea would be to map a high-number port to the SSH port on the intranet
server (this is PAT or NAPT).
iptables –t nat –A PREROUTING –d 1.2.4.2 –p tcp –-dport 65521 –j DNAT
–-to 192.168.1.100:22
This way, when we are not at the ofce and we want to SSH into the intranet server,
we open an SSH connection to 1.2.4.2 port 65521.
After a while, suppose we installed a web server with the IP address 192.168.1.200.
The web server is www.mycompany.whatever and points in DNS to 1.2.4.5. To be
accessible to the outside world, we perform the following:
iptables –t nat –A PREROUTING –d 1.2.4.5 –p tcp –-dport 80 –j DNAT –-
to 192.168.1.200
Transparent Proxy
Transparent proxy is a way to force users to use a proxy server, even if their browsers
are congured not to. You probably know about the benets of using a proxy server—
NAT and Packet Mangling with iptables
[ 106 ]
bandwidth saving for cached pages and access control implementation (e.g. deny
downloads of les that have dangerous extensions).
We can perform transparent proxy for all or some users to prevent them from
bypassing the proxy whenever they want. This is especially good for children's
computers to deny them access to sexually explicit sites, for example.
On our Linux router, we installed a Squid proxy server to cache some content from
the Web. Also, we want to deny access to sex sites or malicious downloads for
users. The users are not very pleased about using our proxy server, and they usually
remove it from their browser conguration. We can force them to use the proxy
server anyway. If the proxy server listens on port 3128 we will do the following:
iptables –t nat –A PREROUTING –s 192.168.1.0/24 –p tcp –-dport 80 –j
REDIRECT –-to-port 3128
If we want to allow the manager (who has the IP address 192.168.1.50) to bypass the
proxy server, we do so like this:

iptables –t nat –I PREROUTING –s 192.168.1.50 –p tcp –-dport 80 –j
ACCEPT
So this rule will be matched in the PREROUTING chain, and she will be SNATed in the
POSTROUTING chain.
Setting Up the Script
This is a commonly used conguration, but there are many other things we can
do with the NAT support for netlter. We will discuss more NAT issues and
congurations in the third section of this book in the small networks case studies. For
now, let's see how we should set up the script for this example scenario.
The NAT part of the rewall should be included in the same script as the rest of the
rewall rules as described earlier. So, we have:
#!/bin/bash
IP=/sbin/iptables
# some packet filtering rules
### NAT SECTION
#first of all, we want to flush the NAT table
$IP –t nat –F
Chapter 4
[ 107 ]
############ SNAT PART
#Jane's special rule.
#Don't SNAT any TCP connections from her computer except www and all
#udp connections except DNS
$IP –t nat –A POSTROUTING –s 192.168.1.31 –p tcp –-dport ! 80 –j DROP
$IP –t nat –A POSTROUTING –s 192.168.1.31 –p udp –-dport ! 53 –j DROP
#Don't SNAT anything from 192.168.1.0/24 to 192.168.2.0/24
$IP –t nat –A POSTROUTING –s 192.168.1.0/24 –d 192.168.2.0/24 –j ACCEPT
#The boss needs DNAT but we should also SNAT her IP address to 1.2.4.1
$IP –t nat –A POSTROUTING –s 192.168.1.50 –j SNAT –-to 1.2.4.1
#Snat Everyone

$IP –t nat –A POSTROUTING –s 192.168.1.0/24 –o eth1 –j SNAT –-to
1.2.4.0-1.2.4.32 –-to 1.2.3.1
############ DNAT PART
#Dnat the boss so she can access her PC from home
$IP –t nat –A PREROUTING –d 1.2.4.1 –j DNAT –-to 192.168.1.50
#DNAT the intranet server for the guy in the financial department
$IP –t nat –A PREROUTING –s 1.2.5.17 –d 1.2.4.2 –p tcp –-dport 80 –j
DNAT -–to 192.168.1.100
#DNAT for us to ssh into the intranet server
$IP –t nat –A PREROUTING –d 1.2.4.2 –p tcp –-dport 65521 –j DNAT –-to
192.168.1.100:22
#DNAT the web server
$IP –t nat –A PREROUTING –d 1.2.4.5 –p tcp –-dport 80 –j DNAT –-to
192.168.1.200
############ Transparent Proxy
#Allow the boss to bypass the proxy server
NAT and Packet Mangling with iptables
[ 108 ]
$IP –t nat –A PREROUTING –s 192.168.1.50 –p tcp –-dport 80 –j ACCEPT
#Do transparent proxy for the rest of the people
$IP –t nat –A PREROUTING –s 192.168.1.0/24 –p tcp –-dport 80 –j
REDIRECT –-to-port 3128
### End of NAT section
Verifying the Conguration
To verify the conguration, we need to see the chains of the nat table.
root@router:~# iptables -t nat -L -n
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DNAT all 0.0.0.0/0 1.2.4.1 to:192.168.1.50
DNAT tcp 1.2.5.17 1.2.4.2 tcp dpt:80

to:192.168.1.100
DNAT tcp 0.0.0.0/0 1.2.4.2 tcp dpt:65521
to:192.168.1.100:22
DNAT tcp 0.0.0.0/0 1.2.4.5 tcp dpt:80
to:192.168.1.200
ACCEPT tcp 192.168.1.50 0.0.0.0/0 tcp dpt:80
REDIRECT tcp 192.168.1.0/24 0.0.0.0/0 tcp dpt:80 redir
ports 3128
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
DROP tcp 192.168.1.31 0.0.0.0/0 tcp dpt:!80
DROP udp 192.168.1.31 0.0.0.0/0 tcp dpt:!53
ACCEPT all 192.168.1.0/24 192.168.2.0/24
SNAT all 192.168.1.50 0.0.0.0/0 to:1.2.4.1
SNAT all 192.168.1.0/24 0.0.0.0/0 to:1.2.4.0-1.2.
4.32 1.2.3.1
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
root@router:~#
We can see here that all the lines we wrote in the script have been successfully
entered in the nat table.
After building a script like this, the only way to test its correct functionality is to send
test packets for each line and track them with a network analyzer like TCPdump,
ethereal, etc.
Chapter 4
[ 109 ]
For example, if we capture packets on our Linux router and try to initiate a
connection from the Internet to 1.2.4.1 on a random port and TCPdump shows a
sequence of packets like:
1. In on Eth0 from 2.2.2.2 to 1.2.4.1

2. Out on Eth0 from 1.2.3.1—destination host unreachable
and nothing on Eth1, then we will know from the start that the DNAT rule was not
matched.
If the packet ow from the analyzer looks OK, then we should see the packets
matching the rules using the -v when listing the rules (in this case iptables –L –n –v).
A Less Normal Situation: Double NAT
Our company opened a remote ofce in a third-world country that didn't have an
internet connection. The administrator hired in that location congured the local
network with IP addresses in the private class C network 192.168.1.0/24.
After a while, they were able to install a permanent internet connection with a static
assigned IP address 1.2.8.1. The database server on their location has the same IP
address as the database server in our location—192.168.1.60.
The conguration is the same as in the following gure:
In the headquarter's location, we have:
HQ local network: 192.168.1.0/24
HQ database server: 192.168.1.60


NAT and Packet Mangling with iptables
[ 110 ]
Linux Router 1 with two Ethernet interfaces: Eth0, which connects to the local
network and has the IP address 192.168.1.1, and Eth1, which connects to the
Internet with the IP address 1.2.7.1
In the remote location, we have:
Remote local network: 192.168.1.0/24
Remote database server in the remote location: 192.168.1.60
Linux Router 2 with two Ethernet interfaces: Eth0, which connects to the local
network and has the IP address 192.168.1.1, and Eth1, which connects to the
Internet with the IP address 1.2.8.1
The next step is to create a VPN between these locations. On Linux Router 1 at the

headquarters, we perform the following:
iptunnel add vpn1 mode gre remote 1.2.8.1 local 1.2.7.1 key 8132912
ifconfig vpn1 10.10.10.1 pointopoint 10.10.10.2 netmask
255.255.255.252
On Linux Router 2 at the remote location, what we do is:
iptunnel add vpn1 mode gre remote 1.2.7.1 local 1.2.8.1 key 8132912
ifconfig vpn1 10.10.10.2 pointopoint 10.10.10.1 netmask
255.255.255.252
In a normal situation, we would have a network at the headquarters and another
network at the remote location, and we would route them on the vpn1 interface
and don't perform SNAT. As the heading says, this is not a normal situation. On
Linux Router 1 we can route on the Linux Router 1 network 192.168.1.0/24 through
10.10.10.2 (Linux Router 2), but it would have absolutely no effect, because the Linux
kernel prefers directly connected routes (and it is normal for it to be this way).
In order for a computer from headquarters to communicate with a computer from
the remote location, we have to "fake" the fact that we have different networks on
each side. So, we will tell the headquarters' computers that the computers in the
remote location are in the network 192.168.20.0/24. We will also tell the remote
computers that the computers in the headquarters location are in the network
192.168.10.0/24.
In the following example, we will show how the database servers can communicate,
for example, for data replication. So, we will teach you how to map one IP, and you
can do the same for the other 252 IP addresses (i.e. from 254, excluding the database
server and the gateway).




Chapter 4
[ 111 ]

From their point of view, the database server in the headquarters location is
communicating with the database server in the remote location that has the
IP address 192.168.20.60, and the database server in the remote location is
communicating with the database server in the headquarters location that has the IP
address 192.168.10.60. In fact, they both have the IP address 192.168.1.60.
Let's congure Linux Router 1 (at the headquarters).
Step 1
ifconfig eth1:0 192.168.10.1 netmask 255.255.255.0
This is an optional step. IP packets with destination IP addresses in 192.168.10.0/24
will arrive at this router, and if we have no rules in the PREROUTING chain, we don't
want to forward them on the default route.
Step 2
route add –net 192.168.20.0 netmask 255.255.255.0 gw 10.10.10.2
This will add a route to network 192.168.20.0/24 via 10.10.10.2 on the vpn1 interface.
Step 3
iptables –t nat –A POSTROUTING –s 192.168.1.60 –d 192.168.20.60 –j
SNAT –-to 192.168.10.60
This will create a SNAT rule on Linux Router 1 that will map the IP address
192.168.1.60 to 192.168.10.60 if the destination IP address is 192.168.20.60.
Step 4
iptables –t nat –A PREROUTING –d 192.168.10.60 –j DNAT –-to
192.168.1.60
This will create an DNAT rule for all packets arriving at Linux Router 1 having the
destination IP address 192.168.10.60 to send the packets to 192.168.1.60.
This is all we need on Linux Router 1.
On Linux router 2, we do basically the same thing.
Step 1
ifconfig eth1:0 192.168.20.1 netmask 255.255.255.0
Step 2
route add –net 192.168.10.0 netmask 255.255.255.0 gw 10.10.10.1

NAT and Packet Mangling with iptables
[ 112 ]
This will add a route to network 192.168.10.0/24 via 10.10.10.1 on the vpn1 interface.
Step 3
iptables –t nat –A POSTROUTING –s 192.168.1.60 –d 192.168.10.60 –j
SNAT –-to 192.168.20.60
This will create an SNAT rule on Linux Router 2 that will map the IP address
192.168.1.60 to 192.168.20.60 if the destination IP address is 192.168.10.60.
Step 4
iptables –t nat –A PREROUTING –d 192.168.20.60 –j DNAT –-to
192.168.1.60
This will create a DNAT rule for all packets arriving at Linux Router 2 with the
destination IP address 192.168.20.60 to send the packets to 192.168.1.60.
This is the end of the conguration we need to make. Let's see if it works both ways:
The database server in the headquarters location sends a packet to the database
server in the remote location, which it thinks is 192.168.20.60. Since 192.168.20.60
is not directly connected to 192.168.1.60, it will forward the packet to the default
gateway, Linux Router 1. Linux Router 1 checks out the PREROUTING chain and nds
no rule to match this packet, and so it looks up the routing table for 192.168.20.60
and nds the best route through 10.10.10.2 on interface vpn1. Now, Linux Router
1 checks out the POSTROUTING chain and matches the rule that states that for every
packet from 192.168.1.60 to 192.168.20.60, it should change the source IP address to
192.168.10.60. Linux Router 1 does that, and due to ip_conntrack it keeps a record
of this connection. The packet with the changed source IP address is forwarded
according to the routing table to 10.10.10.2 on interface vpn1.
Now, the packet arrives at Linux Router 2 at the remote location having the source
IP address 192.168.10.60 and destination 192.168.20.60. Linux Router 2 looks in
its PREROUTING chain and matches the rule that says to change the destination IP
address to 192.168.1.60 if the packet is destined for 192.168.20.60. Linux Router 2
does this and then looks up 192.168.1.60 in its routing table and sees that 192.168.1.60

is directly connected with itself on Eth0. After analyzing the POSTROUTING chain
and seeing that no rule matches this packet, Linux Router 2 forwards the packet to
192.168.1.60 as being from 192.168.10.60.
Packets traveling the other way around follow the exact same steps; so we can say
"Mission Accomplished!"
Chapter 4
[ 113 ]
Packet Mangling with iptables
The term "mangling" might mislead people to conceive it as malicious—packet
mangling is nothing like that at all. Packet mangling refers to the process of
intentionally altering data in IP packet headers before or after the routing process.
Well, not all elds of the IP packet header can be modied in the mangle table, but
that is not necessary.
Let's recall what an IP packet header looks like:
We have already discussed NAT, where we saw that we can "mangle" a packet by
modifying the Source IP address and Destination IP address elds of the IP header.
This mangling of packets is done only with NAT and is a part of the NAT process.
So, using the mangle table of netlter we can modify the following two elds:
TOS: the 8 bit Type Of Service eld
TTL: the 8 bit Time To Live eld
iptables can also set a mark to IP packets that can be used internal by iproute2 for
source routing and/or QoS with tc. This internal mark, called nfmark (netlter
mark), doesn't alter any of the IP packet headers' elds. Nfmarks can be set using
the MARK target in iptables, which has three options that we can see using help in
conjunction with the MARK target:
root@router:~# iptables -j MARK help
… some lines missing …
MARK target v1.3.1 options:
set-mark value Set nfmark value
and-mark value Binary AND the nfmark with value

or-mark value Binary OR the nfmark with value


NAT and Packet Mangling with iptables
[ 114 ]
Example: mark packets to 192.168.1.100 with nfmark 6:
iptables -t mangle -A POSTROUTING -d 192.168.1.100 -j MARK set-mark 6
The TOS eld is 8 bits long and was discussed in the previous chapter. Alteration of
the TOS eld is very useful for QoS. For this, iptables uses the TOS target, which has
the set-tos option. We can see TOS target options using help in the
command line:
root@router:~# iptables -j TOS help
… some lines missing…
TOS target v1.3.5 options:
set-tos value Set Type of Service field to one of the
following numeric or descriptive values:
Minimize-Delay 16 (0x10)
Maximize-Throughput 8 (0x08)
Maximize-Reliability 4 (0x04)
Minimize-Cost 2 (0x02)
Normal-Service 0 (0x00)
Example: set TOS to Maximize-Throughput for outgoing FTP data:
iptables -t mangle -A POSTROUTING -p tcp sport 20 -j TOS set-tos 8
There are only ve TOS values we can set; so the TOS target doesn't modify the
whole TOS byte. However, this can be done with DSCP (Differentiated Services
Field Codepoints). The DSCP bits are the rst six bits in the TOS byte, as shown in
the following gure:
iptables has the DSCP target that can be used to alter the DSCP bits. The options can
be found using help with the DSCP target.
root@router:~# iptables -j DSCP help

… some lines missing…
DSCP target options
set-dscp value Set DSCP field in packet header to value
Chapter 4
[ 115 ]
This value can be in decimal (ex: 32)
or in hex (ex: 0x20)
set-dscp-class class Set the DSCP field in packet header
to the value represented by the DiffServ class
value.
This class may be EF,BE or any of the CSxx
or AFxx classes.
These two options are mutually exclusive !
Example: set DSCP 32 to packets arriving on interface Eth0:
iptables -t mangle -A PREROUTING -i eth0 -j DSCP set-dscp 32
DSCP is explained in more detail in RFC2474, which can be found at

The TTL eld of the IP packet header is the Time To Live for that IP packet, and can
be altered using the TTL target of iptables.
root@router:~# iptables -j TTL help
… some lines missing…
TTL target v1.3.1 options
ttl-set value Set TTL to <value 0-255>
ttl-dec value Decrement TTL by <value 1-255>
ttl-inc value Increment TTL by <value 1-255>
Altering TTL can be useful, for example, if you want a client not to distribute the
Internet to others. If you set the TTL value to 1 for packets going to a certain IP
address, then only the device having that IP address receives the IP packets. If the
packet is destined to a host behind that IP address, the TTL will be decremented and
the IP packet will be dropped.

Example: set TTL to 1 for packets going out interface ppp0:
iptables -t mangle -I POSTROUTING -o ppp0 -j TTL ttl-set 1
The netlter mangle Table
The mangle table has ve chains, named PREROUTING, INPUT, FORWARD, OUTPUT, and
POSTROUTING. Let's look again at the packet ow diagram again:
NAT and Packet Mangling with iptables
[ 116 ]
The rules in the PREROUTING chain of the mangle table are analyzed by the kernel
when a packet comes in, before the routing process takes place.
If the packet is not for the router (is destined to a host behind it), the kernel looks
up the rules in the mangle table FORWARD chain and afterwards the mangle table
POSTROUTING chain.
Chapter 4
[ 117 ]
If the packet is destined to the router, then the mangle table INPUT chain is analyzed.
When the response is generated, the kernel looks up the rules in the OUTPUT chain of
the mangle table rst, and then in the POSTROUTING chain of the mangle table.
On those chains, all iptables operations are possible.
It is not recommended to perform packet ltering in the
mangle table. Even if you are not restricted to drop packets
in the mangle table, it should be only for rules that mangle
IP packets.
A particularity of the mangle table is that, unlike the filter or nat tables, all rules
are analyzed, even if a packet is matched against one rule. This functionality of the
mangle table was needed, because you might want to alter the same IP packet in
several ways (set DSCP, nfmark, and TTL at the same time), and so, unlike the other
tables, if a match is found against one rule in a chain, the kernel doesn't stop there,
and tries to match the packet against all the other rules in that chain.
This is one of the major reasons for which packet ltering in the mangle table is
strongly discouraged.

Summary
This chapter showed you how to perform Network Address Translation and IP
packet mangling using netlter/iptables.
We saw:
What Network Address Translation is
Types of NAT: SNAT or Masquerading, DNAT, full cone NAT
Requirements for performing NAT with netlter/iptables
How to SNAT with iptables
How to DNAT with iptables
How to perform transparent proxy with iptables
How to perform double NAT with iptables
What packet mangling is
What elds of the IP packet header can be modied using iptables
How packets are matched against the chains of rules in the netter
mangle table











Layer 7 Filtering
In Chapter 1 of this book, we presented the OSI and TCP/IP networking models.
As we saw there, even if the TCP/IP model has the widest usage, the reference
model is OSI.

Let's have a look at the TCP/IP and OSI models again:
At Layer 7 of the OSI model, we nd Application (HTTP, FTP, SSH, etc.). As
you can see from the picture above, TCP/IP compacted OSI Layers 7, 6, and 5
into one Layer, TCP/IP Layer 4 (Application), which has the same name, but
different functionality.
Filtering and prioritizing trafc from some applications can be very easy and
very hard at the same time. Normally, we would lter/prioritize web trafc by
matching TCP packets with source or destination port 80, which is the standard
HTTP port. However, web servers can be congured to use any port; so our
lters/prioritizations won't work for that particular trafc.
Layer 7 Filtering
[ 120 ]
Another big problem network administrators have is ltering trafc belonging to
P2P (peer to peer) applications like Kazaa, DC++, Emule, etc., as those applications
don't use standard ports and, even worse, they can be congured to use other
applications' standard ports for communication (e.g. TCP port 80).
At one point, some people decided to do something about it and they did a
pretty good job by starting the project named "Layer 7 Filtering" at
.
As you probably guessed, "Layer 7 Filtering" is a method to lter Layer 7 data. That
means ltering network trafc generated by an application regardless of the protocol
or port it uses at Layer 4.
L7-lter is a packet classier for the Linux kernel that doesn't look up port numbers
or Layer 4 protocols, but instead looks up the data in an IP packet and does a regular
expression match on it to determine what kind of data it is, mainly what application
protocol is being used.
Another project we will talk about is IP2P; it is an alternative to L7-lter, but
has been designed for ltering only P2P applications while L7-lter takes into
consideration a wider range of applications.
When to Use L7-lter

L7-lter is a great solution for matching application data in a network, but, as with
almost every good thing, there are downsides to it too. As we will go deeper into
how L7-lter works, you will see that it has to actually analyze data contained in
IP packets, so it is quite obvious that this can eat up a lot of CPU power. So, using
L7-lter on a Linux router with high trafc is not quite recommended, as L7-lter
is CPU-consuming and can thus introduce latency and packet loss in the network.
However, it really depends on the type of trafc passing through that router rather
than the amount of trafc. For example, if you have 20 Mbps average of WWW
data, L7-lter can work pretty well, but for 2 Mbps of VoIP trafc, the router's
performance would dramatically drop.
Normally, we would consider using L7-lter for SOHO environments. In this case,
L7-lter is very good for ltering viruses, limiting the bandwidth consumed by
children when downloading music, etc.
Another situation when L7-lter is recommended would be for small-to-medium-
sized companies that want to shape and prioritize trafc consumed by applications
that are not vital or productive to the company. For example, in a company that
has a 10 Mbps internet connection, an employee using P2P software can ll up the
bandwidth and other trafc like Web, SSH, database replication, and so on would
suffer because of that.
Chapter 5
[ 121 ]
Another downside to using L7-lter is that it needs the connection tracking module
to function. We have already discussed in the previous chapter about connection
tracking (ip_conntrack) and we saw that it is not suitable for very high trafc
conditions. So, when using L7-lter, you must also consider the disadvantage of
using connection tracking.
Anyway, to draw a conclusion on this topic, L7-lter is a great tool but it also is
CPU-consuming and can be used only with ip_conntrack; so it's quite difcult to
make exact statements about when to use and when not to use L7-lter, and with what
machines. I'd recommend not to use L7-lter on machines with rates over 5000 pps

(packets per second), but, at the end of the day, if the machine can handle it, use it.
How Does L7-lter Work?
What L7-lter does is provides a way for iptables to match packets based on the
application they belong to.
The TCP/IP model contains four layers and, before the L7-lter project, netlter
could match data by the rst three layers:
Network access layer: iptables -A CHAIN -m mac mac-source …"
Internet: iptables -A CHAIN -s IP_ADDRESS …"
Transport: iptables -A CHAIN -p tcp dport 80 …
At the network access layer, netlter uses -m mac to match packets from or to a
MAC address in the network. At the layer above, the Internet layer, we have the
IP protocol; netlter matches packets from or to an IP address, regardless of the
transport protocol, port number, or application the packet uses. At the transport
layer, we have TCP or UDP, and netlter can match packets by protocol, and more
specically, by port number within the protocol.
Any combination of the three lower layers is permitted; for instance:
iptables –A FORWARD –s 192.168.0.2 –p tcp -–dport 80 –m mac –-mac-
source 00:01:BC:2D:EF:2A –j DROP"
will drop all packets from the IP address 192.168.0.2 if the source MAC address is
00:01:BC:2D:EF:2A and the packets use the TCP protocol and have the destination
TCP port 80.
L7-lter adds a new feature to netlter by matching packets that belong to an
application that is found at the TCP/IP Layer 4. A very important thing is that
L7-lter is just another match option for iptables, and so all the rules of the other
match options apply in this case. Therefore, you can do all the iptables operations
with the packets matched by L7-lter.



Layer 7 Filtering

[ 122 ]
The short and easy version of L7-lter is that after installing it you have -m layer7
l7proto [http|ftp| ]. This is the match option we were talking about.
In order to match Layer 7 data, netlter looks deeper into an IP packet than just at
its header. However, the actual data contained in the packet doesn't just say "I'm a
P2P packet; lter me!"; so the data is matched against a set of regular expressions that
are common to different applications. This set of regular expressions is probably the
most important part of this project, and is called "protocol denitions".
The L7-lter project contains three important parts:
A kernel patch, which provides a way for the kernel to look into the
IP packets
An iptables patch, which provides the match option for iptables
A collection of pattern les that contain the regular expressions for supported
protocols (protocol denitions)
Installing L7-lter
To install the L7-lter project, we need to patch our kernel with the patch provided
by the source found at . To do that, we need
the kernel source. The next operation would be to apply the iptables patch, recompile
iptables, and install the protocol denitions les. Let's go deeper into the process.
Applying the Kernel Patch
The rst step is to download the kernel source we want from .
Next, we need to download L7-lter from .
For this chapter, we used kernel source 2.6.12.5 and L7-lter version 2.0 beta. After
downloading what you need to the /usr/src folder, unzip the L7-lter TAR archive
as follows:
router:/usr/src# tar xfvz netfilter-layer7-v2.0-beta.tar.gz
netfilter-layer7-v2.0-beta/
netfilter-layer7-v2.0-beta/stray_code
netfilter-layer7-v2.0-beta/for_older_kernels/
netfilter-layer7-v2.0-beta/for_older_kernels/

kernel-2.6.9-2.6.10-layer7-1.2.patch
netfilter-layer7-v2.0-beta/for_older_kernels/
kernel-2.6.0-2.6.8.1-layer7-0.9.2.patch
netfilter-layer7-v2.0-beta/for_older_kernels/
kernel-2.6.11-2.6.12-layer7-1.4.patch
netfilter-layer7-v2.0-beta/CHANGELOG



Chapter 5
[ 123 ]
netfilter-layer7-v2.0-beta/README
netfilter-layer7-v2.0-beta/iptables-layer7-2.0.patch
netfilter-layer7-v2.0-beta/kernel-2.6.13-layer7-2.0.patch
netfilter-layer7-v2.0-beta/kernel-2.4-layer7-2.0.patch
router:/usr/src#
Next, go to the kernel source root and patch the kernel using the appropriate patch:
router:/usr/src/linux-2.6.12.5# patch -p1 < /netfilter-layer7-v2.
0-beta/for_older_kernels/kernel-2.6.11-2.6.12-layer7-1.4.patch
patching file include/linux/netfilter_ipv4/ip_conntrack.h
patching file include/linux/netfilter_ipv4/ipt_layer7.h
patching file net/ipv4/netfilter/Kconfig
patching file net/ipv4/netfilter/Makefile
patching file net/ipv4/netfilter/ip_conntrack_core.c
patching file net/ipv4/netfilter/ip_conntrack_standalone.c
Hunk #1 succeeded at 189 with fuzz 2 (offset 37 lines).
patching file net/ipv4/netfilter/ipt_layer7.c
patching file net/ipv4/netfilter/regexp/regexp.c
patching file net/ipv4/netfilter/regexp/regexp.h
patching file net/ipv4/netfilter/regexp/regmagic.h

patching file net/ipv4/netfilter/regexp/regsub.c
router:/usr/src/linux-2.6.12.5#
Next, run make config, make menuconfig, or make Xconfig. You need to enable the
following options:
Code maturity level options | Prompt for development and/or incomplete
code/drivers
Netlter (Device Drivers | Networking support | Networking Options |
Network packet ltering)
Connection tracking (Network packet ltering | IP: Netlter Conguration
| Connection tracking)
Connection tracking ow accounting and IP tables support (on the
same screen)
Layer 7 match support





Layer 7 Filtering
[ 124 ]
Next, compile the kernel, install it as usual, and reboot your machine with the
new kernel.
When compiling, you might see a warning, depending on the compiler version:
CC [M] net/ipv4/netfilter/ipt_layer7.o
net/ipv4/netfilter/ipt_layer7.c:457: warning: initialization from
incompatible pointer type
Just ignore the warning and go on.
Applying the iptables Patch
To apply the iptables patch, we need the iptables sources from
. Go to the iptables source root and patch it with

the patch provided by the L7-lter project.
router:/usr/src/iptables-1.3.4# patch -p1 < /
netfilter-layer7-v2.0-beta/iptables-layer7-2.0.patch
patching file extensions/.layer7-test
patching file extensions/libipt_layer7.c
Chapter 5
[ 125 ]
patching file extensions/libipt_layer7.man
router:/usr/src/iptables-1.3.4#
Because le permissions can't be included in a patch, you need to set execute
permission for the le extensions/.layer7-test.
router:/usr/src/iptables-1.3.4# chmod +x extensions/.layer7-test
Next, we will compile iptables using make and specifying the path to our patched
kernel. In our case:
router:/usr/src/iptables-1.3.4# make KERNEL_DIR=/usr/src/
linux-2.6.12.5
Making dependencies: please wait
Extensions found: IPv4:CLUSTERIP IPv4:layer7 IPv4:recent IPv6:ah IPv6:
esp IPv6:frag IPv6:ipv6header IPv6:hbh IPv6:dst IPv6:rt

Now we will install iptables using the make install command and also specifying
the path to the patched kernel. In our case:
router:/usr/src/iptables-1.3.4# make install KERNEL_DIR=/usr/src/
linux-2.6.12.5
cp iptables /usr/local/sbin/iptables
cp iptables.8 /usr/local/man/man8/iptables.8

Now, we're almost done. Please note that the new iptables tool might be in a
different folder than the original. For example, we can see that the make install
command installed iptables in /usr/local/sbin/iptables because we didn't

specify the BINDIR option when compiling iptables. We also need to make sure
that we're using the right tool when issuing commands. We can verify that using
iptables –V and comparing the versions we have:
router:~# iptables -V
iptables v1.2.11
router:~# type iptables
iptables is hashed (/sbin/iptables)
router:~# /usr/local/sbin/iptables -V
iptables v1.3.4
Protocol Denitions
First, we need to download the protocol denitions archive from the L7-lter project
page at sourceforge,
l7-protocols-2006-06-03.tar.gz?download. Next, we need to copy the pattern
les (.pat) from the archive to the /etc/l7-protocols folder.
Layer 7 Filtering
[ 126 ]
router:/usr/src/l7-protocols-YYYY-MM-DD# mkdir /etc/l7-protocols
router:/usr/src/l7-protocols-YYYY-MM-DD# cp protocols/* /etc/
l7-protocols
The /etc/l7-protocols folder is the default folder for pattern les, and iptables
will look into it and its subfolders, but not recursively. This means that iptables will
search for pattern les in /etc/l7-protocols and in any /etc/l7-protocols/
subdir, but not in /etc/l7-protocols/subdir/subsubdir.
If you don't wish to set up the /etc/l7-protocols folder, you can specify the
pattern les folder by doing:
iptables […] –m layer7 –-l7dir /path-to/patterns –-l7proto […]
Please note that you have to specify the patterns folder before the protocol.
Testing the Installation
First, we might want to see if our module is in place. We can do that using the
modinfo command:

router:~# modinfo ipt_layer7
filename: /lib/modules/2.6.12.5-home.made/kernel/net/ipv4/
netfilter/ipt_layer7.ko
author: Matthew Strait <>,
Ethan Sommer <>
license: GPL
description: iptables application layer match module
vermagic: 2.6.12.5-home.made preempt PENTIUMIII gcc-3.3
depends: ip_tables
The output shows that we have a module called ipt_layer7 and some information
about it, such as lename, author, license, description, version, and other module
dependencies.
Next, we will try to load the module using the modprobe command:
router:~# modprobe ipt_layer7
router:~# lsmod
Module Size Used by
ipt_layer7 12364 0
The modprobe command didn't produce any errors. By using the lsmod command,
we can see the module loaded into the kernel, its size, and the number of processes it
is used by (in our case 0), because we didn't used it yet.
Next, we might want to test it and see if it works. We will do that by using Apache
web server, placing some les in the web folder and downloading them.
Chapter 5
[ 127 ]
When downloading the les, we should see that all packets are matched. First, we
will use the command iptables –Z to zero the counters of all the rules in all chains,
and then we will insert an accounting rule in the OUTPUT chain to match all the
outgoing HTTP trafc.
router:~# iptables -Z
router:~# iptables -A OUTPUT -m layer7 l7proto http

router:~# iptables -L OUTPUT -n -v
Chain OUTPUT (policy ACCEPT 10168 packets, 3433K bytes)
pkts bytes target prot opt in out source destination
0 0 all * * 0.0.0.0/0 0.0.0.0/0
LAYER7 l7proto http
Next, we download the le whale.qt (for example) from this server; and look in the
apache access.log:
"GET /whale.qt HTTP/1.1" 200 11727970 "-"
So we must have 11 Mb matched on the accounting rule in the OUTPUT chain.
router:~# iptables -L OUTPUT -n -v
Chain OUTPUT (policy ACCEPT 172K packets, 65M bytes)
pkts bytes target prot opt in out source destination
0 0 all * * 0.0.0.0/0 0.0.0.0/0
LAYER7 l7proto http
router:~#
Oops! No packet was matched. Did we do something wrong or is L7-lter not good
at all? Well, in most cases, the rst option is valid, so when looking again at the
ipt_layer7 module, we can see that it depends only on the ip_tables module.
We now quickly verify what modules are loaded in the kernel, but we don't see the
ip_conntrack module. Normally, ipt_layer7 should have had ip_conntrack in
the dependencies, but it doesn't. That is why we neither got any errors while loading
the module nor did we get any result.
We know that L7-lter uses the ip_conntrack module; so we need to load it. Let's
see what happens now.
router:~# modprobe ip_conntrack
router:~# iptables -L OUTPUT -n -v
Chain OUTPUT (policy ACCEPT 457K packets, 159M bytes)
pkts bytes target prot opt in out source destination
0 0 all * * 0.0.0.0/0 0.0.0.0/0
LAYER7 l7proto http

router:~# wget http://127.0.0.1/whale.qt
00:37:21 http://127.0.0.1/whale.qt
=> `whale.qt'
Connecting to 127.0.0.1:80 connected.
Layer 7 Filtering
[ 128 ]
HTTP request sent, awaiting response 200 OK
Length: 11,727,970 [video/quicktime]
100%[=================================================================
=================>] 11,727,970 12.74M/s
00:37:22 (12.71 MB/s) - `whale.qt' saved [11727970/11727970]
router:~# iptables -L OUTPUT -n -v
Chain OUTPUT (policy ACCEPT 467K packets, 175M bytes)
pkts bytes target prot opt in out source destination
1433 12M all * * 0.0.0.0/0 0.0.0.0/0
LAYER7 l7proto http
Well, as you can see, it worked. Now we have a Linux router with application layer
ltering capabilities.
L7-lter Applications
We can use L7-lter with any iptables option; after all, L7-lter provides just another
match option. However, not all the things we can do with our new match option are
recommended, because L7-lter might match packets belonging to other applications
than the one you want.
Filtering Application Data
Blocking application data that passes through your router is one of the non-
recommended things that you can do with L7-lter.
Trafc from different applications might look similar; so you might experience
problems when dropping data based on the L7-lter match. For example, if you
drop packets that belong to eDonkey, there might be some other protocols that will
experience problems. The eDonkey pattern matches about 1% of other streams with

random data.
If you still want to use L7-lter for blocking several applications passing through
your Linux router, it can be done as follows:
router:~# iptables -A FORWARD -m layer7 l7proto edonkey -j DROP
You can also use L7-lter in conjunction with port numbers or IP addresses.
For example:
router:~# iptables -A FORWARD -m layer7 l7proto edonkey –d
192.168.1.131 -j DROP
will drop eDonkey packets that have the destination 192.168.1.131.

×