Пишем свой caching nameserver с фильтрацией
пост написан и отправлен в печать 2011-04-09 примерно в 10:58
Прежде чем начинать свое повествование, маленькое сообщение для всех, кто прочитал топик поста и закачал убеленной сединой\лысиной головой с неприкрытым укором: да, я знаю о существовании BIND и да, я знаю про MySQL BIND SDB, или даже про MyDNS тоже слышал, и настроить кеширующий child неймсервер умею. Увы, реализация такой комбинации не виделась мне целесообразной по ряду причин о которых я не буду тут писать. В любом случае, мне нужно было сделать DNS с фильтрацией определенных доменных имен с хранением списка этих имен на центральном сервере в MySQL базе данных. Нужно было сделать его не намного медленней родного варианта, что было вполне нетривиальной задачей. Думаю, что для начала мне стоит объяснить, зачем это все задумывалось. Как упоминалось в прошлом посте, я работаю в компании основным направление деятельности которой является предоставление сервиса защищенного VPN туннеля для обхода корпоративных фаерволов, шифрования трафика, защиты от man-in-the-middle и прочих мерзких снифферов, получения своего личного реального IP где-то в странах экваториальной Америки, ну и для защиты от вирусов с помощью решений от тов. Касперского. В качестве серверных площадок используются разнообразные virtual dedicated и root dedicated от разных провайдеров по всему миру. И вот тут возникает основная проблема, которая загубила большинство подобных сервисов - торренты. Да, в большинстве TOS-ов большинства хостеров ясно прописано, что если с вашего сервера будет замечена подозрительная активность по загрузке из интернета нелегального контента, то вы автоматически лишаетесь предоставляемой услуги без какой-либо надежды на материальное возмещение. Звучит достаточно печально, учитывая предоплату на целый год. В итоге, часто получаешь подобные письма, рассылаемые полуавтоматическими системами правозащитных ищеек, что не добавляет хорошего настроения в твой и так не особо веселый рабочий день. Каким образом они отслеживают попытку скачивания торрента? Fake Seed к примеру? Или просто фильтруют запросы к торрент трекерам? Я без понятия, но вот если правильным образом не среагировать на подобное письмо, убедив хостера, что этот мудак, качающий Спанжбоба, физически устранен, а вся его семья стерилизована - можно получить серьезные проблемы. Вплоть даже до судебного разбирательства, все мы новости читаем. Это проблема, теперь поговорим о решении. Любой системный администратор скажет вам, что не существует оптимального решения перекрытия кислорода p2p трафику. Да, можно ограничивать количество udp сессий одного хоста (что достаточно глупое решение, учитывая саму природу протокола с неявным закрытием соединения), можно вообще закрыть udp (что еще глупее, одним махом лишаем пользователя всяких скайпов\сипов, а торрент клиенты могут спокойно и через TCP работать), можно использовать всякие модули фильтрации уровня iptables вроде ipp2p, OpenDPI, l7-filter (на сайте пишут про высокий perfomance, но у меня la вскакивал до 1 при 10 соединениях и иногда всплывали defunct зомби) или вообще пускать весь трафик OpenVPN  в лоб через фильтрующий прокси сервер (мною было опробовано все из списка, увы, все решения крайне требовательны к системным ресурсами из-за необходимости прочесывания регулярками большого потока данных и по этой причине не подошли, не все сервера в сети могли позволить себе такую роскошь). Есть еще решения для дураков: закрытие типичных портов, что не работает в условиях современных клиентов и тот вариант, который выбрал я - DNS блокировка главных торрент трекеров. Защита ужасная, ничто не мешает клиенту после подключения выставить вместо присваиваемого неймсервера какой-то другой, данное решение к тому же не помогает, если пользователь начал скачивание торрента до подключения к нашему VPN-у (хотя моя практика показывает, что в таких случаях правозащитные ищейки молчат, что еще раз служит подтверждением конспирологической теории, что софт копирайтеров просто отслеживает announce запросы к трекерам), и конечно же данный вариант не спасает от DHT, которому вообще ничего не нужно: ни трекеры, ни днсы. Но работает же, количество писем от правообладателей сократилось до 1-2х за 3 месяца, возвращаем NXDOMAIN для всех доменных имен в блеклисте и живем припеваючи. Кстати, если кто имеет идеи, как побороть bittorrent в сети - скиньте мне хоть пару строк на mail@smirnoff.sumy.ua, чтоб я примерно знал, куда копать. С меня благодарности в приемном для вас эквиваленте.

Возвращаемся к теме реализации. Прежде всего, отвечаю на вопрос: зачем мне нужно много неймсерверов, а не один центральный без всех этих заморочек с MySQL и т.д. В качестве master мы будем использовать Google Public DNS, на нем был замечен load balancing для некоторых крупных сайтов, на запрос по тому же ютубу с разных географических точек отдавались разные A-записи. К тому же, проводить NS query с гонконгского сервера через туннель на центральный сервер где-то в Люксембурге или США - очень медленно, поэтому наши DNS-ы будут отвечать по тому же адресу, что и шлюз. Языком реализации стал Perl. Почему? Да просто в нем есть все необходимые нам компоненты. Использовать мы будем Net::DNS для резолвера и Net::DNS::Nameserver для сервера. Разумеется, без кеширования никуда. В качестве решения я советую смотреть в сторону Cache::Bounded, которое является по сути оберткой вокруг Cache::MemoryCache с оптимизацией и обнулением кеша по достижению определенного размера, что спасет нас от переполнения памяти. В результате получилось что-то вроде такого кода. Сразу замечу, что 3 цикла for при чтении ответа из кеша - необъяснимая мною мистика. Казалось бы с помощью тех же элементов исходного массива путем перебора формируем новый, а вот простое присваивание - не работает. И хоть ты тресни. По скорости вполне нормально, первый запрос конечно отнимает определенное время, но в дальнейшем из кеша в памяти все читается очень быстро. В качестве бонуса, держите список из 1800 самых крупных торрент трекеров для блокировки.

Как по мне, сервисы vpn туннелей должны служить исключительно 2м целям: скачивание торрентов в странах, где за это находят и бьют по рукам; и просмотр католическими священниками детской порнографии там, где это тоже не особо приветствуется. Первых случаев становится все больше, а последних - все меньше. Мы же нашим TOS-ом запрещаем основные приоритетные направления. А все остальные истории с  защитой вашей информации, все это сказки для детей. Мы то с вами знаем, что от паяльника еще ни один фаерволл или канал с шифрованием не спасал. 

Пишем свой web анонимайзер с пасьянсом и блудницами
пост написан и отправлен в печать 2011-04-04 примерно в 12:31
В качестве предыстории: я в поте лица и прочих не менее неудачных частей своего бренного тела работаю на славу, процветание и доброе имя компании, которая занимается разработкой "убийцы http://hidemyass.com/" и доброго десятка подобных ему сервисов. О развертывании и структуре сети vpn серверов на базе openvpn, борьбе с torrent трафиком, тоннами спамма, дешевыми vds-ками, индусским англоговорящем на китайском саппортом и прочими прелестями я напишу чуть позже, сегодня мы поговорим с вами об анонимайзере. Вас ист дас, Фальдемар? Дас ист такой себе быстрый браузерный "прокси", что-то типа http://www.hidemyass.com/proxy/, вы вводите ссылку, скрипт скачивает ее и отдает вам, минуя ограничения корпоративных firewall-ов например или скрывая ваш user-agent (кому в хуй ввалился ваш юзерагент, простите? ох уж эта paranoia™). В Педевикии есть много текста по данной теме. Как по мне, между нами девочками, - абсолютно ненужная затея, учитывая все сложности ее функционирования. Но, имей мое мнение хоть какой-либо удельный вес, мы бы сейчас занимались производством русского студенческого качественного порно, а не разработкой сервисов анонимности и безопасности в сети. Что достаточно грустно, спрос на порнуху все же много больше, ящетаю. Игнорирование потребностей рынка ведет нас в глухой угол.

Хиханьки-хахоньки, но изначально были осмотрены 2 бесплатных решения. PHPproxy и Glype. Вот только как-то не удалось мне получить дозу эстетического удовольствия от внутренностей и что самое главное - быстродействия, ну пацаны, 30 регулярок на 1 страницу - как-то слишком, ага. Да и совместимость с современными сайтами, расфуференными AJAX-ами, оставляла желать лучшего. Пришлось писать собственный велосипед. Сразу прошу простить за PHP, увы и ах, но таковы требования заказчиков для "глубокой интеграции" этого говна в глотку сайта. Прежде всего, я отказался от передачи URL проксимизируемого сайта в GET переменной, избрав более интересный путь. Для наглядного примера, данный блог, открытый посредством моего web-прокси, выглядит как https://mindcollapse.com.proxy.domain.com/blabla.html. Плюсы такого элегантного решения: удобная работа с кукисами, которые просто можно назначать данному сабдомену, а не хранить во временных файлах, как это делали вышеназванные реализации, легкость подмены ссылок в странице, в том числе и relative links, которые вообще трогать не нужно.  То бишь, мы просто добавляем .proxy.domain.com после доменного имени и направляем весь трафик через наш сервер. Теперь по поводу технологий реализации. Для начала, нам не помешает wildcard SSL сертификат с маской *.domain.com. Ну и никак не обойдемся без *.proxy A Record на неймсерверах нашего с вами домена. В апачевский конфиг sites-enabled/proxy.domain.com.conf добавляем ServerAlias *.proxy.domain.com. Пол работы сделано, теперь дело за малым - написать обработчик данных. Прежде всего, нам нужен правильный .htaccess с RewriteRule ^(.*)$ /proxy.php?$1 [L]. Теперь любые запросы будут реврайтится в REQUEST_URI proxy.php. Не забываем и про RewriteCond %{REQUEST_FILENAME} !-f, а иначе получите вечный редирект в поисках счастья. 

Лирическое отступление по поводу содержания proxy.php. Я как-то уже давненько не подходил к PHP, все в компилируемых языках, да в перлах по самые локти. Кстати, насчет последнего, кто там говорит, что перл мертв - посмотрите на количество живых велосипедов в CPAN. Одних только интерфейсов кеширования хватит даже чрезвычайно изощренному уму. Ну а про скоропостижную кончину кричит всякая школота, читающая клоаку вроде хабрахабра и мечтающая о заветном инвайте. Да, есть RubyForge и RubyGems, есть Pypi для монти пайтона, даже C# в Microsoft Visual Studio имеет менеджер компонентов, а совсем недавно силами коммьюнити еще и nuget вышел, который я все никак не посмотрю. И да, есть PEAR для PHP. Набор библиотек в нем, мягко говоря, скудный. PEAR "из коробки" не дает ставить пакеты у который релиз статус ниже stable, а как это отключить - приходится гуглить или устанавливать по ссылке, как-то не очень сопоставляется данные действия с определением "удобного менеджера компонентов". Ну да не важно, для нашего прокси мы будем использовать обвязку не вокруг CURL-а, а над fsockopen. Называется HTTP_Request2. Библиотека, между прочим, очень даже ничего. Пожалуй, хватит ходить вокруг да около: вот вам код proxy.php в копипастере. Хочу заметить, что это скорее болванка из которой я убрал большу часть кода используемую при разборе джаваскриптов и css, да и добрый 10к плагинов, которые заставляли работать ютубы и фейсбуки. Ничего там сложного нет, просто firebug или chrome developer tools вам в руки и копайтесь в куче непонятных кукисов и сжатых js-скриптов. Для последних, кстати, есть отличная утилита - JSBeautifier. Так что не нужно кричать "хааа, лох, у тебя же никак не проверяется вводимый урл, хаааа". Проверяется. Христом богом клянусь. У меня все.