Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

How can I identify download traffic and set a mark so that I can route those packets using the fwmark through another link ?

share|improve this question
2  
I believe this question, as it stands, is too big to reasonably answer. You should update with some specifics. – Scott Pack Mar 20 '11 at 14:44
    
You really need to start by defining "downloads". Technically, everything the comes into your network from the Internet is download traffic. – John Gardeniers Mar 20 '11 at 20:35
    
Here "download" means files that are being downloaded more than 1MB size. I want to mark such traffic and route them to another link (ISP connection) using iproute2 – Supratik Mar 21 '11 at 5:01
up vote 5 down vote accepted

The iptables modules connbytes, connlimit and length can be used to identify downloads. Here the setup is use:

#Mark downloads
$IPT -t mangle -N BULKCONN   
#Small packet is probably interactive or flow control
$IPT -t mangle -A BULKCONN -m length --length 0:500 -j RETURN
#Small packet connections: multi purpose (don't harm since not maxed out)
$IPT -t mangle -A BULKCONN -m connbytes --connbytes 0:250 --connbytes-dir both --connbytes-mode avgpkt -j RETURN

#After one megabyte a connection is considered a download
$IPT -t mangle -A BULKCONN -m connbytes --connbytes 1048576: --connbytes-dir both --connbytes-mode bytes -j MARK --set-mark 6
$IPT -t mangle -A BULKCONN -j RETURN

$IPT -t mangle -A PREROUTING -i eth1 -j BULKCONN

I use queuing disciplines to prioritize downloads and other traffic.

About sending through another link: I am not ready to answer this, but it would be done with iproute2 (assuming you mean another IP link). However it will only work downstream, since you can not control where upstream traffic reaches you.

share|improve this answer
    
@Ganwell thanks for providing this wonderful solution. Yes I am using iproute2 to route packets to another link (other ISP connection). I found that the modules connbytes and connlimit is not present with the kernel. Is there any easy way to include this modules without recompiling the kernel ? – Supratik Mar 21 '11 at 4:58
    
@Supratik It is in the mainstream kernel since 2.6.16, maybe you can update the kernel. It is possible to add modules but usually it is as complicated as compiling the whole kernel. What is your kernels version and what distribution are you using? – Ganwell Mar 21 '11 at 12:44
    
@Ganwell thanks for the reply. I am using kernel-2.6.18-194.3.1.el5 and I am using CentOS 5. I am getting "Couldn't load match `connbytes':/lib/iptables/libipt_connbytes.so" error. Can you please advice how should I proceed ? – Supratik Mar 21 '11 at 14:42
    
@Supratik Wow that is outdated (from 2006). It seems that the CentOSPlus repo has newer kernels. Unfortunately I use this other distribution and I can only tell that I never had any problems when upgrading kernels there. Maybe you can test it on a other box first: Clone your system and do the upgrade, if everything works and connbytes is available, do it on the hot system. – Ganwell Mar 21 '11 at 16:04
    
@Supratik No newer kernels in CentOSPlus. A fresh install is generally strongly preferred over an upgrade. <- Probably you should switch to a upgradable distribution. From MigrationGuide – Ganwell Mar 21 '11 at 16:17

I was inspired by @Ganwell solution to this, and managed to solve this on top of adding in a tc classful traffic shaping. I blogged about this solution in my personal wiki: https://giki.wiki/@nubela/Software-Engineering/Per-Connection-Throttling

Here's my solution to this question with an actual shell script:

#!/bin/sh

dev=eth0
ip_port=3002
rate_limit=512kbit
rate_ceil=1024kbit
htb_class=10
max_byte=10485760

if [ "$(id -u)" != "0" ]; then
    echo "This script must be run as root" 1>&2
    exit 1
fi

if [ "$1" = "enable" ]; then
    echo "enabling rate limits"
    tc qdisc del dev $dev root > /dev/null 2>&1
    tc qdisc add dev $dev root handle 1: htb

    tc class add dev $dev parent 1: classid 1:$htb_class htb rate $rate_limit ceil $rate_ceil
    tc filter add dev $dev parent 1: prio 0 protocol ip handle $htb_class fw flowid 1:$htb_class

    #iptables -t mangle -A OUTPUT -p tcp --sport $ip_port -j MARK --set-mark $htb_class

    # small packet is probably interactive or flow control
    iptables -t mangle -A OUTPUT -p tcp --sport $ip_port -m length --length 0:500 -j RETURN

    # small packet connections: multi purpose (don't harm since not maxed out)
    iptables -t mangle -A OUTPUT -p tcp --sport $ip_port -m connbytes --connbytes 0:250 --connbytes-dir both --connbytes-mode avgpkt -j RETURN

    #after 10 megabyte a connection is considered a download
    iptables -t mangle -A OUTPUT -p tcp --sport $ip_port -m connbytes --connbytes $max_byte: --connbytes-dir both --connbytes-mode bytes -j MARK --set-mark $htb_class
    iptables -t mangle -A OUTPUT -j RETURN

elif [ "$1" = "disable" ]; then
    echo "disabling rate limits"
    tc qdisc del dev $dev root > /dev/null 2>&1

    iptables -t mangle -F
    iptables -t mangle -X

elif [ "$1" = "show" ]; then
    tc qdisc show dev $dev
    tc class show dev $dev
    tc filter show dev $dev
    iptables -t mangle -vnL INPUT
    iptables -t mangle -vnL OUTPUT
else
    echo "invalid arg $1"
fi
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.