We can use L7-filter with any iptables option; after all, L7-filter provides just another match option. However, not all the things we can do with our new match option are recommended, because L7-filter might match packets belonging to other applications than the one you want.
Blocking application data that passes through your router is one of the non-recommended things that you can do with L7-filter.
Traffic from different applications might look similar; so you might experience problems when dropping data based on the L7-filter 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-filter 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-filter 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.
Before deciding on blocking certain applications, please take a look at http://l7-filter.sourceforge.net/protocols. You will see the list of protocols supported by the L7-filter project, and how good the patterns are. If pattern matching is poor, don't use L7-filter with DROP
or REJECT!
The creators of the L7-filter project describe this as being the best way to use their project. To limit bandwidth consumed by applications or users, we will use the tc
tool described in Chapter 3.
L7-filter can match some or all application data in IP packets. Therefore, we can set a mark on the packets belonging to a specific application. Due to the fact that L7-filter is a match option, we can use netfilter mark to mark the packets, TOS to set a specific type of service, or DSCP to set a DSCP value, whatever we think is best to use with tc
.
As an example, we will build a script that will limit BitTorrent to 2 Mbps for all our users, and FTP traffic to 512 Kbps for one user and to 1 Mbps for another user.
First, we need to mark BitTorrent and FTP data with arbitrary integer values. We can do it like this:
router:~# iptables -t mangle -A POSTROUTING -m layer7 -- l7proto bittorrent -j MARK --set-mark 5 router:~# iptables -t mangle -A POSTROUTING -m layer7 -- l7proto ftp d 192.168.1.100 -j MARK --set-mark 6 router:~# iptables -t mangle -A POSTROUTING -m layer7 -- l7proto ftp d 192.168.1.112 -j MARK --set-mark 7
Now, let's verify the POSTROUTING
chain:
router:~# iptables -t mangle -L POSTROUTING -n -v Chain POSTROUTING (policy ACCEPT 5855K packets, 4686M bytes) pkts bytes target prot opt in out source destination 3183 1404K MARK all -- * * 0.0.0.0/0 0.0.0.0/0 LAYER7 l7proto bittorrent MARK set 0x5 119 1012K MARK all -- * * 0.0.0.0/0 192.168.1.100 LAYER7 l7proto ftp MARK set 0x6 12 100K MARK all -- * * 0.0.0.0/0 192.168.1.112 LAYER7 l7proto ftp MARK set 0x7
OK, it seems that packets are matched and marked with the values we want (5
for BitTorrent and 7
for FTP).
We will use CBQ in this example; so we need to create the cbq
classes we want. Let's create a script called limits
like this:
#!/bin/bash #delete root class. When running this #script we need to delete limits first tc qdisc del dev eth1 root #create the root class tc qdisc add dev eth1 root handle 10: cbq bandwidth 100Mbit avpkt 1000 tc class add dev eth1 parent 10:0 classid 10:1 cbq bandwidth 100Mbit rate 100Mbit allot 1514 weight 10Mbit prio 8 maxburst 20 avpkt 1000 #create a 2 mbps class for bittorrent tc class add dev eth1 parent 10:1 classid 10:100 cbq bandwidth 100Mbit rate 2Mbit allot 1514 weight 256Kbit prio 5 maxburst 20 avpkt 1000 bounded tc qdisc add dev eth1 parent 10:100 sfq quantum 1514b perturb 15 tc filter add dev eth1 parent 10:0 protocol ip prio 25 handle 5 fw flowid 10:100 #create a 512 kbps class for ftp for the client 192.168.1.100 tc class add dev eth1 parent 10:1 classid 10:200 cbq bandwidth 100Mbit rate 512Kbit allot 1514 weight 64Kbit prio 5 maxburst 20 avpkt 1000 bounded tc qdisc add dev eth1 parent 10:200 sfq quantum 1514b perturb 15 tc filter add dev eth1 parent 10:0 protocol ip prio 25 handle 6 fw flowid 10:200 #create a 1 mbps class for ftp for the client 192.168.1.112 tc class add dev eth1 parent 10:1 classid 10:300 cbq bandwidth 100Mbit rate 1Mbit allot 1514 weight 128Kbit prio 5 maxburst 20 avpkt 1000 bounded tc qdisc add dev eth1 parent 10:300 sfq quantum 1514b perturb 15 tc filter add dev eth1 parent 10:0 protocol ip prio 25 handle 7 fw flowid 10:300
After running the script, to verify the configuration, we need to zero the POSTROUTING
chain in the mangle
table and run the script.
router:~# chmod +x limits router:~# iptables -t mangle -Z POSTROUTING; ./limits RTNETLINK answers: No such file or directory router:~#
The error we got when running the limits
script was generated because no limits existed on that interface, meaning that no root class was present. If we will run it again, we will not get any errors.
Now, the commands iptables -t mangle -L POSTROUTING -n -v
and tc -s class show dev eth1
should generate the same number of bytes and packets matched for each rule and corresponding class.
Accounting is the easiest application that you can do with L7-filter. You can set up accounting scripts to see how many bytes are consumed by applications in your network.
Let's take the following example on a building router with 11 clients connected. We want to see what the traffic looks like at the application layer; so we will set up an accounting script like this:
iptables -A FORWARD -m layer7 --l7proto directconnect iptables -A FORWARD -m layer7 --l7proto bittorrent iptables -A FORWARD -m layer7 --l7proto http iptables -A FORWARD -m layer7 --l7proto ftp iptables -A FORWARD -m layer7 --l7proto yahoo iptables -Z
After a few minutes, we can get an idea on what type of traffic is most popular with those clients:
router:~# iptables -L FORWARD -n -v Chain FORWARD (policy ACCEPT 289K packets, 209M bytes) pkts bytes target prot opt in out source destination 62318 55M all -- * * 0.0.0.0/0 0.0.0.0/0 LAYER7 l7proto directconnect 6978 1202K all -- * * 0.0.0.0/0 0.0.0.0/0 LAYER7 l7proto bittorrent 8037 6116K all -- * * 0.0.0.0/0 0.0.0.0/0 LAYER7 l7proto http 0 0 all -- * * 0.0.0.0/0 0.0.0.0/0 LAYER7 l7proto ftp 108 10724 all -- * * 0.0.0.0/0 0.0.0.0/0 LAYER7 l7proto yahoo
And the winner is dc++ with about 25% of the traffic!
3.16.22.161