Для начала необходимо разобраться с тем, как движутся пакеты через iptables:
+------------+ принятие +---------+ +-------------+
Вход ---| PREROUTING |--- решения о --| FORWARD |-------+-------| POSTROUTING |- Выход
+------------+ маршрутизации +---------+ | +-------------+
| |
+-------+ +--------+
| INPUT |-Локальные процессы-| OUTPUT |
+-------+ +--------+
Далее я буду исходить из предположения, что всем таблицам назначена политика по-умолчанию -P ACCEPT. Наша локальная сеть относится к классу b, с адресами 172.17.0.0/16. Реальный IP-адрес — 212.170.21.172
Добавим правило iptables, которое будет выполнять snat, что позволит пользователям локальной сети общаться с внешним миром, и разрешим форвардинг пакетов:
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables –t nat –A POSTROUTING –s 172.17.0.0/255.255.0.0 –o eth0 –j SNAT –to-source 212.170.21.172
Проверим, что пакеты уходят через класс 1:15:
tc –s class show dev eth0
Добавим в цепочку PREROUTING, таблицы mangle, правила для установки меток на пакеты:
iptables –t mangle –A PREROUTING –p icmp –j MARK –set-mark 0x1
iptables –t mangle –A PREROUTING –p icmp –j RETURN
Теперь вы должны наблюдать увеличение значения счетчика пакетов в классе 1:10, при попытке ping-ануть из локальной сети какой-нибудь сайт в Интернете.
tc-s класс показывают dev eth0
Действие -j RETURN предотвращает движение пакетов по всем правилам. Поэтому все ICMP-пакеты будут проходить только это правило. Добавим еще ряд правил, которые будут изменять биты в поле TOS:
iptables –t mangle –A PREROUTING –m tos –tos Minimize-Delay –j MARK –set-mark 0x1
iptables –t mangle –A PREROUTING –m tos –tos Minimize-Delay –j RETURN
iptables –t mangle –A PREROUTING –m tos –tos Minimize-Cost –j MARK –set-mark 0x5
iptables –t mangle –A PREROUTING –m tos –tos Minimize-Cost –j RETURN
iptables –t mangle –A PREROUTING –m tos –tos Maximize-Throughput –j MARK –set-mark 0x6
iptables –t mangle –A PREROUTING –m tos –tos Maximize-Throughput –j RETURN
Поднимем приоритет для ssh-пакетов:
iptables –t mangle –A PREROUTING –p tcp –m tcp –sport 22 –j MARK –set-mark 0x1
iptables –t mangle –A PREROUTING –p tcp –m tcp –sport 22 –j RETURN
а так же для пакетов, с которых начинается TCP-соединение, т.е. SYN-пакетов:
iptables –t mangle –I PREROUTING –p tcp –m tcp –tcp-flags SYN,RST,ACK SYN –j MARK –set-mark 0x1
iptables –t mangle –I PREROUTING –p tcp –m tcp –tcp-flags SYN,RST,ACK SYN –j RETURN
И так далее. После того, как в цепочку PREROUTING, таблицы mangle, будут внесены все необходимые правила, закончим ее правилом:
iptables –t mangle –A PREROUTING –j MARK –set-mark 0x6
Это заключительное правило отправит оставшиеся немаркированные пакеты в класс 1:15. Фактически, это правило можно опустить, так как класс 1:15 был задан по-умолчанию, но тем не менее, я оставляю его, чтобы сохранить единство настроек и кроме того, иногда бывает полезно увидеть счетчик пакетов для этого правила.
Нелишним будет добавить те же правила в цепочку OUTPUT, заменив имя цепочки PREROUTING на OUTPUT (s/PREROUTING/OUTPUT/). Тогда трафик, сгенерированный локальными процессами на маршрутизаторе, также будет классифицирован по категориям. Но, в отличие от вышеприведенных правил, в цепочке OUTPUT, я устанавливаю метку -j MARK –set-mark 0x3, таким образом трафик от маршрутизатора получает более высокий приоритет.
15.10.3. Дополнительная оптимизация
В результате приведенных настроек, мы получили вполне работоспособную конфигурацию. Однако, в каждом конкретном случае, эти настройки всегда можно немного улучшить. Найдите время и проследите – куда идет основной трафик и как лучше им распорядиться. Я потратил огромное количество времени и наконец довел свою конфигурацию до оптимального уровня, практически сведя на нет бесчисленные таймауты.
Если вдруг обнаружится, что через некоторые классы проходит подавляющее большинство трафика, то к ним можно прикрепить другую дисциплину организации очереди, чтобы распределить канал более равномерно:
tc qdisc add dev eth0 parent 1:13 handle 130: sfq perturb 10
tc qdisc add dev eth0 parent 1:14 handle 140: sfq perturb 10
tc qdisc add dev eth0 parent 1:15 handle 150: sfq perturb 10
15.10.4. Выполнение настроек во время загрузки системы.
Уверен, что можно найти множество способов, чтобы произвести настройку маршрутизатора во время загрузки. Для себя я создал скрипт /etc/init.d/packetfilter, который принимает команды [start | stop | stop-tables | start-tables | reload-tables]. Он конфигурирует дисциплины (qdiscs) и загружает необходимые модули ядра. Этот же сценарий загружает правила iptables из файла /etc/network/iptables-rules, которые предварительно могут быть сохранены утилитой iptables-save и восстановлены — iptables-restore.