Сеть

firewalld

firewalld позволяет описывать брандмауэр в терминах зон, сервисов и т.д. Конфигурация firewalld компилируется в правила iptables или nftables.

Список стандартных сервисов

firewall-cmd --get-services

Добавление разрешения на сервис или порт

firewall-cmd --permanent --add-service=ssh
firewall-cmd --permanent --add-port=4444/tcp

Удаление разрешения

firewall-cmd --permanent --remove-service=ssh

Список установленных разрешений

firewall-cmd --permanent --list-all

После всех установок необходимо их применить

firewall-cmd --reload

Запуск сетевых служб через systemd

Для запуска сетевой службы в стиле inetd, но через systemd необходимо создать два файла:

  1. Файл, описывающий сокет, на котором ожидается соединение;
  2. Файл, описывающий сервис - программу, которую надо запустить после подключения клиента к сокету.

В файле сокета ListenStream - указывает на протокол TCP (для UDP используется параметр ListenDatagram=). В качестве значения ListenStream может быть указан номер порта или пара IP:Port. Параметр Accept=yes указывает на то, что для каждого подключения надо стартовать отдельный экземпляр программы. Чтобы проинформировать приложение о свойствах соединения, ему передаются переменные окружения REMOTE_ADDR и REMOTE_PORT.

/etc/systemd/system/baz.socket:

[Unit]
Description=Baz Socket

[Socket]
ListenStream=127.0.0.1:9999
Accept=yes

[Install]
WantedBy=sockets.target

Имя файла сервиса должно заканчиваться на @, чтобы указать, что одновременно может быть запущено много экземпляров данной программы. В данной конфигурации стандартный ввод программы будет назначен на /dev/null, стандартный вывод будет перенаправлен в сокет, сообщения об ошибках будут сохранены в логах journald. Программа может быть написана на чем угодно. Переменным окружения VAR1 и VAR2 будут назначены значения "word1 word2" и 'word3" соответственно, текущий каталог будет изменен на /tmp, вместо %i будет подставлено имя экземпляра программы, которое также будет видно в списке запущенных сервисов между @ и .service.

/etc/systemd/system/baz@.service:

[Unit]
Description=Baz Service
Requires=baz.socket

[Service]
Type=simple
Environment="VAR1=word1 word2" VAR2=word3
ExecStart=/usr/local/baz %i
WorkingDirectory=/tmp
StandardInput=socket
StandardOutput=socket
StandardError=journal
TimeoutStopSec=5

[Install]
WantedBy=multi-user.target

/usr/local/bin/baz:

#!/bin/bash
pwd
echo ${VAR1}
echo ${VAR2}
echo $1

Отключение IPv6 в Linux

Отключение IPv6 в ядре

Добавляем в файл /etc/sysctl.conf (или куда-нибудь в /etc/sysctl.d/50-noipv6.conf) строки

net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1

Обновляем текущую конфигурацию ядра sysctl -p.

Применяем настройки к сетевым интерфейсам systemctl restart network

Проверяем адреса на сетевых интерфейсах ip addr

Отключение IPv6 в Apache

В конфигурации исправляем директиву Listen 80 на

Listen 0.0.0.0:80

Отключение IPv6 в Squid

Добавляем в squid.conf

dns_v4_first on

Отключение IPv6 в Postfix

В main.cf

inet_protocols = ipv4

Отключение IPv6 в BIND

Для того, чтобы сам BIND не использовал IPv6 при запуске надо указать опцию -4. В CentOS это делается строчкой в файле /etc/sysconfig/named

OPTIONS="-4"

Дополнительно можно добавить в named.conf опцию

listen-on-v6 port 53 { none; };

Для того, чтобы BIND не выдавал записи AAAA (адреса IPv6) клиентам, подключенным по IPv4 необходимо добавить в файл named.conf опцию

filter-aaaa-on-v4 yes;

Ручная настройка сети в Linux

Для доступа к сетевым картам в Linux используются так называемые интерфейсы. Интерфейсы это не файлы устройств и их нет в каталоге /dev. Интерфейсы создаются динамически и не всегда связаны с сетевыми картами. Например интерфейс ppp0 - это интерфейс VPNа, организованного по протоколу PPTP, а интерфейс lo это виртуальная сетевая карта с адресом localhost (127.0.0.1). В Linux имена интерфейсов традиционно состоят из мнемонического типа интерфейса и его порядкового номера. Карты ethernet доступны через интерфейсы eth0, eth1 и т.д. В системах, использующих systemd способ именования другой - интерфейсы имеют имена вида enp2s0 (en -Ethernet, p - PCI, 2 - номер на шине) Список всех интерфейсов можно посмотреть командой ifconfig -a или ip link.

Привязка интерфейса к карте

При наличии нескольких сетевых карт возникает вопрос о порядке их нумерации. В CentOS 6 эта задача возложена на подсистему обнаружения и конфигурации устройств - udev. В системах с systemd правила именования встроены в udev, но могот быть переопределены, как написано ниже.

Конфигурационный файл переименования интерфейсов обновляется автоматически при первом обнаружении очередной сетевой карты и находится в файле /etc/udev/rules.d/70-persistent-net.rules. Файл состоит из строк такого содержания:

# PCI device 0x1af4:0x1000 (virtio-pci)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="52:54:00:29:24:1e", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"

Видно, что нумерация опирается на аппаратный (MAC) адрес карты. Если в компьютере заменить карту, то интерфейс eth0 станет недоступным, а новая карта получит имя eth1. Если есть желание вручную назначить имена картам, то можно отредактировать этот файл, выставив желаемые соответствия между MAC адресами именами интерфейсов (возможно потребуется перезагрузка).

ifcfg

Классическая утилита конфигурации сетевых интерфейсов ifcfg

#просмотр списка активных интерфейсов
ifcfg

#просмотр конфигурации конкретного интерфейса
ifcfg eth0

#просмотр списка доступных интерфейсов
ifcfg -a

#настройка ip адреса и активация интерфейса
ifconfig eth0 192.168.0.1 netmask 255.255.255.0 up 

#деактивация интерфейса
ifconfig eth0 down

route

Настройка таблицы маршрутизации route

#добавление шлюза по умолчанию
route add default gw 192.168.0.1

#добавление маршрута в локальную сеть
 route add -net 192.56.76.0 netmask 255.255.255.0 dev eth0

#добавление маршрута в удаленную сеть
route add -net 192.57.66.0 netmask 255.255.255.0 gw 192.168.0.2

#удаление маршрута
route del -net 192.57.66.0 netmask 255.255.255.0 gw 192.168.0.2

#просмотр таблицы маршрутизации
route
#или
netstat -r

ip

В современных дистрибутивах линукса на смену ifconfig и route приходит универсальная утилита ip

#просмотр списка доступных интерфейсов
ip link

#просмотр статистики по интерфейсам
ip -s link

#просмотр ip адресов
ip addr

#просмотр таблицы маршрутизации
ip route

DNS

Адреса серверов DNS и имя локального домена вписываются в файл /etc/resolv.conf

search example.com
nameserver 8.8.8.8

Ручная настройка сети в ArchLinux

Для просмотра доступных сетевых интерфейсов используется команда ip link

ArchLinux использует для настройки сети systemd/netctl. Для конфигурации используются файлы профилей, которые хранятся в /etc/netctl/. В данном каталоге есть подкаталог examples/ из которого можно копировать файлы с образцами профилей в /etc/netctl/. Например:

cp /etc/netctl/examples/ethernet-static /etc/netctl/enp1s0-work

Содержимое enp1s0-work после редактирования

Interface=enp1s0
Connection=ethernet
IP=static
Address=('10.1.10.2/24')
Gateway='10.1.10.1'
DNS=('10.1.10.1')

Базовые команды netctl

#активация профиля 
netctl start enp1s0-work

#включение автоматической активации с текущими настройками профиля при старте системы
netctl enable enp1s0-work

#обновление конфигурации автостарта после изменения настроек профиля
netctl reenable enp1s0-work

Ручная настройка сети в Ubuntu 20 и старше

В Ubuntu 20 система скриптов ifup/ifdown заменена программой netplan, со своими конфигурационными файлами на языке YAML — /etc/netplan/имяфайла.yaml

Пример конфигурации

Здесь только секция ethernets, но могут быть секции для vlan, bonding и т.д. Массивы имеют две альтернативные формы записи — в квадратных скобках и построчно, где каждая строка начинается с "- ". link-local: [] — запрет IPV6

network:
  version: 2
  renderer: networkd
  ethernets:
    enp3s0f0:
      link-local: []
      addresses:
        - 192.168.56.110/24
      routes:
        - to: 172.16.0.0/24
             via: 192.168.56.100
      gateway4: 192.168.56.1
    nameservers:
        addresses: [8.8.8.8, 8.8.4.4]

Команды

netplan generate — генерация из файлов YAML конфигураций для бэкендов NetworkManager или systemd-networkd в каталогах /run/каталог_бэкенда/. Здесь же проходит валидация синтаксиса.

netplan apply — применение конфигурации

Статья: https://habr.com/ru/post/448400/

Ручная настройка сети в Ubuntu

Просмотр доступных интерфейсов - ifcfg -a

Файл конфигурации интерфейсов - /etc/network/interfaces. auto - говорит о том, что интерфейс надо конфигурировать при старте системы.

iface eth0 inet static 
address 192.168.0.1 
netmask 255.255.255.0 
gateway 192.168.0.254 
auto eth0 

iface eth1 inet dhcp
auto eth1 

После смены настроек в /etc/network/interfaces, необходимо отключить и снова включить интерфейс.

ifdown eth0
ifup eth0

Ручная настройка сети в CentOS 6

Общие настройки сети

Файл /etc/sysconfig/network используется стартовыми скриптами и содержит ключевые параметры - нужна ли сеть, нужно ли конфигурировать IP v6, имя компьютера. Сюда можно вписать шлюз по умолчанию, но CentOS 6 ориентируется на динамическое подкючение к сетям через WiFi и вписывает его в конфигурацию подходящего интерфейса.

NETWORKING=yes
NETWORKING_IPV6=no
HOSTNAME=wwww.example.com

GATEWAY=10.10.10.1

Конфигурация интерфейса

Файлы в каталоге /etc/sysconfig/network-scripts с именами вида ifcfg-eth0

Интерфейс, получающий адрес по DHCP

# динамическая конфигурация интерфейса
ONBOOT="yes"
DEVICE="eth0"
BOOTPROTO="dhcp"

Ручная конфигурация

# статическая конфигурация интерфейса
ONBOOT="yes"
DEVICE="eth1"
BOOTPROTO="static"
IPADDR=145.14.137.221
PREFIX=24
# конфигурация шлюза и DNS
GATEWAY=192.168.1.1
DEFROUTE=yes
DNS1=192.168.1.14
# NM - NetworkManager - графическая оболочка + автоматизация настроек
NM_CONTROLLED="no"

Дополнительный IP адрес на интерфейсе eth1

ONBOOT=no
DEVICE=eth1:0
BOOTPROTO=static
IPADDR=172.16.12.6
NETMASK=255.255.0.0
# следующие два параметра можно не писать
# они вычисляются из IP и маски
BROADCAST=172.16.255.255
NETWORK=172.16.0.0

Инициализация VLAN на eth1

DEVICE=eth1.72
VLAN=yes
VLAN_TRUNK_IF=eth1
BOOTPROTO=static
IPADDR=10.10.0.1
NETMASK=255.255.255.192
ONBOOT=yes

Настройка DNS

Файл /etc/resolv.conf

# мой домен, для подстановки в короткие имена
search example.com
# сервер DNS
nameserver 8.8.8.8

Ручная настройка имен хостов файл /etc/hosts

127.0.0.1               localhost.localdomain localhost ANY
::1             localhost6.localdomain6 localhost6

194.87.0.50           www.ru

Настройка брандмауэра

Файл /etc/sysconfig/system-config-firewall правила для настройки программой system-config-firewall

Файл /etc/sysconfig/iptables текущие правила, сохраненные на случай перезагрузки.

После ручного изменения правил их можно сохранить командой service iptables save

Запуск сетевых служб через xinetd

Для написания сетевой службы в Linux не обязательно уметь программировать сокеты. Сокет, с точки зрения прикладной программы, выглядит как обычный файловый дескриптор, из которого можно читать и в который можно писать любыми стандартными функциями ввода/вывода. Поэтому появляется возможность перенаправить стандартный ввод/вывод любой программы в заранее подготовленный сокет. Для такого перенаправления служит программа xinetd.

Конфигурация xinetd, как правило, разделяется на две части: значения по умолчанию – /etc/xinetd.conf и настройки для отдельных служб, по одному файлу в каталоге /etc/xinetd.d/ на службу.

Чтобы запустить свою сетевую службу, необходимо создать ещё один файл в /etc/xinetd.d/. Имя файла особого значения не имеет, но обычно выбирается по имени службы. Предположим, что служба называется mynetd, запускается от имени пользователя user1 и выполняет команду sleep 10. Служба должна ожидать TCP соединение на порту 8888.

Конфигурационный файл /etc/xinetd.d/mynetd будет выглядеть так:

service mynetd
{
    disable = no
    # Если не написать UNLISTED, то xinetd будет искать имя службы и номер порта
    # в файле /etc/services
     type = UNLISTED

    # stream = TCP, datagram = UDP
    socket_type = stream
    port = 8888
    # Можно считать, что для протокола TCP wait всегда равен 'no',
    # а для протокола UDP – всегда 'yes'
    wait = no

    user = user1
    # При считывании конфигурации файл службы должен существовать и заданный пользователь
    # должен иметь право на его выполнение
      server = /bin/sleep
      server_args = 10
}

Параметр wait интерпретируется следующим образом: если socket_type = datagram и wait = yes, то при появлении на порту данных стартует новый процесс со входом/выходом, перенаправленным в сокет. Пока этот процесс не завершится, xinetd не контролирует наличие новых данных на порту, оставляя их запущенной программе. Если поставить wait = no, то на каждую дейтаграмму будет запускаться новый процесс, разделяющий со своими предшественниками общий сокет. В такой ситуации невозможно предсказать, какой копии программы достанутся входные данные из сокета. В принципе, такой подход возможен, если обработка дейтаграммы идёт долго, а писать многопоточный сервис лень. Для TCP ситуация обратная, wait = yes имеет смысл только для многопоточных программ, иначе первый процесс захватит сокет и не отдаст его, пока программа не завершится.

Брандмауэр уровня приложений - tcpwrappers

TCP Wrappers – изначально набор вспомогательных программ 'запускалок' (tcpd, miscd и вспомогательные программы), для контроля за IP адресами клиентов, стартующих сетевые сервисы через inetd. Основная функция, управляющая проверкой правил, hosts_access(request) была в последующем выделена в отдельную библиотеку libwrap. В настоящее время эту библиотеку используют самые разнообразные сервисы, такие как xinetd, sshd, rsyncs и т.п. Полный список программ, использующих TCP Wrappers, можно получить, выполнив следующую команду:

strings -f  /usr/sbin/* /usr/local/sbin/* |  grep hosts_access

Функция hosts_access использует два конфигурационных файла /etc/hosts.allow и /etc/hosts.deny (в FreeBSD только /etc/hosts.allow), которые могут иметь классический или расширенный синтаксис.

Классический вариант

В классическом варианте вначале проверяются все правила из hosts.allow. Если хоть одно правило применимо к паре сервис-клиент, то соединение устанавливается. Затем проверяются все правила из hosts.deny. При нахождении соответствия соединение отклоняется. Если правила нет, то соединение устанавливается. Чтобы явно разрешить доступ только по правилам из hosts.allow, необходимо добавить в hosts.deny правило ALL:ALL.

Классический синтаксис описан в man странице HOSTS_ACCESS(5). Файлы состоят из строк вида

daemon_list : client_list [ : shell_command ]

где

  • daemon_list – список имён сервисов (в xinetd имена прописываются явно в конфигурации службы, для остальных программ они совпадают с именем исполняемого файла) или ключевое слово ALL;
  • client_list – список имён/адресов клиентов;
  • shell_command – вспомогательная команда, например, для логирования событий. В современном варианте это поле имеет другой формат.

Современный вариант

Файлы /etc/hosts.allow и /etc/hosts.deny эквивалентны по своему назначению. Каждое правило может содержать результат – allow или deny. Если в правиле результат не прописан явно, то он вычисляется по правилу классического варианта. Можно считать, что все правила находятся hosts.allow, а hosts.deny остается пустым. Выполняется первое найденное правило.

Синтаксис правил описан в man странице HOSTS_OPTIONS(5). Файлы состоят из строк вида

daemon_list : client_list : option [: option ...]

daemon_list, client_list полностью совместимы с классическим синтаксисом, а опции позволяют понизить привилегии, запустить дополнительную программу параллельно с сервисом или вместо него, и, наконец, принять решение allow или deny. Опции выполняются слева направо. Опция allow/deny должна стоять последней, поскольку после неё произойдёт запуск сервиса или прекращение работы.

Для запуска дополнительных программ используются две опции: spawn shell_command – запуск программы в параллельном процессе одновременно с сетевым сервисом, и twist shell_command – запуск программы в текущем процессе вместо сервиса. Командам в качестве параметров можно передать некоторую информацию о соединении. spawn не влияет на запуск основного сервиса, поэтому за ней должна следовать опция allow или deny. twist затирает текущий процесс и, соответственно, дальнейшие проверки опций. Однако, через параметры в twist можно передать имя исполняемого файла сервиса, чтобы выполнить его после дополнительных проверок.

Кроме опций запуска программ, существуют опции смены владельца, установки маски создаваемых файлов, понижение приоритета и т.п.

В конце списка правил можно добавить правило по умолчанию ALL:ALL:deny, иначе подразумевается наличие ALL:ALL:allow.

Формат списка client_list

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

Ключевые слова (часть опущена):

  • ALL – все хосты
  • PARANOID – хосты, у которых цепочка преобразований IP->Имя->IP даёт адрес, отличный от исходного.

Шаблоны (часть опущена):

  • .example.org – все имена из домена
  • 192.168.1. – все IP адреса подсети
  • 192.168.132.0/255.255.254.0 – IP адреса по маске
  • /etc/deny.list – текстовый файл, состоящий из строк, содержащих списки хостов в любой описанной выше форме
  • www.*.ru - подстановка вместо звёздочки любого количества символов. Не может быть частью предыдущих шаблонов.

Подстановки при запуске внешних команд

  • %a (%A) Адрес клиента (сервера)
  • %h (%H) Имя клиента (сервера)
  • %d Имя сервиса
  • %p Идентификатор процесса (PID)

Примеры

#классический стиль
sshd : .example.com
vsftpd : 192.168. 
ALL : 192.168.1.0/255.255.255


# Разрешаем подключение из домена .example.com
# кроме station15.example.com
sshd : station15.example.com : deny
sshd : .example.com : allow
#Дополнительно запрещаем всем кроме домена *.hacker.org
sshd : ALL EXCEPT *.hacker.org:twist /bin/echo "Reject - bad host name %h"
# Фактически разрешаем *.hacker.org (остальные уже заблокированы)
# с логированием соединений в файл /tmp/sshd.connections
sshd : ALL:spawn /bin/echo "%d at %I connected from %i" > /tmp/sshd.connections: allow
# Запрещаем остальные соединения
ALL:ALL:deny

Ограничение трафика на маршрутизаторе

Ограничение трафика на маршрутизаторе делается в два этапа:
1. Классификация пакетов с помощью netfilter или фильтров iproute2
2. Создание нескольких очередей пакетов с помощью iproute2

Пакеты распределяются в зависимости от класса на несколько очередей в которых ждут своей очереди на отправку. Каждая очередь имеет ограничения на полосу пропускания, приоритет и еще некоторые параметры. При переполнения очереди пакеты соответствующего класса начинают отбрасываться.
Очереди организованы в древовидную иерархию. Каждая очередь может быть разбита на более мелкие. Корневые очереди, связанные непосредственно с «хэндлером» интерфейса имеют абсолютные ограничения по пропускной способности. Дочерние очереди могут «заимствовать» друг у друга неиспользуемую полосу пропускания.

Классификация пакетов с iptables

Первый этап выполняется с помощью программы /sbin/iptables.

Маркируем пакеты в зависимости от каких либо параметров, например по размеру, номеру порта, ip адресу. Для специфических случаев можно дописывать свои модули для netfilter. Например модуль IP2P http://www.ipp2p.org позволяет выбирать пакеты p2p сетей.

Приписываем класс пакета в соответствии с проставленными меткам

Вообще говоря, можно было бы классифицировать пакеты сразу. Например выделим входящий HTTP трафик в отдельный класс

iptables -t mangle -A POSTROUTING -o eth0 -s 0/0 --source-port 80 -j CLASSIFY --set-class 1:10

Маркировка позволяет проверять только несколько первых пакетов в соединении. Для того, чтобы не исследовать каждый пакет используется модуль CONNMARK который позволяет маркировать все пакеты принадлежащие соединению.

Пример классификации P2P трафика. Классы для различных интерфейсов определяются независимо, что позволило использовать класс 1:20 для входящего и для исходящего трафика.

iptables -t mangle -A PREROUTING -p tcp -j CONNMARK --restore-mark
iptables -t mangle -A PREROUTING -p tcp -m mark ! --mark 0 -j ACCEPT
iptables -t mangle -A PREROUTING -p tcp -m ipp2p --ipp2p -j MARK --set-mark 1
iptables -t mangle -A PREROUTING -p tcp -m mark --mark 1 -j CONNMARK --save-mark

iptables -t mangle -A POSTROUTING -o eth0 -m mark --mark 1 -j CLASSIFY --set-class 1:20
iptables -t mangle -A POSTROUTING -o eth1 -m mark --mark 1 -j CLASSIFY --set-class 1:20

Создание очередей пакетов

Этап второй выполняется с помощью /sbin/tc.

Создаем связанную с интерфейсом очередь исходящих пакетов, указываем класс по умолчанию. Создаем корневой класс, назначаем лимит. Создаем дочерние классы, указываем лимиты для них (Обязательно должен быть создан класс используемый по умолчанию).

Теперь каждый пакет попадает в свою очередь. Если очередь переполняется, пакеты отбрасываются не доходя до аппаратного уровня.
Пример: Общая пропускная способность канала 10 Мбит/с. Внешний интерфейс eth0, внутренний eth1. Ограничиваем исходящий трафик P2P сетей из предыдущего примера полосой 32 Кбит/с, входящий 256 Кбит/с.

/sbin/tc qdisc add dev eth0 root handle 1: htb default 10
/sbin/tc class add dev eth0 parent 1: classid 1:1 htb rate 10mbit
/sbin/tc class add dev eth0 parent 1:1 classid 1:10 htb rate 10mbit
/sbin/tc class add dev eth0 parent 1:1 classid 1:20 htb rate 32kbit

/sbin/tc qdisc add dev eth1 root handle 1: htb default 10
/sbin/tc class add dev eth1 parent 1: classid 1:1 htb rate 10mbit
/sbin/tc class add dev eth1 parent 1:1 classid 1:10 htb rate 10mbit
/sbin/tc class add dev eth1 parent 1:1 classid 1:20 htb rate 256kbit

Пример стартового скрипта /etc/init.d/shaper (написан не мною и не связан с примером iptables)

#!/bin/sh
# init script written by shane at knowplace dot org
# this script only creates the qdiscs and classes required for shaping, it
# does NOT create the necessary filters

INTERFACE='eth0'
rc_done=" done"
rc_failed=" failed"

return=$rc_done

TC='/sbin/tc'

tc_reset ()
{
# Reset everything to a known state (cleared)
$TC qdisc del dev $INTERFACE root 2> /dev/null > /dev/null
}

tc_status ()
{
echo "[qdisc - $INTERFACE]"
$TC -s qdisc show dev $INTERFACE
echo "------------------------"
echo
echo "[class - $INTERFACE]"
$TC -s class show dev $INTERFACE
}

tc_showfilter ()
{
echo "[filter - $INTERFACE]"
$TC -s filter show dev $INTERFACE
}

case "$1" in

start)
echo -n "Starting traffic shaping"
tc_reset
U320="$TC filter add dev $INTERFACE protocol ip parent 1:0 prio 0 u32"
#
# dev eth0 - creating qdiscs & classes
#
$TC qdisc add dev $INTERFACE root handle 1: htb default 60
$TC class add dev $INTERFACE parent 1: classid 1:1 htb rate 116kbit
$TC class add dev $INTERFACE parent 1:1 classid 1:10 htb rate 32kbit ceil 116kbit prio 0
$TC class add dev $INTERFACE parent 1:1 classid 1:20 htb rate 22kbit ceil 116kbit prio 1
$TC class add dev $INTERFACE parent 1:1 classid 1:30 htb rate 22kbit ceil 116kbit prio 2
$TC class add dev $INTERFACE parent 1:1 classid 1:40 htb rate 20kbit ceil 116kbit prio 3
$TC class add dev $INTERFACE parent 1:1 classid 1:50 htb rate 18kbit ceil 116kbit prio 4
$TC class add dev $INTERFACE parent 1:1 classid 1:60 htb rate 2kbit ceil 116kbit prio 5
$TC qdisc add dev $INTERFACE parent 1:10 handle 10: sfq perturb 10
$TC qdisc add dev $INTERFACE parent 1:20 handle 20: sfq perturb 10
$TC qdisc add dev $INTERFACE parent 1:30 handle 30: sfq perturb 10
$TC qdisc add dev $INTERFACE parent 1:40 handle 40: sfq perturb 10
$TC qdisc add dev $INTERFACE parent 1:50 handle 50: sfq perturb 10
$TC qdisc add dev $INTERFACE parent 1:60 handle 60: sfq perturb 10
tc_status
;;

stop)
echo -n "Stopping traffic shaper"
tc_reset || return=$rc_failed
echo -e "$return"
;;

restart|reload)
$0 stop && $0 start || return=$rc_failed
;;

stats|status)
tc_status
;;

filter)
tc_showfilter
;;

*)
echo "Usage: $0 {start|stop|restart|stats|filter}"
exit 1

esac
test "$return" = "$rc_done" || exit 1
##################################

Примечания.

В параметрах iptables цель CLASSIFY в iptables может использоваться только в таблице mangle и только в цепочке POSTROUTING.

В параметрах tc встречаются сокращения:
qdisc – Classful Queuing Disciplines – базовый объект связанный с сетевым интерфейсом и обеспечивающий управление очередями
htb – Hierarchical Token Bucket – имя собственное одного из планировщиков очередей пакетов в ядре Linux

Имена классов имеют вид M:N. M: эквивалентно M:0 и используется для создания общего корня очередей (хэндлера) связанного напрямую с интерфейсом.