Чем отличается от подобных материалов?


  • Реализация на чистом OpenWrt
  • Использование WireGuard
  • Конфигурация роутера организуется с помощью конфигов OpenWrt, а не кучей в одном скрипте
  • Предусмотрены ситуации при рестарте сети и перезагрузке
  • Потребляет мало ресурсов роутера: заблокированные подсети содержатся в iptables, а не в таблицах маршрутизации. Что позволяет развернуть это дело даже на слабых устройствах
  • Автоматизация конфигурации с помощью Ansible (не требуется python на роутере)

Видеоверсия



Почему OpenWrt и WireGuard?


OpenWrt ставится на очень много моделей soho роутеров, конфигурируется и расширяется как душа пожелает. Сейчас многие прошивки роутеров — это надстройки над OpenWrt.


Wireguard используется из-за его быстрой и простой настройки, а так же из-за высокой скорости передачи через туннель.


Немного о WireGuard


В нашем случае сервер — это VPS вне РКН, клиент — OpenWrt роутер дома. Когда вы захотите зайти на pornolab telegram, ваш роутер направит трафик через сервер с WireGuard.
WireGuard поднимает site-to-site соединение, т.е. и у сервера и у клиента имеется серверная и клиентская часть конфигурации. Если не понятно — станет понятно когда увидите конфигурацию.


У сервера и у клиента есть свои собственные приватный и публичный ключи.


Настройка WireGuard на сервере


Я проделываю всё на Ubuntu 18.04, но в официальной документации есть инструкции по установке для всех известных и не очень ОС.


Установка


sudo add-apt-repository ppa:wireguard/wireguard

При возникновении ошибки
sudo: add-apt-repository: command not found


Установите software-properties-common — пакет предоставляет возможность добавления и удаления PPA
sudo apt install software-properties-common


sudo apt update
sudo apt install wireguard-dkms wireguard-tools

Генерируем ключи для сервера. Ключи сохраним в директории WireGuard для удобства


cd /etc/wireguard/
wg genkey | tee privatekey-server | wg pubkey > publickey-server

Соответственно в файле privatekey-server будет приватный ключ, а в publickey-server — публичный.
Так же сгенерируем сразу ключ для клиента:


wg genkey | tee privatekey-client | wg pubkey > publickey-client


Конфигурация


Конфиг хранится в /etc/wireguard/wg0.conf. Серверная часть выглядит так:


[Interface]
Address = 192.168.100.1
PrivateKey = privatekey-server
ListenPort = 51820
PostUp   = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o ens3 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o ens3 -j MASQUERADE

Address — адрес для интерфейса wg (адрес внутри туннеля)
PrivateKey — Приватный ключ (privatekey-server)
ListenPort — Порт на котором служба ожидает подключения


Ну и делаем маскарадинг, потому что мы будем использовать этот сервер для выхода в интернет
Обратите внимание, что имя интерфейса в вашем случае может отличаться:


Клиентская часть


[Peer]
PublicKey = publickey-client
AllowedIPs = 192.168.100.3/24

PublicKey — публичный ключ нашего роутера (publickey-client)
AllowedIPs — подсети, которые будут доступны через этот туннель. Серверу требуется доступ только до адреса клиента.


Обе части хранятся в одном конфиге.


Включаем автозапуск при перезагрузке:


systemctl enable wg-quick@wg0

Делаем сервер маршрутизатором:


sysctl -w net.ipv4.ip_forward=1

Настроим фаервол. Предположим, что у нас на сервере только WireGuard и ssh:


sudo iptables -A INPUT -i lo -j ACCEPT
sudo iptables -A INPUT -p udp -m udp --dport 51820 -j ACCEPT
sudo iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A INPUT -p icmp -j ACCEPT
sudo iptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
sudo iptables -A INPUT -j DROP

Сохраним конфигурацию iptables:


sudo apt-get install iptables-persistent
sudo netfilter-persistent save

Поднимаем wg интерфейс первый раз вручную:


wg-quick up wg0


WireGuard сервер готов.


Настройка роутера


Я использую OpenWrt версии 18.06.1 на Xiaomi mi 3G и Asus RT-N16.


Логика работы роутера


Загружаем списки, помещаем их в iptables, все адреса из этих списков iptables помечает маркером 0x1. Далее все пакеты помеченные 0x1 идут в отдельную таблицу маршрутизации, все пакеты попавшие в эту таблицу маршрутизации идут через wg интерфейс.



Установка пакетов


Насчет занимаемого места на флеше, на всё понадобится примерно 0.9МБ. Если у вас совсем плохо с местом, замените curl wget'ом и можете не ставить dnscrypt-proxy.


Ставим пакеты. В OpenWrt это просто сделать через менеджер пакетов opkg:


opkg update
opkg install ipset wireguard curl

Загрузка списков


Всё, что можно сделать через стандартные возможности OpenWrt, сделано через них. Всё остальное (кроме hotplug) я поместил в небольшой скрипт:


#!/bin/sh

dir=/tmp/lst

mkdir -p $dir

echo "Run download lists"
curl -z $dir/subnet.lst https://antifilter.download/list/subnet.lst --output $dir/subnet.lst

curl -z $dir/ipsum.lst https://antifilter.download/list/ipsum.lst --output $dir/ipsum.lst

echo "Firewall restart"
/etc/init.d/firewall restart

Списки запрещенных подсетей и адресов получаем файлами. Для них создаём директорию в /tmp. В /tmp — потому что это RAM, такая особенность OpenWrt, довольно удобная. На ROM роутера что-то писать лишний раз не стоит.


Выкачиваем списки с antifilter.download curl'ом, флаг z означает, что curl будет скачивать файл, только если удаленный файл отличается от локального или если его нет, как например в случае при загрузке роутера.


subnet.lst — список заблокированных подсетей, изменяется не часто.
ipsum.lst — список заблокированных адресов, который суммаризирован по маске. Вместо 150 тысяч записей получаем 15 тысяч — удобно.


После того как файлы у нас — рестартуем firewall, это нужно для того что бы ipset отработал и добавил списки в iptables, ipset у нас будет сконфигурен в /etc/config/firewall.


Скрипт этот мы добавляем в /etc/init.d/ назовём hirkn. Сделаем его исполняемым


chmod +x /etc/init.d/hirkn

Теперь у нас не просто скрипт, а целая служба. Для того, что бы он запускался при загрузке, делаем симлинк в /etc/rc.d. Нам нужно, что бы он запускался после всех остальных служб, поэтому делаем приставку S99


ln -s /etc/init.d/hirkn /etc/rc.d/S99hirkn

Списки нужно обновлять время от времени, добавляем запись в cron:


crontab -e

0 4 * * * /etc/init.d/hirkn

Мне кажется вполне достаточным обновлять их раз в сутки. Имейте в виду, что при добавлении списков в ipset, отваливается сеть, в моём случае это 2 секунды.


Так же включите крон, по дефолту он отключен:


/etc/init.d/cron enable
/etc/init.d/cron start

Конфигурация таблицы маршрутизации


Создаем таблицу маршрутизации для трафика через туннель, просто добавив строку:


99  vpn

в файл /etc/iproute2/rt_tables.


Создать дефолтный маршрут для таблицы "vpn" через wg интерфейс можно командой:


ip route add table vpn default dev wg0

Но при рестарте сети маршрут пропадёт, поэтому создаём файл 30-rknroute в директории /etc/hotplug.d/iface/ с простым содержимым:


#!/bin/sh

ip route add table vpn default dev wg0

Это означает, что при включении\выключении интерфейсов будет добавляться наш маршрут. И соответственно, этот маршрут будет всегда прописан.


Конфигурация сети


Нам необходимо сконфигурировать WireGuard и правило для пакетов с меткой 0x1.


Конфигурация WireGuard располагается в /etc/config/network


"Серверная" часть:


config interface 'wg0'
        option private_key 'privatekey-client'
        list addresses '192.168.100.3/24'
        option listen_port '51820'
        option proto 'wireguard'

private_key — это privatekey-client, который мы генерировали при настройке сервера
list addresses — адрес wg интерфейса
listen_port — порт на котором WireGuard принимает соединения. Но соединение будет происходить через порт на сервере, поэтому здесь мы не будем открывать для него порт на firewall
proto — указываем протокол, что бы openwrt понимало что это конфигурация WireGuard


"Клиентская" часть:


config wireguard_wg0
        option public_key 'publickey-server'
        option allowed_ips '0.0.0.0/0'
        option route_allowed_ips '0'
        option endpoint_host 'wg-server-ip'
        option persistent_keepalive '25'
        option endpoint_port '51820'

public_key — ключ publickey-server
allowed_ips — подсети, в которые может ходить трафик через тунель, в нашем случае никаких ограничей не требуется, поэтому 0.0.0.0/0
route_allowed_ips — флаг, который делает роут через wg интерфейс для перечисленных сетей из параметра allowed_ips. В нашем случае это не нужно, эту работу выполняет iptables
endpoint_host — ip/url нашего wg сервера
persistent_keepalive — интервал времени, через который отправляются пакеты для поддержки соединения
endpoint_port — порт wireguard на сервере


Ещё в конфигурацию network добавим правило, которое будет отправлять весь трафик, помеченный 0x1, в таблицу маршрутизации "vpn":


config rule
        option priority '100'
        option lookup 'vpn'
        option mark '0x1'

Конфигурация firewall


Добавим два правила маркировки пакетов, они не вписываются в синтаксис UCI openwrt, поэтому добавляем их "как есть" в /etc/firewall.user.


iptables -t mangle -A PREROUTING -i br-lan -m set --match-set vpn_subnets dst -j MARK --set-xmark 0x1
iptables -t mangle -A PREROUTING -i br-lan -m set --match-set vpn_ipsum dst -j MARK --set-xmark 0x1

Эти правила подразумевают под собой, что все пакеты идущие в подсети из списков vpn_subnets и vpn_ipsum необходимо помечать маркером 0x1.


Переходим непосредственно в конфигурацию фаервола в /etc/config/firewall.


Добавляем зону для wireguard. В openwrt зоны — это кастомные цепочки в iptables. Таким образом создаётся зона с одним\несколькими интерфейсами и уже на неё вешаются правила. Зона для wg выглядит например вот так:


config zone
        option name 'wg'
        option family 'ipv4'
        option masq '1'
        option output 'ACCEPT'
        option forward 'REJECT'
        option input 'REJECT'
        option mtu_fix '1'
        option network 'wg0'

Мы разрешаем только выход трафика из интерфейса и включаем маскарадинг.


Теперь нужно разрешить переадресацию с lan зоны на wg зону:


config forwarding
        option src 'lan'
        option dest 'wg'

Ну и последнее — это формирование списков в iptables с помощью ipset:


config ipset
        option name 'vpn_subnets'
        option storage 'hash'
        option loadfile '/tmp/lst/subnet.lst'
        option match 'src_net'

config ipset
        option name 'vpn_ipsum'
        option storage 'hash'
        option loadfile '/tmp/lst/ipsum.lst'
        option match 'src_net'

loadfile — файл из которого берем список
name — имя для нашего списка
storage, match — здесь указываем как хранить и какой тип данных. Будем хранить тип "подсеть"


После этого рестартуем сеть:


/etc/init.d/network restart


и запускаем скрипт:


/etc/init.d/hirkn


После отработки скрипта у вас должно всё заработать. Проверьте маршрут на клиенте роутера:


mtr/traceroute telegram.org/linkedin.com


Бонусом настроим DNSCrypt


Зачем? Ваш провайдер может заботливо подменять ip-адрес заблокированного ресурса, таким образом перенаправляя вас на свой ip с заглушкой, ну и наш обход по ip в данном случае не поможет. Для подмены не всегда даже нужно использовать dns сервер провайдера, ваши запросы могут перехватываться и ответы подменяться. Ну и к слову, это может делать не только провайдер.


opkg install dnscrpt-proxy

Настраиваем конфиг /etc/config/dnscrypt-proxy примерно так:


config dnscrypt-proxy ns1
        option address '127.0.0.1'
        option port '5353'
        option resolver 'cpunks-ru'

Таким образом у нас есть сервис dnscrypt на порту 5353 доступный на localhost.


Resolver — это dns, сервер поддерживающий шифрование. На роутере в файле /usr/share/dnscrypt-proxy/dnscrypt-resolvers.csv содержится список доступных, на момент выпуска установленной версии dnscrypt, серверов. А вот здесь https://dnscrypt.info/public-servers/ вообще все доступные серверы dnscrypt. Можете выбрать другого резолвера и/или добавить серверов для отказоустойчивости. Имейте в виду, что бы DNSCrypt работал с выбраным резолвером, он должен быть указан в dnscrypt-resolvers.csv.


Настраиваем dnsmasq на работу с dnscrypt. В /etc/config/dhcp комментируем строчку:


option resolvfile       '/tmp/resolv.conf.auto'

для того что бы не были задействованы dns серверы провайдера.


И добавляем:


        option noresolv '1'
        list server '/pool.ntp.org/208.67.222.222'
        list server '/antifilter.download/208.67.222.222'
        list server '127.0.0.1#5353'

noresolv '1' — отключает обработку файла /etc/resolv.conf


Запись list server 'domain/ip_dns' указывает какой dns сервер использовать для резолва указанного домена. Таким образом мы не задействуем dnscrypt для синхронизации ntp — для работы службе dnscrypt важно иметь актуальное время.


При загрузке роутера, скрипт hirkn запускается быстрее чем стартует dnscrypt, таким образом домен antifilter.download не резолвится и списки не скачиваются. Можно сделать задержку или ещё что придумать, но пока что не вижу смысла.


В итоге мы получаем такую вставку в конфиг:


        #option resolvfile       '/tmp/resolv.conf.auto'
        option noresolv '1'
        list server '/pool.ntp.org/208.67.222.222'
        list server '/antifilter.download/208.67.222.222'
        list server '127.0.0.1#5353'

Добавляем в автозагрузку и стартуем dnscrypt:


/etc/init.d/dnscrypt-proxy enable
/etc/init.d/dnscrypt-proxy start

Рестартуем dnsmasq:


/etc/init.d/dnsmasq restart


Илюстрация работы без DNSCrypt и c DNSCrypt


Автоматически развертываем с помощью Ansible


Playbook и темплейты лежат на github. Используется модуль, в нём не нужен python на роутере и есть поддержка uci. Я постарался сделать так, что бы ваша конфигурация OpenWrt осталась не тронутой, но всё равно будьте бдительны.


Устанавливаем модуль gekmihesg/ansible-openwrt:


ansible-galaxy install gekmihesg.openwrt

Копируем плейбук и темлпейты:


cd /etc/ansible
git clone https://github.com/itdoginfo/ansible-openwrt-hirkn
mv ansible-openwrt-hirkn/* .
rm -rf ansible-openwrt-hirkn

Добавляйте ваш роутер в hosts:


[openwrt]
192.168.1.1

Подставляете свои переменные в hirkn.yml:


  vars:
    ansible_template_dir: /etc/ansible/templates/
    wg_server_address: wg_server_ip/url
    wg_private_key: privatekey-client
    wg_public_key: publickey-server
    wg_listen_port: 51820
    wg_client_port: 51820
    wg_client_address: 192.168.100.3/24

Обязательно нужно задать:


wg_server_address — ip/url wireguard сервера
wg_private_key, wg_public_key — приватный ключ клиента и публичный сервера
Остальное можно не менять или менять, в зависимости от того как настроен WireGuard сервер


Запускаем playbook


ansible-playbook playbooks/hirkn.yml

После выполнения плейбука, роутер сразу начнёт выполнять обход блокировок через ваш wireguard сервер.


Почему не BGP?


Под openwrt есть две утилиты реализующих BGP — quagga и bird. Quagg'у мне не удалось заставить забирать данные с antifilter. Bird подружился с сервисом с полпинка, но как заставить добавлять полученным подсетям интерфейс по умолчанию я, к сожалению, не понял. (Буду рад узнать как это можно реализовать).


В комментариях к подобным статьям я видел, что роутеры у людей "призадумывались" на некоторое время, когда те загоняют списки в таблицу маршрутизации. С реализацией через ipset мой Xiaomi mi 3G задумывается на 2 секунды (Asus rt-n16 на 5 секунд), когда скармливаешь ему список из 15ти тысяч подсетей. При дальнейшей работе нагрузки на процессор не замечал.


Все материалы не являются призывом к действию и представлены для ознакомления с функционалом ОС Linux.

Комментарии (67)


  1. build_your_web
    12.02.2019 17:03
    +1

    Жаль, MikroTik не поддерживает пока.


    1. Renaissance
      12.02.2019 17:44
      +1

      Зато OpenWrt поддерживает Mikrotik.


    1. itdog Автор
      12.02.2019 18:12
      +2

      Лично мне надоело ждать openvpn udp и lzo от них, молчу уже про какое-нибудь шифрование dns. Поэтому микротик положил на полочку до лучших дней


      1. hasu
        12.02.2019 18:31
        +1

        А зачем нужно UDP с LZO? Шифрование днс можно прикрутить костылём типа метароутера с dnscrypt.


        1. Silvarum
          12.02.2019 19:00
          +3

          LZO вроде как уже deprecated и нужно использовать lz4. В любом случае, сжатие трафика на лету — довольно сомнительное преимущество, особенно если внутри шифрованный трафик типо HTTPS, который практически не сжимается. У меня на практике получалась выгода только для очень медленных линий, а для быстрых пропускная способность даже уменьшалась.
          А вот UDP — очень полезная вещь для туннелей, поскольку не получается ситуаций TCP over TCP с ужасным оверхедом и задержками. Да и UDP over TCP тоже не айс — убивает весь смысл UDP.


      1. arkamax
        12.02.2019 18:59
        +1

        Я вот тоже хотел бы OpenVPN over UDP у них. Есть ли какие-то варианты роутеров с адекватной ценой с поддержкой оного? Само собой, можно хоть отдельный сервер поднять в крайнем случае, но хотелось бы что-то менее колхозное.


        1. itdog Автор
          12.02.2019 22:29

          Многие Tp-link, Asus и все Xiaomi можно прошить OpenWrt, там нормальный Openvpn. Очень хороший по характеристикам\цене сейчас xiaomi mi 3g, перешивать его конечно — это квест небольшой. В Москве\Али можно взять за 2.5к. Я взял на авито новый за 1.8к — повезло.
          Можно найти у знакомых ненужный роутер, поддерживающий openwrt и на нём завести всё что захотите (если памяти хватит).


        1. stvorl
          12.02.2019 23:32

          Можно загнать в Mikrotik виртуальный экземпляр OpenWRT под METARouter, а там паркет старый развернуть OpenVPN в любом удобном виде (и по UDP, и с сертификатами, и с подсеткой). Маршруты и другие настройки, правда, через push сами на основной роутер не придут, придется заворачивать вручную.
          Но да, извращение страшное.


    1. hasu
      12.02.2019 18:17
      +1

      Почему не умеет? Поднимаете L2TP/IPSEC тунель, между микротиком и VPS. Curlом загоняете в addresslist микротика список заблокированных сайтов и настраиваете маршрутизацию этого адрес листа в L2TP/IPSEC интерфейс


      1. build_your_web
        12.02.2019 18:21
        +3

        Я про WireGuard. Это не L2TP/IPSEC.


        1. hasu
          12.02.2019 18:23

          Подобное реализовать можно и на микротике. Функционал будет такой же.


    1. stvorl
      12.02.2019 22:30

      Вроде как тут на Хабре была статья про обход блокировок через сторонний линукс-прокси и микротик, причем с автоматической подгрузкой маршрутов из реестра РКН.


    1. Vovanys
      13.02.2019 08:30

      Микротик сам умеет это без openwrt. Маркируем трафик и кидаем в тунель. Полно таких статей.


      1. build_your_web
        13.02.2019 09:10

        Не поделитесь ссылкой как поднять WireGuard туннель?


        1. Vovanys
          13.02.2019 10:34

          Да, WireGuard не поднять на нем. Но обычный openvpn и обход нужных хостов работает.
          Если нужно спрятать openvpn нужно воспользоваться stunnel через другой хост


    1. nemoforum
      13.02.2019 13:44

      На микротике то же самое настраивается даже проще.
      1. Поднять VPN до VPS
      2. Создать список IP адресов
      3. Создать правило в фаерволле, которое будет маркировать пакеты, попадающие в список IP
      4. Пускать маркированный траффик в VPN

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


  1. build_your_web
    12.02.2019 17:09
    +2

    Очень интересно было узнать какую скорость шифрованного канала получил автор поста, чтоб примерно понять на что способен, к примеру, упомянутый в статье Xiaomi mi 3G.


    1. itdog Автор
      12.02.2019 18:05
      +2

      Мой провайдер даёт 50мбит\с, на сервере во Франции тоже 50мбит\с
      Замерил с помощью iperf3, по два теста через провайдера и через туннель:

      Через провайдер
      koala@x220 ~> iperf3 -c speedtest.serverius.net -p 5002
      Connecting to host speedtest.serverius.net, port 5002
      [ 4] local 192.168.50.232 port 59668 connected to 178.21.16.76 port 5002
      [ ID] Interval Transfer Bandwidth Retr Cwnd
      [ 4] 0.00-1.00 sec 9.49 MBytes 79.6 Mbits/sec 5 861 KBytes
      [ 4] 1.00-2.00 sec 8.20 MBytes 68.8 Mbits/sec 4 246 KBytes
      [ 4] 2.00-3.00 sec 4.54 MBytes 38.1 Mbits/sec 70 192 KBytes
      [ 4] 3.00-4.00 sec 3.60 MBytes 30.2 Mbits/sec 38 153 KBytes
      [ 4] 4.00-5.00 sec 2.80 MBytes 23.5 Mbits/sec 35 120 KBytes
      [ 4] 5.00-6.00 sec 2.73 MBytes 22.9 Mbits/sec 0 134 KBytes
      [ 4] 6.00-7.00 sec 2.92 MBytes 24.5 Mbits/sec 0 150 KBytes
      [ 4] 7.00-8.00 sec 3.36 MBytes 28.1 Mbits/sec 0 167 KBytes
      [ 4] 8.00-9.00 sec 3.67 MBytes 30.8 Mbits/sec 0 182 KBytes
      [ 4] 9.00-10.00 sec 3.48 MBytes 29.2 Mbits/sec 44 146 KBytes
      - - - - - - - - - - - - - - - - - - - - - - - - -
      [ ID] Interval Transfer Bandwidth Retr
      [ 4] 0.00-10.00 sec 44.8 MBytes 37.6 Mbits/sec 196 sender
      [ 4] 0.00-10.00 sec 41.1 MBytes 34.4 Mbits/sec receiver

      iperf Done.
      koala@x220 ~> iperf3 -c speedtest.serverius.net -p 5002
      Connecting to host speedtest.serverius.net, port 5002
      [ 4] local 192.168.50.232 port 59676 connected to 178.21.16.76 port 5002
      [ ID] Interval Transfer Bandwidth Retr Cwnd
      [ 4] 0.00-1.00 sec 7.69 MBytes 64.5 Mbits/sec 10 567 KBytes
      [ 4] 1.00-2.00 sec 7.77 MBytes 65.2 Mbits/sec 16 298 KBytes
      [ 4] 2.00-3.00 sec 4.78 MBytes 40.1 Mbits/sec 70 230 KBytes
      [ 4] 3.00-4.00 sec 3.36 MBytes 28.1 Mbits/sec 82 124 KBytes
      [ 4] 4.00-5.00 sec 2.49 MBytes 20.8 Mbits/sec 0 141 KBytes
      [ 4] 5.00-6.00 sec 2.73 MBytes 23.0 Mbits/sec 0 151 KBytes
      [ 4] 6.00-7.00 sec 2.92 MBytes 24.5 Mbits/sec 0 167 KBytes
      [ 4] 7.00-8.00 sec 3.23 MBytes 27.1 Mbits/sec 0 181 KBytes
      [ 4] 8.00-9.00 sec 2.92 MBytes 24.5 Mbits/sec 38 143 KBytes
      [ 4] 9.00-10.00 sec 2.92 MBytes 24.5 Mbits/sec 0 168 KBytes
      - - - - - - - - - - - - - - - - - - - - - - - - -
      [ ID] Interval Transfer Bandwidth Retr
      [ 4] 0.00-10.00 sec 40.8 MBytes 34.2 Mbits/sec 216 sender
      [ 4] 0.00-10.00 sec 37.1 MBytes 31.1 Mbits/sec receiver

      iperf Done.


      1. build_your_web
        12.02.2019 18:17
        +1

        Очень даже неплохо! Спасибо!


    1. blaka
      12.02.2019 22:57

      Xiaomi mi 3G 100 мегабит провайдер. speedtest показывает прямо и через wireguard 91-94мб


  1. Ryav
    12.02.2019 17:30
    +3

    Ооооо, я давно искал подобную информацию. Уже думал разбираться в том, что написано в zaborona, и городить что-то своё, но это решение прям очень интересное, надо пробовать.


    1. blaka
      12.02.2019 23:07

      C zaborona проще. Для тех, кто не дружит с консолью, есть пакет luci-app-wireguard, а также есть скрипты настройки сервера. Да и правила меняются редко, что убирает необходимость автоматического обновления.


  1. Renaissance
    12.02.2019 17:46
    +1

    К слову, в стандартной поставке OpenWrt нет средств для работы с https, поэтому указанные 0.9МБ под установку пакетов увеличатся еще на размер пакетов для поддержки работы с https.


  1. almuerto
    12.02.2019 18:04
    +4

    Для bird4 в openwrt использую такой конфиг:

    bird4.conf
    log syslog all;
    router id 10.20.0.2;

    protocol kernel {
    import none;
    export all;
    scan time 20; # Scan kernel routing table every 20 seconds
    }
    protocol device {
    scan time 60;
    }

    protocol direct {
    interface "wireguard"; # Restrict network interfaces it works with
    }

    filter ibgp_policy {
    if ( dest = RTD_UNREACHABLE ) then {
    gw = 10.20.0.1;
    print "Alias accepted: ",net," next hop ",bgp_next_hop;
    accept;
    }
    reject;
    }
    protocol bgp OurRouter {
    description "Our Router";
    neighbor 10.20.0.1 as 64999;
    import all;
    export none;
    local as 64999;
    passive off;
    direct;
    }


    1. dartraiden
      12.02.2019 20:15
      +1

      Который пока всё равно рекомендуется отключать, поскольку неоднократно были жалобы. Ну, и, например, если развёрнута гостевая сеть и хочется ограничить её по скорости, то аппаратный NAT Offloading превращается в тыкву, ведь он несовместим с QoS.


  1. le9i0nx
    12.02.2019 18:18
    +2

    добавить маршруты в bird можно так


    Заголовок спойлера
    root@scw:/etc/bird# cat /usr/local/bin/chklist.sh 
    #!/bin/bash
    TMP_DIR=/tmp/blacklist
    mkdir -p $TMP_DIR/list
    cd $TMP_DIR/list
    wget -N https://antifilter.download/list/ipsum.lst https://antifilter.download/list/subnet.lst
    old=$(cat $TMP_DIR/md5.txt);
    new=$(cat $TMP_DIR/list/*.lst | md5sum | head -c 32);
    if [ "$old" != "$new" ]
    then
        cat $TMP_DIR/list/ipsum.lst | sed 's_.*_route & reject;_' > /etc/bird/ipsum.txt
        cat $TMP_DIR/list/subnet.lst | sed 's_.*_route & reject;_' > /etc/bird/subnet.txt
        /usr/sbin/birdc configure;
        logger "RKN list reconfigured";
        echo $new > $TMP_DIR/md5.txt;
    fi

    root@scw:/etc/bird# cat /etc/bird/bird.conf 
    log syslog all;
    router id 172.24.2.2;
    
    protocol kernel {
            scan time 60;
            import none;
            export where proto = "OurRouter";
    }
    
    protocol device {
            scan time 60;
    }
    
    protocol direct {
            interface "venet*", "tun*", "ppp*"; # Restrict network interfaces it works with
    }
    
    protocol static static_bgp {
            include "subnet.txt";
            include "ipsum.txt";
            include "custom.txt";
    }
    
    protocol bgp OurRouter {
            description "Our Router";
            neighbor 172.24.2.1 as 64999;
            import all;
            export where proto = "static_bgp";
            next hop self;
            local as 64998;
            source address 172.24.2.2;
            passive off;
    }

    root@scw:/etc/bird# cat subnet.txt 
    route 46.101.128.0/17 reject;
    route 64.137.0.0/17 reject;
    ...


  1. fenst
    12.02.2019 18:45
    +1

    Вопрос от нуба: а если мой VPS внезапно неожиданно закончится, я останусь без инета, пока не перенастрою роутер? Или же роутер сам поймет, что на том конце туннеля его никто не ждет, и перенаправит трафик в дефолтное РКНовское русло?


    1. KawaiDesu
      12.02.2019 19:00
      +2

      В тоннель заруливаются только заблокированные сайты. Так что сломает вам доступ умерший тонеель (сервер) или РКН силами вашего провайдера — всё равно. Остальной интернет продолжит работать напрямую как обычно.


      1. Silvarum
        12.02.2019 22:46

        В данном случае не только заблокированные — используются суммаризованные списки. Маршрутов меньше лопатить, но страдает точность.
        Но с полными списками возможно не всё так плохо будет на более менее домашних устройствах: я на Микротик hEX загружаю полные списки через BGP (сейчас порядка 190к маршрутов) — проглатывает не глядя.


    1. itdog Автор
      12.02.2019 22:44

      В дополнение к KawaiDesu скажу, что если вы используйте суммаризированый список, то и некоторые незапрещенные ресурсы перестанут работать.
      Маршрут убирается одной командой
      ip route del table vpn default dev wg0
      И весь трафик идёт как обычно через провайдера. Но при любом рестарте сети он пропишется заново


  1. foxyrus
    12.02.2019 19:06
    +1

    Эх еще бы что нибудь такое для поделок от МГТС, правда не понятно потянет ли железо (SERCOM RV66)


    1. Silvarum
      12.02.2019 20:14
      +1

      Можно перед МГТСом поставить вторую железку. Конечно, лишнюю железку обслуживать не ахти какое решение, но проблему решает.


      1. foxyrus
        12.02.2019 21:17

        Перед не получится — оптика. После можно, но доп железка.


        1. IRainman
          12.02.2019 22:44

          Мне кажется стоит спросить у МГТС какой сторонний ONT модем можно к ним подключить и заменить на него.


    1. itdog Автор
      12.02.2019 22:54

      Если у них есть консоль и там есть busybox, iptables и можно поднять какой-нибудь туннель/прокси — то можете попробовать. А так, да, только вторая железка


  1. Silvarum
    12.02.2019 23:02

    А можете пояснить этот момент:

    Потребляет мало ресурсов роутера: заблокированные подсети содержатся в iptables, а не в таблицах маршрутизации. Что позволяет развернуть это дело даже на слабых устройствах
    Почему так? Это связано с какими-то особенностями маршрутизации в OpenWrt? Вроде голая маршрутизация наоборот должна быть проще.


    1. loltrol
      13.02.2019 01:51

      Особенность linux в целом. Тут что то про это есть. iptables+ipset реально выход, учитывая колличество заблокированых адресов :)


      1. Silvarum
        13.02.2019 08:25

        Вот оно как. Спасибо!
        А не пробовали загружать полный список? Судя по той статье, куча /32 маршрутов должна отрабатывать очень быстро, поскольку глубина поиска будет минимальная.


        1. sigo73
          14.02.2019 11:33

          У меня работает под OpenWRT похожая схема, только я подгружаю каждый час индивидуальные адреса (сейчас там около 190 тыс. адресов), роутер (tp-link wdr3600) «приседает на 40 секунд для обновления ipset), а далее на скорость работы вообще никакого влияния. IPSet именно для таких случае разрабатывался


    1. itdog Автор
      13.02.2019 12:04

      Отличный вопрос
      Ещё дело в том, что ipset использует hash таблицы, что ускоряет поиск. Например, он может использовать бинарный поиск.
      Вроде как в ядре версии 4.4 появились снова Hash-based multipath routing. Какого-то сравнения ipset vs route table vs hash route table я не видел. Надо ставить эксперимент. Но последнее пока недоступно для моих роутеров — в 18.06 ядро 4.14.


  1. snizovtsev
    13.02.2019 00:07

    Спасибо!


    Я себе тоже на Xiaomi R3G настроил точечный обход, но средствами пакета shadowsocks-libev-ss-rules (который загружает список подсетей в ipset). Накостылял скрипт, генерирующий список из гитхаба zapret-info, мерджил и резолвил тулзой iprange.


    Wireguard это, конечно, тема интереснее, нужно будет попробовать. Из вашей статьи открыл для себя сервис antifilter.download и ansible для openwrt. Попробую разобраться с BGP, раз такая полезная возможность представилась :) Давно хотел, но не знал что могу в одиночку с ним на практике замутить.


  1. Compolomus
    13.02.2019 05:44

    Походу мой аппарат кинули
    Dir 825
    12.09 стоит лет < 10


    1. itdog Автор
      13.02.2019 12:10

      А у вас какая ревизия?
      Для b1 и c1 есть свежая 18.06.2 downloads.openwrt.org/releases/18.06.2/targets/ar71xx/generic


      1. Compolomus
        13.02.2019 12:37

        я уже и не помню какая, можно как то глянуть? у меня мод на второй usb (внутри флэха 2 гб) и мод оперативы 128. глянул, что то там пакетов кот наплакал


        1. itdog Автор
          13.02.2019 15:58

          Ревизию обычно пишут на наклейке роутера. По ней смотрите архитектуру процессора в вики и уже по архитектуре ищете прошивку


          1. Compolomus
            13.02.2019 22:06

            Глянул, b2. Ну может руки дойдут когда нибудь обновить


  1. AlanDrakes
    13.02.2019 09:49

    Помнится, в настройках запуска демона можно указать, что тот зависит от другого демона и не может запуститься, пока не будет запущен второй. Естественно, обсуждалось и имеется простенькая справка в /etc/init.d/skeleton

    unix.stackexchange.com/questions/80768/how-to-specify-daemon-dependency-upon-another-daemon

    В Вашем случае потребуется указать, что dnscrypt предоставляет 'dnscrypt', а hirkn для работы требует запущеного 'dnscrypt'. И система при запуске сервисов разрулит всё самостоятельно.


    1. itdog Автор
      13.02.2019 12:12

      Спасибо за наводку, попробую — отпишусь



  1. Lordbl4
    13.02.2019 12:07

    Неужели великий и могучий МикроТик не умеет в обход без танцев с бубном?


    1. itdog Автор
      13.02.2019 12:19

      Умеет конечно, даже с bgp. Просто шифрования dns нет и с выбором туннелей у них печально.


  1. wiseboa
    13.02.2019 12:16

    Из комментариев видно, что у каждого уважающего себя пользователя Хабра есть свой сервер, за границами зоны РКН, на котором можно развернуть WireGuard.
    Это действительно так теперь? Дорогое удовольствие?


    1. itdog Автор
      13.02.2019 12:24

      Ну по-другому сейчас никак. Найти за 200р в месяц — очень просто. Чисто для тунеля\прокси можно вообще минимальную конфигурацию за 80-100р на одном известном сервисе поиска vds найти.


      1. Lordbl4
        13.02.2019 13:09

        Единственное — платить скорее всего придётся сразу за год.
        У Итальянцев была акция vds — по 1 Евро в месяц, минимальная оплата — за месяц. Сейчас данного варианта нет, но есть по 2.79, что весьма неплохо.


        1. rogoz
          13.02.2019 13:55

          Тогда уж hetzner за 2.99 евро, пинг получше будет.


        1. itdog Автор
          13.02.2019 15:56

          Я плачу 82рубля за месяц вместе с платежной комиссией. По месяцам


          1. Energizer0
            14.02.2019 15:07

            Поделитесь, пожалуйста, названием этого хостера.


            1. itdog Автор
              14.02.2019 15:12

              good-host.net/vps
              Такие предложения отлично ищутся на vds.menu


  1. zelenin
    13.02.2019 14:52

    если мы дальше юзаем apt, то можно использовать


    apt add-repository -y ppa:wireguard/wireguard

    вместо отсутствующего add-apt-repository


  1. Mako_357
    14.02.2019 10:33

    Разве не логичнее весь трафик спрятать в vpn?


    1. sigo73
      14.02.2019 11:38

      не логичнее. Зачем нагружать излишним образом туннель? Там ведь используется шифрование, и второй момент — при доступе к ресурсам внутри РФ может оказаться что маршрут к разрешенным адресам будет длиннее чем без использования туннеля.


    1. Merifri
      14.02.2019 13:13

      Это может быть не всегда удобно.
      Например, если гоняешь большие объемы данных — датасеты, всякие докер-образы и т.п.
      Во-первых, меньшая скорость. Во-вторых, трафик на недорогих VPS, как правило, лимитирован — т.е. дополнительные затраты.

      А если делить трафик — то там можно уже и анонимность прикрутить при желании (например, поставить tor-proxy за vpn).


      1. Mako_357
        15.02.2019 19:31

        Зачем лишний раз провайдеру и остальным знать куда я хожу? Терабайта трафика на месяц в DO или Vscale не хватит?


  1. sigo73
    14.02.2019 12:10

    Отличная работа. Но если позволите несколько замечаний/предложений. У меня используется похожая схема с максимальным использованием конфигов опенврт:

    Заголовок спойлера
    1) для описания статического маршрута, который привязывается к поднятию/опусканию интерфейса используется секция route в /etc/config/network:
    config route 'anti_rkn'
    	option interface 'vpn'
    	option target '0.0.0.0'
    	option netmask '0.0.0.0'
    	#у меня используется L2 VPN, поэтому вручную указываю
    	#а для нормального VPN он сам возьмёт адрес некстхопа
    	#option gateway '192.168.30.1'
    	option table 'anti-rkn'
    

    таким образом маршрут по умолчанию поднимется после поднятия интерфейса vpn и ему будет установлена таблица маршрутизации из /etc/iproute2/rt_tables

    2) Использовать агрегированные адреса на мой взгляд не имеет смысл из-за высокой производительности при использовании ipset, там можно миллионы адресов загнать. Я у себя создал 3 ipset:
    config ipset
    	option name 'RKN-BLOCKED'
    	option storage 'list'
    	option match 'set'
    
    config ipset
    	option name 'RKN-BLOCKED-NET'
    	option storage 'hash'
    	option match 'net'
    
    config ipset
    	option name 'RKN-BLOCKED-IP'
    	option storage 'hash'
    	option match 'ip'
    	option maxelem '256000'
    

    Первый — это список из двух последующих

    3) Обновлять списки адресов раз в сутки недостаточно, у меня стоит каждые 2 часа и очень мало случаев когда изменений не было, всё остальное время получаю новые заблокированные адреса. Поэтому я сделал свой скрипт, который и вызываю каждые 2 часа:
    root@tl-wdr3600:~# cat /etc/anti-rkn/update-rkn-ip.sh 
    #!/bin/sh
    # Скрипт не сохраняет файлы с адресами на диске, все операции проводит в памяти
    
    start=`date +%s`
    
    # create temporary sets
    ipset create _tmp1 hash:net
    ipset create _tmp2 hash:ip maxelem 256000
    
    # load new content to ipset
    curl -s https://antifilter.download/list/subnet.lst | awk '{print "add _tmp1 "$1;} END {print FNR > "/tmp/rkn_nets"}' | ipset -! restore
    curl -s https://antifilter.download/list/ip.lst | awk '{print "add _tmp2 "$1;} END {print FNR > "/tmp/rkn_ips"}' | ipset -! restore
    
    # swap content
    ipset swap RKN-BLOCKED-NET _tmp1
    ipset swap RKN-BLOCKED-IP _tmp2
    
    # delete temporary sets
    ipset destroy _tmp1
    ipset destroy _tmp2
    
    end=`date +%s`
    
    logger -t update-rkn-ip "Updating the list of Anti-RKN IPs was completed, subnet="$(cat /tmp/rkn_nets)", ip="$(cat /tmp/rkn_ips)", running time="$((end-start))"sec."
    


    4) У вас при создании правил пометки пакетов осутствует строка с OUTPUT и таким образом пакеты исходящие с самого роутера не уйдут в туннель. Мой вариант:
    root@tl-wdr3600:~# cat /etc/firewall.user 
    # This file is interpreted as shell script.
    # Put your custom iptables rules here, they will
    # be executed with each firewall (re-)start.
    
    ipset add RKN-BLOCKED RKN-BLOCKED-NET
    ipset add RKN-BLOCKED RKN-BLOCKED-IP
    
    iptables -t mangle -A PREROUTING -i br-lan -m set --match-set RKN-BLOCKED dst -j MARK --set-mark 0x1000
    iptables -t mangle -A OUTPUT -m set --match-set RKN-BLOCKED dst -j MARK --set-mark 0x1000
    


    5) Ну и при использовании hotplug можно (и наверное нужно) делать проверку на поднятие интерфейса в интернет (чтобы не вызывать загрузку адресов, если инета нет или отвалился):
    root@tl-wdr3600:~# cat /etc/hotplug.d/iface/99-vpn.link-up 
    #!/bin/sh
    
    # run only after WAN link up
    [ "$ACTION" = ifup -a "$INTERFACE" = wan ] || exit 0
    
    /etc/init.d/firewall enabled || exit 0
    
    fw3 -q network "$INTERFACE" >/dev/null || exit 0
    
    /etc/anti-rkn/update-rkn-ip.sh
    


    1. itdog Автор
      14.02.2019 13:58

      Спасибо за комментарий
      1) Отлично, не подумал об этом, исправлю
      2) Лично меня устраивает суммаризированый список. Я привёл это для примера, тут каждый для себя сам решает. Но да, хотя бы эксперимента надо попробовать
      3) Ну тут зависит от задач же. Понятное дело, что ркн постоянно блочит что-то новенькое и antifilter обновляет списки. У меня лично нет необходимости иметь каждые два часа свежий список (%
      4) Да, это сделано намерено, обход только для трафика из br-lan. Роутеру нужно только ntp и ресурсы openwrt, на какие-то запрещенные ресурсы ему ходить не нужно. Поэтому на данный момент необходимости в этом не вижу
      5) Если вы о скрипте который загружает списки, то curl и сам поймет, что у него нет доступа к ресурсу, ничего не загрузит и это ничего не сломает. Ну тут тоже дело вкуса конечно

      Насчет использования конфигов, вы списки для ipset в скрипте создаёте и явно уничтожаете, подскажите почему? Вроде при перезагрузке фаервола (когда ipset в firewall сконфигурён) он стирает существующий список и создаёт по новой, а не просто добавляет адреса


      1. sigo73
        14.02.2019 18:33
        +1

        Я первоначально тоже делал агрегированый список, но потом решил посмотреть на загрузку полного списка и не увидел ухудшений в скорости работы или потребления памяти и решил оставить действительно «точечный» обход)

        Если вы про скрипт /etc/firewall.user — то стандартными средствами нельзя в список ipset добавить другой ipset, только адреса/сети/… Поэтому я после каждого рестарта файрвола созадаю новый ipset, который содержит два других ipset и устанвливаю маркировку при попадании в этот ipset.

        А если про скрипт для обновления адресов, то там используется встроенная возможность ipset обменять содержимое разных ipset, так чтобы список адресов ни на секунду не оставался пустым (потери пакетов в случае наличия трафика с адресами из запрещенных)
        Ну и соответственно не «передергиваю» файрволл чтобы загруженные новые адреса подгрузились в ядро. Сейчас у меня уходит на выполнение скрипта по обновлению около 45-50 секунд (на tp-link wdr3600), из них большая часть времени на загрузку во временные ipset, около 190 тыс.адресов и потом мгновенно обмениваю с рабочими ipset.


  1. aborouhin
    14.02.2019 14:00
    +1

    Спасибо автору статьи за наводку на antifilter.download. Промучился полдня, но завёл-таки получение от них маршрутов по BGP на Ubiquiti EdgeOS (система на базе Vyatta, за BGP там отвечает несколько своеобычная версия Quagga). EdgeRouter-4 проглотил без малого 200 тыс. маршрутов, вообще не поперхнувшись.

    Если кто ещё будет мучиться с подобной же системой — главная магия была в том, что если настраивать просто отдельного neighbor — то пиринг запускался, префиксы были видны, но не применялись (prefix list и route map не наполнялись маршрутами), хоть ты тресни.
    Но если сначала создать peer group, а потом добавить в неё neighbor — то всё сразу заработало.