Как Spotify может помочь в изучении демонов, RFC, сетей и продвижении опенсорса. Или что бывает, если заплатить не получается, а некоторые премиумные плюшки очень хочется.
Начало
Третьего дня было замечено, что Спотифай выдаёт рекламу на основании страны ip-адреса. Там же было замечено, что в некоторых странах рекламу не завезли совсем. Например, в РБ. И тут же созрел "гениальный" план по отключению рекламы в не премиумном аккаунте.
Немного про Spotify
Вообще говоря, у Спотифая странная политика. Нашему брату приходится изрядно извращаться, чтобы купить премиум: менять локацию в профиле на заморскую, искать подходящий гифткард, который можно оплатить только paypal-ом, который в последнее время чудит и хочет ворох документов. В общем, тоже приключение, но иного порядка. Хотя, большинство этим занимается ради мобильной версии, меня таковая не интересует. Поэтому всё нижеследующее поможет только в случае с десктопной версией. Мало того, никакого расширения функций не будет. Только отрезание некоторых лишних.
А чего сложного?
И я так думал, прописывая данные socks-proxy в конфиге Spotify. Проблема оказалась в том, что у них не работает аутентификация в socks по логину и паролю. Плюс разработчики регулярно что-то крутят вокруг проксика: то разрешая, то запрещая, то ломая его, что порождает целые полотнища обсуждений на офф.сайте.
Было решено не полагаться на нестабильные функции и найти что-то более надёжное и любопытное.
Где-то здесь читатель должен спросить: а чего бы не взять ssh
с ключиком -D
и дело с концом? И, в общем-то, будет прав. Но, во-первых, это ещё нужно демонизировать и подружить с autossh, чтобы не думать о рвущихся конектах. И во-вторых: это слишком просто и скучно.
По-порядку
Как обычно, давайте пойдём слева направо, сверху вниз и опишем всё что нам нужно для реализации нашей "простой" затеи.
Для начала нужен прокси
И сразу много альтернатив:
- можно просто пойти и взять из открытых проксилистов. Дёшево (точнее даром), но абсолютно ненадёжно и время жизни таких проксиков стремится к нулю. Поэтому надо бы найти/написать парсер прокси списков, фильтровать их по нужному типу и стране и вопрос подстановки найденного прокси в Spotify остаётся открытым (ну, разве что, через
HTTP_PROXY
передавать и кастомную обёртку для бинарника делать, чтобы весь остальной трафик туда же не отправить). - Можно купить аналогичный прокси и избавить себя от большинства вышеописанных проблем. Но при цене прокси можно сразу купить премиум на Спотифай, а это не спортивно в рамках исходной задачи.
- Поднять свой. Как вы, наверное, догадались — это наш выбор.
Чисто случайно может оказаться, что у вас есть друг с сервером в РБ или иной небольшой стране. Этим нужно пользоваться и раскатывать на нём желаемый проксик. Особые же ценители, могут довольствоваться другом с роутем на DD-WRT или аналогичном ПО. Но там свой дивный мир и в рамки сего рассказа этот мир явно не поместится.
Итак, наши варианты: Squid — не вдохновляет, да и не хочется HTTP-проксик, сего протокола и так слишком много вокруг. А в области SOCKS ничего толкового кроме Dante пока не завезли. Посему, берём его.
Манула по установке и настройке Данте не ждите. Он просто гуглится и особого интереса не представляет. В минимальной комплектации надо накидать всяких client pass
, socks pass
, правильно прописать интерфейсы да не забыть добавить socksmethod: username
. В таком виде для аутентификации логопас будет браться из пользователей системы. А часть про безопасность: запрет доступа к локалхосту, ограничение по юзерам и прочее — это уже чисто индивидуально в зависимости от личной паранойи.
Развернуть прокси лицом в сеть
Спектакль в двух актах.
Акт первый
С прокси разобрались, теперь надо получить к нему доступ из глобальной паутины. Если у вас есть машинка с белым IP в нужной стране, то можете смело пропускать этот пункт. У нас же таковой нет (мы, как говорилось выше, хостимся у друзей дома) и ближайший белый айпи где-то в Германии, поэтому будем изучать сети.
Таки да, внимательный читатель снова будет спрашивать: а чего бы вам не взять существующий сервис типа ngrok или ему подобный? И снова будет прав. Но ведь это сервис, его опять-таки нужно демонизировать, он тоже может стоить денег и вообще это не спортивно. Поэтому будем творить велосипеды из подручных материалов.
Задача: есть прокси где-то далеко за NAT-ом, надо его повесить на один из портов VPS, имеющей белый IP и расположенной на краю света.
Логично предположить, что это решается либо пробросом порта (который реализуется через вышеупомянутый ssh
), либо объединением железок в виртуальную сеть через VPN. С ssh
работать умеем, autossh
брать скучно, поэтому возьмём OpenVPN.
У DigitalOcean есть замечательный манул по этому делу. Добавить к нему мне нечего. А полученный конфиг можно довольно легко подружить клиентом OpenVPN и systemd
. Достаточно положить его (конфиг) в /etc/openvpn/client/
и не забыть сменить расширение на .conf
. После этого дёрнуть службу openvpn-client@openvpn-client-config-name.service
, не забыть сделать для неё enable
и радоваться тому, что всё полетело.
Конечно же, нужно отключить любое перенаправление трафика в свежесозданный VPN, ведь мы не хотим порезать скорость на клиенской машине за счёт перегона трафика через полшарика.
И да, нужно прописать статический ip-адрес на VPN-сервере для нашего клиента. Это понадобится чуть далее по повествованию. Для этого нужно включить ifconfig-pool-persist
, поредактироввть ipp.txt
, идущий в комплекте с OpenVPN и включить client-config-dir, плюс поредактировать конфиг нужного клиента, добавив ifconfig-push
с правильной маской и желаемым IP-адресом.
Акт второй
Теперь у нас в "сети" есть машина, которая повёрнута лицом в интернет и ей можно воспользоваться в корыстных целях. А именно, перенаправить часть трафика через неё.
Итак, новая задача: нужно завернуть трафик, прилетающий на один из портов VPS с белым айпи так, чтобы этот трафик улетел в свежеподключенную виртуальную сеть и ответ смог оттуда вернуться.
Способ решения: конечно же iptables
! Когда ещё представится такая замечательная возможность с ним поупражняться?
Нужна конфигурация находится довольно скоро, за тройку часов, сотню бранных слов и пригоршню потраченных нервов, ибо дебаг сетей — это очень специфическая процедура.
Во-первых, нужно включить перенаправление трафика в ядре. Эта штука называется ipv4.ip_forward
и включается немного по-разному в зависимости от ОС и сетевого менеджера.
Во-вторых, нужно выбрать порт, на VPS и завернуть весь трафик, идущий на него в виртуальную подсеть. Это можно сделать, например, вот так:
iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 8080 -j DNAT --to-destination 10.8.0.2:8080
Здесь мы перенаправляем весь TCP-трафик, пришедший на порт 8080 внешнего интерфейса на машину с айпи 10.8.0.2 и такой же порт 8080.
Тем, кто хочет грязных подробностей работы netfilter
, iptables
и вообще роутинга, абсолютно необходимо созерцать это или это.
Итак, теперь у нас пакеты улетают в виртуальную подсеть и… там и остаются. Точнее ответ от socks-прокси улетает обратно через дефолтный gateway на машине с Dante и адресат его дропает, ибо в сетях не принято отправлять запрос на один IP, а получать ответ — с другого. Посему, нужно колдовать дальше.
Итак, теперь нужно перенаправить все пакеты от проксика обратно в виртуальную подсеть в сторону VPS с белым IP. Тут ситуация немного хуже, так как просто iptables
нам не хватит, ибо если мы поправим адрес назначения до роутинга (PREROUTING
), то наш пакет в интернет не улетит, а если не поправим — пакет уйдёт в default gateway
. Итак, нужно делать следующее: вспомнить про цепочку mangle
, дабы пометит пакеты через iptables
и завернуть их в кастомную таблицу маршрутизации, которая отправит их куда следует.
Сказано — сделано:
iptables -t mangle -A OUTPUT -p tcp --sport 8080 -j MARK --set-mark 0x80
ip rule add fwmark 0x80 table 80
ip route add default via 10.8.0.1 dev tun0 table 80
Берём исходящий трафик, маркируем всё, что летит с порта, на котором сидит прокси (8080 в нашем случае), перенаправляем весь помеченный трафик в таблицу маршрутизации с номером 80 (вообще номер ни от чего не зависит, просто так захотелось) и добавляем единственное правило, по которому все пакеты, попавшие в эту таблицу улетают в подсеть VPN.
Отлично! Теперь пакеты улетают обратно в сторону VPS… и умирают там. Потому что VPS не в курсе что с ними делать. Поэтому, если не заморачиваться, то можно просто взять и перенаправить весь трафик, прилетающих из виртуальной подсети обратно в интернет:
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j SNAT --to-source 172.42.1.10
Здесь всё, что прилетает из подсети 10.8.0.0 с маской 255.255.255.000 заворачивается в source-NAT и улетает в дефолтный интерфейс, который повернут в интернет. Важно отметить, что эта штука будет работать только если мы прозрачно пробрасываем порт, то есть входящий порт на VPS совпадает с портом нашего прокси. Иначе нужно будет страдать чуть больше.
Где-то сейчас всё должно начать работать. И останется самая малость: не забыть сделать так, чтобы все конфиги iptables
и route
не продолбались после рестарта. Для iptables
есть специальные файлики типа /etc/iptables/rules.v4
(в случае Ubuntu), а для роутов всё немного сложнее. Я их затолкал в up/down
скрипты OpenVPN-а, хотя, думается мне, можно было и поприличнее сделать.
Завернуть трафик от приложения в proxy
Итак, у нас есть прокси с аутентификацией в нужной стране, доступный по статическому белому IP-адресу. Осталось им воспользоваться и перенаправить туда трафик от Spotify. Но есть нюанс, как говорилось выше, логин-пароль для проксика в Спотифае не работает, поэтому будем искать как извернуться.
Для начала, вспомним про proxifier. Отличная штука, только стоит как звездолёт (40$). Мы за эти деньги снова можем купить премиум и дело с концом. Поэтому поищем более бесплатные и открытые аналоги на мак (таки да, мы же на маке хотим музыку слушать). Обнаружим целый один инструмент: proximac. И радостно пойдём его тыкать.
Но радость будет недолгой, ибо окажется, что нужно включить режим дебага и кастомные расширений ядра в MacOS, запилить несложный конфиг и понять, что у этой тулзы ровно так же проблема, что и у Spotify: она не может пройти аутентификацию по логину-паролю на socks-proxy.
Где-то здесь пора психануть и таки купить премиум… но нет! Попробуем попросить починить, этож опенсорс! Делаем тикет. И в ответ получаем душещипательную историю о том, что у единственного мэйнтейнера больше нет макбука и хрен вам, а не фикс.
Снова расстроимся. Но потом вспомним молодость и Си, включим дебаг режим в Dante, покопаемся в сотне килобайт логов, сходим в RFC1927 за информацией о протоколе SOCKS5, разберёмся с Xcode и таки найдём проблему. Достаточно поправить один символ в списке кодов методов, которые предлагает клиент для аутентификации и всё начинает работа как часы. Радуемся, собираем релизный бинарник, делаем пул-реквест и уходим в закат идём к следующему пункту.
Автоматизируй это
Раз Proximac заработал, его нужно демонизировать и забыть про него. Для этого подходит целая одна система инициализации, которая есть в MacOS, а именно launchd.
Быстро находим мануал и понимаем, что это совсем не systemd
и тут почти совок и xml
. Никаких тебе красивых конфигов, никаких команд вида status
, restart
, daemon-reload
. Только хардкор вида start-stop
, list-grep
, unload-load
и ещё много странностей. Превозмогая всё это пишем plist
, загружаем. Не работает. Изучаем способ дебага демона, дебажим, понимаем что там в ENV
даже PATH
не завезли нормальный, ругаемся, завозим (добавляя /sbin
и /usr/local/bin
) и наконец-то радуемся автостарту и стабильной работе.
Выдыхаем
Что в итоге? Неделя приключений, наколеночный зоопарк из сервисов, который дорог сердцу и делает то, что от него требуется. Немного знаний в сомнительных технических областях, капелька опенсорса и улыбка на лице от мысли "Я сделяль!"
P.S.: это не призыв к бойкоту капиталистов, к экономии на спичках или к тотальной хитропопости, а всего лишь указание на возможности исследования и развития там, где их, в общем-то, не ожидаешь.
crtx
Разве для прослушивания музыки в Spotify, что на сайте, что в приложении/настольном клиенте, нужен какой-нибудь VPN?
Всё прошлое лето активно пользовался данным сервисом, так сказать, прямым подключением. Разве только для первой авторизации нужен прокси или VPN.
Возможно с Премиум подпиской есть какие-то нюансы, конечно.
Loriowar Автор
Да, слушать можно из любой локации, но реклама по минуте через трек ух как надоела. Ради неё весь сыр-бор.
crtx
Не знаю причину, но у меня такая реклама отсутствовала :(