Немного о Iptables, Iproute2 и эмуляции сетевых проблем

    Однажды мне понадобилось в Zabbix сделать мониторинг потери пакетов между мастером и репликами (репликация плохо себя чувствует если канал не очень хороший). Для этого, в Zabbix есть встроенный параметр icmppingloss, на удаленный хост отправляется серия ICMP пакетов и результат фиксируется в системе мониторинга. И вот параметр добавлен, триггер настроен. Казалось бы задача выполнена, однако как говорится «Доверяй, но проверяй». Осталось проверить что триггер сработает когда потери действительно будут. Итак, как сэмулировать потерю пакетов? Об этом, да и не только, пойдет речь под катом.

    image


    Первая мысль которая пришла мне в голову это использовать iptables. И правда, недолгий поиск привел меня к модулю statistic — если вкратце, то этот модуль обрабатывает пакеты привнося в процесс некоторую статистическую вероятность.
    В общем, задача была решена с помощью правила:

    iptables -A INPUT -p icmp -s zabbix_ip -m statistic --mode random --probability 0.1 -j DROP
    

    Или:

    iptables -A INPUT -p icmp -s zabbix_ip -m statistic --mode nth --every 10 -j DROP
    

    Как видно тут есть 2 варианта --mode random --probability 0.1 — означает что пакет будет выбран случайно, c вероятностью 10%. И --mode nth --every 10 — обрабатывать каждый десятый пакет. Таким способом я добился потери пакетов около 10%, триггер сработал, все замечательно.

    На этом вроде бы можно и остановиться, но совершенно случайно я узнал о такой функциональности как Network Emulator из ядерной подсистемы Network QoS. Причем возможности NetEm гораздо шире чем у модуля statistic:
    • задержка (delay) — добавление указанной задержки к отправляемым пакетам на указанном интерфейсе;
    • распределение (distribution) — позволяет указать вариант распределения задержки;
    • сброс (drop) — позволяет указать потерю пакетов;
    • повреждение (corrupt) — определяет возможность повреждения пакетов;
    • дублирование (duplicate) — позволяет определить дублирование пакетов перед тем как они будут поставлены в очередь;
    • переупорядочивание (reorder) — определяет переупорядочивание пакетов (используется совместно с задержкой);
    • лимитирование (limit) — ограничивает эффект выше указанных опций на указанное число пакетов.

    Теперь обо всем этом поподробнее.
    Network emulator поддерживается с ядер 2.6 и на данный момент оно присутствует во всех современных дистрибутивах (речь о Linux конечно же). Чтобы проверить наличие поддержки Network Emulator в ядре, проверяем конфиг ядра в /boot (либо /proc/config.gz):

    # grep NETEM /boot/config-$(uname -r)
    CONFIG_NET_SCH_NETEM=m
    


    Как видно из вывода, поддержка в виде модуля, поэтому подгружаем его. Также нам понадобится утилита tc из пакета iproute:

    # modprobe sch_netem
    

    Если же ничего нет, необходимо пересобрать ядро. Кто знаком со сборкой ядра — небольшая подсказка, Network emulator находится здесь:

     Networking -->
       Networking Options -->
         QoS and/or fair queuing -->
            Network emulator
    

    Кто незнаком со сборкой ядра, ищите статьи по сборке ядра в документации к вашему дистрибутиву.

    Когда все готово, можно приступать. Рекомендую открыть вторую сессию в которой запустить ping до какого-либо узла в локальной сети. Таким образом вносимые эмуляции будут наблюдаться достаточно четко.

    Для экспериментов нам понадобится утилита tc из пакета iproute2. Полный синтаксис выглядит следующим образом:

    tc qdisc ACTION dev DEVICE add netem OPTIONS
           ACTION := [ add | change | delete ]
           OPTIONS := [ LIMIT ] [ DELAY ] [ DROP ] [ CORRUPT ] [ DUPLICATION ] [ REORDER ]
           LIMIT := limit packets
           DELAY := delay TIME [ JITTER [ CORRELATION ]]] [ distribution { uniform | normal | pareto |  paretonormal } ]
           DROP := drop PERCENT [ CORRELATION ]
           CORRUPT := corrupt PERCENT [ CORRELATION ]]
           DUPLICATION := duplicate PERCENT [ CORRELATION ]]
           REORDER := reorder PERCENT [ CORRELATION ] [ gap DISTANCE ]
    


    1) Задержка пакетов.
    Добавляем к отправке пакетов задержку в 100ms:
    # tc qdisc add dev eth0 root netem delay 100ms
    

    Здесь мы указываем джиттер и таким образом к уже имеющейся задержке в 100ms и добавляем некоторое отклонение в ± 10ms.
    # tc qdisc add dev eth0 root netem delay 100ms 10ms
    

    Теперь добавляем корреляцию, таким образом задержка при отправке слеудющего пакета будет зависеть от задержки предыдущего пакета.
    # tc qdisc add dev eth0 root netem delay 100ms 10ms 50%
    


    2) Распределение задержки.
    В предыдущих примерах мы получали более-менее равномерное распределение задержек на все количество отправленных пакетов. Однако в настоящем мире, сетевые задержки совсем неравномерны. Для получения более реалистичной картины используется распределение (по-умолчанию, если не указывать распределение явно, то используется normal).

    В примере ниже мы указываем распределение pareto, также доступны normal и paretonormal — задержка будет рассчитываться по математическим формулам. Кроме того можно создать свои таблицы распределения. На мой взгляд, это довольно специфичный кейс применения, но вдруг кто-то заинтересуется.

    # tc qdisc add dev eth0 root netem delay 100ms 10ms distribution pareto
    


    3) Потеря пакетов.
    С этого все и началось, да…
    Указывает потерю пакетов в размере 20%.

    # tc qdisc add dev eth0 root netem drop 20%
    


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

    # tc qdisc add dev eth0 root netem drop 20% 10%
    


    4) Повреждение пакетов.
    Намеренное повреждение пакетов, каким образом оно делается? С указанной вероятностью, в случайное место внутри случайно выбранного пакета, записывается некорректный бит. В итоге, контрольная сумма не сходится — пакет отбрасывается. Также как и в случае потерь, можно указать корреляцию для формирования всплесков.

    # tc qdisc add dev eth0 root netem corrupt 20%
    


    5) Дублирование пакетов.
    Дублирование пакетов определяется таким же образом как и потеря либо коррупция пакетов. И конечно же можно указать и корреляцию.
    # tc qdisc add dev eth0 root netem duplicate 20%
    


    6) Переупорядочивание пакетов
    В следующем примере 30% пакетов будут отправлены сразу же, остальные будут задержаны на 100ms.

    # tc qdisc add dev eth0 root netem delay 100ms reorder 30%
    

    В примере ниже, первые 4 пакета (gap — 1) будут задержаны на 100ms, последующие пакеты будут отправлены немедленно с вероятностью 25% (+корреляция 50%) или наоборот задержаны с вероятностью 75%. Как только пакет будет переупорядочен, итерация повторяется и следующие 4 пакета задерживаются, остальные отправляются немедленно либо задерживаются с указанной вероятностью.

    # tc qdisc add dev eth0 root netem delay 100ms reorder 25% 50% gap 5
    


    Кому лень заморачиваться с этим делом, есть небольшой демо-ролик.

    Вот такие дела. Всем спасибо за внимание, экспериментируйте на здоровье.
    • +46
    • 32,4k
    • 8
    Поделиться публикацией
    Комментарии 8
      +8
      WANem
      Готовый аплайанс. Сейчас — надстройка над tc с удобным GUI.
      image

      Несколько лет уже пользуюсь в лабе. Работает на ESX, у виртуалки четыре интерфейса, два в бридже и еще два маршрутизируют. Реально незаменимая штука для ряда задач.
        0
        о отличный комбайн
          0
          Поддерживаю! По моему аналогов просто нет!
          Все скрипты и интерфейс легко переносятся на Ubuntu и т.д… (ну просто, нельзя последнею версию WANem установить на диск)
            0
            У меня 2.3 была установлена на диск. Перенос с ISO был элементарный.
        • НЛО прилетело и опубликовало эту надпись здесь
            0
            Я бы выставил двухстороннюю задержку в полторы секунды с джиттером в полсекунды. Ну ладно, сверху польем соусом полпроцентом потерь (при таком RTT это будет убийственно).
              +2
              Эмуляция управления танком через спутник :)
                +1
                Преимущество такого подхода по сравнению с 30% потерь — им реально удастся залогиниться и войти в игру. А дальше начнется хардкор. Можно предположить, что при такой задержке их будут рвать в клочья все подряд.

          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

          Самое читаемое