Обход блокировок с использованием BGP

Есть ещё один довольно изящный способ направить обращения к заблокированным ресурсам через VPN-туннель, не городя простыни самописных скриптов, не заботясь об обновлении и фильтрации списков блокировки с помощью единственного пакета с компактным конфигурационным файлом.

На пробу подтолкнула статья, где упомянут сервис Antifilter, готовый отдавать список заблокированных ресурсов по протоколу BGP. Работает это так:

  • на роутере служба bird получает от Antifilter по BGP актуальный список заблокированных подсетей,
  • bird самостоятельно поддерживает в актуальном состоянии заданную таблицу роутинга, получая анонсы от сервиса,
  • если запрашиваемый пользователем ресурс входит в эту таблицу, то обращение к нему пойдёт по VPN-туннелю.

Требования

  • Белый IP-адрес, пусть и динамический,
  • Последняя Beta/Draft-прошивка,
  • Развёрнутая среда Entware,
  • Рабочее VPN-соединение или EoIP/GRE-туннель поверх провайдерского, по которому будет идти обращение к заблокированным ресурсам.

Подразумевается, что провайдер не занимается перехватом и/или подменой DNS-ответов. Защита DNS-трафика — это отдельная тема.

Настройка bird

Установите bird:

opkg install bird1-ipv4

Замените файл конфигурации /opt/etc/bird4.conf содержимым:

log syslog all;
log stderr all;

router id 44.44.44.44; # current external ip

function martians()
{
    return net ~ [ 100.64.0.0/10+,
                   169.254.0.0/16+,
                   172.16.0.0/12+,
                   192.168.0.0/16+,
                   10.0.0.0/8+,
                   127.0.0.0/8+,
                   224.0.0.0/4+,
                   240.0.0.0/4+,
                   0.0.0.0/32-,
                   0.0.0.0/0{0,7}
                 ];
}

protocol device {
    scan time 15;
}

protocol kernel kernel_routes {
    scan time 60;
    import none;
    export all;
    kernel table 1000; # kernel routing table number
}

protocol static static_routes {
    import all;
    #route 192.168.X.Y/24 via 192.168.A.B;
}

protocol bgp antifilter {
    import filter {
        if martians() then reject;
        gw = 10.8.0.1; # override route nexthop
        accept;
    };
    export none;
    local as 64999; # local default as-number
    neighbor 192.3.134.152 as 65432;
    multihop;
    hold time 240;
}

В этом файле будут лишь две правки, специфичные для вашего подключения, в примере это:

  • 44.44.44.44 - текущий внешний IP-адрес роутера, который будет использоваться в качестве ID вашего роутера. После того как будет установлен пиринг с сервисом Antifilter, ваш IP адрес может меняться, стороны продолжат различать друг друга по ID.

  • 10.8.0.1 - IP адрес удалённого конца VPN-соединения.

Добавьте скрипт, который будет срабатывать при установки VPN-соединения, он добавлять правило маршрутизации обращений к заблокированным ресурсам через VPN-туннель. В частности, для OpenVPN-соединения отлично подходит /opt/etc/ndm/openvpn-route-up.d/010-add_antizapret_route.sh:

#!/bin/sh

ip rule add iif br0 table 1000

и не забудьте сделать его исполняемым:

chmod +x /opt/etc/ndm/openvpn-route-up.d/010-add_antizapret_route.sh

Настройка BGP-пиринга

Перейдите на эту страницу и нажмите «Активировать управление BGP». После ввода капчи настройки вступят в силу.

Использование

Запустите bird и примените правило роутинга для заблокированных ресурсов. При перезагрузки роутера это будет происходить автоматически:

/opt/etc/init.d/S04bird1-ipv4 start
/opt/etc/ndm/openvpn-route-up.d/010-add_antizapret_route.sh

И через несколько минут проверьте доступ к выбранному ресурсу, входящему в число блокируемых.

Диагностика проблем

  • Убедитесь, что при старте из консоли нет никаких ошибок, а в системном логе появляются строчки:
I [Jan 22 09:26:04] root: Started bird4 from .
W [Jan 22 09:26:09] bird4: Kernel dropped some netlink messages, will resync on next scan.
  • Через несколько минут работы bird посмотрите, заполняется ли выбранная таблица записями:
ip route list table 1000
  • Убедитесь, что нужная таблица маршрутизации (1000) участвует в маршрутизации и мелькает в выводе ip rule list.

Детали по потребляемым ресурсам

Потребление памяти. Загружать в таблицу роутинга список по каждому IP из числа заблокированных идея плохая, будет неприемлемое число записей. К счастью, сервис Antifilter «упрощает» список, собирая IP адреса в подсети /24 и уже в виде подсетей отдаёт информацию по BGP. Подсетей получается ~15 тысяч, что уже лучше. Если грубо, то на каждый маршрут тратится 512 байт, поэтому на всю таблицу получается меньше восьми мегабайт. Сам процесс bird при работе занимает 1,5МБ памяти, что очень хорошо.

Потребление ресурсов CPU. В отличие от IP set, принятие решения по роутингу ведётся не по предварительно посчитанным хэшам записей, а по построенному LC trie дереву, что быстрее, и, кроме того, не ограничивает число записей как в случае с IP set’ами. На роутерах со слабеньким процессором на базе MT7628 видимых задержек при обращении к ресурсам на стамегабитном канале субъективно нет, но выявить их можно только в момент установления нового TCP-соединения, этот момент требует дополнительного исследования. Первоначальная загрузка ~15 тыс. подсетей в таблицу проходит практически мгновенно.

Если обрабатывать список блокироваки самостоятиельно, то это timeout driven решение, связанное с периодической загрузкой обновлённого списка заблокированных ресурсов и перезаписью всей таблицы роутинга. Использование bird позволяет перейти к event driven решению по BGP-анонсам от Antifilter, при этом таблица роутинга обновляется лишь в той части, где произошли изменения.

Низкий поклон тов. @themiron за пинки в нужную сторону.

Удачи в начинаниях!