The Network Brief

// kzdev.ru · 2026
01
eBPF
eBPF: суперсила, которую добавили в Linux, пока вы не смотрели
Без боли, без кода на C, без страданий. Просто понять — что это и почему все крупные компании уже на нём.
12 мин
02
BGP
Почему ваш трафик идёт через Лондон, когда сервер в Москве
BGP path selection человеческим языком. Без формул, с примерами из реальных traceroute.
10 мин
03
История
15 лет в сетях: что я понял про инциденты, которые случаются в 3 ночи
Личная история. Про усталость, паттерны, и почему лучшие сетевые инженеры всегда спокойны.
8 мин
04
eBPF / XDP
Как я дропаю 14 миллионов пакетов в секунду тремя строчками кода
XDP на практике: как это работает, почему это быстрее iptables в 10 раз, и как это запустить.
14 мин
05
DDoS
Нас атаковали на 400 Гбит/с. Вот что реально спасло
Честный постмортем без прикрас. Что сломалось, что сработало, и что мы сделали бы иначе.
16 мин
06
eBPF
iptables мёртв. Вот что его убило и что пришло на замену
nftables, eBPF, XDP — три претендента. Разбираем честно, с цифрами и без маркетинга.
11 мин
07
BGP
Что происходит с вашим пакетом за 50 миллисекунд
Путешествие одного TCP SYN от вашего браузера до сервера — со всеми остановками и задержками.
13 мин
08
BGP
Как я объясняю BGP своей маме — и почему это помогает на собесах
Аналогия, которая работает. Плюс бонус: как объяснять сложные концепции на техническом интервью.
7 мин
09
Производительность
Почему ваш nginx отдаёт 10к RPS, а у соседа 100к на том же железе
Сетевой стек Linux не настроен для высокой нагрузки по умолчанию. Вот 7 параметров которые меняют всё.
15 мин
10
Ресурсы
Что читает CTO по сетям: 10 источников которые реально двигают мышление
Не курсы Cisco. Не YouTube-туториалы. То, что читают люди которые строят сети на миллионы пользователей.
6 мин
eBPF// 12 мин чтения

eBPF: суперсила, которую добавили в Linux, пока вы не смотрели

Cloudflare, Netflix, Google, Meta — все они переписали часть своей сетевой инфраструктуры на eBPF. Объясняю, что это такое, как работает и почему это важно даже если вы никогда не напишете ни строчки BPF-кода.

Несколько лет назад коллега показал мне как Cloudflare обрабатывает DDoS-атаки. Я ожидал увидеть кластер специализированного железа, FPGA, что-то дорогое. Вместо этого — обычные x86-серверы и несколько строчек кода, которые дропали миллионы пакетов в секунду до того, как они вообще доходили до ядра Linux. Это был eBPF.

С тех пор я не могу перестать думать о том, насколько незаметно произошла эта революция.

Что такое eBPF и зачем он нужен

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

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

Аналогия: JavaScript в браузере. Браузер позволяет запускать чужой код (ваши скрипты), но в песочнице, где вы не можете сломать операционную систему. eBPF — это JavaScript для ядра Linux.

Где именно работает eBPF

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

Конкретные цифры: насколько это быстро

Вот реальные замеры с одного из наших серверов (Intel E5-2690v4, 10GbE NIC):

14M
пакетов/сек дропает XDP
1.2M
пакетов/сек дропает iptables
~200нс
задержка на пакет у XDP

Разница в 10-12 раз. На одном и том же железе. Без каких-либо аппаратных ускорителей.

Почему такая разница?

Когда пакет приходит и обрабатывается через iptables, он проходит через весь сетевой стек Linux: выделение skb (socket buffer), обработку в netfilter, прохождение через все цепочки правил. Это сотни функций и тысячи инструкций.

XDP-программа запускается до всего этого — пакет ещё в DMA-буфере сетевой карты. Программа смотрит на него, принимает решение (PASS/DROP/REDIRECT), и всё. Если DROP — пакет не существует с точки зрения ядра.

Кто это использует и как

Cloudflare — фильтрация DDoS на XDP. Когда на вас летит 1 Тбит/с мусора, iptables просто не успевает. XDP успевает.

Meta (Facebook) — Katran, L4-балансировщик на eBPF. Заменил IPVS. Обрабатывает весь трафик Facebook на входе.

Google — Calico с eBPF в Kubernetes, замена kube-proxy. Меньше латентность, больше throughput.

Netflix — bpftrace для отладки латентности в продакшне без перезапуска сервисов.

Нужно ли вам писать BPF-код?

Скорее всего нет. Большинство практических кейсов уже решены готовыми инструментами:

Когда стоит писать свой BPF-код: нестандартная фильтрация трафика, кастомные метрики на уровне ядра, специализированный балансировщик. В остальных случаях — берите готовые инструменты.

Как начать прямо сейчас

Если хотите потрогать руками — вот самый быстрый путь:

bashустановка bpftrace
# Ubuntu 22.04+ apt install bpftrace # Смотрим все входящие соединения в реальном времени bpftrace -e 'tracepoint:syscalls:sys_enter_connect { printf("%s -> %s\n", comm, str(args->uservaddr)); }' # Топ процессов по количеству syscall'ов bpftrace -e 'tracepoint:raw_syscalls:sys_enter { @[comm] = count(); } interval:s:5 { print(@); clear(@); }'

Первая команда — и вы уже видите каждое сетевое соединение на машине, в реальном времени, без tcpdump, без прав на запись пакетов. Это eBPF.

Вывод

eBPF — не хайп и не академическая концепция. Это production-технология, которая уже работает в инфраструктуре компаний обслуживающих миллиарды пользователей. Она меняет то, как мы думаем о сетевом стеке, observability и безопасности.

Если вы работаете с Linux-инфраструктурой и ещё не разобрались с eBPF — это пробел который стоит закрыть. Не потому что модно. Потому что это реально меняет что возможно сделать.

BGP// 10 мин чтения

Почему ваш трафик идёт через Лондон, когда сервер в Москве

BGP — протокол который решает куда идут пакеты в интернете. Он не выбирает кратчайший путь. Он выбирает путь по правилам, которые придумали люди. И иногда эти правила приводят к абсурду.

Однажды мне написал разработчик: «Почему мой запрос от сервера в Амстердаме до сервера в Москве идёт 180ms? Это же рядом!» Я попросил сделать traceroute. Трафик шёл через Лондон, Нью-Йорк и обратно.

Это не баг. Это BGP.

Интернет — это не одна сеть

Физически интернет — это тысячи отдельных сетей (их называют автономными системами, AS), которые соединены между собой. Провайдеры, университеты, датацентры, крупные компании — у каждого свой AS с уникальным номером.

BGP (Border Gateway Protocol) — это язык, на котором эти сети общаются между собой. Каждый AS говорит соседям: «Я умею доставлять трафик вот в эти IP-адреса». Соседи передают эту информацию своим соседям. Так строится глобальная таблица маршрутизации.

Аналогия: Представьте что вы хотите отправить посылку в другой город. Почта не знает всех маршрутов — она знает только своих соседних партнёров. Каждый партнёр говорит: «Через меня можно доставить в такие-то регионы». BGP — это этот разговор между почтовыми компаниями, только про пакеты данных.

Как BGP выбирает маршрут

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

1. Local Preference (локальное предпочтение). Каждый AS может сказать «этот путь мне нравится больше» — через атрибут local-pref. Кто поставил выше — тот и победил, независимо от физического расстояния.

2. AS Path Length (длина пути). Сколько автономных систем нужно пройти. Меньше — лучше. Но это количество AS, не километров.

3. MED (Multi-Exit Discriminator). Подсказка от соседнего AS: «входи через этот интерфейс, он ближе к получателю».

И вот в чём проблема: нигде в этих критериях нет физического расстояния или задержки. BGP не знает про миллисекунды.

Почему трафик пошёл через Нью-Йорк

Вернёмся к нашему примеру. Провайдер в Амстердаме мог купить транзит у крупного tier-1 оператора с хорошим local-pref. Этот оператор имеет поп (point of presence) в Лондоне и Нью-Йорке, но его BGP-сессия с российским провайдером настроена через Нью-Йорк — потому что там исторически стоит оборудование, потому что контракт, потому что «так сложилось».

BGP увидел: путь через этого оператора имеет высокий local-pref → выбрал его → физика стала неважна.

tracerouteреальный пример субоптимального маршрута
1 ams-gateway.provider.nl 2ms 2 lon-peer.tier1.net 18ms ← Лондон 3 nyc-core.tier1.net 98ms ← Нью-Йорк (!) 4 nyc-msk-link.tier1.net 172ms 5 msk-server.target.ru 185ms ← Москва

185ms вместо ~25ms которые были бы при прямом маршруте. В 7 раз медленнее.

Как это можно починить

Если вы управляете своим AS — у вас есть инструменты:

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

Вывод: интернет — это политика, не физика

BGP-маршруты определяются коммерческими договорами, историческими решениями и техническими конфигурациями — а не географией. Это одновременно его слабость (субоптимальные пути) и сила (гибкость, устойчивость, возможность traffic engineering).

В следующий раз когда сделаете traceroute и увидите странный маршрут — знайте: где-то между двумя NOC-командами есть контракт, который объясняет почему ваши пакеты летят через другой континент.

История// 8 мин чтения

15 лет в сетях: что я понял про инциденты, которые случаются в 3 ночи

Это не технический пост. Это про то, что происходит с человеком, который годами встаёт по ночам когда что-то падает. И про то, почему лучшие инженеры всегда выглядят спокойными.

Первый серьёзный инцидент я помню до деталей. 2011 год, 2:47 ночи, BGP-сессия с аплинком упала и не поднялась. Я паниковал. Руки тряслись. Я делал одно и то же по три раза — рестартил демон, смотрел логи, снова рестартил. Прошло 40 минут прежде чем я сел, выдохнул, и начал думать системно.

Оказалось — MTU mismatch на новом линке провайдера. Сессия устанавливалась но BGP OPEN-пакеты были больше 1500 байт и дропались по дороге. Три команды и пять минут после того как я успокоился.

С тех пор прошло 15 лет и сотни инцидентов. Вот что я понял.

Паника — это физиология, не слабость

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

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

Действие без данных в 80% случаев удлиняет инцидент.

Паттерны которые я вижу снова и снова

«Оно само упало».  Не бывает. Всегда есть причина. «Само» означает что причину не нашли.

Инцидент в 3 ночи почти всегда связан с изменением в 17:00.  Деплой, ребут, обновление конфига. Что-то поменяли перед уходом домой, и это всплыло ночью под нагрузкой или после истечения таймера.

Первый симптом — не причина.  Упал nginx — причина не в nginx. Смотрите глубже: память, сеть, зависимый сервис, ядро.

Мой личный чеклист для первых 5 минут любого инцидента: что упало → когда → что менялось → где ещё симптомы → кто ещё знает. Только потом — что делать.

Про усталость говорят мало, а надо

После трёх лет постоянного oncall я заметил: я стал медленнее. Не технически — реакция на стресс притупилась. Я мог сидеть на инциденте два часа и не заметить очевидного, потому что мозг был просто истощён.

Хронический oncall без нормального сна — это не героизм. Это деградация качества работы в тихом режиме. Компания которая не ротирует oncall и не даёт восстановление после тяжёлых инцидентов — тратит деньги: следующий инцидент будет дольше и дороже.

Что отличает лучших

Я работал с десятками сетевых инженеров. Лучшие из них не самые умные — они самые методичные. У них есть процесс на любой тип инцидента, и они следуют ему даже в 4 утра.

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

Главное что я хотел бы знать 15 лет назад

Инциденты не делают вас хорошим инженером. Хорошим инженером вас делает то, что вы делаете после инцидентов: постмортем без поиска виноватых, исправление системных проблем, улучшение мониторинга.

Компания которая наказывает за инциденты — это компания которая учится медленнее конкурентов. Это стратегический проигрыш.

И последнее: если вы читаете это в 3 ночи пока что-то горит — выдохните. Вы справитесь. Соберите данные. Думайте медленно.

eBPF / XDP// 14 мин чтения

Как я дропаю 14 миллионов пакетов в секунду тремя строчками кода

XDP позволяет обработать пакет раньше чем ядро Linux его «увидит». Это делает фильтрацию в 10-15 раз быстрее iptables. Показываю как это работает на практике — с кодом, числами и объяснением каждого шага.

Во время DDoS-атаки мощностью 80 Гбит/с наш сервер с iptables держал примерно 1.2 миллиона пакетов в секунду. При 2 миллионах — ядро начинало захлёбываться, CPU уходил в 100%, latency для легитимного трафика улетала в секунды.

После переезда на XDP тот же сервер обрабатывал 14 миллионов пакетов в секунду. Атака продолжалась, но сервис работал.

Почему iptables медленный

Когда пакет приходит на сетевую карту, ядро Linux делает много работы прежде чем его «увидят» iptables-правила:

Это сотни операций и несколько переходов между уровнями. При миллионах пакетов в секунду — это огромная нагрузка.

Что делает XDP

XDP (eXpress Data Path) — хук в самом начале пути пакета, сразу после получения данных от NIC, до выделения sk_buff. Ваша программа получает прямой доступ к сырым байтам пакета и должна вернуть одно из трёх решений:

Самая простая XDP-программа

C / eBPFxdp_drop_udp.c — дропаем весь UDP
#include <linux/bpf.h> #include <linux/if_ether.h> #include <linux/ip.h> #include <linux/udp.h> #include <bpf/bpf_helpers.h> SEC("xdp") int xdp_drop_udp(struct xdp_md *ctx) { void *data = (void *)(long)ctx->data; void *data_end = (void *)(long)ctx->data_end; // Проверяем ethernet header struct ethhdr *eth = data; if (eth + 1 > data_end) return XDP_PASS; if (eth->h_proto != __constant_htons(ETH_P_IP)) return XDP_PASS; // Проверяем IP header struct iphdr *ip = data + sizeof(*eth); if (ip + 1 > data_end) return XDP_PASS; // Если UDP — дропаем if (ip->protocol == IPPROTO_UDP) return XDP_DROP; return XDP_PASS; } char _license[] SEC("license") = "GPL";

Вот и всё. Это программа на C которая компилируется в eBPF bytecode и загружается в ядро. Она дропает весь UDP-трафик со скоростью которую ограничивает только NIC.

Загрузка и запуск

bashкомпиляция и загрузка
# Компилируем clang -O2 -target bpf -c xdp_drop_udp.c -o xdp_drop_udp.o # Загружаем на интерфейс eth0 ip link set dev eth0 xdp obj xdp_drop_udp.o sec xdp # Проверяем что загрузилось ip link show eth0 | grep xdp # Снять программу ip link set dev eth0 xdp off

Реальные цифры с нашего сервера

14.2M
пакетов/сек XDP DROP
1.15M
пакетов/сек iptables DROP
2-4%
CPU при XDP vs 100% при iptables
Важно: XDP в режиме native (поддержка в драйвере NIC) работает быстрее чем generic (любой интерфейс). Список NIC с native XDP: mlx5, i40e, ixgbe, ena (AWS), virtio_net. Проверьте свой драйвер перед сравнением.

Практический кейс: фильтрация по source IP

Во время атаки вы часто знаете список источников. XDP-карта позволяет хранить IP-адреса для блокировки и обновлять её из userspace без перезагрузки программы:

C / eBPFблокировка по IP через BPF map
// Объявляем карту: IP -> 1 (заблокирован) struct { __uint(type, BPF_MAP_TYPE_LRU_HASH); __uint(max_entries, 100000); __type(key, __u32); // source IP __type(value, __u8); // 1 = drop } blocklist SEC(".maps"); SEC("xdp") int xdp_filter(struct xdp_md *ctx) { // ... parse headers ... __u32 src_ip = ip->saddr; __u8 *blocked = bpf_map_lookup_elem(&blocklist, &src_ip); if (blocked) return XDP_DROP; return XDP_PASS; }

Lookup в BPF hash map — это O(1), порядка 50-100 наносекунд. 100 тысяч заблокированных IP — не проблема.

Вывод

XDP — не замена всему сетевому стеку. Это инструмент для конкретной задачи: очень быстрое решение «пустить или нет» на входе. Если нужна сложная логика, statefull inspection, NAT — смотрите на TC или работайте в userspace.

Но если у вас DDoS и вам нужно дропать мусор со скоростью линка — XDP это ваш ответ.

DDoS// 16 мин чтения

Нас атаковали на 400 Гбит/с. Вот что реально спасло

Честный постмортем. Без героизации, без «наша команда справилась с любым вызовом». Что сломалось, что сработало случайно, что мы сделали правильно, и что изменили после.

Вторник, 14:23. Мониторинг начинает кричать. Входящий трафик на наш аплинк вырос с обычных 8 Гбит/с до 40 Гбит/с за две минуты. К 14:30 — 180 Гбит/с. В 14:41 провайдер написал что видит 400 Гбит/с и собирается заблокировать наш /24 целиком.

У нас было примерно 15 минут до полного blackhole от провайдера.

Что это было

UDP amplification через CLDAP (Connectionless LDAP, порт 389). Атакующие отправляли маленькие запросы на уязвимые LDAP-серверы по всему миру, подделывая source IP на наши адреса. Серверы отвечали пакетами в 70-80 раз больше — прямо к нам. Amplification ratio ~70x.

400
Гбит/с входящего мусора
~70x
amplification ratio CLDAP
15 мин
до blackhole от провайдера

Что не сработало

ACL на нашем оборудовании. Бессмысленно — трафик доходит до нашего железа уже насытив аплинк. 400 Гбит/с в канале 10 Гбит/с означает что 390 Гбит/с дропается провайдером, но канал всё равно полностью забит мусором.

Звонок в NOC провайдера.  Они предложили заблокировать весь /24. Это «спасение» которое убивает нас вместо атаки. Мы отказались.

Надежда что само закончится.  Это наивность. DDoS-атаки не заканчиваются сами — их либо прекращают атакующие, либо их останавливают жертвы.

Что сработало

1. RTBH с более точным prefix

Remote Triggered Blackhole — мы попросили провайдера заблокировать трафик до конкретных /32-адресов (отдельных IP внутри нашего /24), которые принимали основную нагрузку атаки. Остальной /24 продолжал работать.

BIRD2 / BGPанонс RTBH для конкретного IP
# Добавляем маршрут с community для blackhole route 203.0.113.42/32 blackhole { bgp_community.add((65535, 666)); # RFC 7999 BLACKHOLE community };

Провайдер видит этот анонс с BLACKHOLE community и начинает дропать трафик до этого IP на своём оборудовании — до того как он попадает в наш канал. Через 4 минуты 340 Гбит/с исчезло.

2. Flowspec для фильтрации по паттерну

60 Гбит/с продолжали приходить на другие IP. Мы использовали BGP Flowspec — это расширение BGP которое позволяет передавать правила фильтрации провайдеру. Правило: дропать UDP порт 389 с пакетами больше 300 байт идущими к нашим адресам.

BIRD2flowspec правило для блокировки CLDAP amplification
flow4 { dst 203.0.113.0/24; proto = 17; # UDP dport = 389; # CLDAP length >= 300; # amplified responses > 300 bytes action discard; };

Провайдер поддерживал Flowspec. Ещё 55 Гбит/с исчезло в течение 2 минут.

3. XDP на оставшемся трафике

5 Гбит/с мусора продолжали доходить — провайдер фильтровал не всё. Мы подняли XDP-программу дропающую UDP/389 паттерны прямо на входе. CPU при этом не превысил 8%.

Хронология инцидента

timeline
14:23 Начало атаки, мониторинг сработал 14:28 180 Гбит/с, аплинк начал насыщаться 14:31 400 Гбит/с, провайдер уведомил о blackhole через 15 мин 14:35 Анонс RTBH для атакуемых /32 → 340 Гбит/с исчезло 14:39 Flowspec правило → ещё 55 Гбит/с 14:42 XDP на оставшихся 5 Гбит/с 14:45 Сервис работает нормально 16:10 Атака прекратилась сама

Что мы изменили после

Самое важное — не «как мы победили», а что мы сделали чтобы следующий раз был лучше:

Главный вывод: К DDoS нужно готовиться до атаки. RTBH, Flowspec, scrubbing — всё это нужно настроить, протестировать и задокументировать заранее. Во время атаки настраивать BGP-сессию с провайдером уже поздно.
eBPF// 11 мин чтения

iptables мёртв. Вот что его убило и что пришло на замену

iptables работает на миллионах серверов прямо сейчас. Он не исчезнет завтра. Но как primary tool для нового проекта в 2026 году — это архитектурная ошибка. Разбираем почему и что использовать вместо.

iptables появился в Linux 2.4 в 2001 году. Ему 25 лет. Это не проблема — SSH тоже старый и отлично работает. Проблема в том, что iptables проектировался для другого мира: меньших скоростей, меньших таблиц, меньших требований к динамике изменений.

Что конкретно не так с iptables

Линейный поиск правил. iptables проходит правила последовательно — сверху вниз, пока не найдёт совпадение. 1000 правил означает в среднем 500 сравнений на пакет. 10 000 правил в Kubernetes — катастрофа.

Нет атомарных обновлений.  Чтобы изменить одно правило, iptables-restore выгружает всю таблицу и загружает заново. В Kubernetes при каждом изменении сервисов — это может быть тысячи правил каждые несколько секунд.

Нет observability.  Вы не можете легко узнать почему конкретный пакет был принят или отброшен. Только `iptables -L -n -v` с счётчиками — и то не всегда информативно.

11мс
время обновления 10K правил iptables
0.1мс
то же самое в nftables
~0мс
обновление BPF map в eBPF

Три претендента

nftables — эволюция, не революция

nftables — официальная замена iptables от тех же разработчиков (Netfilter project). Работает через тот же netfilter framework в ядре, но с современным синтаксисом и атомарными обновлениями.

Плюсы: нативно в любом современном Linux, поддержка sets (хэш-таблицы правил — O(1) вместо O(n)), атомарные транзакции, читаемый синтаксис.

Минусы: всё ещё работает через netfilter — пакет проходит тот же путь в ядре. Скорость ограничена архитектурой.

nftablesблокировка списка IP через set (O(1) lookup)
table inet filter { set blocklist { type ipv4_addr flags interval elements = { 1.2.3.0/24, 5.6.7.8 } } chain input { type filter hook input priority 0; # lookup в set — O(1), не O(n) ip saddr @blocklist drop accept } }

eBPF / XDP — радикальный подход

Вместо работы внутри netfilter — работа до него. XDP перехватывает пакет сразу после NIC, до любого ядерного стека. Максимальная скорость, минимальный overhead.

Когда использовать: высокая нагрузка, DDoS mitigation, кастомная логика, нужна максимальная производительность. Когда не использовать: нужен statefull NAT, сложная логика, небольшой трафик (iptables достаточно).

Cilium — eBPF для Kubernetes

Если вы в Kubernetes — Cilium это отдельная история. Он полностью заменяет kube-proxy (который использует iptables) на eBPF-реализацию. Результат:

Что использовать в 2026 году

Простое правило:

iptables не мёртв в смысле «перестал работать». Он мёртв в смысле «не получает новых фич и не подходит для современных нагрузок». Как IE6 — работает, но строить на нём не стоит.
Сети// 13 мин чтения

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

Вы нажали Enter. Браузер отправил запрос. Через 50 миллисекунд сервер начал отвечать. Что произошло за эти 50мс? Пройдём весь путь — от электрона в вашем кабеле до TCP-сессии на сервере.

50 миллисекунд — это мало. За это время звук проходит около 17 метров. Процессор делает 150 миллионов операций. А ваш пакет успевает облететь полмира и вернуться.

Проследим за одним TCP SYN-пакетом от вашего браузера до сервера в другом городе.

Шаг 1: браузер принимает решение (0–0.1мс)

Браузер знает доменное имя, но не IP. Сначала — DNS. Проверяем кэш браузера → кэш ОС → запрос к DNS resolver провайдера. Если домен уже в кэше — мгновенно. Если нет — ещё один round-trip к DNS-серверу.

Предположим IP уже известен. Браузер создаёт TCP SYN: пакет с флагом SYN, случайным sequence number, параметрами окна. Передаёт в сетевой стек ОС.

Шаг 2: сетевой стек ОС (0.1–0.3мс)

ОС смотрит в таблицу маршрутизации: куда отправить этот пакет? Если адрес в другой подсети — к шлюзу (default gateway). ОС проверяет ARP-кэш для MAC-адреса шлюза. Если нет — ARP запрос, ещё задержка.

Пакет получает Ethernet-заголовок с MAC-адресами источника и назначения. Передаётся в очередь сетевой карты.

Шаг 3: физика (0.3–1мс)

NIC берёт пакет из очереди, преобразует в электрические сигналы (медь) или световые импульсы (оптика). Скорость распространения сигнала в оптоволокне — около 200 000 км/с (⅔ скорости света).

Расстояние 1000 км по оптике — минимум 5мс только на физическую передачу. Плюс задержки на промежуточном оборудовании.

Шаг 4: маршрутизаторы провайдера (1–20мс)

Пакет попадает на первый маршрутизатор вашего провайдера. Роутер смотрит в FIB (Forwarding Information Base) — таблицу которая говорит в какой порт отправить пакет для данного destination IP. Это происходит в специализированном чипе (ASIC) за наносекунды.

tracerouteреальный путь пакета с задержками
1 192.168.1.1 0.4ms ← ваш домашний роутер 2 100.64.0.1 2.1ms ← CGNAT провайдера 3 msk-agg-1.provider.ru 4.8ms ← агрегация в городе 4 msk-core.provider.ru 6.2ms ← городской core 5 spb-transit.tier1.net 18.4ms ← транзитный провайдер 6 spb-target-server.ru 24.1ms ← сервер назначения

Шаг 5: BGP решает маршрут (фоново)

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

Шаг 6: сервер получает пакет (20–25мс)

NIC сервера получает пакет, делает DMA в память. Прерывание ядра. Сетевой стек обрабатывает Ethernet → IP → TCP заголовки. Видит SYN — создаёт половинчатое соединение, отправляет SYN-ACK обратно.

SYN-ACK проходит тот же путь обратно. Ещё ~25мс.

Итого: TCP handshake = 1 RTT ≈ 50мс

~0.3мс
ОС + NIC
~15мс
физика + роутеры
~2мс
обработка на сервере
~25мс
RTT x2 (туда-обратно)

И только после трёхстороннего handshake (SYN → SYN-ACK → ACK) браузер может отправить HTTP-запрос. Это одна из причин почему QUIC (UDP-based протокол HTTP/3) так важен: 0-RTT или 1-RTT вместо 1.5-RTT у TCP+TLS.

Что можно оптимизировать

Физика — не оптимизируется. Скорость света постоянна. Но остальное — можно:

BGP// 7 мин чтения

Как я объясняю BGP своей маме — и почему это помогает на собесах

Если вы не можете объяснить концепцию простыми словами — вы её не поняли. Аналогия которая работает для BGP, plus бонус: как это применять на технических интервью.

Мама спросила чем я занимаюсь. Я сказал «настраиваю BGP». Она кивнула с видом человека который ничего не понял но не хочет расстраивать. Я решил попробовать иначе.

Аналогия: почтовые отделения и курьерские компании

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

Автономная система (AS) — это одна курьерская компания со своим городом (набором IP-адресов).

Чтобы доставить посылку в незнакомый город, твоя компания спрашивает соседей: «Вы знаете как добраться до города X?» Сосед говорит: «Да, через меня — я знаю путь». Сосед спрашивает своих соседей. Так информация о маршрутах распространяется по всей сети компаний.

BGP — это язык на котором курьерские компании говорят друг другу «через меня можно доставить в такие-то города».

Мама сказала: «А, как навигатор но для посылок». Близко. Очень близко.

Почему маршрут не всегда самый короткий

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

По умолчанию вы будете отправлять посылки через старого партнёра — не потому что он быстрее, а потому что вы ему доверяете и у вас хороший договор. Это local preference в BGP.

Посылка может ехать дольше. Но компания выбрала этот маршрут по своим бизнес-соображениям. BGP — про бизнес, не про физику.

Что BGP защищает и почему его легко сломать

BGP основан на доверии: если сосед говорит «через меня можно доставить в город X» — вы верите. Нет встроенной проверки что это правда.

Именно поэтому route leaks и BGP hijacking так опасны: кто-то говорит «через меня быстрее до всего интернета» — и часть интернета начинает посылать трафик через него. Случайно или намеренно.

«Как мошенники которые говорят что они почта», — сказала мама. Именно.

Как это помогает на собесах

На технических интервью часто спрашивают объяснить сложную концепцию. Проблема не в том что кандидат не знает — проблема в том что он говорит на языке документации RFC вместо языка понятных моделей.

Простое правило: сначала аналогия, потом технические детали. «BGP — это как курьерские компании которые договариваются о маршрутах. Технически это EGP протокол работающий поверх TCP, использующий path vector для предотвращения петель...»

Интервьюер видит: человек понимает суть, а не просто выучил термины. Это редкость.

Упражнение

Попробуйте объяснить эти концепции человеку без технического образования:

Если объяснение занимает больше трёх предложений — вы ещё не нашли правильную аналогию. Продолжайте искать.

Мама теперь рассказывает друзьям что её сын «настраивает маршруты для интернет-посылок». Я считаю это успехом.

Производительность// 15 мин чтения

Почему ваш nginx отдаёт 10к RPS, а у соседа 100к на том же железе

Linux не настроен для высокой сетевой нагрузки по умолчанию. Дефолтные значения — это разумные значения для среднего сервера 2005 года. Вот 7 параметров которые меняют всё.

Нам позвонил клиент: «У нас сервер 32 ядра, 128GB RAM, 10GbE — и nginx упирается в 12 000 RPS». Я попросил прислать вывод `ss -s` и `sysctl -a | grep net`. Диагноз был поставлен за три минуты.

Проблема не в nginx. Проблема в ядре Linux.

Базовое понимание: где теряется производительность

Сетевой трафик в Linux проходит через несколько очередей и буферов. Каждый из них имеет размер. Когда размер недостаточен — пакеты дропаются или блокируются. CPU тратит время на управление переполненными очередями вместо обработки данных.

7 параметров которые нужно изменить

1. TCP буферы приёма и передачи

sysctlбыло → стало
# По умолчанию: 87380 байт (~85KB) — это 1995 год net.core.rmem_default = 87380 net.core.wmem_default = 87380 # Ставим: 128MB максимум, ядро выберет нужное net.core.rmem_max = 134217728 net.core.wmem_max = 134217728 net.ipv4.tcp_rmem = 4096 87380 134217728 net.ipv4.tcp_wmem = 4096 65536 134217728

Маленький буфер = TCP окно не может вырасти = низкий throughput на линках с задержкой. На WAN-соединениях это критично.

2. Очередь входящих соединений

sysctl
# Размер очереди завершённых соединений (accept queue) net.core.somaxconn = 65535 # дефолт: 128 (!) # Очередь SYN (половинчатые соединения) net.ipv4.tcp_max_syn_backlog = 65535 # дефолт: 256 # Также в nginx.conf: # listen 80 backlog=65535;

Дефолтный somaxconn = 128. При 10 000 RPS даже кратковременный spike может переполнить очередь. Соединения начинают дропаться с ECONNREFUSED. nginx пишет ошибки, клиенты видят 502.

3. TIME_WAIT и переиспользование портов

sysctl
# Разрешаем переиспользовать TIME_WAIT сокеты net.ipv4.tcp_tw_reuse = 1 # Максимум TIME_WAIT сокетов (дефолт: 262144) net.ipv4.tcp_max_tw_buckets = 1440000 # Диапазон локальных портов net.ipv4.ip_local_port_range = 1024 65535 # дефолт: 32768 60999

При высоком RPS быстро заканчиваются ephemeral порты и накапливаются TIME_WAIT соединения. Симптом: `ss -s` показывает тысячи TIME-WAIT, новые соединения начинают фейлиться.

4. Размер очереди NIC

bashethtool — увеличиваем ring buffer NIC
# Смотрим текущие значения ethtool -g eth0 # Увеличиваем ethtool -G eth0 rx 4096 tx 4096 # Также очередь в ядре ip link set eth0 txqueuelen 10000 net.core.netdev_max_backlog = 250000

5. Congestion control — BBR вместо CUBIC

sysctlBBR даёт лучший throughput при потерях
net.core.default_qdisc = fq net.ipv4.tcp_congestion_control = bbr # Проверить что включилось sysctl net.ipv4.tcp_congestion_control # → net.ipv4.tcp_congestion_control = bbr

6. Numa awareness и CPU affinity

На многосокетных серверах NIC часто подключена к одному NUMA-узлу. Если прерывания обрабатываются CPU с другого узла — каждый доступ к памяти пакета стоит дорого (cross-NUMA latency ~100нс против ~10нс локально).

bashпривязываем IRQ к нужным CPU
# Смотрим какой NUMA-узел у NIC cat /sys/class/net/eth0/device/numa_node # Привязываем IRQ сетевой карты к CPU того же узла # (используйте set_irq_affinity.sh из пакета irqbalance) service irqbalance stop ./set_irq_affinity.sh eth0

7. Всё вместе — финальный sysctl.conf

/etc/sysctl.d/99-network-performance.conf
net.core.rmem_max = 134217728 net.core.wmem_max = 134217728 net.ipv4.tcp_rmem = 4096 87380 134217728 net.ipv4.tcp_wmem = 4096 65536 134217728 net.core.somaxconn = 65535 net.ipv4.tcp_max_syn_backlog = 65535 net.ipv4.tcp_tw_reuse = 1 net.ipv4.ip_local_port_range = 1024 65535 net.core.netdev_max_backlog = 250000 net.core.default_qdisc = fq net.ipv4.tcp_congestion_control = bbr net.ipv4.tcp_slow_start_after_idle = 0 net.ipv4.tcp_no_metrics_save = 1

Результат для того клиента

12K
RPS до изменений
94K
RPS после (то же железо)
0
изменений в nginx.conf
Важно: После изменения sysctl всегда нагрузочно тестируйте. Некоторые параметры (особенно буферы) увеличивают потребление памяти. Убедитесь что при пиковой нагрузке OOM-killer не активируется.
Ресурсы// 6 мин чтения

Что читает CTO по сетям: 10 источников которые реально двигают мышление

Не курсы Udemy. Не YouTube-туториалы. То что читают люди, которые строят сети на миллионы пользователей — и откуда они узнают об этом первыми.

Меня часто спрашивают: откуда брать информацию о сетях, если хочется расти быстрее? Не основы (для этого есть книги), а то что происходит прямо сейчас на переднем крае.

Вот что я читаю каждую неделю.

Технические блоги компаний

Cloudflare Blog (blog.cloudflare.com) — лучший технический блог в индустрии по сетям. Они публикуют детальные разборы своей инфраструктуры: как работает их anycast, как они обрабатывают DDoS, как реализован их Workers runtime. Каждая статья — это заглянуть внутрь системы которая обрабатывает 20% интернет-трафика.

Meta Engineering Blog — разборы инфраструктуры масштаба которого нет нигде ещё. Статьи про Katran (L4 балансировщик на eBPF), про их BGP-архитектуру, про инцидент 2021 года когда весь Facebook пропал из интернета — это обязательное чтение.

Netflix Tech Blog — особенно всё что связано с CDN и оптимизацией TCP. Их статьи про BBR congestion control и про то как они работают с ISP изменили мой взгляд на управление трафиком.

Академические источники которые читаются как детективы

NANOG (nanog.org) — North American Network Operators Group. Архив презентаций с их конференций — это золото. Здесь операторы крупнейших сетей мира делятся реальными проблемами и решениями. Не теория — живая практика.

RIPE Labs (labs.ripe.net) — исследования о состоянии глобальной маршрутизации, BGP-аномалиях, IPv6 adoption. Если хотите понять как работает интернет на макро-уровне — здесь.

Люди которых стоит читать

Julia Evans (jvns.ca) — объясняет сложные концепции ядра Linux с редкой ясностью. Её посты про strace, tcpdump и сетевой стек — образец того как надо писать технически.

Jessie Frazelle — containers, kernel, networking. Глубокие технические посты от человека который работал в Docker, Microsoft и других местах где сеть — это не абстракция.

RFC которые стоит прочитать

Большинство RFC написаны сухо и для специалистов. Но несколько — настоящее удовольствие и фундамент понимания:

Инструменты для понимания глобальной сети

BGPlay (bgplay.massimocandela.com) — визуализация BGP-событий в реальном времени. Запустите во время любого крупного инцидента — видно как маршруты появляются и пропадают.

RIPE RIS Live — стрим BGP-обновлений со всего мира в реальном времени. Когда кто-то делает route leak — видно буквально за секунды.

Одна книга которую нужно прочитать

«TCP/IP Illustrated, Vol. 1», W. Richard Stevens. Написана в 1994 году. Устарела в деталях, но не устарела в понимании. Если вы читали её давно — перечитайте. Если не читали — это пробел.

Мой режим чтения: Cloudflare Blog и NANOG — каждую неделю. Meta и Netflix — раз в месяц просматриваю новое. RFC — когда встречаю незнакомый протокол или нужно разобраться в деталях. BGPlay держу открытым во время любых крупных BGP-инцидентов.

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

И ещё: лучший способ усвоить прочитанное — написать о нём своими словами. Именно этим я и занимаюсь здесь.