Скопипизжено с http://habrahabr.ru/post/237217/
Первая мысль которая пришла мне в голову это использовать 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):
<span class="comment"># grep NETEM /boot/config-$(uname -r)</span>
CONFIG_NET_SCH_NETEM=m
Как видно из вывода, поддержка в виде модуля, поэтому подгружаем его. Также нам понадобится утилита tc из пакета iproute:
<span class="comment"># modprobe sch_netem</span>
Если же ничего нет, необходимо пересобрать ядро. Кто знаком со сборкой ядра — небольшая подсказка, Network emulator находится здесь:
Networking -->
Networking Options -->
QoS and/or fair queuing -->
Network emulator
Кто незнаком со сборкой ядра, ищите статьи по сборке ядра в документации к вашему дистрибутиву.
Когда все готово, можно приступать. Рекомендую открыть вторую сессию в которой запустить ping до какого-либо узла в локальной сети. Таким образом вносимые эмуляции будут наблюдаться достаточно четко.
Для экспериментов нам понадобится утилита tc из пакета iproute2. Полный синтаксис выглядит следующим образом:
tc qdisc ACTION dev DEVICE add netem OPTIONS
ACTION := <span class="test_condition">[ add | change | delete ]</span>
OPTIONS := <span class="test_condition">[ LIMIT ]</span> <span class="test_condition">[ DELAY ]</span> <span class="test_condition">[ DROP ]</span> <span class="test_condition">[ CORRUPT ]</span> <span class="test_condition">[ DUPLICATION ]</span> <span class="test_condition">[ REORDER ]</span>
LIMIT := limit packets
DELAY := delay TIME <span class="test_condition">[ JITTER [ CORRELATION ]</span>]] <span class="test_condition">[ distribution { uniform | normal | pareto | paretonormal } ]</span>
DROP := drop PERCENT <span class="test_condition">[ CORRELATION ]</span>
CORRUPT := corrupt PERCENT <span class="test_condition">[ CORRELATION ]</span>]
DUPLICATION := duplicate PERCENT <span class="test_condition">[ CORRELATION ]</span>]
REORDER := reorder PERCENT <span class="test_condition">[ CORRELATION ]</span> <span class="test_condition">[ gap DISTANCE ]</span>
1) Задержка пакетов.
Добавляем к отправке пакетов задержку в 100ms:
<span class="comment"># tc qdisc add dev eth0 root netem delay 100ms</span>
Здесь мы указываем джиттер и таким образом к уже имеющейся задержке в 100ms и добавляем некоторое отклонение в ± 10ms.
<span class="comment"># tc qdisc add dev eth0 root netem delay 100ms 10ms</span>
Теперь добавляем корреляцию, таким образом задержка при отправке слеудющего пакета будет зависеть от задержки предыдущего пакета.
<span class="comment"># tc qdisc add dev eth0 root netem delay 100ms 10ms 50%</span>
2) Распределение задержки.
В предыдущих примерах мы получали более-менее равномерное распределение задержек на все количество отправленных пакетов. Однако в настоящем мире, сетевые задержки совсем неравномерны. Для получения более реалистичной картины используется распределение (по-умолчанию, если не указывать распределение явно, то используется normal).
В примере ниже мы указываем распределение pareto, также доступны normal и paretonormal — задержка будет рассчитываться по математическим формулам. Кроме того можно создать свои таблицы распределения. На мой взгляд, это довольно специфичный кейс применения, но вдруг кто-то заинтересуется.
<span class="comment"># tc qdisc add dev eth0 root netem delay 100ms 10ms distribution pareto</span>
3) Потеря пакетов.
С этого все и началось, да…
Указывает потерю пакетов в размере 20%.
<span class="comment"># tc qdisc add dev eth0 root netem drop 20%</span>
Дополнительно можно указать корреляцию, в таком случае, генератор случайных чисел будет менее случайным и можно будет наблюдать всплески в потерях:
<span class="comment"># tc qdisc add dev eth0 root netem drop 20% 10%</span>
4) Повреждение пакетов.
Намеренное повреждение пакетов, каким образом оно делается? С указанной вероятностью, в случайное место внутри случайно выбранного пакета, записывается некорректный бит. В итоге, контрольная сумма не сходится — пакет отбрасывается. Также как и в случае потерь, можно указать корреляцию для формирования всплесков.
<span class="comment"># tc qdisc add dev eth0 root netem corrupt 20%</span>
5) Дублирование пакетов.
Дублирование пакетов определяется таким же образом как и потеря либо коррупция пакетов. И конечно же можно указать и корреляцию.
<span class="comment"># tc qdisc add dev eth0 root netem duplicate 20%</span>
6) Переупорядочивание пакетов
В следующем примере 30% пакетов будут отправлены сразу же, остальные будут задержаны на 100ms.
<span class="comment"># tc qdisc add dev eth0 root netem delay 100ms reorder 30%</span>
В примере ниже, первые 4 пакета (gap — 1) будут задержаны на 100ms, последующие пакеты будут отправлены немедленно с вероятностью 25% (+корреляция 50%) или наоборот задержаны с вероятностью 75%. Как только пакет будет переупорядочен, итерация повторяется и следующие 4 пакета задерживаются, остальные отправляются немедленно либо задерживаются с указанной вероятностью.
<span class="comment"># tc qdisc add dev eth0 root netem delay 100ms reorder 25% 50% gap 5</span>
Кому лень заморачиваться с этим делом, есть небольшой демо-ролик .
Вот такие дела. Всем спасибо за внимание, экспериментируйте на здоровье.