Пару лет назад возникла идея сделать локальный bittorrent-ретрекер для пользователей нашей «домашней» городской сети, чтобы и пользователи быстрее скачивали и у нас меньше трафика было. Установкой самого ретрекера дело только начиналось, необходимо было как-то анонсировать его для скачиваемых торрентов. В процессе выяснения способов и механизмов анонса я пришёл к достаточно общему и универсальному алгоритму, с которым и предлагаю познакомиться.
Итак, первое:
Существуют три способа обьявить о существовании трекера в локальной сети:
Каждый из них имеет свои преимущества и недостатки, соответственно:
Для начала сделали поддержку первых двух вариантов, благо никаких особых усилий для этого не требовалось: добавить в DNS несколько записей (retracker.local IN A и retracker.smarthome.spb.ru _SRV_) просто.На несовместимость .local с zeroconf в данном случае можно закрыть глаза, поскольку в идеале DNS-запросы клиента с включенным zeroconf даже не должны доходить до нашего сервера. Update: Важная ремарка cadmi — для работоспособности .local у пользователя и нашего ретрекера нужно создавать зону не .local, а .retracker.local, что как раз и позволит совместить оба варианта.
Но всё же наиболее интересным и заманчивым выглядел третий вариант, так что я решил поискать информацию об общей технике изменения скачиваемых файлов на лету. Требования к серверу были просты:
К своему удивлению я обнаружил, что техник и open-source программ для такого перехвата и редактирования файлов практически нет. По большому счёту, их всего две: это Squid с экспериментальными модулями ICAP/ECAP и некий фильтрующий прокси под названием "MiddleMan", последний релиз которого вышел в далёком 2004 году, но который продолжает поддерживаться в портах.
От использований Squid я отказался практически сразу: несмотря на наличие сразу двух экспериментальных модулей для работы с проходящим трафиком, решение оказалось чрезвычайно «кривым» и неустойчивым даже в установке и настройке, не говоря уж о работе.
Перешёл к middleman. Поразительно, но факт — старая программа оказалась функциональней и удобней современного монстра Squid. В сущности, он удовлетворяет всем требованиям, кроме полной прозрачности для пользователя — source ip пользователя переписывается на ip сервера с прокси. Замечу, что возможность оставлять source ip есть только у Squid с модулем TPROXY под Linux. Более того, у него есть уникальная опция — при превышении настраиваемого таймаута ожидания прокси отдаёт пользователю неизменённый исходный файл.
Для начала я написал небольшой perl'овый скрипт, который через pcap слушает 80 порт и собирает ip-адреса, на которые идут запросы с «Content-Type: application/x-bittorrent». Нужно это для того, чтобы перехватывать не весь http-трафик, а только тот, который принадлежит крупным трекерам.
Затем путём нехитрых манипуляций эти ip-адреса заносятся в таблицу ipfw, используемую при перенаправлении на наш прокси:
Скрипту mypatcher.pl передаются файлы с mime-типом «application/x-bittorrent», он добавляет в него запись локального трекера (убирая при этом retracker.local, если он там есть, что решает проблемы клиентов с zeroconf) и передаёт содержимое обратно прокси, попутно сохраняя файл ещё и на диск, в таком виде:
Итог работы: на сервере, который выполняет NAT, шейпинг и роутинг сети из 3000 пользователей, загрузка mman вообще не ощутима. В день сейчас таким образом редактируется порядка 200-400 файлов. Нареканий за почти год работы не было, все довольны.
Update 1. «Сохранение файлов на диск» служит исключительно для сбора обезличенной статистики в виде, указанном выше. Ну и попросту я забыл отключить этот механизм отладки скрипта. :) Cadm
Итак, первое:
Что делать
Существуют три способа обьявить о существовании трекера в локальной сети:
- Использовать добавляемыми некоторыми трекерами адрес retracker.local
- Анонсировать локальный трекер посредством механизма isp.bep22
- Перехватывать скачиваемые торрент-файлы и редактировать их, добавляя адрес нашего торрента, «на лету»
Каждый из них имеет свои преимущества и недостатки, соответственно:
- Использование зоны .local противоречит черновику RFC «Multicast DNS» и вызывает проблемы в работе zeroconf-сервисов Linux и Apple; добавляется лишь немногими трекерами
- Isp.bep22 работает, насколько мне известно, лишь в клиенте µTorrent и то выключен по умолчанию
- О перехвате трафика нет никаких упоминаний с success stories, за исключением единственного опыта дружественной сети
Для начала сделали поддержку первых двух вариантов, благо никаких особых усилий для этого не требовалось: добавить в DNS несколько записей (retracker.local IN A и retracker.smarthome.spb.ru _SRV_) просто.
Но всё же наиболее интересным и заманчивым выглядел третий вариант, так что я решил поискать информацию об общей технике изменения скачиваемых файлов на лету. Требования к серверу были просты:
- Работа во FreeBSD
- Open-source
- Прозрачность (незаметность) работы для клиента
- Определение трафика 7 уровня и восстановление файлов из http-потока
- Передача этих файлов редактирующему скрипту и получение их обратно
- Передача отредактированных файлов клиенту
Чем делать
К своему удивлению я обнаружил, что техник и open-source программ для такого перехвата и редактирования файлов практически нет. По большому счёту, их всего две: это Squid с экспериментальными модулями ICAP/ECAP и некий фильтрующий прокси под названием "MiddleMan", последний релиз которого вышел в далёком 2004 году, но который продолжает поддерживаться в портах.
От использований Squid я отказался практически сразу: несмотря на наличие сразу двух экспериментальных модулей для работы с проходящим трафиком, решение оказалось чрезвычайно «кривым» и неустойчивым даже в установке и настройке, не говоря уж о работе.
Перешёл к middleman. Поразительно, но факт — старая программа оказалась функциональней и удобней современного монстра Squid. В сущности, он удовлетворяет всем требованиям, кроме полной прозрачности для пользователя — source ip пользователя переписывается на ip сервера с прокси. Замечу, что возможность оставлять source ip есть только у Squid с модулем TPROXY под Linux. Более того, у него есть уникальная опция — при превышении настраиваемого таймаута ожидания прокси отдаёт пользователю неизменённый исходный файл.
Как делать
1. Определение самых популярных торрент-серверов
Для начала я написал небольшой perl'овый скрипт, который через pcap слушает 80 порт и собирает ip-адреса, на которые идут запросы с «Content-Type: application/x-bittorrent». Нужно это для того, чтобы перехватывать не весь http-трафик, а только тот, который принадлежит крупным трекерам.
Затем путём нехитрых манипуляций эти ip-адреса заносятся в таблицу ipfw, используемую при перенаправлении на наш прокси:
${ipfw} add fwd ${proxy_ip}, ${proxy_port} tcp from $lan_customers to 'table(15)' dst-port 80 in via ${int_if}
2. Конфигурация прокси-сервера middleman
Секция, ответственная за отдачу файлов редактирующему скрипту, называется external в mman.xml.3. Редактирующий «внешний» скрипт
Скрипту mypatcher.pl передаются файлы с mime-типом «application/x-bittorrent», он добавляет в него запись локального трекера (убирая при этом retracker.local, если он там есть, что решает проблемы клиентов с zeroconf) и передаёт содержимое обратно прокси, попутно сохраняя файл ещё и на диск, в таком виде:
#for i in `find /home/torrents/patched/ -type d`; do echo -n "$i" && ls -1 $i| wc -l; done | awk '{print $2" "$1}' | sort -rn | head -n 10
24103 /home/torrents/patched/dl.rutracker.org
7817 /home/torrents/patched/dl.torrents.ru
6184 /home/torrents/patched/tfile.ru
3744 /home/torrents/patched/kinozal.tv
2928 /home/torrents/patched/rutor.org
2872 /home/torrents/patched/torrents.thepiratebay.org
2583 /home/torrents/patched/www.tfile.ru
2582 /home/torrents/patched/www.torrentino.ru
2531 /home/torrents/patched/pornolab.net
1032 /home/torrents/patched/www.rutor.org
Итог работы: на сервере, который выполняет NAT, шейпинг и роутинг сети из 3000 пользователей, загрузка mman вообще не ощутима. В день сейчас таким образом редактируется порядка 200-400 файлов. Нареканий за почти год работы не было, все довольны.
Update 1. «Сохранение файлов на диск» служит исключительно для сбора обезличенной статистики в виде, указанном выше. Ну и попросту я забыл отключить этот механизм отладки скрипта. :) Cadm