Admin
Администратор
Утечка DNS при использовании SOCKS прокси
Утечка DNS при использовании SOCKS прокси и методы, позволяющие её предотвратить.
Прежде чем начать, поговорим о том, как вообще работает DNS.
Как вы понимаете, нельзя просто так взять и обратиться к сетевому хосту по имени example.com, потому что протоколом IP, на котором базируется интернет, для обращения к сетевым хостам предусмотрена числовая адресация. Примером такого адреса может быть хорошо известный читателям IPv4 адрес, который имеет вид 1.2.3.4
Приведу аналогию. Вы не можете набрать в таксофоне имя и фамилию своего друга и таким образом дозвониться до него, потому что ваша телефонная служба использует не буквенные имена, а состоящие из цифр номера телефонов, что обусловлено архитектурой телефонной сети.
Однако нам, людям, было не очень удобно запоминать цифры и держать в голове десятки номеров, поэтому мы придумали телефонные справочники.
DNS сервер представляет собой оператора, у которого есть такой телефонный справочник. Таким образом вам совсем не обязательно иметь свой справочник, ведь достаточно помнить один номер - номер телефона оператора. Вы позвоните оператору, назовёте ему имя своего друга и в ответ получите номер телефона, по которому сможете дозвониться.
Если DNS сервер чего-то не знает, он обращается к следующему DNS серверу, и так вплоть до корневых DNS серверов - справочников колоссального размера - являющихся китами, на которых стоит наш интернет.
Конечно, это очень упрощённое объяснение. Разумеется, DNS протокол намного сложнее и поддерживает различные виды записей, в том числе произвольные текстовые записи, которые могут содержать, например, вашу цифровую подпись. Всё это выходит далеко за рамки статьи, однако на случай, если кто-то захочет погрузиться в эту тему с головой, рекомендую начать с бесплатной книги Domain Name Sanity авторства Edward Loveall.
Как это работает на уровне программ.
На более высоком уровне, например, в скриптовых языках программирования, возможно вы встречали что-то подобное:
Код:
response = http.get("https://example.com/");
Код:
remote_ip = getaddrbyname("example.com");
remote_port = 443;
conn = tcp_connect(remote_ip, remote_port);
if (!conn) { /* ... */ }
write(conn, bytes, len);
/* ... */
close(conn);
Операционная система, в свою очередь, обратится к указанному в её настройках DNS серверу, который чаще всего соответствует адресу вашего маршрутизатора либо корпоративного сервера DNS. Но так как вашему DNS мало что известно о внешнем мире, как уже было сказано ранее, он будет вынужден обратиться к следующему DNS серверу, который скорее всего будет иметь отношение к вашему интернет-провайдеру. И так далее по цепочке.
Подавляющее большинство программ устроены именно так, как было показано выше. Однако для справки отметим, что отдельно взятая программа может напрямую обратиться к любому доступному DNS серверу, минуя все настройки вашей операционной системы. Конечно же, такое поведение можно ограничить на уровне фаерволла, и даже возможно обмануть подобную программу, но мы не будем этого делать, потому что это выходит за пределы обсуждаемой темы.
Проблема.
Предположим, что есть некий веб сайт example.com.
Вы планируете войти этот сайт, используя socks proxy с IP адресом 12.34.56.78
При этом на стороне сервера example.com применяется следующая манипуляция: сервер запоминает ваш IP адрес и соответствующее ему сгенерированное уникальное значение, например, abcdefg12345, и внедряет в HTML страницу следующий HTML код:
Код:
<img src="https://abcdefg12345.fraudcheck.example.com/">
Если ваш прокси сервер имеет IP адрес из Нью-Йорка, а DNS сервер принадлежит провайдеру МедиаЛан из Костромы, вывод напрашивается сам собой.
К тому же, даже в случае менее явного несовпадения, сервис example.com сможет произвести проверку принадлежности IP вашего DNS сервера к сети Tor, или же поискать этот IP в списке известных публичных DNS серверов.
Почему так происходит.
Начнём с того, что DNS в большинстве случаев работает по протоколу UDP, и не все соксификаторы поддерживают проксирование UDP через socks версии 5, которая позволяет это делать. Но не это главное.
Когда мы рассматривали принцип работы DNS, я объяснил, что адрес вашего DNS сервера обычно соответствует вашему маршрутизатору или корпоративному DNS. То есть ваш DNS сервер находится в вашей локальной сети. Чтобы избежать утечки DNS, адрес локального DNS сервера нужно заменить на какой-то другой.
Возникает вопрос, а к какому DNS серверу проксировать трафик? Этот вопрос является одним из ключевых и мы вернёмся к нему немного позднее.
А пока что мы рассмотрим понятие Remote DNS.
Как работает socks-remote-dns в Firefox.
К великому счастью, протокол socks, начиная с версии 4а поддерживает адресацию в виде доменных имён, поэтому вся рутина, связанная с ресолвингом DNS, может происходить на стороне прокси сервера.
Иными словами, теперь таксофоном пользуетесь не вы, а ваш приятель, и находится он не в Костроме, а в Нью-Йорке. Вы звоните приятелю и просите соединить вас с вашим другом, при этом для вас уже совершенно не имеет значения, как именно он это сделает и какому нью-йоркскому оператору он будет звонить, чтобы получить данные из телефонного справочника.
Возвращаясь к нашему псевдокоду, выглядит это примерно так
Код:
hostname = "example.com";
if (socks_remote_dns) {
req.dst.addr = hostname;
req.atyp = 0x3; /* address type is HOSTNAME */
else {
req.dst.addr = getaddrbyname(hostname);
req.atyp = 0x1; /* address type is IP V4 */
}
/* ... */
send(socks, req, len);
И теперь мы закономерно возвращаемся к нашему вопросу о выборе DNS сервера, который будет использоваться в таких случаях.
Рассмотрим возможные решения.
Public DNS
Можно скрыть свой DNS, настроив операционную систему на использование какого-то публичного DNS сервера, например, 8.8.8.8
Очевидный минус, что как только сервис example.com обнаружит, что у вас есть возможность менять IP адреса, настанет время вычислить какой-то другой статичный параметр, по которому можно будет выявить вашу активность. Этим параметром будет ваш публичный DNS сервер.
Также вам вряд ли понравится, что публичный DNS сервер видит ваш IP адрес за соксом. Следовательно, вам нужно позаботиться и о том, чтобы ваш IP был скрыт. Для этого вам нужен или локальный DNS сервер, который одновременно будет являться сокс клиентом, или, как альтернатива, публичный DNS сервер с поддержкой DNS over HTTP.
dns-tcp-socks-proxy
Это именно то, о чём мы говорили выше. Данный инструмент представляет собой простейший DNS сервер, который работает через сокс прокси.
Все ваши DNS запросы будут перенаправляться через сокс прокси на случайный публичный DNS из списка. По умолчанию данный список содержит 40 публичных DNS серверов.
С одной стороны, вы решите проблему смены DNS и даже скроете свой IP адрес.
С другой стороны, обнаружить вашу активность станет ещё легче. Вспомним наш пример с внедрением HTML кода на страницу:
Код:
<img src="https://abcdefg12345.dns.fraudcheck.example.com/">
<img src="https://hijklmn67890.dns.fraudcheck.example.com/">
а) вы используете рандомный DNS сервер,
б) ваш DNS сервер входит в список публичных DNS серверов.
Tor
Пакет tor имеет свой собственный DNS сервер, который позволяет вам отправлять DNS запросы через сеть Tor.
Однако вы должны понимать, что вряд ли легитимные пользователи сервиса example.com используют Tor DNS. Таким образом будет очень легко вычислить вашу активность на веб сайте сервиса.
Fake IP
Это мой любимый метод. Примерно такая реализация используется в программе Proxifier.
Достаточно надёжное решение, которое может быть реализовано в любой операционной системе.
Суть заключается в том, чтобы запустить свой собственный локальный DNS сервер, который присваивает каждому домену локальный фейковый IP адрес вида 127.8.x.x, например, 127.8.123.45.
Таким образом сокс клиенту достаточно всего лишь отслеживать трафик, маркированный подменённым IP, и выполнять обратную замену фейкового IP на доменное имя, чтобы ресолвинг происходил уже на стороне сокс сервера, как это происходит при использовании remote DNS.
Минус здесь только в том, что поскольку мы не знаем настоящий IP, мы не можем применять к нему какие-либо правила, потому что ваш прокси клиент будет думать, что example.com имеет IP адрес 127.8.123.45.
Также если говорить о работе приложения, которое находится под контролем противодействующей вам стороны, в нашем примере сервиса example.com, ничто не мешает приложению выявлять факт использования проксифаера, просто сравнивая ответ DNS сервера с ожидаемым либо проверяя, не содержит ли ответ такой локальный фейковый IP.
Код:
remote_ip = getaddrbyname("example.com");
if (is_local_ip(remote_ip)) {
fraudscore += 10;
}
В конечном счете можно прийти к выводу, что универсального решения, которое бы смогло покрыть все 100% возможных сценариев, на стороне пользователя просто не существует.
Пожалуй, идеальным решением было бы предоставить пользователям возможность выполнять DNS запросы, минуя все эти костыли.
Возможно, настало время задаться теоретическим вопросом, а почему бы сокс клиенту просто не обращаться напрямую к тому же DNS, к которому обращается сокс сервер при активации remote DNS?
Теоретически это возможно, однако для этого необходимо решить следующие практические задачи:
Во-первых, мы не знаем адрес DNS, который используется сокс сервером.
Во-вторых, как уже было сказано, DNS чаще всего находится во внутренней сети, и в большинстве случаев сокс сервер будет настроен так, чтобы не позволить вам обращаться к своей внутренней сети в нарушение всех политик безопасности. И к тому же никто не сможет вам гарантировать, что вы не столкнётесь с конфликтом из-за одниковой адресации в вашей локальной сети и в локальной сети сокс сервера.
В-третьих, вам нужно, чтобы все используемые сокс серверы позволяли вам реализовать данный метод.
Как мы видим, справиться со всем этим возможно только на уровне какого-то частного решения. Владелец такого решения должен озаботиться, чтобы на всех сокс серверах был выделен локальный адрес, который не блокируется соксом и не конфликтует с сетями пользователей. И тогда вам лишь останется обзавестись локальным DNS сервером, который будет обрабатывать все ваши DNS запросы соответствующим образом.
В заключение - А что по поводу VPN?
Разумеется всё что касается утечки DNS справедливо и для VPN. Однако в отличии от SOCKS протокола, VPN позволяет вам осуществлять то что мы называем remote DNS вообще без каких-либо ограничений. Даже если DNS находится во внутренней сети сервера. Потому как VPN как раз и предназначен для предоставления доступа ко внутренним сетям. Также с VPN вы без труда сможете скрыть свой IP от используемого вами публичного DNS сервера. И конечно же ваш конфиг не будет зависеть от того какой протокол используется DNS сервером (UDP или TCP).
Полезные ссылки.
- DNS Socks Proxy: https://github.com/jtRIPper/dns-tcp-socks-proxy
- Список публичных DNS с выборкой по странам: https://public-dns.info/
- Proxifier: https://www.proxifier.com/
- Remote DNS в Chromium: https://www.chromium.org/developers/design-documents/network-stack/socks-proxy/
- Описание протокола SOCKS Version 5: https://www.rfc-editor.org/rfc/rfc1928.html