Вопрос или проблема
Проблема
Я искал в интернете
всё, что мог, но не смог найти много информации о том, как ограничить 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
-
Установка параметров: Определите интерфейс, максимальную пропускную способность и специфические лимиты для клиентов.
-
Очистка предыдущих настроек: Убедитесь, что предыдущие настройки
tc
удалены, чтобы избежать конфликтов. -
Настройка
htb
(Hierarchical Token Bucket): Создайте родительский класс и дочерние классы для IP-адресов, которые вы хотите лимитировать. -
Фильтрация пакетов: Используйте фильтры
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-уровне, ограничивая трафик от определённых устройств в вашей сети.