Фильтрация DNS запросов от браузера
От: Аноним  
Дата: 16.05.11 09:50
Оценка:
Здравствуйте

Возникла задача написать приложение Parental Control, которое работает под двумя системами — BSD и Windows(XP-7).

И нужна точка старта, с которой я бы мог начать копаться в документации
Мне нужно распознать, что приложение, которое ломиться в сеть — браузер, и не позволить этому браузеру перейти по ссылке, если ее доменное имя находится в черном списке. Собственно, на фильтрации DNS запросов я и застрял.
Подскажите, как лучше такое сделать?

Первое решение которое приходит в голову — Windows TDI фильтр (BSD — NKE фильтр, что практически аналогично TDI фильтру, только для BSD), который просматривает все DNS запросы системы, и возвращает DNS-ответ вида 127.0.0.1 на "неугодные" домены.

Но DNS кешируется, в BSD есть файл /etc/hosts, который просматривается перед каждым запросом "в настоящий Интернет" для разрешения DNS-имени (не уверен насчет Windows — но и там очевидно что-то кешируется). То есть нужно обработать и запросы к кешу DNS . Слышал что существует некая LSP для Windows. Также можно использовать pcap для просмотра трафика (и остановки его). Под BSD можно использовать ipfw. Но вот что именно лучше подходит для этой цели пока не знаю .

Возможно ли как-то идентифицировать, что запрос к DNS был сделан именно от браузера, а не от другого приложения вроде Windows Update?

Заранее благодарен!
Re: Фильтрация DNS запросов от браузера
От: acDev Россия  
Дата: 16.05.11 10:49
Оценка: 1 (1)
Здравствуйте, Аноним, Вы писали:

А>Первое решение которое приходит в голову — Windows TDI фильтр ...

A>Также можно использовать pcap для просмотра трафика (и остановки его).

Зачем вам вообще DNS отсеживать? У меня вот все DNS адреса кеширует фаервол (это уже давно "модно").
Почему просто не смотреть на содержимое HTTP залоловка всех TCP пакетов?
Нафига вам WinPCap, коли TDI решили заюзать?

А>Возможно ли как-то идентифицировать, что запрос к DNS был сделан именно от браузера, а не от другого приложения вроде Windows Update?

Вы сначала попробуйте процесс браузера Х отличить от процесса НЕ_браузера Y ... нафиг это не нужно.
Re[2]: Фильтрация DNS запросов от браузера
От: Аноним  
Дата: 16.05.11 14:36
Оценка:
Здравствуйте, acDev,

Спасибо за ответ

А>>Первое решение которое приходит в голову — Windows TDI фильтр ...

A>>Также можно использовать pcap для просмотра трафика (и остановки его).

D>Зачем вам вообще DNS отсеживать? У меня вот все DNS адреса кеширует фаервол (это уже давно "модно").


хотелось бы еще и HTTPS фильтровать, поэтому смотрел в сторону DNS..

D>Почему просто не смотреть на содержимое HTTP залоловка всех TCP пакетов?


Поля HTTP (я так понимаю, поле Host), все браузеры их добавляют для абсолютно всех сайтов? Оно всегда совпадает с тем, что написано в адресной строке браузера до первого слеша?

D>Нафига вам WinPCap, коли TDI решили заюзать?

Потому что в ядре опыт у меня не большой и если я могу обойтись только юзермодом, я бы воспользовался этой возможностью.
Re[3]: Фильтрация DNS запросов от браузера
От: IID Россия  
Дата: 17.05.11 10:55
Оценка: 2 (1)
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, acDev,


А>Спасибо за ответ


А>>>Первое решение которое приходит в голову — Windows TDI фильтр ...

A>>>Также можно использовать pcap для просмотра трафика (и остановки его).

D>>Зачем вам вообще DNS отсеживать? У меня вот все DNS адреса кеширует фаервол (это уже давно "модно").


DNS шлётся не от имени процесса браузера, а от имени системной службы.

А>хотелось бы еще и HTTPS фильтровать, поэтому смотрел в сторону DNS..


D>>Почему просто не смотреть на содержимое HTTP залоловка всех TCP пакетов?


А>Поля HTTP (я так понимаю, поле Host), все браузеры их добавляют для абсолютно всех сайтов? Оно всегда совпадает с тем, что написано в адресной строке браузера до первого слеша?


Поля Host может и не быть.

D>>Нафига вам WinPCap, коли TDI решили заюзать?

А>Потому что в ядре опыт у меня не большой и если я могу обойтись только юзермодом, я бы воспользовался этой возможностью.

WinPCap не позволяет модифицировать пакеты.

Если привязка к процессу не нужна — перехватывать и модифицировать пакеты можно с помощью WinPkFilter. (гугл в помощь). Но он платный. Зато есть под все версии Win.
kalsarikännit
Re[4]: Фильтрация DNS запросов от браузера
От: x64 Россия http://x64blog.name
Дата: 17.05.11 11:19
Оценка: 1 (1)
IID>Поля Host может и не быть.

Да, к слову, некоторые крупные сайты не отдают контент, пока не придёт поле Host.
JID: x64j@jabber.ru
Re[3]: Фильтрация DNS запросов от браузера
От: x64 Россия http://x64blog.name
Дата: 17.05.11 11:21
Оценка: 2 (2)
А>хотелось бы еще и HTTPS фильтровать...

Это делается совсем по-другому.
Либо перехватывать внутренние вызовы в каждом броузере.
Либо внедрять собственные сертификаты и делать универсальный фильтр.
JID: x64j@jabber.ru
Re[4]: Фильтрация DNS запросов от браузера
От: Аноним  
Дата: 17.05.11 21:21
Оценка:
Здравствуйте, IID, Вы писали:

А>>Поля HTTP (я так понимаю, поле Host), все браузеры их добавляют для абсолютно всех сайтов? Оно всегда совпадает с тем, что написано в адресной строке браузера до первого слеша?


IID>Поля Host может и не быть.


то есть сканирование пакетов с HTTP запросами мне никак не поможет, и нужно ловить все запросы к DNS и разобраться со всеми существующими в системах BSD/Windows XP/7 кешами DNS?
Не подскажете тогда с чего начать чтение? Если даже файерволы кешируют dns, то я не знаю что делать

D>>>Нафига вам WinPCap, коли TDI решили заюзать?

А>>Потому что в ядре опыт у меня не большой и если я могу обойтись только юзермодом, я бы воспользовался этой возможностью.

IID>WinPCap не позволяет модифицировать пакеты.


модифицировать и не нужно, но можно же сгенерировать пустой подложный пакет и отдать браузеру? Где то встречал такое..

IID>Если привязка к процессу не нужна — перехватывать и модифицировать пакеты можно с помощью WinPkFilter. (гугл в помощь). Но он платный. Зато есть под все версии Win.


Но если Host не всегда включается в пакет, то это мне не сильно поможет . А в каких случаях на практике браузеры "забывают" его добавить в заголовок запроса?
Re[5]: Фильтрация DNS запросов от браузера
От: x64 Россия http://x64blog.name
Дата: 17.05.11 23:08
Оценка: 2 (1)
А>Но если Host не всегда включается в пакет, то это мне не сильно поможет

Да нет же. Просто в этом случае доменное имя следует брать не из заголовка запроса, а из IP-адреса, на который идёт коннект, предварительно сконвертировав его в доменное имя посредством отправки DNS-запроса самостоятельно. Это либо через DnsQuery_Xxx() можно сделать, либо вручную, если из ядра, при этом адрес DNS-сервера брать либо из реестра, либо с DHCP-сервера, адрес которого опять же брать из реестра.

А>А в каких случаях на практике браузеры "забывают" его добавить в заголовок запроса?


Не помню. Возможно, в тех случаях, когда пользователь вводит в адресной строке IP-адрес, вместо имени домена? Хотя, по идее, даже в этом случае броузер должен заполнить поле Host:, просто вместо доменного имени написать там полученный от пользователя IP-адрес.
JID: x64j@jabber.ru
Re: Фильтрация DNS запросов от браузера
От: okman Беларусь https://searchinform.ru/
Дата: 18.05.11 07:02
Оценка: 2 (1)
Здравствуйте, Аноним, Вы писали:

А>...


А>Первое решение которое приходит в голову — Windows TDI фильтр (BSD — NKE фильтр, что практически аналогично TDI фильтру, только для BSD), который просматривает все DNS запросы системы, и возвращает DNS-ответ вида 127.0.0.1 на "неугодные" домены.


А>Но DNS кешируется, в BSD есть файл /etc/hosts, который просматривается перед каждым запросом "в настоящий Интернет" для разрешения DNS-имени (не уверен насчет Windows — но и там очевидно что-то кешируется). То есть нужно обработать и запросы к кешу DNS . Слышал что существует некая LSP для Windows. Также можно использовать pcap для просмотра трафика (и остановки его). Под BSD можно использовать ipfw. Но вот что именно лучше подходит для этой цели пока не знаю .


А>...


Фильтрацией DNS эта задача в полном объеме не решается.
Во-первых, сказывается кэширование DNS-запросов, а время жизни данных в кэше может
быть очень продолжительным.
Во-вторых, ничто не защитит от пользователя, который наберет 87.240.188.249 в адресной строке
браузера и окажется на главной странице "В Контакте", в обход DNS-фильтра.

Относительно несложное решение (для Windows) заключается в написании TDI-фильтра,
перехватывающего исходящие соединения на 80 порт (TDI_CONNECT) и проверки IP пункта
назначения по базе "черных" адресов. Неугодные адреса элементарно перекидываются на
127.0.0.1:спецпорт, где работает простенький HTTP-сервер, возвращающий страницу-заглушку.
Поскольку на одном IP может находиться несколько сайтов, логично к этой проверке добавить
мониторинг заголовка Host в исходящих запросах — это, кстати, можно делать уже за пределами
режима ядра.

С LSP связываться не советовал бы.
Во-первых, приличный объем стартового кода (порядка нескольких тысяч строк для простого прототипа).
Во-вторых, слабая документация и почти полное отсутствие вменяемых исходников, которые можно
просто взять и скомпилировать.
В-третьих, упоминания об этой технологии в MSDN весьма скудные и, как правило, снабжены тавро "deprecated".
Более того, я неоднократно слышал упреки в том, что LSP реализована кривовато и может "откидывать
коленца" на ровном месте. Лучше обратиться к более актуальным и перспективным вещам — WFP, например.
Re: Фильтрация DNS запросов от браузера
От: ononim  
Дата: 18.05.11 11:24
Оценка:
А>Но DNS кешируется, в BSD есть файл /etc/hosts, который просматривается перед каждым запросом "в настоящий Интернет" для разрешения DNS-имени (не уверен насчет Windows — но и там очевидно что-то кешируется). То есть нужно обработать и запросы к кешу DNS . Слышал что существует некая LSP для Windows.
В данном случае надо NSP — namespace provider — http://msdn.microsoft.com/en-us/library/ms739923(v=vs.85).aspx
Как много веселых ребят, и все делают велосипед...
Re[6]: Фильтрация DNS запросов от браузера
От: Аноним  
Дата: 19.05.11 08:05
Оценка:
Здравствуйте, x64, Вы писали:

А>>Но если Host не всегда включается в пакет, то это мне не сильно поможет


x64>Да нет же. Просто в этом случае доменное имя следует брать не из заголовка запроса, а из IP-адреса, на который идёт коннект, предварительно сконвертировав его в доменное имя посредством отправки DNS-запроса самостоятельно. Это либо через DnsQuery_Xxx() можно сделать, либо вручную, если из ядра, при этом адрес DNS-сервера брать либо из реестра, либо с DHCP-сервера, адрес которого опять же брать из реестра.


Спасибо!

А>>А в каких случаях на практике браузеры "забывают" его добавить в заголовок запроса?


x64>Не помню. Возможно, в тех случаях, когда пользователь вводит в адресной строке IP-адрес, вместо имени домена? Хотя, по идее, даже в этом случае броузер должен заполнить поле Host:, просто вместо доменного имени написать там полученный от пользователя IP-адрес.


Спасибо!
А в TDI возможно "задержать" пакет с GET-запросом от браузера (на время верификации запрошенного адреса)? Просто я проверяю доменное имя запрошенного браузером адреса на внешнем "верификационном" сервере — этот сервер возвращает "да/нет" в зависимости от того, запрещенный ли это ресурс.
В BSD задержка пакетов делается просто, а вот в TDI как — без понятия. Не подскажете?
Re[2]: Фильтрация DNS запросов от браузера
От: Аноним  
Дата: 19.05.11 08:25
Оценка:
Здравствуйте, okman, Вы писали:

Спасибо за развернутый ответ

O>Фильтрацией DNS эта задача в полном объеме не решается.

O>Во-первых, сказывается кэширование DNS-запросов, а время жизни данных в кэше может
O>быть очень продолжительным.
O>Во-вторых, ничто не защитит от пользователя, который наберет 87.240.188.249 в адресной строке
O>браузера и окажется на главной странице "В Контакте", в обход DNS-фильтра.

x64 посоветовал обойти эту проблему с помощью reverse dns запроса, и вместо dns проверять IP.

O>Относительно несложное решение (для Windows) заключается в написании TDI-фильтра,

O>перехватывающего исходящие соединения на 80 порт (TDI_CONNECT) и проверки IP пункта
O>назначения по базе "черных" адресов. Неугодные адреса элементарно перекидываются на
O>127.0.0.1:спецпорт, где работает простенький HTTP-сервер, возвращающий страницу-заглушку.
O>Поскольку на одном IP может находиться несколько сайтов, логично к этой проверке добавить
O>мониторинг заголовка Host в исходящих запросах — это, кстати, можно делать уже за пределами
O>режима ядра.

мне хотелось бы чтоб использование прокси не позволяло обойти фильтр. Ведь не всегда GET запросы идут через 80 порт. Поэтому я просматриваю (вернее, собираюсь так сделать) TDI_SEND содержимое (а GET запрос всегда "умещается" в одном TDI_SEND вызове?). Также я пропускаю и этот TDI_SEND, и жду RECEIVE — которые собираю в буфере. Затем я обращаюсь к внешнему серверу, который говорит что данный Host является запрещенным/разрешенным. Если разрешен, то я буфер "сбрасываю" в сокет браузера. Если запрещен, буфер освобождается, а в сокет возвращается HTTP OK и HTML код сообщения "Not allowed".

Запрос к внешнему серверу мне нужно сделать обязательно.
Если вас и x64 не затруднит, не могли бы вы прокомментировать описанный способ и проблемы с которыми мне придется воевать?

O>С LSP связываться не советовал бы.

O>Во-первых, приличный объем стартового кода (порядка нескольких тысяч строк для простого прототипа).
O>Во-вторых, слабая документация и почти полное отсутствие вменяемых исходников, которые можно
O>просто взять и скомпилировать.
O>В-третьих, упоминания об этой технологии в MSDN весьма скудные и, как правило, снабжены тавро "deprecated".
O>Более того, я неоднократно слышал упреки в том, что LSP реализована кривовато и может "откидывать
O>коленца" на ровном месте.

Поверю вам и не буду с ним связываться

O>Лучше обратиться к более актуальным и перспективным вещам — WFP, например.


А TDI и WFP как-то связаны? Или мне нужно отдельно писать TDI, а отдельно — WFP, если я хочу чтоб работало на Windows XP, Vista и Windows 7?
Спасибо за помощь
Re[6]: Фильтрация DNS запросов от браузера
От: Аноним  
Дата: 19.05.11 08:47
Оценка:
Здравствуйте, x64, Вы писали:

А>>Но если Host не всегда включается в пакет, то это мне не сильно поможет


x64>.... либо вручную, если из ядра, при этом адрес DNS-сервера брать либо из реестра, либо с DHCP-сервера, адрес которого опять же брать из реестра.


И, простите за наглость, но есть какие-нибудь варианты максимально перенести задачу из ядра в юзермод? В последнем я намного комфортнее себя чувствую и не смогу угробить систему пользователя, если что-то забуду предусмотреть
Может быть стоит попробовать WinPkFilter?
Re[3]: Фильтрация DNS запросов от браузера
От: okman Беларусь https://searchinform.ru/
Дата: 19.05.11 09:09
Оценка: 3 (1)
Здравствуйте, Аноним, Вы писали:

...

А>мне хотелось бы чтоб использование прокси не позволяло обойти фильтр. Ведь не всегда GET запросы идут через 80 порт.


Никто не заставляет мониторить только 80 порт. Только тогда встает вопрос определения протокола.

А>Поэтому я просматриваю (вернее, собираюсь так сделать) TDI_SEND содержимое (а GET запрос всегда "умещается" в одном TDI_SEND вызове?). Также я пропускаю и этот TDI_SEND, и жду RECEIVE — которые собираю в буфере.


Хорошо, а если юзер запросом GET скачивает гигабайтный файл ?

А>Затем я обращаюсь к внешнему серверу, который говорит что данный Host является запрещенным/разрешенным.


А пока выполняется этот запрос, у пользователя истекает таймаут соединения (или не выдерживают нервы).
Надо подумать о кэшировании.

А>Если разрешен [Host], то я буфер "сбрасываю" в сокет браузера. Если запрещен, буфер освобождается, а в сокет возвращается HTTP OK и HTML код сообщения "Not allowed".


А если Ваш сервер не ответит ?

----------------

Первое, чем бы я посоветовал заняться — изучить досконально спецификацию HTTP.
Поверьте, там много неочевидных, на первый взгляд, тонкостей, которые выявляются уже на той
стадии, когда приходится менять и переписывать слишком многое.

Вы готовы обработать ситуацию, когда сервер вернет код 401 (требуется авторизация) или
302 (объект найден по другому URI) ? Например, www.google.com перекидывает меня на www.google.by.
Более того, распостранена ошибка считать, что после ответа сервер закрывает соединение — это не так.
То есть, запросы-ответы могут сновать туда-сюда и еще надо принять во внимание потенциально возможную
ситуацию, когда тело GET-запроса режется на 2 и более кусков. И сервер может отдать
ответ сразу же после прочтения первых двух-трех заголовков запроса, не дожидаясь остальных.

...

O>>Лучше обратиться к более актуальным и перспективным вещам — WFP, например.


А>А TDI и WFP как-то связаны? Или мне нужно отдельно писать TDI, а отдельно — WFP, если я хочу чтоб работало на Windows XP, Vista и Windows 7?


TDI прекрасно себя чувствует и в Vista/Seven, несмотря на то, что эта технология объявлена устаревшей.
Windows Filtering Platform появилась в Vista.
Ну можно было бы написать, что выбор — дело вкуса, но я лично с WFP вообще не работал, поэтому промолчу.
Re[7]: Фильтрация DNS запросов от браузера
От: x64 Россия http://x64blog.name
Дата: 19.05.11 09:55
Оценка: 2 (1)
А>А в TDI возможно "задержать" пакет с GET-запросом от браузера...

Да.

А>...в TDI как — без понятия. Не подскажете?


Также, как и любой I/O запрос.
См. TDI_SEND, техника Cancel-Safe IRP Queues.
JID: x64j@jabber.ru
Re[7]: Фильтрация DNS запросов от браузера
От: x64 Россия http://x64blog.name
Дата: 19.05.11 10:09
Оценка:
А>...есть какие-нибудь варианты максимально перенести задачу из ядра в юзермод?

Начиная с Vista есть WFP, но без поллитра там не разберёшься, а так обычно LSP пишут.

А>Может быть стоит попробовать WinPkFilter?


Может быть, но я не пробовал.
JID: x64j@jabber.ru
Re[3]: Фильтрация DNS запросов от браузера
От: ononim  
Дата: 19.05.11 10:38
Оценка: 1 (1)
O>>Фильтрацией DNS эта задача в полном объеме не решается.
O>>Во-первых, сказывается кэширование DNS-запросов, а время жизни данных в кэше может
O>>быть очень продолжительным.
O>>Во-вторых, ничто не защитит от пользователя, который наберет 87.240.188.249 в адресной строке
O>>браузера и окажется на главной странице "В Контакте", в обход DNS-фильтра.
А>x64 посоветовал обойти эту проблему с помощью reverse dns запроса, и вместо dns проверять IP.
reverse dns штука очень не надежная:

F:\Downloads>ping vkontakte.ru -n 1

Pinging vkontakte.ru [93.186.224.242] with 32 bytes of data:

Reply from 93.186.224.242: bytes=32 time=50ms TTL=56

...

F:\Downloads>ping -a 93.186.224.242 -n 1

Pinging srv242-224.vkontakte.ru [93.186.224.242] with 32 bytes of data:
..

— почти хорошо..

F:\Downloads>ping google.com -n 1

Pinging google.com [74.125.77.147] with 32 bytes of data:
...

F:\Downloads>ping -a 74.125.77.147

Pinging ew-in-f147.1e100.net [74.125.77.147] with 32 bytes of data:
...

— уже хуже

F:\Downloads>ping mail.ru -n 1

Pinging mail.ru [94.100.191.201] with 32 bytes of data:
...

F:\Downloads>ping -a 94.100.191.201 -n 1

Pinging 94.100.191.201 with 32 bytes of data:

— совсем плохо
Как много веселых ребят, и все делают велосипед...
Re: Фильтрация DNS запросов от браузера
От: Michael7 Россия  
Дата: 20.05.11 10:52
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Мне нужно распознать, что приложение, которое ломиться в сеть — браузер, и не позволить этому браузеру перейти по ссылке, если ее доменное имя находится в черном списке. Собственно, на фильтрации DNS запросов я и застрял.

А>Подскажите, как лучше такое сделать?

Я вот не могу понять зачем для родительского контроля проверять не ломится ли именно браузер, а не просто отсекать всех и сразу? Просто на ум не приходит ничего, что надо было бы закрывать от детей, но при этом оно необходимо для системных целей, обновления программ и т.п. Кроме того, фильтрация DNS-запросов вещь не самая тривиальная.

Задача существенно упрощается если фильтровать всех, причем по IP, а не DNS.
Re[2]: Фильтрация DNS запросов от браузера
От: x64 Россия http://x64blog.name
Дата: 21.05.11 13:25
Оценка:
M>Я вот не могу понять зачем для родительского контроля проверять не ломится ли именно браузер, а не просто отсекать всех и сразу?

Какой ужос.
Даже отвечать не охота.
JID: x64j@jabber.ru
Re[6]: Фильтрация DNS запросов от браузера
От: IID Россия  
Дата: 23.05.11 05:49
Оценка:
Здравствуйте, x64, Вы писали:

x64>доменное имя следует брать не из заголовка запроса, а из IP-адреса, на который идёт коннект, предварительно сконвертировав его в доменное имя посредством отправки DNS-запроса самостоятельно.


А вот это очень плохая идея. Корректно сконвертировать IP адрес в доменное имя можно только при выполнении следующих условий:
1) на этом IP адресе есть только данный хост
2) в DNS прописана Reverse запись

Кроме того, такой запрос ещё и тормозной.

Чтобы корректно (и быстро) конвертировать IP адреса в доменные имена надо кешировать все отправленные DNS запросы и полученные ответы. Только учесть следующие моменты:
— на одном IP адресе может быть несколько хостов (всякие виртуалхостинги). Не актуально для ТС, т.к. у него в этом случае обязательно будет Host в HTTP запросе.
— TTL для DNS записи не стоит воспринимать слишком буквально. Да, DNS кеширование в ОС работает по этому TTL, но браузеры могут дополнительно "попридержать" полученный адрес, не обращаясь к системному резолверу.
— DNS запрос может поехать по TCP (на практике малореально)
kalsarikännit
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.