от alex_c(20-04-2005)

рейтинг (37)   [ добре ]  [ зле ]

Printer Friendly Вариант за отпечатване

Поради молбата на един от посетителите на форума реших да покажа как са реализирани нещата за ограничаване на изходящ трафик при мен.

Преди да започна, искам да заявя, че не претендирам за уникалност – не аз съм открил топлата вода, може да има и по-елегантни решения от моето. Целта ми е да намаля броя на постингите във форума с молби за помощ, както и да призова за алтернативни решения, от които ще имат полза всички, посещаващи този сайт.

Бих искал да изкажа благодарност на екипа на ludost.net, откъдето се сваля актуална информация за всички български мрежи (вероятно съществуват и други източници) и без която се обезсмисля цялата операция.

Ограничаването на изходящия трафик става на няколко етапа

1. Определяне на максималните параметри на канала и мрежов интерфейс, на който ще се прилагат ограниченията.

Под максималните параметри на канала се има в предвид максималните скорости за upload (BG и International), разрешени ви от вашия доставчик. Този въпрос се уточнява с него, но да приемем, че за случая скоростите са: BG – 2 Mbit/s, INT – 512 Кbit/s.

За определяне на мрежов нтерфейс, на който ще се прилагат ограниченията, трябва да се има в предвид, че ограничаването на скоростите става само за изходящ трафик. Трябва да изясните кой е интерфейсът, от който излиза upload трафика. В повечето случаи това е интерфейсът, през който се свързвате с доставчика си (да приемем, че това е eth0).

2. Определяне на алгоритъм за ограничаване на трафика

Като алгоритъм е избран HTB, макар че могат да се ползват и други такива.

3. Определяне на клиентски адреси, които ще бъдат ограничавани и стойностите на самото ограничаване.

Да приемем, че клиентските адреси са от мрежа клас С, която е (съвсем произволно) 212.104.111.0/24.

Нека ограниченията на IP адрес да са: 32 – 96 Kbit/s за INT и 64 – 160 Kbit/s за BG.

4. Изтегляне на файла с българските мрежи

Актуалната версия на файла с българските мрежи може да се изтегли от http://ip.ludost.net/ след попълване на съответната форма. За автоматизирано изтегляне може да се използва следната команда:

#wget -q -O bg_nets-new.txt \ "http://ip.ludost.net/cgi/process?country=1&country_list=bg&format_template=prefix&format_name=&format_target=&format_default="

С тази команда информацията за българските мрежи се записва във файла bg_nets-new.txt.

Форматът на файла е следния:

# ipformat.pm: (c) Boyan Krosnov, (soon to be released) under the GPL

# ipformat.pm: using template prefix

# prefix notation

# ipgetintervals.pm: (c) Boyan Krosnov, (soon to be released) under the GPL

# prefix data acquired from http://ip.ludost.net/

# ipgetintervals.pm: datasets list cleared

# ipgetintervals.pm: added bg to the list of datasets

# ipgetintervals.pm: loading file var/country.db

# ipgetintervals.pm: dumping database

62.44.96.0/19

62.73.64.0/18

62.176.64.0/18

62.200.195.0/24

62.204.128.0/19

62.213.160.0/19

80.72.64.0/19

80.80.128.0/19

и т.н.

Т.к. има вероятност да настъпят промени в българските мрежи, файлът с мрежите трябва периодически да се изтегля и правилата за ограничаване на трафика периодически да се променят. Предполага се, че ще се създаде скрипт, с който ще се прави това. Горната команда стои в началото на този скрипт. Удачно е скриптът да се изпълнява през определен период от време чрез cron.

5. Маркиране на пакети, идващи от даден IP адрес и предназначени за BG или INT пространството.

Идеята е всички пакети, идващи от даден IP адрес и предназначени за BG да се маркират с една марка (напр. 1) чрез iptables, а пакетите, идващи от същия IP адрес и предназначени за INT – с друга (напр. 2). Това става по следния начин:

Създава се верига mark-out в таблицата mangle:

#/sbin/iptables -t mangle -N mark-out

Изходящият трафик към BG пространството се прекарва през тази верига и се маркира с едни марки.


file=bg_nets.txt

line_count=`wc $file | awk '{ print $1 }'`

for name in `seq $line_count`

do

read name

mat=`expr match "$name" '#'`

if [ "$mat" -eq 0 ]

then

/sbin/iptables -t mangle -I POSTROUTING 1 -d $name -j mark-out

fi

done


Целта на реда

mat=`expr match "$name" '#'`

е да открие има ли символ # в текущия ред.

След това в зависимост от резултата съответния ред се игнорира (ако има #) или се използва като адрес на BG мрежа.

Правилата за съвпадение на пакети, насочени към BG пространството, се вмъкват в началото на веригата POSTROUTING, за да сме сигурни, че няма други правила, които да „отклоняват“ пакети за BG пространството от веригата mark-out.

Всички останали пакети от даден IP адрес, които не са попаднали във веригата mark-out, са насочени към INT пространството и трябва да се маркират със съответната марка за международен трафик.

Маркирането на пакети от конкретен IP адрес, попаднали във веригата mark-out и такива, които са останали извън веригата mark-out (медународен трафик) става с командите:

ip=2

while [ $ip -lt 255 ]; do

/sbin/iptables -t mangle -A mark-out -s 212.104.111."$ip" -j MARK --set-mark 1`printf "%03d" $ip`

/sbin/iptables -t mangle -A POSTROUTING -s 212.104.111."$ip" -j MARK --set-mark 2`printf "%03d" $ip`

ip=`expr $ip + 1`

done

По този начин всички пакети за BG ще бъдат маркирани съответно 1002, 1003 ... 1254, а за INT – 2002, 2003 ... 2254.

За ip е избрана начална стойност 2, защото се предполага, че 212.104.111.1 е default gateway за клиентската мрежа и е назначен на вторият интерфейс на рутиращата машина.

Ако искате изходящият трафик към дадени адреси да не се маркира – например трафика към „локални сървъри“ (абе, останаха ли такива?), след цикъла трябва да се вмъкнат специални правила за тях:

/sbin/iptables -t mangle -I POSTROUTING 1 -o eth0 -d ip.ad.re.ss -j ACCEPT

6. Създаване на класове и насочване на трафик през тях.

Както вече бе споменато, като алгоритъм ще се използва HTB.

/sbin/tc qdisc del dev eth0 root

/sbin/tc qdisc add dev eth0 root handle 1: htb default 30

/sbin/tc class add dev eth0 parent 1: classid 1:1 htb rate 3mbit burst 20k

/sbin/tc class add dev eth0 parent 1: classid 1:10 htb rate 2mbit burst 20k

/sbin/tc class add dev eth0 parent 1: classid 1:20 htb rate 512kbit burst 20k

/sbin/tc class add dev eth0 parent 1:1 classid 1:30 htb rate 256kbit burst 10k

ip=2

while [ $ip -lt 255 ]; do

/sbin/tc class add dev eth0 parent 1:10 classid 1:1`printf "%03d" $ip` htb rate 64kbit ceil 160kbit burst 15k

/sbin/tc class add dev eth0 parent 1:20 classid 1:2`printf "%03d" $ip` htb rate 32kbit ceil 96kbit burst 15k

/sbin/tc filter add dev eth0 protocol ip parent 1: prio 1 handle 1`printf "%03d" $ip` fw flowid 1:1`printf "%03d" $ip`

/sbin/tc filter add dev eth0 protocol ip parent 1: prio 1 handle 2`printf "%03d" $ip` fw flowid 1:2`printf "%03d" $ip`

ip=`expr $ip + 1`

done


По този начин се създават класове за BG трафик 1002, 1003 ... 1254 и класове за INT трафик 2002, 2003 ... 2254. В тези класове попада трафика, маркиран със съответните марки чрез iptables.

7. Пълен листинг на скриптовете

Скрипт mark_peering.sh


#!/bin/bash

#mark_peering.sh Script for marking of Peering & International upload traffic via iptables

wget -q -O bg_nets-new.txt "http://ip.ludost.net/cgi/process?country=1&country_list=bg&format_template=prefix&format_name=&format_target=&format_default="

newfile=bg_nets-new.txt

file=bg_nets.txt

#Check for existence of the files

if [[ ! -r "$newfile" || ! -r "$file" ]]

then

echo "Both files to be compared must exist and be readable."

exit 1

fi

cmp $newfile $file &> /dev/null

if [ $? -ne 0 ] # Test exit status of "cmp" command.

then

echo "Doing changes"

mv -f $newfile $file

line_count=`wc $file | awk '{ print $1 }'`


for name in `seq $line_count`

do

read name

mat=`expr match "$name" '#'`

if [ "$mat" -eq 0 ]

then

/etc/init.d/iptables restart

/sbin/iptables -t mangle -I POSTROUTING 1 -d $name -j mark-out

fi

done

ip=2

while [ $ip -lt 255 ]; do

/sbin/iptables -t mangle -A mark-out -s 212.104.111."$ip" -j MARK --set-mark 1`printf "%03d" $ip`

/sbin/iptables -t mangle -A POSTROUTING -s 212.104.111."$ip" -j MARK --set-mark 2`printf "%03d" $ip`

ip=`expr $ip + 1`

done

/sbin/iptables -t mangle -A mark-out -j ACCEPT

else

echo "Everything is the same"

rm -f $newfile

fi

exit 0


Скрипт htb_eth0.sh


#!/bin/bash

# htb_eth0.sh Script for upload traffic shaping divided to International & Peering classes

/sbin/insmod sch_htb 2>/dev/null

/sbin/insmod cls_fw 2>/dev/null

/sbin/tc qdisc del dev eth0 root

/sbin/tc qdisc add dev eth0 root handle 1: htb default 30

/sbin/tc class add dev eth0 parent 1: classid 1:1 htb rate 10mbit burst 20k

/sbin/tc class add dev eth0 parent 1:1 classid 1:10 htb rate 2mbit burst 20k

/sbin/tc class add dev eth0 parent 1:1 classid 1:20 htb rate 512kbit burst 20k

/sbin/tc class add dev eth0 parent 1:1 classid 1:30 htb rate 256kbit burst 10k

ip=2

while [ $ip -lt 255 ]; do

/sbin/tc class add dev eth0 parent 1:10 classid 1:1`printf "%03d" $ip` htb rate 64kbit ceil 160kbit burst 15k

/sbin/tc class add dev eth0 parent 1:20 classid 1:2`printf "%03d" $ip` htb rate 32kbit ceil 96kbit burst 15k

/sbin/tc filter add dev eth0 protocol ip parent 1: prio 1 handle 1`printf "%03d" $ip` fw flowid 1:1`printf "%03d" $ip`

/sbin/tc filter add dev eth0 protocol ip parent 1: prio 1 handle 2`printf "%03d" $ip` fw flowid 1:2`printf "%03d" $ip`

ip=`expr $ip + 1`

done

Е, това е всичко. За коментари и предложения - пишете
P.S. Извинете ме за ужасния HTML, но предпочитам да пиша скриптове, а не Web страници


<< Инсталация на Postfix Admin с поддръжка на PostgreSQL | Нелегитимен достъп до ресурси (уеб-базирани пощенски услуги) >>