written on Thursday, September 13, 2012
Є такий хороший SIP-клієнт Telephone.app. У ньому використовується одна хороша бібліотека pjsip, правда вона під GPL, а бібліотеки під GPL публікують не дуже хороші люди.
І в цієї бібліотеки є досить стрьомна поведінка, яка напевно десь сто разів описана, але зайвий раз тицьнути паличкою не завадить.
У нотатці про webrtc є опис примітивної реалізації voip, короткий зміст такий: дві програми кажуть одна одній UDP-адреси, через які будуть обмінюватися голосовим трафіком. Ліричні відступи щодо кодеків, автентифікації, віртуального номеронабирача та віртуального підйому трубки залишимо за кадром.
Сучасний інтернет — це така жопа з дефіцитом адрес і криво налаштованими маршрутизаторами, де у кожної хріновини є по сто різних адрес.
Один із частих випадків — зв'язок двох абонентів у межах однієї локальної мережі.
Перший абонент має внутрішню адресу 192.168.1.44, другий абонент — 192.168.1.45, зовнішня адреса роутера, через який вони виходять назовні — 109.109.255.230, а сервер, на якому вони зареєстровані, має якийсь свій адрес, наприклад 109.200.152.80
Коли один абонент дзвонить іншому, оскільки вони спілкуються SIP-пакетами через сервер, обидва вказують як свою адресу зовнішню адресу роутера:
192.168.1.44 -> 109.200.152.80 -> 192.168.1.45 c=IN IP4 109.109.255.230 m=audio 5320 RTP/AVP 102
192.168.1.45 -> 109.200.152.80 -> 192.168.1.44 c=IN IP4 109.109.255.230 m=audio 4001 RTP/AVP 102
Оскільки роутер може бути налаштований черезжопу або хтось із абонентів виявиться дохуя розумним і відправить свій внутрішній адрес, може статися наступне: перший абонент буде відправляти свій потік на зовнішню адресу роутера, а отримувати вхідний з внутрішньої адреси другого абонента:
// на 192.168.1.44
sendto(192.168.1.45, msg)
// на 192.168.1.45 sendto(109.109.255.230:4001, msg) recvmsg(&addr, &msg) // addr == 192.168.1.44:4001
Я поки що не бачив у стандартах якоїсь вказівки на цей рахунок, але pjmedia роблять фінт вухами — якщо голосовий потік приходить не з тієї адреси, яка вказана в SDP, то на адресу в SDP всім забивають і подальша комунікація вже йде туди.
Тобто живий MiTM, який дозволяє вкрасти голосову сесію і сісти посередині, знаючи адреси обох абонентів і пославши їм пару валідних RTP пакетів, навіть із гівняним пейлоадом або шумом.
Я розумію, нахуй це зроблено — раптом у абонента кривий роутер, кривий UA або взагалі змінилася адреса під час розмови. Я також розумію, що в тому софті, який я бачив, шифрування голосового потоку немає або воно вимкнене при збірці, або при конфігурації. А якщо немає шифрування, то все спочатку погано, а активний MiTM просто робить все ще гівніше, при тому що шифрування одразу все виправило б.