Утечки WebRTC: почему ваш IP виден даже при включенном VPN
Чтобы установить P2P-соединение, WebRTC спрашивает у STUN-сервера, как выглядит ваш публичный адрес, и этот запрос часто идет мимо VPN. Как устроена утечка, почему для проверки из Китая нужны местные STUN-серверы и чем обходится полное отключение WebRTC.
5 мин чтения · Опубликовано 10 сентября 2026 г.
Вы подключаетесь через прокси, открываете страницу проверки IP и видите адрес в Токио или Лос-Анджелесе. Спокойно. Тем временем JavaScript на той же странице, возможно, уже держит в руках ваш настоящий домашний публичный IP. Не из-за ошибки, а благодаря вполне легитимной функции браузера под названием WebRTC.
Зачем нужен WebRTC
WebRTC — встроенный в браузер стек для связи в реальном времени. Видеовстречи во вкладке, звонки из браузера, P2P-передача файлов на некоторых файлообменниках — все это работает поверх объекта RTCPeerConnection. Чтобы два браузера могли общаться напрямую, каждому нужно узнать, как его адрес выглядит снаружи. Этот процесс называется ICE, Interactive Connectivity Establishment.
ICE собирает список «кандидатов», которые делятся примерно на три вида:
- host — адреса ваших собственных сетевых интерфейсов, например
192.168.1.23. - srflx (server-reflexive) — браузер отправляет UDP-пакет на STUN-сервер, а тот отвечает адресом источника, который увидел. Это и есть ваш публичный внешний IP.
- relay — трафик, проброшенный через TURN-сервер. Обычно требует учетных данных и к утечке отношения не имеет.
Важный момент: каждый кандидат передается скрипту страницы как есть — через событие onicecandidate и текст SDP. Странице не нужно доводить дело до звонка. Достаточно создать RTCPeerConnection, добавить data channel, вызвать createOffer, и через несколько сотен миллисекунд список кандидатов лежит в переменной JavaScript. Ни запроса разрешения, ни индикатора.
Что такое STUN
STUN — это зеркало. Вы отправляете ему UDP-пакет, он отвечает: «Я вижу вас с адреса 1.2.3.4:51234». Протокол крошечный и не хранит состояния, публичных серверов много. Самый известный — гугловский stun.l.google.com:19302; свои держат Cloudflare и Twilio.
Именно эта простота и делает его точкой входа для утечки.
Почему VPN этого не ловит
Зависит от того, как именно клиент обхода блокировок перехватывает трафик.
Многие клиенты работают в режиме системного прокси: открывают локальный порт SOCKS или HTTP и прописывают его в настройках прокси операционной системы. HTTP-запросы браузера послушно идут через него. Но WebRTC отправляет «сырые» UDP-пакеты, а сырой UDP к настройкам прокси не обращается. Пакет уходит через сетевой интерфейс по умолчанию, и STUN-сервер видит IP вашего домашнего провайдера.
Раздельное туннелирование по правилам страдает тем же: если через прокси идут только определенные домены или диапазоны IP, STUN-серверов в этом списке, как правило, нет, и они получают прямое соединение. Прокси, работающие только с TCP, пропускают UDP мимо по определению.
Проксирование «только для браузера» — через расширение или настройку прокси для отдельного приложения — ведет себя так же, как режим системного прокси.
Что действительно перекрывает утечку, так это режим TUN, он же «глобальный»: клиент создает виртуальный сетевой интерфейс и переписывает таблицу маршрутизации так, что каждый пакет, независимо от протокола, попадает в туннель. Тогда STUN видит IP выходного узла, он совпадает с тем, что видит HTTP, и проверка сообщает: утечки нет.
Так что тест WebRTC говорит больше, чем «течет или нет». Он показывает, какую долю вашего трафика инструмент контролирует на самом деле.
Маскировка mDNS: адреса локальной сети почти перестали утекать
Несколько лет назад WebRTC выдавал приватный адрес локальной сети в host-кандидатах. Сайт видел, сидите ли вы в 192.168.x.x или 10.x.x.x, и мог неплохо угадать, дома вы или в офисе. Сейчас Chrome и Firefox по умолчанию подменяют их именами mDNS, и кандидат выглядит как a1b2c3d4-….local, а не как IP.
Проблема приватных адресов этим решена. Кандидат srflx — публичный IP — не маскируется, потому что для пробивания NAT в ICE он действительно нужен. В современном браузере «утечка WebRTC» практически всегда означает «утечку публичного IP».
Почему для проверки из Китая нужны местные STUN-серверы
Многие сайты проверки утечек делают здесь ошибку.
Допустим, тестовая страница опрашивает только STUN-сервер Google, а вы находитесь на прямом соединении внутри материкового Китая — потому что прокси выключен или потому что UDP идет в обход него. Такой пакет с большой вероятностью будет отброшен или уйдет в таймаут, кандидат не вернется, и страница бодро сообщит: «утечек не обнаружено». Ничего не утекло, потому что зонд ни до чего не добрался, — а это совсем не одно и то же.
С проксированной стороны происходит обратное: STUN Google доступен через туннель, возвращает IP выходного узла, и все выглядит согласованно. Прямой путь при этом никто не измерял.
Browserscan решает это, опрашивая сразу целую пачку STUN-серверов: зарубежные (Google, Cloudflare, Twilio) плюс серверы китайских компаний — Xiaomi, QQ, bilibili. Китайский STUN-сервер на прямом соединении изнутри Китая доступен всегда, поэтому если ваш UDP уходит мимо туннеля, он сообщит ваш настоящий провайдерский адрес. Наша проверка WebRTC делает то же самое: много серверов параллельно, каждый полученный публичный адрес сравнивается с IP на уровне HTTP, и любое расхождение считается утечкой.
Отсюда же понятно, почему на одном сайте можно быть «чистым», а на другом — «с утечкой».
Как защититься
Примерно в порядке возрастания цены:
Отдайте инструменту весь трафик. Переключите клиент в режим TUN или глобальный режим и включите kill switch, чтобы при обрыве туннеля соединение рвалось, а не откатывалось на прямое. Это настоящее решение, и оно не стоит вам ни одной функции браузера.
Firefox. Наберите в адресной строке about:config, найдите media.peerconnection.enabled и поставьте false. WebRTC отключен полностью.
Chrome и Edge. Встроенного переключателя нет. Поставьте расширение WebRTC Network Limiter от самой Google и выберите «use only the default public interface» или «disable non-proxied UDP». В uBlock Origin тоже есть настройка «Prevent WebRTC from leaking local IP addresses».
Safari. Пользовательского переключателя нет; решать придется на уровне прокси.
У отключения WebRTC есть реальная цена. Встречи в браузере (Google Meet, веб-версия Tencent Meeting и подобные) могут не подключаться или работать только через релеи; ломаются веб-телефония, P2P-передача файлов в браузере и часть веб-игр. Если вы созваниваетесь каждый день, «ограничить» лучше, чем «отключить».
Вопросы и ответы
Тест показывает, что публичный IP по WebRTC совпадает с HTTP-IP. Я в безопасности? В рамках именно этой проверки — да: UDP идет через туннель. О DNS это ничего не говорит, это отдельная проблема; см. Утечки DNS и открытые порты.
В кандидатах только имена .local и ни одного IP. Что это значит?
Браузер применил маскировку mDNS и не получил ни одного srflx-кандидата: либо все STUN-серверы были недоступны, либо WebRTC ограничивает расширение. В таком состоянии тест ничего заключить не может, и «нет результата» не значит «безопасно».
На телефонах такое бывает? В мобильных браузерах WebRTC тоже есть. Но мобильные клиенты обхода блокировок в основном работают как системный VPN (режим TUN) и по своей природе захватывают весь трафик, так что утечки там встречаются реже, чем на десктопе. Клиенты в стиле «только прокси» на iOS по-прежнему могут течь.