Налаштування BGP для обходу блокувань або «Як я перестав боятися і полюбив РКН»

Ну гаразд, про «полюбив» — це перебільшення. Швидше «зміг співіснувати з».

Як ви всі знаєте, з 16 квітня 2018 року Роскомнагляд вкрай широкими мазками блокує доступ до ресурсів у мережі, додаючи до «Єдиного реєстру доменних імен, покажчиків сторінок сайтів у мережі «Інтернет» та мережевих адрес, що дозволяють ідентифікувати сайти у мережі «Інтернет», містять інформацію, поширення якої в Російській Федерації заборонено »(за текстом - просто реєстр) /10 іноді. В результаті громадяни Російської Федерації та бізнес страждають, втративши доступ до необхідних їм цілком легальних ресурсів.

Після того, як у коментарях до однієї зі статей на Хабрі я сказав, що готовий допомогти постраждалим із налаштуванням схеми обходу, до мене звернулися кілька людей із проханням про таку допомогу. Коли вони все запрацювало, один з них порекомендував описати методику в статті. Подумавши, вирішив порушити своє мовчання на сайті і спробувати в якісь повіки написати щось проміжне між проектом і постом у Facebook, тобто. хабрапост. Результат – перед вами.

відмова

Оскільки публікувати способи обходу блокувань доступу до інформації, забороненої на території Російської Федерації, не дуже законно, метою цієї статті буде розповісти про метод, що дозволяє автоматизувати отримання доступу до ресурсів, дозволених на території Російської Федерації, але через чиїсь дії недоступні безпосередньо через вашого провайдера. А доступ до інших ресурсів, який отримується в результаті дій зі статті, є прикрим побічним ефектом і метою статті в жодному разі не є.

Також, оскільки я за професією, покликанням та життєвим шляхом насамперед мережевий архітектор, програмування та лінукси не є моїми сильними сторонами. Тому, безумовно, скрипти можна написати краще, питання безпеки VPS можна опрацювати глибше і т.д. Ваші пропозиції будуть прийняті з вдячністю, якщо вони будуть достатньо детальними — із задоволенням додам їх до тексту статті.

TL, д-р

Автоматизуємо доступ до ресурсів через наявний у вас тунель, використовуючи копію реєстру та протокол BGP. Мета – прибрати весь трафік, адресований заблокованим ресурсам, у тунель. Мінімум пояснень, переважно покрокова інструкція.

Що вам для цього потрібно

На жаль, цей пост не для кожного. Для того, щоб скористатися цією методикою, вам потрібно буде зібрати разом кілька елементів:

  1. У вас має бути linux-сервер десь за межами поля блокувань. Або хоча б такий сервер завести — благо це зараз коштує від $9/рік, а можливо й менше. Метод також підходить, якщо у вас є окремий VPN-тунель, тоді сервер може розташовуватись і всередині поля блокувань.
  2. Ваш роутер має бути досить розумним, щоб вміти
    • будь-який VPN-клієнт, що вам подобається (я віддаю перевагу OpenVPN, але це може бути PPTP, L2TP, GRE+IPSec і будь-який інший варіант, що створює тунельний інтерфейс);
    • протокол BGPv4. Що означає, що для SOHO це може бути Mikrotik або будь-який роутер із OpenWRT/LEDE/аналогічними кастомними прошивками, що дозволяють встановити Quagga або Bird. Використання PC-роутера також можна. У разі ентерпрайзу дивіться підтримку BGP у документації до вашого бордер-роутера.
  3. Ви повинні мати уявлення про використання Linux та мережеві технології, у тому числі про протокол BGP. Або хоча б хотіти отримати таку виставу. Оскільки обійняти неосяжне цього разу я не готовий, деякі незрозумілі для вас моменти вам доведеться вивчити самостійно. Втім, на конкретні питання, звичайно ж, відповім у коментарях і навряд чи виявлюся єдиним відповідальним, так що не соромтеся питати.

Що використовується у прикладі

  • Копія реєстру — з https://github.com/zapret-info/z-i 
  • VPS - Ubuntu 16.04
  • Сервіс маршрутизації птах 1.6.3   
  • Маршрутизатор Mikrotik hAP ac
  • Робочі папки - оскільки працюємо від рута, більшість буде розміщуватися в домашній папці рута. Відповідно:
    • /root/blacklist – робоча папка зі скриптом компіляції
    • /root/zi - копія реєстру з github
    • /etc/bird — стандартна папка налаштувань сервісу bird
  • Зовнішньою IP-адресою VPS з сервером маршрутизації та точкою термінації тунелю приймаємо 194.165.22.146, ASN 64998; зовнішньою IP-адресою роутера - 81.177.103.94, ASN 64999
  • IP адреси всередині тунелю - 172.30.1.1 та 172.30.1.2 відповідно.

Налаштування BGP для обходу блокувань або «Як я перестав боятися і полюбив РКН»

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

Коротко – логіка рішення

  1. підготовчі дії
    1. Отримуємо VPS
    2. Піднімаємо тунель від маршрутизатора до VPS
  2. Отримуємо та регулярно оновлюємо копію реєстру
  3. Встановлюємо та налаштовуємо сервіс маршрутизації
  4. Створюємо на підставі реєстру список статичних маршрутів для сервісу маршрутизації
  5. Підключаємо роутер до сервісу та налаштовуємо відправку всього трафіку через тунель.

Власне рішення

підготовчі дії

На просторах мережі є безліч сервісів, які надають VPS за дуже помірні гроші. Поки що я знайшов і користуюся варіантом за $9/рік, але навіть якщо не особливо морочитися — варіантів за 1E/місяць багато на кожному розі. Питання вибору VPS лежить далеко за межами цієї статті, тож якщо комусь щось незрозуміло в цьому — запитайте у коментарях.

Якщо ви використовуватимете VPS не тільки для сервісу маршрутизації, але й для термінації на ньому тунелю — вам потрібно підняти цей тунель і практично однозначно налаштувати NAT для нього. У мережі велика кількість інструкцій щодо цих дій, тут я їх повторюватиму не буду. Основна вимога до такого тунелю він повинен створювати на вашому роутері, що підтримує тунель у бік VPS, окремий інтерфейс. Цій вимогі відповідає більшість використовуваних технологій VPN — наприклад, OpenVPN у tun режимі чудово підходить.

Отримання копії реєстру

Як говорив Джабраїл, "Той, хто нам заважає, той нам допоможе". Якщо РКН створює реєстр заборонених ресурсів, грішно було б не скористатися цим реєстром для вирішення нашого завдання. Копію реєстру ми отримуватимемо з github.

Заходимо на ваш лінукс-сервер, провалюємося в контекст root'а (sudo su -) і встановлюємо git, якщо вона ще не встановлена.

apt install git

Переходимо в домашню директорію та витягуємо копію реєстру.

cd ~ && git clone --depth=1 https://github.com/zapret-info/z-i 

Налаштовуємо оновлення по крону (у мене раз на 20 хвилин, але ви можете вибрати будь-який цікавий для вас інтервал). Для цього запускаємо кронтаб -e і додаємо до нього наступний рядок:

*/20 * * * * cd ~/z-i && git pull && git gc

Підключаємо хук, який створюватиме файли для сервісу маршрутизації після оновлення реєстру. Для цього створюємо файл /root/zi/.git/hooks/post-merge з наступним вмістом:

#!/usr/bin/env bash
changed_files="$(git diff-tree -r --name-only --no-commit-id ORIG_HEAD HEAD)"
check_run() {
    echo "$changed_files" | grep --quiet "$1" && eval "$2"
}
check_run dump.csv "/root/blacklist/makebgp"

і не забуваємо зробити його виконуваним

chmod +x /root/z-i/.git/hooks/post-merge

Скрипт makebgp, на який посилається хук, ми створимо трохи згодом.

Встановлення та налаштування сервісу маршрутизації

Встановлюємо bird. На жаль, викладена в репозиторіях Ubuntu на даний момент версія bird по свіжості можна порівняти з фекаліями археоптерикса, тому нам необхідно попередньо додати в систему офіційний PPA розробників ПЗ.

add-apt-repository ppa:cz.nic-labs/bird
apt update
apt install bird

Після цього відразу відключаємо bird для IPv6 - в цій інсталяції він нам не буде потрібно.

systemctl stop bird6
systemctl disable bird6

Нижче наведено мінімалістичний файл конфігурації сервісу bird (/etc/bird/bird.conf), якого нам цілком вистачить (і ще раз нагадую, що ніхто не забороняє розвивати та дотюнювати ідею під ваші власні потреби)

log syslog all;
router id 172.30.1.1;

protocol kernel {
        scan time 60;
        import none;
#       export all;   # Actually insert routes into the kernel routing table
}

protocol device {
        scan time 60;
}

protocol direct {
        interface "venet*", "tun*"; # Restrict network interfaces it works with
}

protocol static static_bgp {
        import all;
        include "pfxlist.txt";
        #include "iplist.txt";
}

protocol bgp OurRouter {
        description "Our Router";
        neighbor 81.177.103.94 as 64999;
        import none;
        export where proto = "static_bgp";
        local as 64998;
        passive off;
        multihop;
}

router id — ідентифікатор роутера, що візуально виглядає як IPv4-адреса, але ним не є. У нашому випадку може бути взагалі будь-яким 32-бітовим числом у форматі IPv4-адреси, але гарним тоном є вказувати там саме IPv4-адресу вашого пристрою (в даному випадку VPS).

protocol direct визначає, які інтерфейси працюватимуть із процесом маршрутизації. У прикладі дана пара прикладів імен, можна додавати інші. Можна і просто видалити рядок, у цьому випадку сервер слухатиме всі доступні інтерфейси з IPv4-адресою.

protocol static - наше диво, яке підвантажує з файлів списки префіксів та ip-адрес (які насправді, звичайно, префікси /32) для наступного анонсу. Звідки з'являються ці списки буде розглянуто нижче. Зверніть увагу, що завантаження ip-адрес за промовчанням закоментовано, причина цього - великий обсяг вивантаження. Для порівняння, у списку префіксів на момент написання статті 78 рядків, а в списку ip-адрес - 85898. Настійно рекомендую запускатися і налагоджуватися тільки на списку префіксів, а включати або не включати в подальшому підвантаження ip - вирішувати після експериментів зі своїм роутером. Не кожен з них легко перетравить 85 тисяч записів у таблиці маршрутизації.

protocol bgp, власне, налаштовує bgp-пірінг із вашим роутером. ip-адреса - це адреса зовнішнього інтерфейсу роутера (або адреса інтерфейсу тунелю з боку роутера), 64998 і 64999 - номери автономних систем. Їх у цьому випадку можна призначити у вигляді будь-яких 16-бітних чисел, але гарним тоном є використання номерів AS з приватного діапазону, визначеного RFC6996 - 64512-65534 включно (існує формат 32-бітових ASN, але в нашому випадку це точно надмірність). Описана конфігурація використовує eBGP пірінг, у якому номери автономних систем сервісу маршрутизації та роутера повинні відрізнятися.

Як ви можете помітити, сервісу потрібно знати IP-адресу роутера, тому якщо у вас динамічна або немаршрутизована private (RFC1918) або shared (RFC6598) адреса, варіанта піднімати піринг на зовнішньому інтерфейсі у вас немає, але всередині тунелю сервіс все одно працюватиме.

Досить прозоро також, що з одного сервісу ви можете забезпечувати маршрутами кілька різних роутерів — достатньо продублювати налаштування для них копіюванням секції protocol bgp зі зміною IP-адреси сусіда. Саме тому в прикладі показані налаштування для пірингу поза тунелем, як найбільш універсальні. Прибрати їх у тунель нескладно, змінивши відповідно IP-адреси в налаштуваннях.

Обробка реєстру для сервісу маршрутизації

Зараз нам треба, власне, створити списки префіксів та ip-адрес, які на попередньому етапі згадані в protocol static. Для цього ми беремо файл реєстру і робимо з нього потрібні нам файли наступним скриптом, що розміщується в /root/blacklist/makebgp

#!/bin/bash
cut -d";" -f1 /root/z-i/dump.csv| tr '|' 'n' |  tr -d ' ' > /root/blacklist/tmpaddr.txt
cat /root/blacklist/tmpaddr.txt | grep / | sed 's_.*_route & reject;_' > /etc/bird/pfxlist.txt
cat /root/blacklist/tmpaddr.txt | sort | uniq | grep -Eo "([0-9]{1,3}[.]){3}[0-9]{1,3}" | sed 's_.*_route &/32 reject;_' > /etc/bird/iplist.txt
/etc/init.d/bird reload
logger 'bgp list compiled'

Не забуваємо зробити його виконуваним

chmod +x /root/blacklist/makebgp

Тепер можна запустити його вручну і подивитися файли в /etc/bird.

Найімовірніше, в цей момент bird у вас не працює, оскільки на попередньому етапі ви запропонували йому пошукати файли, яких ще не було. Тому запускаємо його та контролюємо, що він запустився:

systemctl start bird
birdc show route

Висновок другої команди повинен показати близько 80 записів (це на даний момент, а коли налаштовуватимете, все залежатиме від завзятості РКН у блокуваннях мережами) виду приблизно такого:

54.160.0.0/12      unreachable [static_bgp 2018-04-19] * (200)

Команда

birdc show protocol

покаже стан протоколів усередині сервісу. Поки ви не налаштували роутер (див. наступний пункт), протокол OurRouter буде у стані start (фази Connect або Active), а після успішного підключення перейде у стан up (фаза Established). Наприклад, у моїй системі висновок цієї команди виглядає так:

BIRD 1.6.3 ready.
name     proto    table    state  since       info
kernel1  Kernel   master   up     2018-04-19
device1  Device   master   up     2018-04-19
static_bgp Static   master   up     2018-04-19
direct1  Direct   master   up     2018-04-19
RXXXXXx1 BGP      master   up     13:10:22    Established
RXXXXXx2 BGP      master   up     2018-04-24  Established
RXXXXXx3 BGP      master   start  2018-04-22  Connect       Socket: Connection timed out
RXXXXXx4 BGP      master   up     2018-04-24  Established
RXXXXXx5 BGP      master   start  2018-04-24  Passive

підключення роутера

Всі вже, мабуть, втомилися читати цю онучу, але бійтеся — кінець близький. Тим більше, що в цьому розділі я не зможу дати покрокову інструкцію – для кожного виробника вона буде своя.

Однак можу показати кілька прикладів. Основна логіка - підняти BGP-піринг і на всі префікси, що отримуються, навісити nexthop, що вказує на наш тунель (якщо потрібно виводити трафік через p2p інтерфейс) або ip-адресу некстхопу, якщо трафік буде йти в ethernet).

Наприклад, на Mikrotik в RouterOS це вирішується так

/routing bgp instance set default as=64999 ignore-as-path-len=yes router-id=172.30.1.2
/routing bgp peer add in-filter=dynamic-in multihop=yes name=VPS remote-address=194.165.22.146 remote-as=64998 ttl=default
/routing filter add action=accept chain=dynamic-in protocol=bgp comment="Set nexthop" set-in-nexthop=172.30.1.1

а в Cisco IOS - ось так

router bgp 64999
  neighbor 194.165.22.146 remote-as 64998
  neighbor 194.165.22.146 route-map BGP_NEXT_HOP in
  neighbor 194.165.22.146 ebgp-multihop 250
!
route-map BGP_NEXT_HOP permit 10
  set ip next-hop 172.30.1.1

У тому випадку, якщо той самий тунель використовується і для BGP-пірінгу, і для передачі корисного трафіку, виставляти nexthop не обов'язково, він виставиться правильно засобами протоколу. Але якщо виставите вручну, гірше від цього теж не буде.

На інших платформах вам доведеться розбиратися в конфігуруванні самостійно, але якщо виникнуть труднощі, пишіть у коментарях, спробую допомогти.

Після того, як у вас піднялася BGP-сесія, прилетіли та встановилися в таблицю маршрути на великі мережі, трафік на адреси з них пішов і щастя близько, ви можете повернутися до сервісу bird та спробувати розкоментувати там запис, що включає список ip-адрес, виконати після цього

systemctl reload bird

та подивитися, як ваш роутер переніс ці 85 тисяч маршрутів. Будьте готові відключати та думати, що з цим робити 🙂

Разом

Чисто теоретично після виконання вищеописаних дій у вас з'явився сервіс, який автоматично перенаправляє трафік до забанених в РФ IP-адрес повз систему фільтрації.

Його, звісно, ​​можна доопрацьовувати. Наприклад, досить легко зробити сумаризацію списку ip-адрес через рішення на perl або python. Простий скрипт на perl, що робить це за допомогою Net::CIDR::Lite, перетворює 85 тисяч префіксів на 60 (не тисяч), але, природно, перекриває набагато більший діапазон адрес, ніж заблоковано.

Оскільки сервіс працює на третьому рівні моделі ISO/OSI, він не врятує від блокувань по сайту/сторінці, якщо воно резолвується не на ту адресу, яка записана в реєстрі. Але разом з реєстром з github прилітає файл nxdomain.txt, який декількома штрихами скрипта легко перетворюється на джерело адрес для, наприклад, плагіна SwitchyOmega в Chrome.

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

У разі виникнення запитань — задавайте, готовий відповідати.

UPD. Дякую navion и TerAnYu за параметри для git, що дозволяють зменшити обсяги завантажуваного.

UPD2. Колеги, схоже, я зробив помилку, не додавши до статті інструкцію з налаштування тунелю між VPS та роутером. Дуже багато питань викликані цим.
Про всяк випадок ще раз зазначу - мається на увазі, що перед початком дій з цього керівництва ви вже налаштували VPN-тунель у потрібному вам напрямку і перевірили його працездатність (наприклад, загорнувши туди трафік дефолтом або статикою). Якщо ця фаза у вас ще не виконана, виконувати дії зі статті не має сенсу. Поки що у мене свого тексту з цього приводу немає, але якщо погуглити «налаштування сервера OpenVPN» разом з ім'ям операційної системи, встановленої на VPS, і «налаштування клієнта OpenVPN» з ім'ям вашого маршрутизатора — найімовірніше, ви знайдете кілька статей з цього приводу , у тому числі і на хабрі.

UPD3. Unsacrificed написав код, який робить з dump.csv результуючий файл для bird з опціональною сумаризацією IP-адрес. Тому розділ «Обробка реєстру для сервісу маршрутизації» можна замінити на виклик програми. https://habr.com/post/354282/#comment_10782712

UPD4. Невелика робота над помилками (не вносив за текстом):
1) замість systemctl reload bird має сенс використовувати команду birdc configure.
2) у маршрутизаторі Mikrotik замість зміни некстхопу на IP другої сторони тунелю /routing filter add action = accept chain = dynamic-in protocol = bgp comment = "Set nexthop" set-in-nexthop = 172.30.1.1 має сенс вказувати маршрут прямо в інтерфейс тунелю, без адреси /routing filter add action = accept chain = dynamic-in protocol = bgp comment = "Set nexthop" set-in-nexthop-direct = <ім'я інтерфейсу>

UPD5. З'явився новий сервіс https://antifilter.downloadзвідки можна забирати вже готові списки ip-адрес. Оновлюються раз на півгодини. На стороні клієнта при цьому залишається лише обрамити записи відповідними «route… reject».
І на цьому, мабуть, уже вистачить лахмітити бабусю та оновлювати статтю.

UPD6. Перероблена версія статті для тих, кому не хочеться розбиратися, а хочеться запуститися. тут.

Джерело: habr.com

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