Network Admin
12.4K subscribers
1.11K photos
14 videos
8 files
1.13K links
Обучающий канал по сетевому и системному администрированию.

Сотрудничество: @dad_admin
Биржа: https://telega.in/c/networkadm

РКН: https://bit.ly/4ioc61C
Download Telegram
Почему UDP checksum опционален в IPv4, но обязателен в IPv6

В IPv4 у UDP-заголовка есть поле checksum, но стандарт позволяет выставить его в ноль, что означает “checksum не вычислен”.

Принимающая сторона видит нули и просто не проверяет целостность. Исторически это делалось ради производительности: железо 80-х не справлялось с вычислением контрольных сумм на лету без потери скорости.


В IPv6 от этого отказались. Checksum в UDP обязателен, нулевое значение считается ошибкой и пакет дропается.

Причина: IPv6 убрал checksum из собственного заголовка (в IPv4 он был), значит если UDP тоже не считает контрольную сумму, целостность данных вообще никем не проверяется на сетевом уровне.

Проверяем, как это выглядит в трафике:

tcpdump -i eth0 -v udp


В выводе увидим UDP checksum и флаг correct или incorrect. На некоторых интерфейсах с offload-ом checksum вычисляется на уровне NIC, а не ядра, и tcpdump может показывать incorrect на исходящих пакетах, хотя реально всё нормально.

Смотрим включён ли UDP checksum offload на интерфейсе:

ethtool -k eth0 | grep checksum


Где это реально создаёт проблемы

Туннели. VXLAN и некоторые GRE-реализации инкапсулируют пакеты с нулевым UDP checksum внутри IPv4. При переходе в IPv6-транспорт это невалидно и требует пересчёта или явного включения checksum на туннельном интерфейсе:

ip link set vxlan0 type vxlan udpcsum


N.A.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5🤔2
Как найти петлю в L2 без доступа к коммутаторам

Петля в L2 без STP это широковещательный шторм: broadcast-фреймы начинают множиться, загружают все порты, сеть деградирует до полной недоступности за секунды.

Диагностировать нужно быстро, и часто без доступа к коммутаторам.
Первый признак: резкий рост broadcast-трафика на интерфейсе.

Смотрим счётчики прямо сейчас:

watch -n 1 'ip -s link show eth0 | grep -A2 RX'


Если счётчик пакетов растёт на тысячи в секунду при минимальной нагрузке, петля активна.
Ловим broadcast-шторм живым трафиком:

tcpdump -i eth0 -n broadcast


Если один и тот же фрейм появляется несколько раз подряд с одинаковым содержимым, это он. Петля гоняет один фрейм по кругу, tcpdump видит каждый проход.

Смотрим источник шторма по MAC:

tcpdump -i eth0 -n -e broadcast | awk '{print $2}' | sort | uniq -c | sort -rn | head -10


MAC который встречается аномально часто, скорее всего источник или точка где петля замыкается.
Ищем дублирующиеся фреймы по содержимому:

tcpdump -i eth0 -w /tmp/capture.pcap
tcpdump -r /tmp/capture.pcap -n | awk '{print $NF}' | sort | uniq -c | sort -rn | head


Локализация физически

Если есть возможность ходить по офису, отключаем патч-корды по одному и смотрим когда шторм прекратится. Момент когда счётчики перестали расти, последний отключённый кабель и есть замыкание.

watch -n 1 'ip -s link show eth0 | grep -A1 RX'


⚡️Если STP включён но петля всё равно есть, скорее всего где-то BPDU Guard сработал и порт ушёл в err-disabled, но петля успела образоваться через другой путь. Проверяй err-disabled порты если есть хоть какой-то доступ к одному коммутатору: show interfaces status err-disabled.

N.A.
Please open Telegram to view this post
VIEW IN TELEGRAM
12👍1
Коммутатор начал флапать порты: где искать

Флап это когда порт циклически уходит в down и возвращается в up. Для STP каждый флап это topology change, пересчёт, временная потеря связности.

На загруженной сети даже один флапающий порт создаёт заметные проблемы.

Смотрим счётчики переходов состояния на всех портах:

show interfaces | include line protocol|changes
show interfaces counters errors


Порт с аномально высоким Link-state change count это он.

На Linux если коммутатор не Cisco:

ip monitor link
journalctl -k | grep "NIC Link"


ip monitor link показывает события в реальном времени, journalctl покажет историю флапов с таймстампами.

Физические причины

Самые частые: плохой кабель, разболтанный коннектор, неисправный SFP. Проверяем уровень сигнала на оптике:

show interfaces Gi0/1 transceiver
ethtool -m eth0


Смотрим на rx_power, если значение плавает или ниже допустимого порога для данного типа модуля, проблема в оптике или трансивере.

Программные причины

Если физика чистая, смотрим на STP и BPDU:

show spanning-tree detail | include changes
debug spanning-tree events


Частые topology change от конкретного порта могут быть вызваны устройством которое периодически уходит в сон, например IP-телефон или ноутбук.
Проверяем autonegotiation, несогласованный duplex тоже вызывает флапы:

show interfaces Gi0/1 | include duplex,speed


⚡️Если флап идёт строго по расписанию, например каждые несколько часов, смотри на spanning-tree hello timer и max-age. Иногда это не физика, а STP решает что сосед умер из-за потери BPDU на перегруженном канале.

N.A.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12
TCP Nagle algorithm: когда включён мешает и когда отключение ломает

Nagle придумали в 1984 чтобы не засорять сеть мелкими пакетами. Алгоритм простой: не отправляй новый пакет пока предыдущий не подтверждён, если данных меньше чем MSS. Мелкие записи буферизуются и отправляются одним куском.

На медленных линках 80-х это спасало. На современных сетях чаще мешает.

Где Nagle создаёт проблемы

Интерактивные протоколы где важна задержка каждого пакета. SSH, Telnet, remote desktop, любой протокол запрос-ответ где клиент шлёт маленький запрос и ждёт ответа. Nagle держит пакет в буфере ожидая подтверждения предыдущего, задержка растёт.

Классический симптом: команды в SSH ощутимо залипают особенно на каналах с высоким RTT.

Проверяем включён ли Nagle на сокете через ss:

ss -tin dst <IP> | grep -i nagle


Отключается через TCP_NODELAY на уровне приложения:

int flag = 1;
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag));


Или глобально через sysctl хотя это грубо:

sysctl -w net.ipv4.tcp_low_latency=1


Когда отключение ломает

Высокопроизводительные системы где приложение шлёт много мелких write().

Без Nagle каждый write() становится отдельным пакетом, количество пакетов растёт в разы, нагрузка на сеть и CPU увеличивается. Базы данных и файловые серверы обычно держат Nagle включённым именно поэтому.

Взаимодействие с delayed ACK

Самая неприятная комбинация: Nagle на отправителе плюс delayed ACK на получателе. Отправитель ждёт ACK перед отправкой следующего пакета, получатель откладывает ACK до 200мс надеясь что будет что пигибэкнуть. Оба ждут друг друга, задержка 200мс гарантирована.

tcpdump -i eth0 -nn host <IP> | grep -E "ACK|PSH"

Если видишь паузы ровно 200мс между пакетами, это оно.

⚡️ Правильное решение не отключать Nagle глобально, а делать это точечно на конкретных сокетах где важна латентность. Глобальное отключение на сервере с mixed workload ухудшит производительность для одних приложений пока улучшает для других.

N.A.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Как устроен транзитный BGP и чем отличается от пиринга

Два способа получить связность в интернете: купить транзит или договориться о пиринге. Внешне похоже, технически и финансово принципиально разные вещи.

Транзит

Платишь провайдеру за то что он несёт твой трафик куда угодно в интернете. Провайдер анонсирует тебе full routing table, десятки тысяч префиксов, ты через него достигаешь любой AS. Он в свою очередь анонсирует твои префиксы своим апстримам и пирам.

Отношение клиент-провайдер в BGP community обозначается как customer cone. Провайдер принимает маршруты от тебя и распространяет их дальше, ты платишь за каждый мегабит.

router bgp 65001
neighbor 198.51.100.1 remote-as 1299
neighbor 198.51.100.1 description Telia-Transit
neighbor 198.51.100.1 route-map TRANSIT-IN in
neighbor 198.51.100.1 route-map TRANSIT-OUT out


Пиринг

Два оператора договариваются обмениваться трафиком бесплатно, но только своим собственным трафиком и трафиком своих клиентов.

Ты не несёшь через пира трафик третьих AS, он не несёт через тебя. Пиринг имеет смысл когда между двумя сетями достаточно взаимного трафика чтобы окупить договорённость. 


Крупные CDN и контент-провайдеры пирятся агрессивно именно поэтому: им выгодно отдавать трафик напрямую, минуя транзит.

neighbor 203.0.113.1 route-map PEER-IN in
neighbor 203.0.113.1 route-map PEER-OUT out

route-map PEER-OUT permit 10
match ip address prefix-list OWN-PREFIXES


PEER-OUT анонсирует только собственные префиксы, не транзитные маршруты клиентов или других пиров.

Технически чем отличается

У транзитного провайдера LOCAL_PREF на маршруты от клиентов обычно выше чем от пиров, выше чем от апстримов.

Это стандартная политика: клиентский трафик приоритетнее всего, потому что клиент платит.
Маршруты полученные от пира не анонсируются другим пирам или апстримам, только клиентам вниз. Это и есть техническая граница пиринга.

route-map TRANSIT-IN permit 10
set local-preference 100

route-map PEER-IN permit 10
set local-preference 150

route-map CUSTOMER-IN permit 10
set local-preference 200


⚡️ Пиринг не всегда бесплатный. Paid peering это когда один из участников платит другому за обмен трафиком, обычно когда трафик сильно асимметричный. Netflix платит за пиринг с крупными ISP именно потому что трафик идёт почти только в одну сторону.

N.A.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍82
Как IGMP snooping решает проблему multicast-флуда и где ломается

Без IGMP snooping коммутатор не знает кто хочет получать multicast-трафик. Multicast MAC не изучается через обычный ARP, поэтому коммутатор обращается с ним как с broadcast: флудит на все порты.

В сети с видеостримингом или IPTV это убивает полосу на портах где этот трафик никому не нужен.

IGMP snooping решает это пассивно: коммутатор подслушивает IGMP-сообщения между хостами и роутером и строит таблицу кто на какую группу подписан. Multicast уходит только на порты где есть реальные получатели.

Смотрим таблицу IGMP snooping на Cisco:

show ip igmp snooping groups
show ip igmp snooping


Где ломается

Первая проблема: querier. IGMP snooping требует чтобы кто-то периодически спрашивал хосты “вы ещё в группе?”. Обычно это роутер. Если роутера нет в сегменте или он не шлёт IGMP queries, коммутатор не получает ответов, записи в таблице устаревают и трафик снова начинает флудить.

Включаем IGMP querier на коммутаторе если роутера нет:

ip igmp snooping querier
ip igmp snooping querier address 192.168.1.1


Вторая проблема: неизвестный multicast. Если группа не в таблице snooping, коммутатор флудит её на все порты по умолчанию. На коммутаторах где это поведение нежелательно:

no ip igmp snooping flood-unknown-multicast

Третья проблема: статические записи против динамических. Если хост не шлёт IGMP join (некоторые приложения не умеют), запись в таблице не появится и трафик не дойдёт. Добавляем вручную:

ip igmp snooping vlan 10 static 239.1.1.1 interface Gi0/5


N.A.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Проверка VLAN-тегов в сети

Когда трафик не проходит через свичи или маршрутизаторы, одна из частых причин — ошибка в настройке VLAN. Пакеты могут теряться, если:

порт настроен как access, а мы отправляем трафик с тегами;
тег VLAN не совпадает с конфигурацией на другом конце;
свич отбрасывает кадры из «неразрешённого» VLAN.

Смотрим теги через tcpdump


sudo tcpdump -i eth0 -nn -e vlan


• -e — выводит Ethernet-заголовок;
• vlan — фильтрует кадры с тегами 802.1Q.

Пример:

12:30:45.123456 ethertype 802.1Q (0x8100), VLAN 100, IP 192.168.10.2 > 192.168.10.1: ICMP echo request


Здесь видно, что кадр принадлежит VLAN 100.

Проверка конкретного VLAN


sudo tcpdump -i eth0 vlan 200


Покажет только кадры из VLAN 200. Полезно, чтобы убедиться, что нужный VLAN действительно идёт по линку.

Тест с arping

Можно проверить связность внутри VLAN:


sudo arping -I eth0.100 192.168.100.1


Здесь eth0.100 — подинтерфейс, созданный для VLAN 100. Если ответ есть, значит VLAN на этом пути работает.

Создание VLAN-интерфейса в Linux


sudo ip link add link eth0 name eth0.100 type vlan id 100
sudo ip addr add 192.168.100.10/24 dev eth0.100
sudo ip link set eth0.100 up


Теперь можно тестировать трафик напрямую по этому VLAN.

N.A.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Что такое RPF check и почему он дропает валидный трафик

RPF (Reverse Path Forwarding) check это механизм защиты от spoofed-источников в multicast и unicast uRPF. Роутер получает пакет и проверяет: если бы я отправлял пакет обратно к источнику, ушёл бы он через тот же интерфейс на котором пришёл? Если нет, пакет дропается.

Логика простая: легитимный трафик приходит с той стороны откуда роутер знает маршрут до источника. Если пакет пришёл с “неправильного” интерфейса, скорее всего адрес подделан.

Где ломается на валидном трафике

Асимметричный роутинг. Пакет от источника 10.0.0.1 пришёл на интерфейс eth1, но маршрут до 10.0.0.1 в таблице указывает через eth0. RPF check проваливается, пакет дропается, хотя трафик абсолютно легитимный.

Это классическая ситуация при ECMP, нескольких аплинках или когда входящий и исходящий трафик идут разными путями.

Проверяем включён ли uRPF на интерфейсе:

show ip interface Gi0/0 | include verify


Смотрим счётчики дропов от RPF:

show ip traffic | include unicast RPF
show cef interface Gi0/0 | include RPF


На Linux:

cat /proc/net/stat/rt_cache | grep rpf


Два режима uRPF

Strict mode: маршрут до источника должен указывать именно на интерфейс где пришёл пакет. Ломается при асимметричном роутинге.

Loose mode: маршрут до источника должен просто существовать в таблице, через любой интерфейс. Защищает от пакетов с несуществующими источниками, но пропускает асимметричный трафик.

На Cisco переключаем в loose:

interface Gi0/0
ip verify unicast source reachable-via any
Strict mode:
interface Gi0/0
ip verify unicast source reachable-via rx


На Linux:

sysctl -w net.ipv4.conf.eth0.rp_filter=1


1 это strict, 2 это loose, 0 отключён.

N.A.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
Что такое GRE keepalive и почему туннель может считать себя живым, когда он мёртвый

GRE туннель по умолчанию stateless: поднял интерфейс, настроил peer, и с точки зрения роутера туннель живой всегда, даже если на другом конце давно ничего нет.

Маршруты через туннель стоят в таблице, трафик уходит в никуда, роутер об этом не знает.


GRE keepalive решает это: один конец периодически шлёт пакеты через туннель, инкапсулированные так что другой конец возвращает их обратно как обычный IP-трафик. Если ответов нет N раз подряд, интерфейс туннеля уходит в down.

Настройка на Cisco:

interface Tunnel0
tunnel source Gi0/0
tunnel destination 203.0.113.1
keepalive 10 3


10 секунд интервал, 3 пропущенных пакета до down. Итого 30 секунд до детекции падения.

Проверяем состояние:

show interface Tunnel0 | include keepalive|line protocol
debug tunnel keepalive


Почему туннель считает себя живым когда мёртвый

Keepalive работает асимметрично: настраивается и проверяется независимо на каждом конце. Если keepalive включён только на одной стороне, эта сторона детектирует падение, вторая нет.

Хуже: keepalive пакет инкапсулируется в GRE и отправляется на destination. Там роутер декапсулирует его и видит пакет с destination равным своему tunnel source, то есть самому себе. Он отвечает через обычную таблицу маршрутизации, не через туннель обратно.

Если на другом конце туннель упал но физический линк жив, keepalive пакет дойдёт до peer, тот ответит через физику, и отправитель решит что туннель живой. Хотя туннель как таковой не работает.

Проверяем реальное состояние туннеля отдельно от keepalive:

ping 10.0.0.2 source Tunnel0
traceroute 10.0.0.2 source Tunnel0


Если пинг через tunnel source проходит, туннель реально работает. Если нет, keepalive врёт.

N.A.
👍82
Как hardware offload ломает диагностику в tcpdump

tcpdump показывает пакеты какими их видит ядро, а не какими они уходят в провод. Когда включён hardware offload, часть работы по формированию пакетов перекладывается на сетевую карту, и ядро никогда не видит финальные пакеты целиком.

Самый частый случай: TSO (TCP Segmentation Offload). Ядро передаёт NIC один большой кусок данных, до 64KB, а карта сама нарезает его на пакеты по MSS перед отправкой.

tcpdump перехватывает трафик до NIC и видит один гигантский пакет которого в реальности никогда не существовало в сети.

Смотрим какие offload включены:

ethtool -k eth0 | grep -E "tcp-segmentation|generic-segmentation|large-receive"


Типичный вывод:

tcp-segmentation-offload: on
generic-segmentation-offload: on
large-receive-offload: on


Где это создаёт проблемы

Видим в tcpdump пакеты по 30-40KB и думаем что MTU на линке огромный или что-то сломано с фрагментацией. На деле это GSO/TSO артефакты, в провод уходят нормальные пакеты по 1500 байт.

LRO (Large Receive Offload) работает в обратную сторону: NIC склеивает входящие пакеты в один большой до передачи в ядро. tcpdump на входящем трафике снова видит гигантские пакеты которых не было в сети.

Если диагностируешь проблему с MTU или фрагментацией, offload полностью искажает картину.

Отключаем для честной диагностики:

ethtool -K eth0 tso off gso off lro off gro off


После диагностики включаем обратно:

ethtool -K eth0 tso on gso on gro on


Альтернатива: снимать трафик не с хостового интерфейса а с зеркального порта на коммутаторе, там пакеты уже после NIC и выглядят как в реальной сети.

N.A.
👍6
Зачем на транках отключать DTP, даже если соседи свои

DTP хорош, пока сеть маленькая и все помнят, что где включено.

В реальной жизни это редкость. Достаточно один раз перепутать порт или скопировать конфиг - и access внезапно начинает вести себя как trunk.


Обычно это выглядит так: линк up, VLAN’ы «вроде» работают, но где-то появляется лишний трафик, а потом выясняется, что порт сам договорился не о том режиме. Формально никто ничего не ломал.

Проще сразу зафиксировать поведение порта и не надеяться на автодоговорённости.

interface GigabitEthernet1/0/24
switchport mode trunk
switchport trunk allowed vlan 10,20,30
switchport nonegotiate


Здесь порт всегда trunk и только с нужными VLAN. Никаких сюрпризов от соседнего устройства.

Для access-портов логика та же:

interface GigabitEthernet1/0/10
switchport mode access
switchport access vlan 20
switchport nonegotiate


Даже если на другом конце кто-то случайно включит trunk, порт не «переобуется» сам.

Проверка простая:

show interfaces Gi1/0/24 switchport


Меньше автоматики - меньше неочевидных проблем. В сетях это почти всегда плюс.

N.A.
👍92
Скрипт детектора изменения AS-path до критичного префикса между запусками

BGP-маршруты могут тихо меняться: провайдер добавил транзитный AS, появился новый пир, кто-то сделал route leak. AS-path становится длиннее или идёт через неожиданные автономные системы. Без мониторинга это замечают только когда уже проблема.

Проверяем AS-path до префикса через утилиты которые есть на любом Linux:

whois -h whois.radb.net -- "-i origin AS64512" | grep route


Или через bgpq4/bgpq3 если установлен, или через looking glass провайдера. Самый доступный способ без BGP-сессии: парсить вывод traceroute и сопоставлять с базой ASN.

Скрипт с сохранением состояния между запусками

#!/bin/bash
TARGET="8.8.8.8"
SNAPSHOT="/var/lib/bgp_check/aspath.snap"
LOG="/var/log/aspath_changes.log"
BOT_TOKEN="ваш_токен"
CHAT_ID="ваш_chat_id"

mkdir -p "$(dirname "$SNAPSHOT")"

get_aspath() {
traceroute -n -q 1 -w 2 "$1" 2>/dev/null \
| awk 'NR>1 && $2 != "*" {print $2}' \
| while read -r hop; do
asn=$(whois -h whois.cymru.com " -v $hop" 2>/dev/null \
| awk 'NR>1 {print $1}' | head -1)
echo -n "AS${asn} "
done
echo
}

CURRENT=$(get_aspath "$TARGET")

if [ ! -f "$SNAPSHOT" ]; then
echo "$CURRENT" > "$SNAPSHOT"
echo "Baseline saved: $CURRENT"
exit 0
fi

PREVIOUS=$(cat "$SNAPSHOT")

if [ "$CURRENT" != "$PREVIOUS" ]; then
MSG="⚠️ AS-path до $TARGET изменился на $(hostname)\nБыло: $PREVIOUS\nСтало: $CURRENT"
echo "$(date) $MSG" >> "$LOG"
curl -s -X POST "https://api.telegram.org/bot${BOT_TOKEN}/sendMessage" \
-d chat_id="${CHAT_ID}" \
-d text="$MSG"
echo "$CURRENT" > "$SNAPSHOT"
else
echo "$(date) AS-path без изменений: $CURRENT" >> "$LOG"
fi


В cron каждые 30 минут:

*/30 * * * * /usr/local/bin/aspath_monitor.sh


Проверяем лог изменений:

grep "изменился" /var/log/aspath_changes.log


N.A.
👍3🤔1
Проверка DNSSEC валидации через dig +dnssec, а не просто наличия настройки

DNSSEC включён в конфиге резолвера, но это не значит что валидация реально работает.

Резолвер может принимать неподписанные ответы, игнорировать сломанные подписи или вообще не проверять цепочку доверия. Проверяем поведение, а не настройку.

Базовая проверка: резолвер возвращает AD флаг

AD (Authentic Data) в ответе означает что резолвер проверил подписи и доверяет ответу:

dig +dnssec sigok.verteiltesysteme.net @127.0.0.1


Смотрим на флаги в строке flags: qr rd ra ad. Если ad есть, валидация работает для этого домена.

Проверка что резолвер отклоняет сломанные подписи

Существуют специальные тестовые домены с намеренно сломанным DNSSEC:

dig sigfail.verteiltesysteme.net @127.0.0.1


Если резолвер валидирует правильно, ответ должен быть SERVFAIL а не реальный IP. Если вернулся IP, резолвер принимает сломанные подписи.

dig dnssec-failed.org @127.0.0.1


Тот же тест, другой домен. SERVFAIL это ожидаемый правильный ответ.

Скрипт массовой проверки нескольких резолверов

#!/bin/bash
RESOLVERS=("127.0.0.1" "1.1.1.1" "8.8.8.8" "9.9.9.9")
VALID_DOMAIN="sigok.verteiltesysteme.net"
BROKEN_DOMAIN="sigfail.verteiltesysteme.net"
LOG="/var/log/dnssec_check.log"

echo "=== DNSSEC check $(date) ===" >> "$LOG"

for resolver in "${RESOLVERS[@]}"; do
valid_ad=$(dig +dnssec +time=3 "$VALID_DOMAIN" @"$resolver" 2>/dev/null \
| grep "flags:" | grep -c " ad ")

broken_status=$(dig +time=3 "$BROKEN_DOMAIN" @"$resolver" 2>/dev/null \
| grep "status:" | awk -F'[,:]' '{print $2}' | tr -d ' ')

if [ "$valid_ad" -eq 1 ] && [ "$broken_status" = "SERVFAIL" ]; then
result="OK"
elif [ "$valid_ad" -eq 0 ]; then
result="FAIL: не возвращает AD флаг"
else
result="FAIL: принимает сломанные подписи ($broken_status)"
fi

echo "$resolver: $result" | tee -a "$LOG"
done


В cron раз в час:

0 * * * * /usr/local/bin/check_dnssec.sh


N.A.
👍5
Поиск процессов, которые ходят напрямую на 53 порт минуя локальный резолвер

Локальный резолвер настроен, политики есть, логирование включено.

Но некоторые приложения жёстко прописывают DNS-сервер в коде или конфиге и ходят напрямую на 8.8.8.8:53, игнорируя /etc/resolv.conf. Такой трафик выпадает из любого мониторинга и фильтрации на уровне резолвера.

Смотрим кто прямо сейчас держит соединения на порт 53 минуя localhost:

ss -tunp 'dport = :53 and not dst 127.0.0.0/8'


Если вывод не пустой, уже есть кандидаты.

Скрипт непрерывного мониторинга через tcpdump

#!/bin/bash
IFACE=${1:-eth0}
LOG="/var/log/dns_bypass.log"
LOCAL_RESOLVER="127.0.0.53"

tcpdump -i "$IFACE" -n -l \
"udp port 53 and not dst $LOCAL_RESOLVER and not src $LOCAL_RESOLVER" 2>/dev/null \
| while read -r line; do
dst_ip=$(echo "$line" | grep -oP '\d+\.\d+\.\d+\.\d+(?=\.53)' | head -1)
[ -z "$dst_ip" ] && continue

ts=$(date '+%Y-%m-%d %H:%M:%S')

conns=$(ss -tunp "dport = :53 and dst $dst_ip" 2>/dev/null \
| awk 'NR>1 {print $NF}' | sort -u)

echo "$ts -> $dst_ip | $conns" | tee -a "$LOG"
done


Через conntrack если tcpdump не вариант

conntrack -L -p udp --dport 53 2>/dev/null \
| awk '{for(i=1;i<=NF;i++) if($i~/dst=/) print $i}' \
| grep -v "dst=127\." \
| sort | uniq -c | sort -rn


Покажет внешние DNS-серверы к которым идут соединения и сколько раз.

Разовый аудит через lsof

lsof -i UDP:53 -i TCP:53 -n -P \
| awk 'NR>1 && $9 !~ /127\./ {print $1, $2, $9}' \
| sort -u


Колонки: имя процесса, PID, адрес назначения. Всё что не 127.x.x.x это обход резолвера.

В cron для периодического снимка:

*/10 * * * * lsof -i UDP:53 -n -P | awk 'NR>1 && $9 !~ /127\./ {print $1,$2,$9}' >> /var/log/dns_bypass.log


N.A.
👍91
Проверяем, что все next-hop в таблице маршрутизации живые

Маршрут в таблице есть, интерфейс поднят, но next-hop давно не отвечает. Такое бывает после замены оборудования, при проблемах с upstream или когда шлюз провайдера ушёл без уведомления.

Маршрутизатор продолжает слать трафик в никуда.

Собираем все уникальные next-hop из таблицы маршрутизации:

ip route show | awk '/via/ {print $3}' | sort -u


Скрипт массового ARP-опроса next-hop

#!/bin/bash
LOG="/var/log/nexthop_check.log"
BOT_TOKEN="ваш_токен"
CHAT_ID="ваш_chat_id"

echo "=== Next-hop check $(date) ===" >> "$LOG"

ip route show | awk '/via/ {print $3, $5}' | sort -u \
| while read -r nexthop iface; do
[ -z "$iface" ] && iface=$(ip route get "$nexthop" 2>/dev/null | awk '{print $3}' | head -1)
[ -z "$iface" ] && continue

result=$(arping -c 2 -W 1 -I "$iface" "$nexthop" 2>/dev/null \
| grep -c "bytes from")

if [ "$result" -eq 0 ]; then
msg="⚠️ Next-hop $nexthop ($iface) не отвечает на ARP на $(hostname)"
echo "$(date '+%Y-%m-%d %H:%M:%S') FAIL: $nexthop via $iface" >> "$LOG"
curl -s -X POST "https://api.telegram.org/bot${BOT_TOKEN}/sendMessage" \
-d chat_id="${CHAT_ID}" \
-d text="$msg" &>/dev/null
else
echo "$(date '+%Y-%m-%d %H:%M:%S') OK: $nexthop via $iface" >> "$LOG"
fi
done


Для IPv6 next-hop отдельно через ndisc6:

ip -6 route show | awk '/via/ {print $3, $5}' | sort -u \
| while read -r nexthop iface; do
result=$(ndisc6 -q -r 2 "$nexthop" "$iface" 2>/dev/null | grep -c "from")
[ "$result" -eq 0 ] && echo "FAIL IPv6: $nexthop via $iface"
done


В cron каждые 5 минут:

*/5 * * * * /usr/local/bin/check_nexthop.sh


Смотрим историю недоступных next-hop:

grep "FAIL" /var/log/nexthop_check.log | tail -20


N.A.
👍3
Почему OSPF соседство не поднимается

Интерфейсы в состоянии up/up, IP-адреса корректные, но соседи в OSPF не переходят в Full.

Чаще всего причина в несовпадении параметров: area ID, network type, hello/dead timers, MTU или authentication. 


Иногда интерфейс попадает под passive-interface, либо multicast 224.0.0.5 блокируется ACL’ом.

Также соседство не установится, если Router ID дублируется в домене или если одна сторона работает в stub/NSSA, а другая - нет.

🤖Что проверить на Cisco

show ip ospf neighbor
show ip ospf interface Gi0/1
show ip ospf interface Gi0/1 | include MTU
show ip protocols
show running-config | section router ospf
show ip ospf database
show access-lists


N.A.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Аудит активных multicast-групп через /proc/net/igmp

Кто и на какие multicast-группы подписан в системе, обычно выясняют через внешние утилиты.

Но всё это есть прямо в ядре без ничего лишнего.

Смотрим что есть в /proc/net/igmp:

cat /proc/net/igmp


Вывод не самый читаемый: адреса групп в hex little-endian. Парсим в человеческий вид:

awk 'NR>1 && $1 !~ /^[0-9]/ {iface=$1}
NR>1 && $1 ~ /^[0-9]/ {
hex=$2
printf "%s: %d.%d.%d.%d\n", iface,
strtonum("0x"substr(hex,7,2)),
strtonum("0x"substr(hex,5,2)),
strtonum("0x"substr(hex,3,2)),
strtonum("0x"substr(hex,1,2))
}' /proc/net/igmp


Показывает интерфейс и группу в читаемом виде.

Скрипт мониторинга с алертом на новые группы

#!/bin/bash
SNAPSHOT="/var/lib/igmp_check/groups.snap"
LOG="/var/log/igmp_changes.log"
BOT_TOKEN="ваш_токен"
CHAT_ID="ваш_chat_id"

mkdir -p "$(dirname "$SNAPSHOT")"

parse_igmp() {
awk 'NR>1 && $1 !~ /^[0-9]/ {iface=$1}
NR>1 && $1 ~ /^[0-9]/ {
hex=$2
printf "%s %d.%d.%d.%d\n", iface,
strtonum("0x"substr(hex,7,2)),
strtonum("0x"substr(hex,5,2)),
strtonum("0x"substr(hex,3,2)),
strtonum("0x"substr(hex,1,2))
}' /proc/net/igmp | sort
}

CURRENT=$(parse_igmp)

if [ ! -f "$SNAPSHOT" ]; then
echo "$CURRENT" > "$SNAPSHOT"
echo "Baseline saved"
exit 0
fi

PREVIOUS=$(cat "$SNAPSHOT")
NEW=$(comm -13 <(echo "$PREVIOUS") <(echo "$CURRENT"))
GONE=$(comm -23 <(echo "$PREVIOUS") <(echo "$CURRENT"))

if [ -n "$NEW" ] || [ -n "$GONE" ]; then
msg="⚠️ IGMP изменения на $(hostname)"
[ -n "$NEW" ] && msg="$msg\nНовые группы: $NEW"
[ -n "$GONE" ] && msg="$msg\nУшли группы: $GONE"
echo "$(date) $msg" >> "$LOG"
curl -s -X POST "https://api.telegram.org/bot${BOT_TOKEN}/sendMessage" \
-d chat_id="${CHAT_ID}" \
-d text="$msg" &>/dev/null
echo "$CURRENT" > "$SNAPSHOT"
fi


В cron каждые 5 минут:

*/5 * * * * /usr/local/bin/igmp_monitor.sh


N.A.
👍4
Скрипт мониторинга TCP retransmit rate через /proc/net/snmp

Ретрансмиты это первый признак проблем на канале: потери, перегрузка, несогласованный duplex. /proc/net/snmp даёт реальную картину по TCP без внешних инструментов.

Смотрим нужные счётчики:

awk '/^Tcp:/ {nr++; if(nr==1) print; if(nr==2) print}' /proc/net/snmp


Первая строка заголовки, вторая значения. Нас интересуют RetransSegs и OutSegs.

Скрипт с дельтой и алертом:

#!/bin/bash
THRESHOLD=1
LOG="/var/log/tcp_retransmit.log"
BOT_TOKEN="ваш_токен"
CHAT_ID="ваш_chat_id"

get_stats() {
awk '/^Tcp:/ {nr++; if(nr==2) print $13, $11}' /proc/net/snmp
}

read -r r1 o1 <<< "$(get_stats)"
sleep 60
read -r r2 o2 <<< "$(get_stats)"

dr=$(( r2 - r1 ))
do_=$(( o2 - o1 ))

[ "$do_" -eq 0 ] && exit 0

rate=$(awk "BEGIN {printf \"%.2f\", $dr/$do_*100}")
echo "$(date '+%Y-%m-%d %H:%M:%S') ${rate}% (${dr}/${do_})" >> "$LOG"

awk -v r="$rate" -v t="$THRESHOLD" 'BEGIN {
if (r+0 > t+0) exit 0; exit 1
}' && curl -s -X POST "https://api.telegram.org/bot${BOT_TOKEN}/sendMessage" \
-d chat_id="${CHAT_ID}" \
-d text="⚠️ TCP retransmit ${rate}% на $(hostname)"


Если rate высокий, смотрим какие соединения виноваты:

ss -tin | grep -v "retrans:0" | grep retrans


В cron каждые 5 минут:

*/5 * * * * /usr/local/bin/tcp_retransmit.sh


⚡️ Позиции $13 и $11 могут отличаться между версиями ядра. Проверяй на своей системе: первая строка /proc/net/snmp с Tcp: это заголовки, считай колонки до RetransSegs и OutSegs вручную.

N.A.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Диагностика соседей: CDP/LLDP/neighbors на Cisco, Микротик и Linux

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

Cisco

show cdp neighbors
show cdp neighbors detail
show lldp neighbors
show lldp neighbors detail


cdp neighbors показывает имя соседа, интерфейс, платформу и capability. detail добавляет IP-адрес управления, версию IOS и native VLAN. LLDP на Cisco выключен по умолчанию, включается глобально:

lldp run


Микротик

/ip neighbor print
/ip neighbor print detail


RouterOS видит соседей через CDP и LLDP одновременно без дополнительной настройки. Вывод включает IP, MAC, платформу, версию и интерфейс через который пришло объявление.

Фильтруем по интерфейсу:

/ip neighbor print where interface=ether1


Linux

lldpd не установлен по умолчанию, ставим и запускаем:

apt install lldpd
systemctl start lldpd


Смотрим соседей:

lldpcli show neighbors
lldpcli show neighbors details


Без lldpd можно поймать LLDP-фреймы напрямую через tcpdump:

tcpdump -i eth0 -v ether proto 0x88cc


Не так удобно но работает без демона.

Быстрое сравнение

На Cisco нужно явно включать LLDP, CDP работает из коробки но только с Cisco-устройствами. Микротик видит обоих без настройки. Linux требует lldpd для полноценной работы, зато отдаёт данные в JSON для автоматизации:

lldpcli -f json show neighbors


N.A.
3
RouterOS: как работает /tool torch и чем лучше обычного tcpdump

tcpdump показывает сырые пакеты, ты сам разбираешь, что происходит.

torch работает на уровне flow: группирует трафик по src/dst IP, протоколу и порту, показывает скорость каждого потока в реальном времени. Не дамп, а живая таблица активных соединений с полосой.

Запускаем через CLI:

/tool torch interface=ether1


По умолчанию показывает все потоки. Фильтруем по протоколу:

/tool torch interface=ether1 ip-protocol=tcp
/tool torch interface=ether1 ip-protocol=udp port=53


Смотрим только трафик конкретного хоста:

/tool torch interface=ether1 src-address=192.168.1.100
/tool torch interface=ether1 dst-address=8.8.8.8


Комбинируем фильтры:

/tool torch interface=ether1 src-address=192.168.1.0/24 ip-protocol=tcp port=443


Покажет все HTTPS-потоки из внутренней подсети с live-скоростью каждого.

Где torch выигрывает у tcpdump

На загруженном интерфейсе tcpdump генерирует огромный поток данных который сложно читать на лету. torch агрегирует: вместо тысяч строк видишь десяток потоков отсортированных по полосе.

Сразу понятно, кто жрёт канал.


torch работает в winbox через меню Tools, там же можно сортировать колонки мышкой. Для быстрой диагностики перегруза удобнее чем любой CLI.

Где tcpdump нужен, а torch нет

Когда нужен payload: содержимое пакетов, флаги TCP, конкретные заголовки. torch видит только flow-статистику, внутрь пакета не смотрит. На Микротик для этого есть packet sniffer:

/tool sniffer start
/tool sniffer packet print
/tool sniffer stop


Или с записью в pcap для анализа в Wireshark:

/tool sniffer set filter-interface=ether1 file-name=capture.pcap
/tool sniffer start


N.A.
6
Cisco: как работает CEF и почему это важно для понимания форвардинга

До CEF Cisco форвардила пакеты через process switching: каждый пакет поднимался на CPU, который смотрел в таблицу маршрутизации и принимал решение.

Медленно и дорого по ресурсам. CEF (Cisco Express Forwarding) решает это через предварительно скомпилированные таблицы которые обновляются при изменении топологии, а не при каждом пакете.

Две ключевые структуры:

FIB (Forwarding Information Base) это скомпилированная копия таблицы маршрутизации. Вместо рекурсивного lookup до следующего хопа, CEF хранит уже resolved next-hop для каждого префикса.

Adjacency table хранит L2-информацию для каждого next-hop: MAC-адрес, исходящий интерфейс, заголовок фрейма который нужно подставить. При форвардинге пакета CEF берёт запись из FIB и сразу знает, какой L2-заголовок писать.

Смотрим, что в FIB:

show ip cef
show ip cef 10.0.0.0/24 detail

Смотрим adjacency table:

show adjacency
show adjacency detail
show adjacency GigabitEthernet0/0 detail

В выводе adjacency detail видно реальный L2-заголовок в hex который подставляется в каждый пакет.

Почему это важно для диагностики

Если маршрут есть в RIB (show ip route) но нет в FIB (show ip cef), пакеты не форвардируются несмотря на правильную таблицу маршрутизации. Такое бывает при проблемах с CEF или при явном отключении.

show ip cef summary
show ip cef not-cef-switched

not-cef-switched покажет трафик который всё равно уходит на process switching, это узкое место.

Проверяем включён ли CEF:

show ip interface Gi0/0 | include CEF
ip cef

N.A.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4