Пригоди на рівному місці

Пригоди на рівному місці

Як Spotify може допомогти у вивченні демонів, RFC, мереж та просування опенсорсу. Або, що буває, якщо заплатити не виходить, а деякі преміумні плюшки дуже хочеться.

Початок

На третій день було помічено, що Спотифай видає рекламу виходячи з країни ip-адреси. Там було помічено, що у деяких країнах рекламу не завезли зовсім. Наприклад, у РБ. І відразу дозрів «геніальний» план з відключення реклами в не преміумному акаунті.

Трохи про Spotify

Взагалі кажучи, у Спотифа дивна політика. Нашому братові доводиться неабияк перекручуватися, щоб купити преміум: змінювати локацію в профілі на заморську, шукати відповідний гіфткард, який можна оплатити тільки paypal-ом, який останнім часом дивує і хоче купу документів. Загалом теж пригода, але іншого порядку. Хоча більшість цим займається заради мобільної версії, мене така не цікавить. Тому все нижченаведене допоможе тільки у випадку з десктопною версією. Більше того, ніякого розширення функцій не буде. Лише відрізання деяких зайвих.

А що складного?

І я так думав, прописуючи дані socks-proxy у конфізі Spotify. Проблема виявилася в тому, що у них не працює аутентифікація в socks за логіном та паролем. Плюс розробники регулярно щось крутять довкола проксика: то дозволяючи, то забороняючи, то ламаючи його, що породжує цілі полотнища обговорень на оф.сайті.

Було вирішено не покладатися на нестабільні функції та знайти щось надійніше та цікавіше.

Десь тут читач має спитати: а чого б не взяти ssh з ключиком -D і справа з кінцем? І, загалом, матиме рацію. Але, по-перше, це ще потрібно демонізувати і подружити з autossh, щоб не думати про конекти, що рвуться. І по-друге: це надто просто і нудно.

По порядку

Як завжди, давайте підемо зліва направо, зверху вниз і опишемо все, що нам потрібно для реалізації нашої «простої» витівки.

Для початку потрібен проксі

І одразу багато альтернатив:

  • можна просто піти та взяти з відкритих проксилістів. Дешево (точніше задарма), але абсолютно ненадійно і час життя таких проксиків прагне нуля. Тому треба було б знайти/написати парсер проксі списків, фільтрувати їх за потрібним типом і країною і питання підстановки знайденого проксі в Spotify залишається відкритим (ну, хіба що, через HTTP_PROXY передавати і кастомну обгортку для бінарника робити, щоб решту всіх трафік туди ж не відправити).
  • Можна купити аналогічний проксі та позбавити себе більшості вищеописаних проблем. Але за ціни проксі можна відразу купити преміум на Спотифай, а це не спортивно в рамках вихідного завдання.
  • Підняти свій. Як ви, мабуть, здогадалися це наш вибір.

Чисто випадково може виявитися, що у вас є один із сервером у РБ чи іншій невеликій країні. Цим потрібно користуватися та розкочувати на ньому бажаний проксик. Особливі ж поціновувачі, можуть задовольнятися другом з роутем на DD-WRT або аналогічне ПЗ. Але там свій чудовий світ і в рамках цієї розповіді цей світ явно не поміститься.

Отже, наші варіанти: Squid - не надихає, та й не хочеться HTTP-проксик, цього протоколу і так багато навколо. А в області SOCKS нічого розумного крім Данте доки не завезли. Тому беремо його.

Манула по установці та налаштуванню Данте не чекайте. Він просто гуглиться та особливого інтересу не становить. У мінімальній комплектації треба накидати всяких client pass, socks pass, правильно прописати інтерфейси та не забути додати socksmethod: username. У такому вигляді для автентифікації логопас братиметься з користувачів системи. А частина про безпеку: заборона доступу до локалхосту, обмеження по користувачах та інше – це вже суто індивідуально залежно від особистої параної.

Розгорнути проксі обличчям у мережу

Вистава у двох актах.

акт перший

З проксі розібралися, тепер треба отримати до нього доступ із глобальної павутини. Якщо у вас є машинка з білим IP у потрібній країні, то можете сміливо пропускати цей пункт. У нас же такої немає (ми, як говорилося вище, хостимось у друзів вдома) і найближчий білий айпі десь у Німеччині, тому вивчатимемо мережі.

Так уважний читач знову запитуватиме: а чого б вам не взяти існуючий сервіс типу ngrok чи йому подібний? І знову буде правий. Але це сервіс, його знову-таки потрібно демонізувати, він теж може коштувати грошей і взагалі це не спортивно. Тому творитимемо велосипеди з підручних матеріалів.

Завдання: є проксі десь далеко за NAT, треба його повісити на один з портів VPS, що має білий IP і розташованої на краю світу.

Логічно припустити, що це вирішується або прокиданням порту (який реалізується через вищезгаданий ssh), або об'єднанням залізниць у віртуальну мережу через VPN. З ssh працювати вміємо, autossh брати нудно, тому візьмемо OpenVPN.

DigitalOcean має чудовий манув у цій справі. Додати мені нічого. А отриманий конфіг можна легко подружити клієнтом OpenVPN і systemd. Достатньо покласти його (конфіг) у /etc/openvpn/client/ і не забути змінити розширення на .conf. Після цього смикнути службу [email protected], не забути зробити для неї 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. Але є нюанс, як говорилося вище, логін-пароль для проксику в Спотифаї не працює, тому шукатимемо як викрутитися.

Для початку, згадаємо про проксі. Чудова штука, тільки коштує як зореліт (40 $). Ми за ці гроші знову можемо купити преміум і справу з кінцем. Тому пошукаємо більш безкоштовні та відкриті аналоги на мак (таки так, ми ж на маку хочемо музику слухати). Виявимо цілий один інструмент: proximac. І радісно підемо його тикати.

Але радість буде недовгою, бо виявиться, що потрібно включити режим дебага і кастомні розширень ядра в MacOS, запиляти нескладний конфіг і зрозуміти, що у цієї тулзи так само проблема, що і у Spotify: вона не може пройти аутентифікацію по логіну-паролю на socks-proxy.

Десь тут час психанути і таки купити преміум ... але ні! Спробуємо попросити відремонтувати, це ж опенсорс! Робимо тикет. І у відповідь отримуємо щиру історію про те, що у єдиного мейнтейнера більше немає макбука і хрін вам, а не фікс.

Знов засмутимося. Але потім згадаємо молодість і Сі, включимо дебаг режим у Dante, покопаємось у сотні кілобайт ліг, сходимо в RFC1927 за інформацією про протокол SOCKS5, розберемося з Xcode і знайдемо проблему. Достатньо виправити один символ у списку кодів методів, які пропонує клієнт для аутентифікації і все починає роботу як годинник. Радіємо, збираємо релізний бінарник, робимо пул-реквест і йдемо в захід сонця йдемо до наступного пункту.

Автоматизуй це

Якщо Proximac заробив, його потрібно демонізувати і забути про нього. Для цього підходить ціла система ініціалізації, яка є в MacOS, а саме запуск.

Швидко знаходимо мануал і розуміємо, що це зовсім не systemd і тут майже совок і xml. Ніяких тобі красивих конфігів, жодних команд вигляду status, restart, daemon-reload. Тільки хардкор виду start-stop, list-grep, unload-load і ще багато дивно. Перемагаючи все це пишемо plist, завантажуємо. Не працює. Вивчаємо спосіб дебагу демона, дебажимо, розуміємо що там ENV навіть PATH не завезли нормальний, лаємося, завозимо (додаючи /sbin и /usr/local/bin) і нарешті радіємо автостарту та стабільній роботі.

Видихаємо

Що зрештою? Тиждень пригод, наколінний зоопарк із сервісів, який дорогий серцю і робить те, що від нього вимагається. Небагато знань у сумнівних технічних областях, крапелька опенсорсу та посмішка на обличчі від думки «Я зроблю!»

PS: це не заклик до бойкоту капіталістів, до економії на сірниках або до тотальної хитроспості, а лише вказівку на можливості дослідження та розвитку там, де їх, загалом, не очікуєш.

Джерело: habr.com

Додати коментар або відгук