Возможно ли ограничить скорость загрузки по каждому IP с помощью tc, htb и iptables? (Ограничение на загрузку не требуется)

Вопрос или проблема

Проблема

Я искал в интернете всё, что мог, но не смог найти много информации о том, как ограничить upload. Предложенные решения не ограничивают на основе IP, как это, а ограничивают целую локальную сеть.

             +-----+
+--------+   |  S  |
| Пользователь A |---+  W  |
+--------+   |  I  |
+--------+   |  T  |     +--------+        +----------+
| Пользователь B |---+  C  +-----| Роутер |--------| Интернет |
+--------+   |  H  |     +--------+        +----------+
   ....     ... / ...
+--------+   |  H  |
| Пользователь N |---+  U  |
+--------+   |  B  |
             +-----+
  • ПользовательA:172.16.10.2
  • ПользовательB:172.16.10.3РоутерПриватный:172.16.0.1
  • ПользовательC:172.16.10.4

Я хочу ограничить только upload для 172.16.10.3 и 172.16.10.4, используя tc htb и iptables.

Что я уже пробовал

Я изменил скрипт в соответствии с моими требованиями.

IF_INET=external

# лимит пропускной способности upload для интерфейса
BW_MAX=2000

# лимит пропускной способности upload для 172.16.16.11
BW_CLIENT=900

# сначала очищаем предыдущие настройки
tc qdisc del dev ${IF_INET} root

# дисциплина очереди htb верхнего уровня; отправляем неклассифицированные данные в класс 1:10
tc qdisc add dev ${IF_INET} root handle 1: htb default 10

# родительский класс (обрамляем всё в этом классе, чтобы позволить заимствование пропускной способности)
tc class add dev externel parent 1: classid 1:1 htb \
  rate ${BW_MAX}kbit ceil ${BW_MAX}kbit

# два дочерних класса
#

# класс дочерний по умолчанию
tc class add dev ${IF_INET} parent 1:1 \
  classid 1:10 htb rate $((${BW_MAX} - ${BW_CLIENT}))kbit ceil ${BW_MAX}kbit

# класс дочерний для трафика от 172.16.16.11
tc class add dev ${IF_INET} parent 1:1 \
  classid 1:20 htb rate ${BW_CLIENT}kbit ceil ${BW_MAX}kbit

# классифицируем трафик
tc filter add dev ${IF_INET} parent 1:0 protocol ip prio 1 u32 \
  match ip src 172.16.16.11/32 flowid 1:20

но это не будет работать для ограничения upload. Так в чем же решение?

Почему вы использовали 172.16.16.11 как исходный IP вместо .10.3 и/или .10.4?!

Я использовал локальные виртуальные машины (работающие командой “nc -klvp 42 >/dev/null”), подключенные к локальному интерфейсу open-vswitch, чтобы продемонстрировать формирование трафика для некоторых исходных IP, я убрал параметр “ceil” в “class 1:20”.

Мой tc скрипт

#!/bin/bash
export IF_INET=ovs-br0
export UNIT=kbps

export BW_MAX=2048
export BW_CLIENT=128

tc qdisc del dev ${IF_INET} root &>/dev/null
tc qdisc add dev ${IF_INET} root handle 1: htb default 10

tc class add dev ${IF_INET} parent 1: classid 1:1 htb rate ${BW_MAX}$UNIT
tc class add dev ${IF_INET} parent 1:1 classid 1:10 htb rate $((${BW_MAX} - ${BW_CLIENT}))$UNIT ceil ${BW_MAX}$UNIT
tc class add dev ${IF_INET} parent 1:1 classid 1:20 htb rate ${BW_CLIENT}$UNIT 

tc filter add dev ${IF_INET} parent 1:0 protocol ip prio 1 u32 match ip src 172.16.10.3/32 flowid 1:20
tc filter add dev ${IF_INET} parent 1:0 protocol ip prio 1 u32 match ip src 172.16.10.4/32 flowid 1:20

локальные IP адреса/маршруты с разными исходными IP

section61:~ # ip a s dev ovs-br0 | grep 172.16.1
inet 172.16.10.4/24 scope global ovs-br0
inet 172.16.10.3/24 scope global secondary ovs-br0
inet 172.16.10.5/24 scope global secondary ovs-br0
inet 172.16.10.6/24 scope global secondary ovs-br0

section61:~ # ip route get 172.16.10.13 | grep -v cache 
172.16.10.13 dev ovs-br0 src 172.16.10.3 uid 0 
section61:~ # ip route get 172.16.10.14 | grep -v cache 
172.16.10.14 dev ovs-br0 src 172.16.10.4 uid 0 
section61:~ # ip route get 172.16.10.15 | grep -v cache 
172.16.10.15 dev ovs-br0 src 172.16.10.5 uid 0 
section61:~ # ip route get 172.16.10.16 | grep -v cache 
172.16.10.16 dev ovs-br0 src 172.16.10.6 uid 0 

Два потока данных с использованием разных исходных IP

section61:~ # dd if=/dev/zero of=/dev/stdout count=$((1*1024*1024)) bs=1024 | pv | nc 172.16.10.13 42
7.03MiB 0:00:58 [ 120KiB/s] [                                                                          <=>               ]

section61:~ # dd if=/dev/zero of=/dev/stdout count=$((4*1024*1024)) bs=1024 | pv | nc 172.16.10.15 42
 135MiB 0:01:17 [1.76MiB/s] [                                        <=>                                                 ]

Чтобы проверить формирование трафика классов qdisc, я настоятельно рекомендую запустить bmon.

Подсказки

  • если вы используете “ceil” в классе 1:20, то вам нужно создать два потока данных одновременно, чтобы полностью загрузить 1:10! иначе 1:20 получит неиспользуемый остаток от 1:10.
  • используя “iptables mangle .. match-set” для классификации пакетов, это также должно работать.

openSUSE Leap 15.1 – Linux 4.12.14-lp151.28.75-default

Ответ или решение

Да, ограничение upload-канала на уровне IP с использованием tc, htb и iptables вполне возможно. Вы можете достичь этой цели, создавая классы трафика с помощью tc и фильтров для классификации пакетов на основе источника IP с помощью iptables. Ниже приведен пример скрипта, который иллюстрирует этот процесс.

Шаги по ограничению пропускной способности upload

  1. Установка параметров: Определите интерфейс, максимальную пропускную способность и специфические лимиты для клиентов.

  2. Очистка предыдущих настроек: Убедитесь, что предыдущие настройки tc удалены, чтобы избежать конфликтов.

  3. Настройка htb (Hierarchical Token Bucket): Создайте родительский класс и дочерние классы для IP-адресов, которые вы хотите лимитировать.

  4. Фильтрация пакетов: Используйте фильтры tc для назначения трафика от конкретных IP-адресов к соответствующим классам.

Пример скрипта

#!/bin/bash

IF_INET=ovs-br0      # Интерфейс, на который будет применяться ограничение
BW_MAX=2048          # Общая максимальная пропускная способность в kbps
BW_CLIENT_1=256      # Ограничение для клиента 172.16.10.3 в kbps
BW_CLIENT_2=128      # Ограничение для клиента 172.16.10.4 в kbps

# Очистка предыдущих настроек
tc qdisc del dev ${IF_INET} root &>/dev/null

# Установка корневого qdisc
tc qdisc add dev ${IF_INET} root handle 1: htb default 10

# Родительский класс
tc class add dev ${IF_INET} parent 1: classid 1:1 htb rate ${BW_MAX}kbps

# Классы для клиентов
tc class add dev ${IF_INET} parent 1:1 classid 1:10 htb rate $((${BW_MAX} - ${BW_CLIENT_1} - ${BW_CLIENT_2}))kbps
tc class add dev ${IF_INET} parent 1:1 classid 1:20 htb rate ${BW_CLIENT_1}kbps
tc class add dev ${IF_INET} parent 1:1 classid 1:30 htb rate ${BW_CLIENT_2}kbps

# Фильтры для классификации трафика
tc filter add dev ${IF_INET} parent 1:0 protocol ip prio 1 u32 match ip src 172.16.10.3/32 flowid 1:20
tc filter add dev ${IF_INET} parent 1:0 protocol ip prio 1 u32 match ip src 172.16.10.4/32 flowid 1:30

Подробности скрипта

  • IF_INET: Интерфейс, к которому вы подключаетесь (например, ovs-br0).
  • BW_MAX: Максимальная доступная пропускная способность для всего интерфейса.
  • BW_CLIENT_1 и BW_CLIENT_2: Лимиты для пользователей, которые вы хотите ограничить, в данном случае для IP 172.16.10.3 и 172.16.10.4.
  • tc qdisc: Команды для работы с очередями.
  • tc class add: Создание классов с заданными лимитами.
  • tc filter add: Назначение фильтров для управления трафиком от определённых IP.

Замечания

  • Используя ceil, можно дополнительно управлять, как трафик будет распределяться, если максимальная пропускная способность не используется.
  • Если вы заметили, что класс с ограничением ceil не используется полностью, убедитесь, что создаёте достаточное количество потоков трафика, поскольку неиспользованная пропускная способность может быть перераспределена, и другие классы могут использовать её.

Рекомендации

  • Для мониторинга и визуализации трафика рекомендую использовать инструменты, такие как bmon или iftop, которые помогут следить за текущими ограничениями и распределением пропускной способности.

Таким образом, с помощью этого подхода вы сможете эффективно управлять загрузкой на IP-уровне, ограничивая трафик от определённых устройств в вашей сети.

Оцените материал
Добавить комментарий

Капча загружается...