VoIP через VPN: припиніть роботизований звук — MTU, джиттер і основи QoS

Було корисно?

Ви знаєте цей звук. Дзвінок починається нормально, а потім хтось наче факс, що проходить відбір на роль робота в кіно.
Усі звинувачують «VPN», потім провайдера, потім софтфон, потім фазу Місяця. Насправді справжній винуватець зазвичай прозаїчний:
невідповідність MTU/MSS, джиттер через bufferbloat або QoS, який не переживає подорож через тунель.

Я керую продукційними мережами, де голос — це просто ще навантаження, поки раптом ним не стане. Голос карає за ліниві припущення.
Йому байдуже, що тест пропускної здатності виглядає чудово; важливіше, щоб невеликі пакети приходили вчасно, послідовно, з мінімальними втратами і перестановками.

Модель мислення, яка реально передбачає відмови

Якщо запам’ятати одне: голос — це потік реального часу на мережі з best-effort. VPN додає заголовки, приховує внутрішні DSCP-маркування, якщо ви навмисно не зберігаєте їх, і може змінювати ритміку пакетів.
Звичні режими відмов не містять містики. Це фізика й черги.

Що зазвичай означає «роботизований звук»

«Робот» рідко є проблемою кодека. Це в дії втрати пакетів і маскування.
RTP-аудіо приходить маленькими пакетами (часто по 20 мс аудіо в пакеті). Втратите кілька, джиттер підстрибує, jitter buffer розтягується, декодер домислює, і ви чуєте робота.
Голос може пережити деякі втрати; просто він не приховує це чемно.

Стек VoIP поверх VPN в одній концепції

Уявіть пакет як набір вкладених конвертів:

  • Внутрішній: SIP сигналізація + RTP медіа (зазвичай UDP) з DSCP-маркуванням, яке ви хочете зберегти
  • Потім: ваша VPN-обгортка (WireGuard/IPsec/OpenVPN) додає оверхед і може змінити MTU
  • Зовнішній: черги ISP та інтернету (де живе bufferbloat) і де QoS може працювати або ігноруватися
  • Кінці: софтфон або IP-телефон, та PBX/ITSP

Поломка зазвичай відбувається в одному з трьох місць:
(1) розмір (MTU/фрагментація),
(2) час (джиттер/черги),
(3) пріоритет (QoS/DSCP і шейпінг).

Перефразовуючи W. Edwards Deming: «Без даних ви — просто ще одна людина з думкою.» Ставтеся до проблем голосу як до інцидентів: вимірюйте, ізолюйте, змінюйте одну змінну, знову вимірюйте.

Швидкий план діагностики

Коли CEO каже «дзвінки не працюють», не починайте з дебатів про кодеки. Почніть з звуження охоплення проблеми та локалізації черги.
Ось порядок, який швидко знаходить корені.

Спочатку: підтвердіть, чи це втрата, джиттер чи MTU

  1. Перевірте статистику RTP у клієнті/PBX: відсоток втрат, джиттер, пізні пакети. Якщо цього немає, захопіть пакети і обчисліть (пізніше).
    Якщо ви бачите навіть 1–2% втрат під час «робота», розглядайте це як мережеву проблему, поки не доведено протилежне.
  2. Швидко виконайте тест PMTUD через VPN. Якщо PMTUD зламаний, великі пакети можуть глушитися, особливо на UDP-основних VPN.
  3. Перевірте затримку в чергах під навантаженням на найвужчому аплінку (зазвичай це завантаження користувача). Bufferbloat — тихий вбивця голосу.

По-друге: ізолюйте місце поломки

  1. Обійдіть VPN для одного тестового дзвінка (split tunnel або тимчасова політика). Якщо голос значно покращується, зосередьтеся на накладних витратах тунелю, MTU та обробці QoS на краях тунелю.
  2. Порівняйте провідне підключення та Wi‑Fi. Якщо Wi‑Fi гірший, ви в зоні конкуренції ефірного часу та повторних передач. Виправляйте це окремо.
  3. Тестуйте з відомо-робочої мережі (лабораторний канал, інший ISP або VM у хмарі з софтфоном). Якщо там чисто, проблема на краю користувача.

По-третє: застосуйте «нудні виправлення»

  • Встановіть MTU інтерфейсу VPN явно і обмежте TCP MSS там, де це релевантно.
  • Застосуйте smart queue management (fq_codel/cake) там, де реальний вузький місце, і трохи шейпте під лінійну швидкість.
  • Відмітьте голосовий трафік і пріоритезуйте його де ви контролюєте чергу (зазвичай WAN-край), а не лише в мріях.

Жарт №1: VPN — як валіза: якщо в неї продовжувати пхати додаткові заголовки, зрештою блискавка (MTU) здасться в найгірший момент.

MTU, MSS і фрагментація: чому «роботизований» часто означає «дрібні втрати»

Проблеми з MTU не завжди виглядають як «не можу підключитися». Вони можуть виглядати як «підключається, але іноді звучить як примара».
Це тому, що сигналізація може виживати, тоді як деякі медіа-пакети або re-INVITE-и втрачаються, або фрагментація підвищує чутливість до втрат.

Що змінюється при додаванні VPN

Кожний тунель додає оверхед:

  • WireGuard додає зовнішній UDP/IP-заголовок плюс власний оверхед.
  • IPsec додає ESP/AH оверхед (плюс можливу UDP-інкапсуляцію для NAT‑T).
  • OpenVPN додає оверхед в простір користувача і може додавати кадрування в залежності від режиму.

Внутрішній пакет, який нормально поміщався при MTU 1500, може вже не проходити. Якщо шлях не підтримує фрагментацію так, як ви вважаєте, щось відкидається.
А UDP не відправляє повторно; він просто підводить вас у реальному часі.

Path MTU discovery (PMTUD) і як воно ламається

PMTUD покладається на ICMP «Fragmentation Needed» (для IPv4) або Packet Too Big (для IPv6). Багато мереж блокують або лімітують ICMP.
Результат: ви надсилаєте пакети, що надто великі, роутери їх відкидають, а відправник не дізнається. Це називається «PMTUD black hole».

Чому RTP зазвичай не «занадто великий» — але все одно страждає

RTP-голосові пакети зазвичай маленькі: від декількох десятків до кількох сотень байт корисного навантаження, плюс заголовки. Чому ж тоді MTU впливає на дзвінки?

  • Сигналізація і зміни сесії (SIP INVITE/200 OK з SDP, TLS записи) можуть ставати великими.
  • Інкапсуляція VPN може фрагментувати навіть помірні пакети, підвищуючи ймовірність втрат.
  • Джиттер-піки виникають, коли фрагментація і збирання взаємодіють із перевантаженими чергами.
  • Деякі софтфони групують або відправляють більші UDP-пакети за певних налаштувань (comfort noise, SRTP або незвичний ptime).

Практичні рекомендації

  • Для WireGuard почніть з MTU 1420, якщо не впевнені. Це не магія; це консервативне значення, що уникає поширених проблем з оверхедом.
  • Для OpenVPN будьте явними з MTU тунелю і клацанням MSS для TCP-потоків, що йдуть через тунель.
  • Не «знижуйте MTU скрізь» без розбору. Ви можете виправити один шлях і нашкодити іншому. Вимірюйте, а потім встановлюйте.

Джиттер, bufferbloat і чому speed test обманює

Ви можете мати 500 Mbps в завантаженні і при цьому звучати так, ніби дзвоните з підводного човна. Голос потребує низької варіації затримки, а не рекордів пропускної здатності.
Найбільший практичний ворог — bufferbloat: надмірні черги в роутерах/модемах, що наростають під навантаженням і додають сотні мілісекунд затримки.

Джиттер vs затримка vs втрата пакетів

  • Затримка: скільки часу пакет йде від кінця до кінця.
  • Джиттер: наскільки ця затримка змінюється пакет за пакетом.
  • Втрата: пакети, що ніколи не приходять (або приходять занадто пізно, щоб мати значення).

Кодеки голосу використовують jitter buffers. Ці буфери можуть згладжувати варіації до певного рівня, але ціною збільшення затримки.
Коли джиттер стає жахливим, буфери або ростуть (збільшуючи затримку), або відкидають запізнілі пакети (збільшуючи втрати). В обох випадках: роботизований звук.

Де народжується джиттер

Більшість джиттера в інцидентах VoIP-over-VPN — не «інтернет», а черга на краю:

  • домашній роутер користувача з глибокою upstream-чергою
  • офісний фаєрвол гілки, що робить інспекцію і буферизацію
  • насичення CPU VPN-концентратора, що спричиняє затримки планування пакетів
  • конкуренція Wi‑Fi/повторні передачі (виглядає як джиттер і втрата)

Менеджмент черг, який реально працює

Якщо ви контролюєте вузьке місце, ви можете виправити голос.
Smart queue management (SQM) алгоритми як fq_codel та cake активно заважають чергам рости без меж і утримують стабільну затримку під навантаженням.

Хитрість: потрібно шейпити трохи нижче фактичної пропускної здатності лінії, щоб ваше пристрій, а не модем провайдера, стало вузьким місцем і цим контролювало чергу.
Якщо цього не зробити, ви чемно просите модем поводитися. Він не стане.

Жарт №2: Bufferbloat — це коли ваш роутер збирає пакети, ніби вони колекційні антикварні речі.

Основи QoS/DSCP для голосу через VPN (і що часто зривається)

QoS — не магічна галочка «зроби все гарним». Це спосіб вирішити, що постраждає першим, коли лінк завантажений.
Ось і все. Якщо немає перевантаження, QoS нічого не змінює.

DSCP і міф про «end-to-end QoS»

Голос часто маркує RTP як DSCP EF (Expedited Forwarding), а SIP як CS3/AF31 залежно від політики.
Всередині LAN це може допомогти. Через інтернет більшість провайдерів ігнорують це. Через VPN маркування може навіть не зберегтися після інкапсуляції.

Що ви можете контролювати

  • Край LAN: пріоритезуйте голос від телефонів/софтфонів до вашого VPN-шлюзу.
  • WAN-egress VPN-шлюзу: шейпте і пріоритезуйте зовнішні пакети, що відповідають голосовим потокам.
  • Гілка/край користувача: якщо ви ним керуєте, розгорніть SQM і маркуйте голос локально.

VPN-специфіка: внутрішні vs зовнішні маркування

Багато імплементацій тунелів інкапсулюють внутрішні пакети у зовнішні. Зовнішній пакет пересилається провайдером.
Якщо зовнішній пакет не маркований (або маркування знімається), ваше внутрішнє «EF» — лише декоративний напис.

Практичний підхід:

  • Класифікуйте голос до шифрування коли можливо, а потім застосуйте пріоритет до зашифрованого потоку (зовнішній заголовок) на egress.
  • Зберігайте DSCP через тунель, якщо ваше обладнання і політика це підтримують.
  • Не покладайтеся на Wi‑Fi WMM, якщо ваша uplink-черга плавиться.

Обережність з QoS: можна зробити гірше

Погана політика QoS може позбавити трафіку керування або створити мікросплески і перестановки. Голос любить пріоритет, але також любить стабільність.
Тримайте класи простими: голос, інтерактив, об’ємний. Потім шейпте.

Практичні завдання: команди, виводи і рішення

Це завдання «запустіть зараз». Кожне містить команду, що каже вивід, і яке рішення ухвалити.
Використовуйте їх на Linux-ендпойнтах, VPN-шлюзах або хостах для трасування. Налаштуйте імена інтерфейсів і IP під своє оточення.

Завдання 1: Підтвердіть MTU інтерфейсу тунелю VPN

cr0x@server:~$ ip link show dev wg0
4: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/none

Значення: MTU інтерфейсу wg0 — 1420. Добра консервативна відправна точка для WireGuard.
Рішення: Якщо MTU на тунелі 1500, вважайте це потенційною проблемою, якщо ви не довели, що шлях це підтримує. Якщо роботизований звук корелює з певними шляхами, тестуйте нижчий MTU.

Завдання 2: Виміряйте path MTU за допомогою ping з «do not fragment» (IPv4)

cr0x@server:~$ ping -M do -s 1372 -c 3 10.20.30.40
PING 10.20.30.40 (10.20.30.40) 1372(1400) bytes of data.
1380 bytes from 10.20.30.40: icmp_seq=1 ttl=63 time=18.4 ms
1380 bytes from 10.20.30.40: icmp_seq=2 ttl=63 time=18.7 ms
1380 bytes from 10.20.30.40: icmp_seq=3 ttl=63 time=18.2 ms

--- 10.20.30.40 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2004ms

Значення: 1400-байтовий пакет (включно з заголовками) проходить без фрагментації.
Рішення: Збільшуйте -s поки не впаде, щоб знайти максимум. Встановіть MTU тунелю безпечно нижче від знайденого мінус оверхед інкапсуляції.

Завдання 3: Спостерігайте симптоми PMTUD-відмови (IPv4)

cr0x@server:~$ ping -M do -s 1472 -c 2 10.20.30.40
PING 10.20.30.40 (10.20.30.40) 1472(1500) bytes of data.
ping: local error: message too long, mtu=1420
ping: local error: message too long, mtu=1420

--- 10.20.30.40 ping statistics ---
2 packets transmitted, 0 received, +2 errors, 100% packet loss, time 1013ms

Значення: Локальний MTU інтерфейсу — 1420; ядро відмовляється відправляти більші пакети з DF-встановленим.
Рішення: Якщо додатки все одно відправляють більші пакети (UDP-інкапсуляція VPN може), обмежте або налаштуйте MTU/MSS так, щоб вони не робили цього.

Завдання 4: Перевірте правила TCP MSS clamping (iptables)

cr0x@server:~$ sudo iptables -t mangle -S | grep -i mss
-A FORWARD -o wg0 -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

Значення: TCP SYN-пакети мають MSS, підкоригований за PMTU.
Рішення: Якщо ви прямуєте SIP через TCP/TLS через VPN і бачите застої або повторні передачі, увімкніть це. Це не виправить RTP (UDP), але стабілізує сигналізацію.

Завдання 5: Перевірте DSCP-маркування на вихідних пакетах

cr0x@server:~$ sudo tcpdump -ni eth0 -vv udp and portrange 10000-20000 -c 5
tcpdump: listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
12:10:41.112233 IP (tos 0xb8, ttl 63, id 44211, offset 0, flags [DF], proto UDP (17), length 214) 192.0.2.10.14562 > 198.51.100.20.10012: UDP, length 186
12:10:41.132244 IP (tos 0xb8, ttl 63, id 44212, offset 0, flags [DF], proto UDP (17), length 214) 192.0.2.10.14562 > 198.51.100.20.10012: UDP, length 186

Значення: TOS 0xb8 відповідає DSCP EF (46). Ваш хост маркує RTP.
Рішення: Далі перевірте, чи маркування переживає інкапсуляцію і чи ваша WAN-черга його враховує. Якщо воно зникає на зовнішньому пакеті, вам потрібен QoS на egress тунелю, а не надії та мрії.

Завдання 6: Підтвердіть DSCP на зовнішньому пакеті VPN

cr0x@server:~$ sudo tcpdump -ni eth0 -vv udp port 51820 -c 5
tcpdump: listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
12:12:03.220011 IP (tos 0x00, ttl 64, id 12001, offset 0, flags [DF], proto UDP (17), length 208) 203.0.113.5.51820 > 203.0.113.9.51820: UDP, length 180
12:12:03.240022 IP (tos 0x00, ttl 64, id 12002, offset 0, flags [DF], proto UDP (17), length 208) 203.0.113.5.51820 > 203.0.113.9.51820: UDP, length 180

Значення: Зовнішні пакети немарковані (tos 0x00). Навіть якщо внутрішній RTP — EF, провайдер бачить тільки зовнішній.
Рішення: Застосуйте класифікацію на VPN-шлюзі: ідентифікуйте голосові потоки до шифрування (або за портом/параметрами peer) і встановіть DSCP/пріоритет на egress.

Завдання 7: Визначте реальне вузьке місце і поточний qdisc

cr0x@server:~$ tc qdisc show dev eth0
qdisc fq_codel 0: root refcnt 2 limit 10240p flows 1024 quantum 1514 target 5.0ms interval 100.0ms memory_limit 32Mb ecn

Значення: fq_codel активний. Це пристойна відправна точка для низької затримки під навантаженням.
Рішення: Якщо ви бачите pfifo_fast або глибокий вендорський qdisc на WAN-краю, плануйте розгорнути шейпінг + fq_codel/cake там, де відбувається перевантаження.

Завдання 8: Перевірте статистику qdisc на наявність drop/overlimits (проблеми шейпінга)

cr0x@server:~$ tc -s qdisc show dev eth0
qdisc fq_codel 0: root refcnt 2 limit 10240p flows 1024 quantum 1514 target 5.0ms interval 100.0ms memory_limit 32Mb ecn
 Sent 98234123 bytes 84521 pkt (dropped 213, overlimits 0 requeues 12)
 backlog 0b 0p requeues 12
  maxpacket 1514 drop_overlimit 213 new_flow_count 541 ecn_mark 0

Значення: Сталися деякі дропи. Дропи не завжди погані — контрольовані дропи можуть запобігти величезній затримці. Але дропи + роботизований звук вказують, що ви втрачаєте RTP, а не bulk-трафік.
Рішення: Додайте класифікацію, щоб голос отримував пріоритет (або принаймні ізоляцію), і переконайтеся, що швидкість шейпінга відповідає реальному аплінку.

Завдання 9: Швидка перевірка джиттера і втрат з mtr (базовий рівень)

cr0x@server:~$ mtr -rwzc 50 203.0.113.9
Start: 2025-12-28T12:20:00+0000
HOST: server                          Loss%   Snt   Last   Avg  Best  Wrst StDev
  1. 192.0.2.1                         0.0%    50    1.1   1.3   0.9   3.8   0.6
  2. 198.51.100.1                      0.0%    50    8.2   8.5   7.9  13.4   1.1
  3. 203.0.113.9                       0.0%    50   19.0  19.2  18.6  26.8   1.4

Значення: Немає втрат, стабільна затримка, низький джиттер (StDev). Добрий базовий рівень.
Рішення: Якщо ви бачите втрати на хопі 1 під навантаженням, це ваш LAN/Wi‑Fi/роутер. Якщо втрати починаються пізніше, це апстрім — але все ще може бути виправлено шейпінгом на вашому краї.

Завдання 10: Подивіться, чи CPU VPN-шлюзу спричиняє затримки планування пакетів

cr0x@server:~$ mpstat -P ALL 1 5
Linux 6.5.0 (vpn-gw) 	12/28/2025 	_x86_64_	(8 CPU)

12:21:01     CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
12:21:02     all   18.20    0.00   22.40    0.10    0.00   21.70    0.00    0.00    0.00   37.60
12:21:02       0   20.00    0.00   28.00    0.00    0.00   30.00    0.00    0.00    0.00   22.00

Значення: Високий softirq може вказувати на інтенсивну обробку пакетів (шифрування, форвард).
Рішення: Якщо softirq завантажено під час проблем з дзвінками, розгляньте multiqueue, перехід на швидший крипто-стек, додавання CPU-голівки або зменшення оверхеду VPN (MTU і offloads).

Завдання 11: Перевірте NIC offloads (можуть псувати захоплення, іноді — таймінг)

cr0x@server:~$ sudo ethtool -k eth0 | egrep 'tso|gso|gro'
tcp-segmentation-offload: on
generic-segmentation-offload: on
generic-receive-offload: on

Значення: Offloads увімкнені. Зазвичай це нормально, але може сплутати захоплення пакетів і в деяких краях взаємодіяти з тунелями.
Рішення: Для точної діагностики тимчасово вимкніть GRO/LRO на тестовому хості, потім повторіть тест. Не відключайте offloads на навантажених шлюзах без плану.

Завдання 12: Перевірте помилки прийому UDP і дропи

cr0x@server:~$ netstat -su
Udp:
    128934 packets received
    12 packets to unknown port received
    0 packet receive errors
    4311 packets sent
UdpLite:
IpExt:
    InOctets: 221009331
    OutOctets: 198887112

Значення: Помилок прийому UDP немає. Добре.
Рішення: Якщо під час дзвінків кількість помилок зростає, можливо, ви досягаєте меж сокетних буферів або ядро відкидає; налаштуйте буфери, вирішіть насичення CPU або зменшіть конкуренцію трафіку.

Завдання 13: Підтвердіть частоту SIP/RTP пакетів під час дзвінка (саніті-чек)

cr0x@server:~$ sudo tcpdump -ni any udp portrange 10000-20000 -ttt -c 10
tcpdump: listening on any, link-type LINUX_SLL2, snapshot length 262144 bytes
 0.000000 IP 192.0.2.10.14562 > 198.51.100.20.10012: UDP, length 186
 0.019884 IP 192.0.2.10.14562 > 198.51.100.20.10012: UDP, length 186
 0.020042 IP 192.0.2.10.14562 > 198.51.100.20.10012: UDP, length 186
 0.019901 IP 192.0.2.10.14562 > 198.51.100.20.10012: UDP, length 186

Значення: Інтер-пакетні інтервали близько 20 ms вказують на ptime=20ms (поширено). Великі паузи свідчать про джиттер або затримки планування.
Рішення: Якщо таймінг нерегулярний біля точки захоплення, перевіряйте CPU/ Wi‑Fi відправника. Якщо він регулярний на відправнику, але нерегулярний на приймачі, проблема в мережі/чергах.

Завдання 14: Визначте, чи йде трафік через VPN чи обходить його

cr0x@server:~$ ip route get 198.51.100.20
198.51.100.20 via 10.10.0.1 dev wg0 src 10.10.0.2 uid 1000
    cache

Значення: Маршрут до кінцевої точки медіа проходить через wg0.
Рішення: Якщо ваш тест «обійти VPN» все одно йде через wg0, ви нічого не обійшли. Виправте політику маршрутизації/split tunnel, потім порівняйте якість дзвінків.

Завдання 15: Підтвердіть MTU на фізичному WAN-інтерфейсі (і помітте невідповідність jumbo)

cr0x@server:~$ ip link show dev eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    link/ether 52:54:00:12:34:56 brd ff:ff:ff:ff:ff:ff

Значення: WAN-інтерфейс стандартно має MTU 1500.
Рішення: Якщо ви на PPPoE або певних cellular-лінках, WAN MTU може бути меншим (1492, 1428 тощо). Це штовхає до зниження MTU тунелю.

Завдання 16: Виявіть bufferbloat під навантаженням простим ping під час насичення uplink

cr0x@server:~$ ping -i 0.2 -c 20 1.1.1.1
PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
64 bytes from 1.1.1.1: icmp_seq=1 ttl=57 time=18.9 ms
64 bytes from 1.1.1.1: icmp_seq=2 ttl=57 time=210.4 ms
64 bytes from 1.1.1.1: icmp_seq=3 ttl=57 time=245.7 ms
64 bytes from 1.1.1.1: icmp_seq=4 ttl=57 time=198.1 ms

--- 1.1.1.1 ping statistics ---
20 packets transmitted, 20 received, 0% packet loss, time 3812ms
rtt min/avg/max/mdev = 18.4/156.2/265.1/72.9 ms

Значення: Затримка різко зростає під навантаженням: класичний bufferbloat.
Рішення: Розгорніть SQM шейпінг на uplink і пріоритезуйте голос; не марнуйте час на гоніння за кодеками.

Три корпоративні міні-історії з передової

Інцидент №1: Неправильне припущення (MTU «не може бути, у нас 1500 скрізь»)

Середня компанія перевела контакт-центр на софтфони через full-tunnel VPN. У пілоті все працювало. Потім розгорнули кілька сотень віддалених агентів.
Через день черга helpdesk стала другим контакт-центром — але з гіршою якістю голосу.

Перше припущення мережевої команди було класичним: «MTU не може бути, Ethernet 1500, VPN налаштований чисто».
Вони зосередилися на SIP-провайдері, потім звинувачували домашній Wi‑Fi, потім міняли кодеки.
Дзвінки випадково покращувалися, що найгірше, бо це заохочувало забобони.

Успадкована закономірність, що зламала справу: роботизований звук сплескував під час певних сценаріїв — трансфери, консультації та коли софтфон погоджував SRTP заново.
Саме тоді сигналізаційні пакети ставали більшими, і в деяких сценаріях шлях тунелю вимагав фрагментації. ICMP «fragmentation needed» блокувався на боці користувача через «безпекове» налаштування.
PMTUD black holes. Не гламурно. Дуже реально.

Виправлення було нудним і рішучим: встановили консервативний MTU тунелю, клацнули MSS для TCP сигналізації і задокументували «не блокувати весь ICMP» у стандарті віддаленого доступу.
Також додали односторінковий тест: DF ping через тунель до відомої кінцевої точки. Це ловило регресії пізніше.

Урок: «1500 скрізь» — не дизайн. Це бажання.

Інцидент №2: Оптимізація, що обернулась проти (пріоритизація голосу… шляхом прискорення всього)

Інша організація мала спроможний VPN-шлюз і хотіла «преміум-якість голосу». Хтось увімкнув апаратне прискорення і fast-path фічі на крайовому фаєрволі.
Пропускна здатність зросла. Затримка в синтетичних тестах впала. Усі святкували.

Через два тижні — скарги: «Робот лише під час великих завантажень файлів». Ця деталь важлива.
Під навантаженням fast path обходив частини стека QoS і менеджменту черг. Bulk-трафік і голос опинялися в одній глибокій черзі на стороні WAN.
Прискорення покращило пікову пропускну здатність, але прибрало механізм, що підтримував стабільну затримку.

Інженери зробили те, що інженери зазвичай роблять: додали більше правил QoS. Більше класів. Більше match-висловів. Стало гірше.
Класифікація навантажувала CPU на slow path, у той час як fast path все одно відправляв більшу частину трафіку в ту саму чергу-горло.
Тепер у них була складність і все ще bufferbloat.

Остаточне виправлення не було «більше QoS». Воно полягало в: шейпити uplink трохи нижче реальної пропускної здатності, увімкнути сучасний qdisc і зберегти модель класів простою.
Потім вирішити, чи сумісне прискорення з цією політикою. Там, де ні — голос переміг.

Урок: оптимізація для throughput без врахування поведінки черг — це як побудувати швидший шлях звучати жахливо.

Інцидент №3: Нудна практика, що врятувала день (стандартні тести + контроль змін)

Глобальна компанія передавала голос через IPsec між філіями та HQ. Нічого надзвичайного. Ключова різниця: вони ставилися до голосу як до production-сервісу.
Кожна зміна мережі мала pre-flight і post-flight чекліст, включно з кількома VoIP-орієнтованими тестами.

Одної п’ятниці ISP поміняв обладнання доступу в регіональному офісі. Користувачі помітили «легкий робот» у дзвінках.
Локальна команда виконала стандартні тести: ping idle vs ping під навантаженням uplink, DF pings для MTU і швидку перевірку DSCP на WAN-egress.
Вони не сперечалися. Вони вимірювали.

Дані показали, що PMTUD зламаний на новому доступі, а upstream-буфер став глибшим, ніж раніше. Дві проблеми. Обидві — що робити.
Вони трохи зменшили MTU тунелю, увімкнули MSS clamping і підкоригували шейпінг, щоб тримати затримку стабільною. Дзвінки стабілізувалися миттєво.

У понеділок вони підняли питання до ISP з чіткими доказами: таймстемпи, поріг відмови MTU і графіки затримки під навантаженням.
ISP пізніше виправив обробку ICMP. Але компанія не чекала, щоб повернути працездатний голос.

Урок: найефективніша функція надійності — це відтворюваний тест, який ви справді виконуєте.

Типові помилки: симптом → корінь → виправлення

1) Симптом: роботизований звук під час завантажень або демонстрацій екрану

  • Корінь: bufferbloat на upstream; голосові пакети застрягають за bulk-трафіком в глибокій черзі.
  • Виправлення: увімкніть SQM (fq_codel/cake) і шейпте трохи нижче uplink; додайте простий пріоритет для RTP/SIP на WAN-egress.

2) Симптом: дзвінок підключається, а потім аудіо падає або стає рваним через хвилину

  • Корінь: MTU/PMTUD black hole, спричинений рекієм, SRTP-ренеготацією або збільшенням розміру SIP re-INVITE.
  • Виправлення: явно встановіть MTU тунелю; дозвольте ICMP «frag needed»/PTB; для TCP сигналізації — clamp MSS.

3) Симптом: односпрямоване аудіо (ви чуєте їх, вони не чують вас)

  • Корінь: проблема NAT traversal або асиметрична маршрутизація; RTP прив’язаний до неправильного інтерфейсу; таймаути stateful-фаєрволу для UDP.
  • Виправлення: забезпечте правильні налаштування NAT (SIP ALG зазвичай вимкнути), підтвердіть маршрути, збільште UDP timeout на stateful-пристроях, перевірте симетричний RTP якщо підтримується.

4) Симптом: нормально на дроті, погано на Wi‑Fi

  • Корінь: конкуренція ефірного часу, повторні передачі або поведінка енергозбереження клієнта; VPN додає оверхед і чутливість до джиттера.
  • Виправлення: переведіть дзвінки на 5 GHz/6 GHz, зменшіть конкуренцію каналів, вимкніть агресивне енергозбереження для голосових пристроїв, віддавайте перевагу дроту для ролей з інтенсивними дзвінками.

5) Симптом: лише віддалені користувачі певного ISP мають проблеми

  • Корінь: upstream shaping/CGNAT від ISP, погане піринг, або фільтрація ICMP що впливає на PMTUD.
  • Виправлення: зменште MTU тунелю, забезпечте шейпінг на боці користувача якщо керуєте ним, протестуйте альтернативний транспорт/порт і збирайте докази для ескалації.

6) Симптом: «QoS увімкнено», але голос все одно деградує під навантаженням

  • Корінь: QoS налаштовано на LAN, а перевантаження на WAN; або DSCP марковано в середині, але не на зовнішніх пакетах тунелю.
  • Виправлення: пріоритезуйте там, де відбувається перевантаження: на egress; мапуйте/класифікуйте голос для зовнішніх пакетів; перевірте tcpdump і статистику qdisc.

7) Симптом: спорадичні сплески робота, особливо в години піку

  • Корінь: мікросплески і осциляція черг; CPU-конкуренція VPN-концентратора; або апстрім-конгестія.
  • Виправлення: перевірте softirq/CPU, увімкніть pacing/SQM, забезпечте запас потужності шлюзу і уникайте надмірно складних ієрархій класів.

8) Симптом: дзвінки нормальні, але «hold/resume» ламається або трансфери не проходять

  • Корінь: фрагментація SIP сигналізації або MTU-проблеми, що впливають на великі SIP-повідомлення; іноді SIP over TCP/TLS уражається MSS.
  • Виправлення: MSS clamping, зменшення MTU, дозвіл ICMP PTB і перевірка налаштувань SIP (і вимкнення SIP ALG, якщо він каламутить пакети).

Контрольні списки / покроковий план

Покроково: стабілізувати VoIP через VPN за тиждень (не за квартал)

  1. Виберіть одного репрезентативного користувача з проблемами і відтворіть проблему на вимогу (завантаження під час дзвінка зазвичай вистачає).
    Без відтворюваності — немає прогресу.
  2. Зберіть статистику голосу (з софтфону/PBX): джиттер, втрати, concealment, RTT якщо доступно.
    Вирішіть: чи це loss-driven (мережа) vs CPU-driven (ендпойнт) vs signaling-driven (SIP транспорт/MTU).
  3. Підтвердіть маршрутизацію: впевніться, що медіа справді йде через VPN, коли ви так вважаєте. Виправте плутанину зі split tunnel рано.
  4. Виміряйте path MTU через тунель використовуючи DF pings до відомих кінцевих точок.
    Вирішіть безпечний MTU (консервативний краще, ніж теоретичний).
  5. Встановіть MTU тунелю явно на обох кінцях (і задокументуйте чому).
    Уникайте «auto», якщо ви не протестували це по всіх типах доступу (домашній broadband, LTE, готельний Wi‑Fi тощо).
  6. Клацніть TCP MSS на тунелі для перенаправлених TCP-потоків (SIP/TLS, provisioning, management).
  7. Знайдіть реальне вузьке місце (зазвичай uplink). Використайте ping під навантаженням, щоб підтвердити bufferbloat.
  8. Розгорніть SQM шейпінг на вузькому місці, трохи нижче лінійної швидкості, з fq_codel або cake.
  9. Тримайте QoS класи простими і пріоритезуйте голос лише там, де це має значення: egress-черга.
  10. Перевірте обробку DSCP пакетом-захватом: внутрішнє маркування, зовнішнє маркування і чи поважає черга це.
  11. Повторно протестуйте початковий кейс (дзвінок + завантаження) і підтвердіть покращення джиттера/втрат.
  12. Розгортайте поступово з канарською групою і планом відкату. Зміни в голосі відчутні миттєво; ставтеся до них як до production-деплою.

Операційний чекліст: кожного разу, коли торкаєтесь VPN або WAN

  • Запишіть поточні MTU налаштування (WAN + тунель) та qdisc/shaping політики.
  • Запустіть DF ping MTU тест через тунель до стабільної кінцевої точки.
  • Запустіть ping idle vs ping під навантаженням, щоб виміряти регрес bufferbloat.
  • Захопіть 30 секунд RTP під час тестового дзвінка і перевірте на втрати/джиттер-сплески.
  • Підтвердіть DSCP на зовнішньому пакеті на WAN-стороні (якщо ви покладаєтесь на маркування).
  • Перевірте softirq CPU шлюзу під навантаженням.

Цікаві факти та історичний контекст

  • Факт 1: RTP (Real-time Transport Protocol) був стандартизований у середині 1990-х для передачі реального часу медіа по IP-мережах.
  • Факт 2: SIP став популярним частково тому, що виглядав як HTTP для дзвінків — текстовий, розширюваний — зручний для фіч, іноді болісний для MTU.
  • Факт 3: Багато болю PMTUD походить від практик фільтрації ICMP, що стали поширені як груба відповідь на безпеку в ранньому інтернет-епоху.
  • Факт 4: Ранні VoIP-розгортання часто покладалися на DiffServ маркування всередині підприємства, але «QoS через публічний інтернет» так і не став надійним.
  • Факт 5: Хвиля прийняття VPN для віддаленої роботи спричинила скарги на голос, бо споживчі uplink-и типовно є найвужчими та найбільш bufferbloated сегментами.
  • Факт 6: WireGuard став популярним частково тому, що він легкий і швидкий, але «швидка криптографія» не скасовує «погані черги».
  • Факт 7: Bufferbloat був ідентифікований і отримав назву через те, що споживче обладнання відвантажувалося з надмірно глибокими буферами, які підвищували бенчмарки throughput, але руйнували затримкочутливі додатки.
  • Факт 8: Сучасні Linux qdisc-і як fq_codel були створені спеціально, щоб тримати затримку обмеженою під навантаженням — велика річ для голосу й ігор.
  • Факт 9: Багато корпоративних VPN-дизайнів історично припускали MTU 1500; поширення PPPoE, LTE і стекування тунелів зробило це припущення крихким.

Поширені питання

1) Чому звук «роботизований», а не просто тихий або запізнений?

Тому що ви чуєте маскування втрат пакетів. Декодер домислює відсутні аудіо-фрейми. Тихий звук зазвичай пов’язаний з гейном або проблемами пристрою; робот — зазвичай втрати/джиттер.

2) Який відсоток втрат стає чутним для VoIP?

Залежить від кодека і concealment, але навіть ≈1% втрат може бути помітним, особливо якщо вони сгруповані. Стабільні 0.1% можуть бути прийнятні; 2% у сплесках часто неприйнятні.

3) Чи MTU — це лише TCP-проблема? RTP ж UDP.

MTU шкодить і UDP. Якщо пакети перевищують path MTU і PMTUD зламаний, їх відкидають. Також фрагментація підвищує чутливість до втрат і джиттера, коли фрагменти конкурують в чергах.

4) Чи просто встановити MTU на 1200 і забути?

Ні. Ви зменшите ефективність і можете необґрунтовано зіпсувати інші протоколи або шляхи. Вимірюйте path MTU, оберіть безпечне значення і задокументуйте його. Консервативно, але не екстремально.

5) Чи DSCP-маркування допомагає через публічний інтернет?

Іноді всередині домену ISP, часто — ні end-to-end. Надійний виграш — пріоритизація там, де ви контролюєте чергу: ваш WAN-egress і керовані краї.

6) Чи QoS виправить втрати пакетів від поганого ISP?

QoS не створить додаткову пропускну здатність. Воно може запобігти self-inflicted втратам/джиттеру, керуючи власними чергами. Якщо провайдер дійсно втрачає upstream, потрібен кращий маршрут або інший провайдер.

7) Чому це ламається тільки коли хтось завантажує файл?

Upload насичує upstream. Upstream-черги надуваються, затримка і джиттер вибухають, і RTP приходить запізно. Speed tests рідко це показують, бо вони винагороджують глибокі буфери.

8) Чи WireGuard автоматично кращий за OpenVPN для голосу?

WireGuard зазвичай має нижчий оверхед і простіший розуміння, але якість голосу переважно залежить від правильного MTU, керування чергами й стабільної маршрутизації. Ви можете зламати голос на будь-якому VPN.

9) Яка найпростіша політика QoS, що реально працює?

Шейпте WAN трохи нижче реальної швидкості, потім пріоритезуйте голос (RTP) над bulk. Тримайте модель класів малою. Перевірте за допомогою qdisc-статистики та реальних тестових дзвінків.

10) Як довести, що це MTU, а не «кодек»?

Відтворіть проблему за допомогою DF ping порогів і спостерігайте відмови навколо певних розмірів пакетів; зіставте з подіями дзвінка, що збільшують розмір сигналізації; виправте MTU і подивіться, чи зникає проблема без зміни кодеків.

Практичні наступні кроки

Якщо хочете, щоб дзвінки звучали людяно — ставте голос як SLO затримки, а не як настрій.

  1. Пройдіть швидкий план діагностики на одному ураженому користувачі і зберіть докази: MTU, джиттер під навантаженням, поведінка DSCP.
  2. Встановіть явний MTU тунелю (почніть консервативно) і клацніть MSS для TCP сигналізації.
  3. Розгорніть SQM шейпінг на вузькому uplink з fq_codel/cake і пріоритезуйте голос на цій черзі.
  4. Підтвердіть вимірюваннями (qdisc-статистика, tcpdump DSCP, mtr і клієнтські статистики джиттера/втрат), а не відчуттями.
  5. Задокументуйте: обраний MTU, чому його обрали, та регресійні тести. Майбутній ви буде втомленим і не враженим.

Більшість «таємниць» VoIP-over-VPN — це просто мережі, що роблять мережеві речі. Зробіть пакети меншими, зробіть черги розумнішими і зробіть пріоритети реальними там, де відбувається перевантаження.

← Попередня
Тай‑аути Docker NFS томів — опції монтування, що справді підвищують стабільність
Наступна →
Майбутня безпека CPU: чи закінчилися сюрпризи класу Spectre?

Залишити коментар