IPv6-прокси и WebRTC: почему браузер сливает реальный IP и как это заблокировать
Содержание
- IPv6-прокси и WebRTC: почему браузер сливает реальный IP и как это заблокировать
- Что такое WebRTC и почему он игнорирует прокси
- Механизм утечки: STUN, ICE и кандидаты
- Как проверить утечку WebRTC
- Почему IPv6-прокси не спасает
- Блокировка WebRTC в браузерах
- Настройка Firefox для полной блокировки
- Блокировка на уровне файрвола
- Проксирование WebRTC через TURN
- Пример: сервер на nginx с блокировкой WebRTC
- Кейс: утечка через IPv6 SLAAC
- Кейс: корпоративная сеть и WebRTC
- Кейс: мобильное приложение с WebRTC
- Что в итоге
IPv6-прокси и WebRTC: почему браузер сливает реальный IP и как это заблокировать
WebRTC — технология, которая не прощает ошибок в конфигурации прокси. Пока вы думаете, что сидите за анонимным IPv6-адресом, ваш браузер спокойно раздаёт реальный IPv4 всем пирам в комнате. Разбираемся, почему так происходит и как закрыть течь.
Что такое WebRTC и почему он игнорирует прокси
WebRTC (Web Real-Time Communication) — это набор протоколов для передачи аудио, видео и данных в реальном времени. Работает напрямую между браузерами, без промежуточных серверов. Вот в этом и проблема.
HTTP-прокси работает на уровне приложений. Он обрабатывает запросы, которые идут через протокол HTTP. WebRTC использует UDP, а не TCP. Прокси, настроенный для HTTP, просто не видит UDP-трафик. Браузер устанавливает соединение напрямую, игнорируя системные настройки прокси.
Технически это выглядит так: браузер создаёт RTCPeerConnection, собирает ICE-кандидаты — список IP-адресов, через которые можно достучаться до пользователя. В этот список попадают все адреса сетевых интерфейсов: и IPv4, и IPv6. Если у вас на машине есть реальный IPv4, он утечёт первым.
Механизм утечки: STUN, ICE и кандидаты
Когда браузер устанавливает WebRTC-соединение, он отправляет запрос на STUN-сервер. STUN (Session Traversal Utilities for NAT) — это сервер, который сообщает браузеру его внешний IP-адрес. Браузер получает ответ и добавляет адрес в список ICE-кандидатов.
Проблема в том, что браузер запрашивает STUN-сервер не через прокси, а напрямую. Даже если вы настроили SOCKS5-прокси на уровне системы, WebRTC-стек браузера его не использует. Он работает на уровне сокетов, обходя все системные настройки.
Пример: вы сидите за IPv6-прокси, ваш реальный IPv4 — 203.0.113.45. Браузер отправляет STUN-запрос, получает ответ с этим адресом и включает его в ICE-кандидаты. Сайт, который вы посещаете, может запросить эти кандидаты через JavaScript и получить ваш реальный IP. Всё.
Как проверить утечку WebRTC
Проверка занимает тридцать секунд. Откройте браузер и выполните в консоли:
```javascript
const pc = new RTCPeerConnection({ iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] });
pc.createDataChannel('test');
pc.onicecandidate = (e) => {
if (e.candidate) {
console.log(e.candidate.candidate);
}
};
pc.createOffer().then((offer) => pc.setLocalDescription(offer));
```
В консоли появятся ICE-кандидаты. Если среди них есть адреса, которые не принадлежат вашему прокси — утечка налицо. Обратите внимание на строки, начинающиеся с `srflx` — это серверные рефлексивные кандидаты, полученные через STUN. Именно они выдают реальный IP.
Почему IPv6-прокси не спасает
IPv6-прокси — это хороший инструмент для обхода блокировок и скрытия трафика в обычных HTTP-запросах. Но WebRTC работает на другом уровне стека. Он не использует прокси для UDP-трафика, поэтому все ваши настройки проксирования бесполезны.
Более того, IPv6-адреса часто раскрывают информацию об устройстве. SLAAC (Stateless Address Autoconfiguration) генерирует адреса на основе MAC-адреса сетевой карты. Даже если вы используете приватные адреса, WebRTC может передать их в ICE-кандидатах. Это дополнительный вектор утечки, о котором часто забывают.
Блокировка WebRTC в браузерах
Самый простой способ — отключить WebRTC в настройках браузера. В Firefox это делается через `about:config`, параметр `media.peerconnection.enabled` — установите `false`. В Chrome и Chromium такой настройки нет, нужен специальный плагин.
Для Chrome подойдёт расширение WebRTC Leak Prevent. Оно перехватывает вызовы API WebRTC и подменяет ICE-кандидаты. Расширение позволяет выбрать режим: блокировать только непубличные IP или все адреса. Настройки расширения:
```json
{
"mode": "disable_non_proxied_udp",
"proxy_only": true
}
```
Режим `disable_non_proxied_udp` блокирует UDP-соединения, которые не идут через прокси. Это заставит WebRTC использовать TCP, а TCP-трафик уже можно прогнать через прокси.
Настройка Firefox для полной блокировки
Firefox даёт больше контроля. Кроме отключения WebRTC целиком, можно настроить проксирование UDP через SOCKS5. В `about:config` установите:
```
media.peerconnection.ice.proxy_only = true
media.peerconnection.ice.default_address_only = true
```
Первый параметр заставляет WebRTC использовать только проксированные соединения. Второй — ограничивает ICE-кандидаты одним адресом, не раскрывая все интерфейсы. С этими настройками Firefox не будет отправлять STUN-запросы напрямую, а пойдёт через прокси.
Блокировка на уровне файрвола
Если вы хотите гарантированно заблокировать утечку, не полагаясь на настройки браузера, используйте файрвол. На Linux это делается через nftables или iptables. Пример для nftables:
```bash
nft add table inet webRTC_block
nft add chain inet webRTC_block output { type filter hook output priority 0; }
nft add rule inet webRTC_block output udp dport 3478-3481 drop
nft add rule inet webRTC_block output udp dport 19302-19309 drop
```
Здесь блокируются порты, которые используют STUN-серверы Google (19302) и стандартные порты TURN (3478-3481). Это не полное решение — WebRTC может использовать другие порты, но основную массу утечек закрывает.
Проксирование WebRTC через TURN
Полное решение проблемы — TURN-сервер. TURN (Traversal Using Relays around NAT) — это ретрансляционный сервер, через который проходит весь WebRTC-трафик. В отличие от STUN, TURN не просто сообщает адрес, а передаёт данные через себя.
Настройка WebRTC с TURN выглядит так:
```javascript
const pc = new RTCPeerConnection({
iceServers: [
{
urls: 'turn:turn.example.com:3478',
username: 'user',
credential: 'password'
}
]
});
```
Все ICE-кандидаты будут использовать TURN-сервер. Браузер установит соединение с TURN, а TURN уже будет общаться с пиром. Реальный IP останется скрытым. Минус — задержка увеличивается на 20-50 мс, так как трафик идёт через промежуточный узел.
Пример: сервер на nginx с блокировкой WebRTC
Рассмотрим реальный кейс. Есть nginx 1.24, который проксирует трафик на бэкенд. Нужно заблокировать WebRTC-соединения на уровне конфигурации. Для этого используется модуль ngx_http_js_module, который позволяет обрабатывать запросы на JavaScript.
```nginx
load_module modules/ngx_http_js_module.so;
http {
js_import app from /etc/nginx/webrtc.js;
server {
listen 443 ssl;
server_name example.com;
js_access app.check_webrtc;
location / {
proxy_pass http://backend;
}
}
}
```
В файле webrtc.js:
```javascript
function check_webrtc(r) {
if (r.headersIn['Upgrade'] === 'websocket' &&
r.headersIn['Sec-WebSocket-Protocol'] === 'webrtc') {
r.return(403, 'WebRTC blocked');
return;
}
r.next();
}
```
Этот конфиг перехватывает WebSocket-соединения с протоколом webrtc и возвращает 403. Не идеальное решение — WebRTC может работать и без WebSocket, но для большинства реализаций работает.
Кейс: утечка через IPv6 SLAAC
Пример из практики. Пользователь настроил IPv6-прокси на роутере, но забыл отключить SLAAC на сетевой карте. В итоге браузер получил два IPv6-адреса: один от прокси, второй — сгенерированный из MAC-адреса. WebRTC отправил оба адреса в ICE-кандидатах, и сайт получил реальный адрес устройства.
Решение — отключить SLAAC и использовать только адреса, назначенные прокси. На Linux это делается через sysctl:
```bash
sysctl -w net.ipv6.conf.eth0.autoconf=0
sysctl -w net.ipv6.conf.eth0.accept_ra=0
```
После этого сетевой интерфейс не будет генерировать адреса из MAC, и все IPv6-адреса будут приходить только от DHCP или прокси.
Кейс: корпоративная сеть и WebRTC
Корпоративная сеть с жёсткими правилами безопасности. Все сотрудники сидят за NAT, реальные IP скрыты. Но WebRTC умудрился утечь внутренние адреса. Сайт получил список внутренних IP-адресов, включая адреса серверов, и использовал их для сканирования сети.
Причина — браузер отправил в ICE-кандидаты адреса всех сетевых интерфейсов, включая внутренние. Даже если внешний IP скрыт за NAT, внутренние адреса раскрывают структуру сети. Решение — настройка `media.peerconnection.ice.default_address_only` в Firefox или использование расширения для Chrome.
Кейс: мобильное приложение с WebRTC
Мобильное приложение на базе WebRTC использовало STUN-сервер для определения внешнего IP. Приложение работало через корпоративный VPN, но WebRTC-стек обходил VPN и отправлял запросы напрямую. В итоге сервер получал реальный IP устройства, а не IP VPN-туннеля.
Решение — перехват DNS-запросов к STUN-серверам и перенаправление их на внутренний TURN-сервер. Это делается на уровне DNS-сервера компании:
```bash
iptables -t nat -A OUTPUT -p udp --dport 53 -m string --string "stun" --algo bm -j DNAT --to-destination 10.0.0.5:53
```
Запросы к STUN-серверам перенаправляются на внутренний DNS, который возвращает адрес внутреннего TURN-сервера. Весь WebRTC-трафик идёт через TURN, реальный IP остаётся скрытым.
Что в итоге
WebRTC — это дыра в анонимности, которая не закрывается простой настройкой прокси. Если вы работаете с чувствительными данными, блокируйте WebRTC на уровне браузера или используйте TURN-сервер. IPv6-прокси от lexic.ml защитит ваш HTTP-трафик, но для WebRTC нужны дополнительные меры. Проверьте свои настройки прямо сейчас — возможно, ваш реальный IP уже утёк.