Назад | Перейти на главную страницу

Ограничить ввод на заданном порту с помощью tc filter и u32 match

Я пытаюсь ограничить скорость всего входящего трафика на портах 8128-8191. Прочитал все, что нашел, раз десять проверил, все равно не работает.

Команды:

tc qdisc del dev eth0 root

tc qdisc add dev eth0 root handle 1: htb default 1
tc class add dev eth0 parent 1:0 classid 1:1 htb rate 1kbit ceil 1kbit
tc filter add dev eth0 parent 1:0 prio 1 protocol ip u32 match ip dport 8128 0xFFC0 classid 1:1  

Вот как я рассчитал маску:

expected = lowest port  = 0b_0001_1111_1100_0000 = 0x1FC0 = 8128d
    mask = highest port = 0b_1111_1111_1100_0000 = 0xFFC0 
           highest port = 0b_0001_1111_1111_1111 = 0x1FFF = 8191d

Выход:

#tc -s class show dev eth0
class htb 1:1 root prio 0 rate 1000bit ceil 1000bit burst 1600b cburst 1600b
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
 rate 0bit 0pps backlog 0b 0p requeues 0
 lended: 0 borrowed: 0 giants: 0
 tokens: 200000000 ctokens: 200000000

# tc filter show dev eth0
filter parent 1: protocol ip pref 1 u32
filter parent 1: protocol ip pref 1 u32 fh 800: ht divisor 1
filter parent 1: protocol ip pref 1 u32 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1
  match 00001fc0/0000ffc0 at 20

Я отправляю поток байтов со своей рабочей станции с помощью:

cat /dev/urandom | pv -L 3k | nc -nvv ${SERVER_ADDRESS} 8128

На сервере я их получаю с:

nc -nvvl -p 8128 > /dev/null

Я проверяю использование eth1 с помощью отличного iptraf, и пропускная способность остается на уровне 3 кбит / с и более, и нет увеличения счетчиков class htb 1:1.

Я считаю, что хорошо с масками. Я также пробовал что-то попроще с dport 8128 0xFFFF без результатов.

При отображении фильтра at 20 кажется правильным, потому что IP-заголовок имеет длину 20 байт. Порты источника и назначения - это первые 4 байта, поэтому 32-битное совпадение является правильным. Я не понимаю других ценностей.

Я использую Debian 7:

# uname -a
Linux node-1 3.2.0-4-amd64 #1 SMP Debian 3.2.68-1+deb7u5 x86_64 GNU/Linux

Я также очищен все в iptables, прежде чем пытаться выполнить вышеуказанное.

Может, я что-то напортачил в том, как подключаю фильтр к классу. Может есть какая-то опция ядра, которую я забыл активировать.

Есть идеи?

1) Ограничение (формирование) входящего трафика с помощью tc со стандартным ядром Linux сложно. Можете попробовать патч IMQ http://www.linuximq.net/ для вашего ядра. Вам также нужен патч для iptables. Затем вы можете «пометить» пакет для перехода на устройство IMQ, и с помощью tc на imq0 устройство вы можете формировать трафик как хотите.

2) Еще одно простое, но не точное решение - использование iptables, но оно основано на подсчете пакетов (вам необходимо приблизить средний размер пакета для вашего протокола / соединения)

iptables -A INPUT -p tcp --dport 8128:8191 -m limit --limit 5/seconds -j ACCEPT
iptables -A INPUT -p tcp --dport 8128:8191 -j DROP

Вам нужны эти две строки: первая будет принимать первые 5 пакетов каждую секунду для всех ip вместе, а вторая отбрасывать все поверх нее.