DN42 - это сеть из VPN-туннелей с маршрутизацией по протоколу BGP. Участники устанавливают между собой соединения, используя различные туннельные технологии (Wireguard, OpenVPN, GRE, Tinc, ZeroTier и другие).
DN42 использует адреса в диапазоне 172.20.0.0/14 (для IPv4), fd00::/8 (для IPv6), а также номера автономных систем (AS) из приватного диапазона 4242420000-4242429999.
В настоящий момент (сентябрь 2023го) для аллокации свободно 314 IPv4-блоков (15% диапазона), ~72058 миллиардов /64-сетей (0.00006% диапазона), 1404 ASN (65% диапазона). ASN можно получить в диапазоне 4242420000-AS4242423999 (остальные блоки пока закрыты для регистрации).
В отличие от Интернет, в DN42 минимальный маршрутизируемый блок - это /29 (IPv4) и /64 (IPv6). Что позволяет делать dual-stack системы.
Для сравнения, в Интернет минимальный маршрутизируемый IPv4-блок - это /24, который стоит ~11000 EUR (покупка), ~200 EUR/месяц (аренда).
Зачем оно нужно?
Можно поэкспериментировать и изучить технологии маршрутизации.
Основная польза от DN42 - это возможность получить опыт настройки туннелей и BGP-соединений. Именно так работает маршрутизация в Интернет.
Можно узнать как устроен Интернет и почувствовать себя провайдером.
В DN42 есть регистр (registry), который очень схож с той же RIPE Database, набор внутренних сервисов и свой корневой домен
.dn42и корневые DNS-сервера.
Что для этого нужно?
Иметь какое-нибудь устройство с доступом в Интернет. Любая Linux/BSD VM может быть DN42-роутером.
В идеале, VM/Компьютер/Роутер должен быть подключен к сети 24/7 и иметь статические адреса.
Разместить это устройство в сегменте, где разрешено делать сетевые туннели (Wireguard, GRE и так далее).
Я использую дешевую VPS (2.50 евро в месяц) в Суоми.
Иметь хотя бы начальные знания о сетях и маршрутизации.
Ключи и начальная настройка
Эти шаги можно делать как на вашем личном компьютере (что безопаснее), так и на VPS (если под рукой нет Linux/BSD машины). Кстати, использовать Windows-PC не получится, так как при создании объектов inet6num и route6 в названии файла используется :, а в Windows это не разрешено.
SSH
Скорее всего у Вас уже есть SSH ключи, но если нет, то генерируем их командой ssh-keygen:
ssh-keygen -t ecdsa -b 521
Она создаст пару ключей ~/.ssh/id_ecdsa (закрытый ключ) и /home/asm/.ssh/id_ecdsa.pub (публичный ключ).
PGP
PGP-ключи для настройки DN42 не обязательны, но желательны. Вот хорошая инструкция от GitHub.
Git
Также нам нужно будет установить git. DN42 Registry - это git-репозиторий.
Создание объектов в DN42 Registry
Настройка учётной записи и добавление ключей в Gitea
Первым делом идём в Registry и регистрируемся.

Затем идём в профиль и добавляем ключи.
В KeyName указать название ключа, в Content - содержимое файла ~/.ssh/id_ecdsa.pub

Также добавим и PGP-ключ

Если адрес электропочты PGP-ключа не совпадает с тем, что использовался при регистрации в Registry, то желательно подтвердить и его. Это можно сделать в настройках учетки

Создание объектов
Наконец-то приступаем к созданию объектов.
Для этого идём в Registry и жмём кнопку Fork.
Это создаст форк проекта, который будет доступен по адресуКлонируем наш форк
git clone git@git.dn42.dev:username/registry.git
cd registry
Первым создаём объект
person.Здесь и далее
USERNAME,Username,usernameиспользуются в качестве примера. Замените их на Ваши значения.vim data/person/USERNAME-DN42person: username e-mail: me@domain.tld nic-hdl: USERNAME-DN42 mnt-by: USERNAME-MNT source: DN42person — ваше имя пользователя (aka ник),
email — адрес электропочты (желательно, тот который указан в PGP‑ключе),
nic‑hdl — должно совпадать с названием файла,
mnt‑by — ссылка на объект mntner (его мы сделаем следующим),
source — DN42.Создаём объект mntner.
vim data/mntner/USERNAME-MNTmntner: USERNAME-MNT admin-c: USERNAME-DN42 tech-c: USERNAME-DN42 mnt-by: USERNAME-MNT source: DN42 auth: ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAAEVWYzitbGM5wyH07zY3iieXH28drL24rYpglGMlnH8QK4Tz+sCCg5LI/XpGd7At+liXWa90zQjAoYjk3q4Vi1+QFseJUC... auth: pgp-fingerprint 88361AC....mntner - название объекта (должно совпадать с названием файла).
admin-c - административный контакт. Ссылка на объектperson.
tech-c - технический контакт. Также ссылка на объектperson.
mnt-by - то же самое, что и поле mntner.
source - DN42.
auth - содержимое файла~/.ssh/id_ecdsa.pub.
auth - fingerprint pgp-ключа (если создавали).Для следующих объектов нам нужно выбрать номер автономной системы (ASN), IPv4 и IPv6 префиксы (сети).
Чтобы найти свободные ASN и префиксы идём в FreeExplorer и выбираем.
Обычно люди выбирают одну ASN, /27 IPv4-сеть (32-адреса) и /48 IPv6-сеть. Если у Вас маленькая сеть, то советую взять /28-ую сеть (16-адресов). Если наоборот, то /26 - её дадут без дополнительных вопросов. Всё что больше /26 (для IPv4) и /48 (для IPv6) потребует объяснения зачем Вам нужна такая большая сеть.
Итак, выбираем. Опять же я взял случайные значения из FreeExplorer и их надо заменять на выбранные Вами.
AS4242422076 172.23.109.240/28 fd46:b10:16::/48Возвращаемся в склонированный репозиторий и создаём объект для нашей ASN
vim data/aut-num/AS4242422076aut-num: AS4242422076 as-name: EXAMPLE-AS descr: My Username Personal AS or another useful desciption admin-c: USERNAME-DN42 tech-c: USERNAME-DN42 remarks: Peer with me at me@domain.tld or another human-oriented message mnt-by: USERNAME-MNT source: DN42as-name - название нашей автономной системы;
descr - описание (для людей);
admin-c, tech-c и mnt-by - ссылки на mntner-объект;
remarks - необязательное поле для заметок (Обычно там указывается информации о способах peering);
source - как и везде DN42.Дальше описываем блоки
vim data/inetnum/172.23.109.240_28inetnum: 172.23.109.240 - 172.23.109.255 cidr: 172.23.109.240/28 netname: EXAMPLE-NETWORK descr: My Personal IPv4 Network remarks: Peer with me at me@domain.tld country: FI admin-c: USERNAME-DN42 tech-c: USERNAME-DN42 mnt-by: USERNAME-MNT status: ASSIGNED source: DN42Название файла должно содержать нашу подсеть и маску (/ заменяется на _).
inetnum - указывается диапазон возможных адресов (можно посчитать с помощью IP calculator);
cird - подсеть в CIRD-нотации;
netname - название сети;
descr - описание для людей;
remarks - то же самое что и для автономной системы (можно писать, а можно и нет).
country - тоже необязательное поле;
admin-c, tech-c и mnt-by - ссылки на mntner-объект;
status - ASSIGNED (там есть и другие, но вроде нужно указывать именно ASSIGNED);
source - как обычно, DN42.IPv6-блок практически тоже самое
vim data/inet6num/fd46:b10:16::_48inet6num: fd46:0b10:0016:0000:0000:0000:0000:0000 - fd46:0b10:0016:ffff:ffff:ffff:ffff:ffff cidr: fd46:b10:16::/48 netname: EXAMPLE-NETWORK descr: My Personal IPv6 Network remarks: peer with me at me@domain.tld country: FI admin-c: USERNAME-DN42 tech-c: USERNAME-DN42 mnt-by: USERNAME-MNT status: ASSIGNED source: DN42Объекты для блоков мы создали, теперь самое время связать блоки с нашей автономной системой. Для этого есть объекты
routeиroute6.vim data/route/172.23.109.240_28route: 172.23.109.240/28 origin: AS4242422076 mnt-by: USERNAME-MNT source: DN42Тут тоже всё понятно. Единственное, в официальной инструкции сказано, что ещё нужен атрибут
max-length, который должен быть равен маске сети. Этот атрибут говорит другим роутерам, что максимально возможный блок будет именно /28, а если мы попробуем анонсировать /29, то этот анонс не пройдёт валидацию.Я не советую его указывать, ибо если появится желание анонсировать свою сеть частями, то этот атрибут придётся убрать. Как показала практика - это совсем не просто, так как основные пользователи против роста маршрутной таблицы.
vim data/route6/fd46:b10:16::_48route6: fd46:b10:16::/48 origin: AS4242422076 mnt-by: USERNAME-MNT source: DN42Ещё есть объекты
dns(для своего домена в .dn42-зоне) иorganisation(для организации), но они необязательны и о них я напишу в другом посте.
Проверка, коммит, подпись и запрос на слияние (Pull Request)
На данный момент все необходимые объекты созданы и теперь нужно проверить, закоммитить и создать Pull Request.
Первым делом, отформатируем наши объекты
./fmt-my-stuff USERNAME-MNT
Затем проверим их на правильность и соответствие схеме
./check-my-stuff USERNAME-MNT
вывод команды check-my-stuff
[NOTE] ## Scan Started at 2023-09-12 15:36:45
CHECK data/mntner/USERNAME-MNT PASS MNTNERS: USERNAME-MNT
[NOTE] ## Scan Completed at 2023-09-12 15:36:46
[NOTE] ## Scan Started at 2023-09-12 15:36:46
CHECK data/aut-num/AS4242422076 PASS MNTNERS: USERNAME-MNT
[INFO] fd46:b10:16::/48
CHECK data/inet6num/fd46:b10:16::_48 PASS MNTNERS: USERNAME-MNT
CHECK data/inetnum/172.23.109.240_28 PASS MNTNERS: USERNAME-MNT
CHECK data/mntner/USERNAME-MNT PASS MNTNERS: USERNAME-MNT
CHECK data/person/USERNAME-DN42 PASS MNTNERS: USERNAME-MNT
CHECK data/route/172.23.109.240_28 PASS MNTNERS: USERNAME-MNT
CHECK data/route6/fd46:b10:16::_48 PASS MNTNERS: USERNAME-MNT
[NOTE] ## Scan Completed at 2023-09-12 15:36:47
Всё хорошо - можно коммитить
git add -A && git commit -am "Join DN42"
Теперь надо этот коммит подписать
./sign-my-commit --ssh --key ~/.ssh/id_ecdsa USERNAME-MNT
вывод команды sign-my-commit
Fetching dn42registry master
From git.dn42.dev:dn42/registry
branch master -> FETCH_HEAD
1 local commits found, no squash is required
Signing using SSH key
Detected git version >= 2.34, using git SSH signature
Using: 2048 SHA256:KJrAwld+1JfuT6zTN3t/fGVsNnIJq+Ltz9LkGdUj6kw /home/username/.ssh/id_ecdsa.pub (ECDSA)
[master d6b44bb97] Join DN42
Date: Tue Sep 12 17:38:42 2023 +0300
7 files changed, 49 insertions(+)
create mode 100644 data/aut-num/AS4242422076
create mode 100644 data/inet6num/fd46:b10:16::_48
create mode 100644 data/inetnum/172.23.109.240_28
create mode 100644 data/mntner/USERNAME-MNT
create mode 100644 data/person/USERNAME-DN42
create mode 100644 data/route/172.23.109.240_28
create mode 100644 data/route6/fd46:b10:16::_48
Verifying SSH signature in git
Good "git" signature for USERNAME-MNT with key SHA256:....
SSH signature verified ok
---
Remember to push your changes using: git push --force
---
Отправляем изменения в гит
git push --force
вывод команды git push
Enumerating objects: 364, done.
Counting objects: 100% (364/364), done.
Delta compression using up to 12 threads
Compressing objects: 100% (142/142), done.
Writing objects: 100% (333/333), 45.11 KiB | 45.11 MiB/s, done.
Total 333 (delta 230), reused 286 (delta 191), pack-reused 0
remote: Resolving deltas: 100% (230/230), completed with 28 local objects.
remote:
remote: Create a new pull request for 'username:master':
remote: https://git.dn42.dev/dn42/registry/compare/master...username:master
remote:
remote: . Processing 1 references
remote: Processed 1 references in total
To git.dn42.dev:username/registry.git
9c55ad3be...d6b44bb97 master -> master (forced update)
Идём по ссылке в сообщении, проверяем изменения, а также что коммит подписан и делаем New Pull Request

Дальше Ваш коммит проверят с помощью автоматической проверки.
Если всё хорошо, то остаётся ждать когда Ваш PR сольют с основной веткой. Этот процесс может занять 1-2 дня. На практике проверено, что слияния происходят утром (в 9-10 EEST) и вечером (17-20 EEST)
Если что-то пошло не так
Если валидатор указал на ошибку, то нужно её исправить и отправить изменения.
vim data/path/to/fileисправляем ошибку
Дальше коммитим
git add -A && git commit -am "Join DN42"Теперь у нас 2 коммита и их надо слить в один. Для этого выполняем:
./squash-my-commits
вывод команды squash-my-commits
Fetching dn42registry master
From git.dn42.dev:dn42/registry
branch master -> FETCH_HEAD
Rebasing local changes against the registry master
Current branch master is up to date.
Squashing 2 commits...
[master ac847fda0] squashed commit:
7 files changed, 49 insertions(+)
create mode 100644 data/aut-num/AS4242422076
create mode 100644 data/inet6num/fd46:b10:16::_48
create mode 100644 data/inetnum/172.23.109.240_28
create mode 100644 data/mntner/USERNAME-MNT
create mode 100644 data/person/USERNAME-DN42
create mode 100644 data/route/172.23.109.240_28
create mode 100644 data/route6/fd46:b10:16::_48
Remember to sign your commit: ./sign-my-commit FOO-MNT
and then push your changes using: git push --force
Как и до этого, коммит надо подписать и отправить.
./sign-my-commit --ssh --key ~/.ssh/id_ecdsa USERNAME-MNT
git push --force
вывод команды git push
Enumerating objects: 26, done.
Counting objects: 100% (26/26), done.
Delta compression using up to 12 threads
Compressing objects: 100% (17/17), done.
Writing objects: 100% (17/17), 2.88 KiB | 2.88 MiB/s, done.
Total 17 (delta 10), reused 0 (delta 0), pack-reused 0
remote:
remote: Visit the existing pull request:
remote: https://git.dn42.dev/dn42/registry/pulls/1234
remote:
remote: . Processing 1 references
remote: Processed 1 references in total
To git.dn42.dev:username/registry.git
d6b44bb97...82037bd0e master -> master (forced update)
Как видно из сообщения, новый PR создавать не надо и изменения уже отправлены в существующий запрос.
На этот раз обе проверки прошли успешно и остаётся только ждать

Подготовка сервера
Первое правило Бойцовского клуба dn42: всегда отключайте rp_filter.
Вообще-то, rp_filter штука полезная и блокирует пакет, если маршрут возврата пакета использует другой интерфейс, чем тот, с которого он прибыл.
Но как и в Интернет, так и в DN42 маршрутизация асимметричная, то пакеты могут идти по разным маршрутам. Вот почему rp_filter необходимо отключить.
vim /etc/sysctl.conf
Также включаем форвардинг между интерфейсами:
vim /etc/sysctl.conf
net.ipv4.ip_forward = 1 net.ipv6.conf.all.forwarding = 1 net.ipv6.conf.default.forwarding = 1
Применяем налету
sysctl -p
Проверяем
sysctl -a | grep rp_filter
sysctl -a | grep forwarding
Находим пиринг-партнера
После того как наши изменения оказались в основной ветке (master), можно искать пиринг-партнера или сразу нескольких пиринг-партнеров.
Но я советую всё же подождать пару-тройку часов. Как и в Интернет, в DN42 есть механизм защиты и верификации маршрутов ROA (Route Origin Authorization).
ROA - это файл конфигурации вида
route 172.23.67.0/25 max 29 as 4242420022; route 172.20.175.96/27 max 29 as 4242421508; ...
Он сообщает BGP-демону, что ASN 4242420022 может анонсировать префикс 172.23.67.0/25 или её подсети вплоть до /29. Данный файл генерируется dn42regsrv ROA Generator-ом и доступен для скачивания отсюда.
Большинство (IMHO) пиров скачивает этот файл по cronjob (или systemd timer) раз в 15-20 минут и подождать надо именно с целью того, чтобы информация о ваших объектах разошлась по сети.
Чтобы найти пиринг-партнера можно использовать сервис DN42 PeerFinder.

Он покажет наиболее близкие к вашей локации роутеры, но так как большинство (опять же IMHO) пирится вручную и надо писать людям на электропочту/телеграм/IRC, я бы советовал бы начать с автоматического пиринга.
Вот список сетей, которые предоставляют автоматический пиринг.
Лично мне больше всего понравился сервис сети Lutoma. Он предоставляет дружелюбный интерфейс и looking glass, который позволяет посмотреть состояние сессии со стороны Lutoma.
Автоматический пиринг
Процесс пиринга состоит из 3 шагов:
Верификация того, что Вы владеете AS, которую используете для пиринга
Создание туннеля
Создание BGP-сессии
Покажем как это выглядит на практике (на примере Lutoma и нашего сервера на ArchLinux).
Регистрация и Верификация AS
Открываем Peering Portal и жмём жёлтую кнопку "Sign up"
Вводим свой maintainer object
USERNAME-MNTи получаем на электропочту ссылку для верификации.
Настройка туннеля Wireguard
Для автоматичес��ого пиринга Lutoma использует Wireguard-туннели (это самый популярный туннельный тип в DN42), поэтому нужно установить wireguard-tools
pacman -Sy wireguard-tools
Дальше нам надо сгенерировать ключи для шифрования в туннеле.
cd /etc/wireguard
wg genkey | (umask 0077 && tee 64719.pri) | wg pubkey > 64719.pub
Тут и далее я использую номер автономной сети пиринг-партнера в названии файлов конфигурации.
После успешной верификации и создания учётки можно, наконец, создавать туннель и настраивать BGP-cессию.
Для этого:
жмём Create Peering
выбираем подходящий Router и вводим название соединения. Что-то вроде
myuserame(потом оно пригодится при отладке)VPN Type - уже выбран.
В Wireguard endpoint - нужно вставить IP вашего роутера (это внешний IP, по которому роутер доступен в Интернете) и порт, на котором будет работать наш Wireguard. Также есть возможность ввести доменное имя, что по идее, позволяет устанавливать соединение с динамическим IP (DynDNS), но я такое не пробовал.
Далее Lutome нужен Ваш публичный ключ. Копируем его и вставляем в поле Wireguard public key.
cat 64719.pub
Заполняем секцию BGP:
вводим номер автономной системы
4242422076В поле Internal IPv4 address нужно ввести один из IP из нашей DN42 подсети, например,
172.23.109.249. У меня сделано таким образом: я разделил свою /28-ую сеть на две /29-ые. Первая часть (172.23.109.240/29) используется для LAN, вторая (172.23.109.248/29) - для пиринга.В Link-local IPv6 address вводим любой адрес из диапазона
fe80::/64(например,fe80::4719).Оставляем галочку на Multi-protocol BGP over IPv6 (Bird2 такое умеет).
В Link bandwidth выбираем пропускную способность своего Интернет соединения.
Cоздаём пиринг

Возвращаемся на сервер и настраиваем туннель.
vim /etc/wireguard/wg64719.conf
/etc/wireguard/wg64719.conf
[Interface] PrivateKey = <Private_key_from_64719.pri> ListenPort = 64719 Table = off PostUp = /sbin/ip addr add dev %i 172.23.109.241/32 peer 172.22.119.1/32 PostUp = /sbin/ip addr add dev %i fe80::4719/128 peer fe80::acab/128 PostUp = sysctl -w net.ipv4.conf.%i.rp_filter=0 PostUp = sysctl -w net.ipv4.conf.%i.forwarding=1 PostUp = sysctl -w net.ipv6.conf.%i.autoconf=0 PostUp = sysctl -w net.ipv6.conf.%i.accept_ra=0 PostUp = sysctl -w net.ipv6.conf.%i.forwarding=1 [Peer] Endpoint = de-fra.dn42.lutoma.org:43229 PublicKey = <Lutoma_Public_Key> AllowedIPs = 172.20.0.0/14, fd00::/8, fe80::/64 PersistentKeepalive = 20
В PrivateKey вставляем наш приватный ключ из файла 64719.pri.
В Endpoint-e нужно вставить хост и порт из Вашей конфигурации.
Lutoma_Public_Key также берём из конфигурации.
Запускаем туннель
systemctl enable --now wg-quick@wg64719
После этого можно проверить соединение.
ping 172.22.119.1
ping fe80::acab%wg64719
Если оба адреса пингуются, то можно переходить к настройке BGP, если нет, то смотрим состояние с помощью команды
wg
Настройка BGP-сессии
В качестве BGP-демона в Linux/BSD можно использовать Bird/Quagga/FRRouting и другие. Я использую Bird2, если Вы планируете использовать другой демон, но у DN42, скорее всего, будет инструкция по его настройке.
Установка Bird2
pacman -S bird
Создаём структуру директорий
mkdir -p /etc/bird/{roa,peers}
ROA
Как я уже писал ранее ROA позволяет проверять соответствие ASN-prefix, это позволяет защититься от BGP hi-jacking.
Это можно и не делать, но я советую использовать ROA-проверку, тем более это несложно.
Для синхронизации ROA-конфигурации я использую curl, который запускается каждые 15 минут Systemd Timer-ом.
vim /etc/systemd/system/roa.service
/etc/systemd/system/roa.service
[Unit] Description=Update DN42 ROA [Service] Type=oneshot ExecStart=curl -sfSLR -o /etc/bird/roa/roa_v4.conf -z /etc/bird/roa/roa_v4.conf https://dn42.burble.com/roa/dn42_roa_bird2_4.conf ExecStart=curl -sfSLR -o /etc/bird/roa/roa_v6.conf -z /etc/bird/roa/roa_v6.conf https://dn42.burble.com/roa/dn42_roa_bird2_6.conf ExecStart=birdc configure
vim /etc/systemd/system/roa.timer
/etc/systemd/system/roa.timer
[Unit]
Description=Update DN42 ROA periodically
[Timer]
OnBootSec=2m
OnUnitActiveSec=15m
AccuracySec=1m
[Install]
WantedBy=timers.target
systemctl enable --now roa.timer
В итоге у нас должны появится два новых файла /etc/bird/roa/roa_v4.conf и /etc/bird/roa/roa_v6.conf
Bird2
Переходим к настройке Bird. Для начала я взял конфигурацию из документации.
В данной конфигурации мы получаем все маршруты, отфильтровываем те, которые не прошли ROA-проверку, остальные устанавливаем в таблицу маршрутов ядра.
Экспортируем (сообщаем пиринг-партнеру) все маршруты, которые имеем, но предварительно отсеиваем не DN42-cети.
bird.conf
################################################ # Variable header # ################################################ define OWNAS = 4242422076; define OWNIP = 172.23.109.241; define OWNIPv6 = fd46:b10:16::1; define OWNNET = 172.23.109.240/28; define OWNNETv6 = fd46:b10:16::/48; define OWNNETSET = [172.23.109.240/28+]; define OWNNETSETv6 = [fd46:b10:16::/48+]; ################################################ # Header end # ################################################ router id OWNIP; protocol device { scan time 10; } /* * Utility functions */ function is_self_net() { return net ~ OWNNETSET; } function is_self_net_v6() { return net ~ OWNNETSETv6; } function is_valid_network() { return net ~ [ 172.20.0.0/14{21,29}, # dn42 172.20.0.0/24{28,32}, # dn42 Anycast 172.21.0.0/24{28,32}, # dn42 Anycast 172.22.0.0/24{28,32}, # dn42 Anycast 172.23.0.0/24{28,32}, # dn42 Anycast 172.31.0.0/16+, # ChaosVPN 10.100.0.0/14+, # ChaosVPN 10.127.0.0/16{16,32}, # neonetwork 10.0.0.0/8{15,24} # Freifunk.net ]; } roa4 table dn42_roa; roa6 table dn42_roa_v6; protocol static { roa4 { table dn42_roa; }; include "/etc/bird/roa_dn42.conf"; }; protocol static { roa6 { table dn42_roa_v6; }; include "/etc/bird/roa_dn42_v6.conf"; }; function is_valid_network_v6() { return net ~ [ fd00::/8{44,64} # ULA address space as per RFC 4193 ]; } protocol kernel { scan time 20; ipv6 { import none; export filter { if source = RTS_STATIC then reject; krt_prefsrc = OWNIPv6; accept; }; }; }; protocol kernel { scan time 20; ipv4 { import none; export filter { if source = RTS_STATIC then reject; krt_prefsrc = OWNIP; accept; }; }; } protocol static { route OWNNET reject; ipv4 { import all; export none; }; } protocol static { route OWNNETv6 reject; ipv6 { import all; export none; }; } template bgp dnpeers { local as OWNAS; path metric 1; ipv4 { import filter { if is_valid_network() && !is_self_net() then { if (roa_check(dn42_roa, net, bgp_path.last) != ROA_VALID) then { print "[dn42] ROA check failed for ", net, " ASN ", bgp_path.last; reject; } else accept; } else reject; }; export filter { if is_valid_network() && source ~ [RTS_STATIC, RTS_BGP] then accept; else reject; }; import limit 1000 action block; }; ipv6 { import filter { if is_valid_network_v6() && !is_self_net_v6() then { if (roa_check(dn42_roa_v6, net, bgp_path.last) != ROA_VALID) then { print "[dn42] ROA check failed for ", net, " ASN ", bgp_path.last; reject; } else accept; } else reject; }; export filter { if is_valid_network_v6() && source ~ [RTS_STATIC, RTS_BGP] then accept; else reject; }; import limit 1000 action block; }; } include "/etc/bird/peers/*.conf";
По факту, нужно только подставить в Header свои значения:
С OWNAS всё понятно - это номер автономной системы
В OWNIP указываем адрес роутер (я использую адрес LAN-адаптера).
С OWNIPv6 - то же самое, что и с OWNIP
В OWNNET и OWNNETv6 - указываем нашу IPv4-подсеть (и в IPv6-подсеть соответственно).
В OWNNETSET/OWNNETSETv6 - то же самое.
Добавим конфигурацию для нашего пиринг-партнера.
vim /etc/bird/peers/lutoma.conf
/etc/bird/peers/lutoma.conf
protocol bgp lutoma from dnpeers {
neighbor fe80::acab % 'wg64719' as 64719;
description "https://dn42.lutoma.org / hello@lutoma.org";
};
Взлетаем Запускаемся!
systemctl enable --now bird
Проверка состояния
Ждём 2-3 минуты и проверяем, что маршруты пришли:
ip route && ip -6 route
Если сессия установилась, то Вы увидите ~565 IPv4 и ~740 IPv6-маршрутов.
Поздравляю! Вы подключены к DN42. Можно даже пингануть какой-нибудь IP (корневой DNS server DN42, например):
ping -c 2 172.20.0.53
ping 172.20.0.53
PING 172.20.0.53 (172.20.0.53) 56(84) bytes of data.
64 bytes from 172.20.0.53: icmp_seq=1 ttl=63 time=24.7 ms
64 bytes from 172.20.0.53: icmp_seq=2 ttl=63 time=25.1 ms
--- 172.20.0.53 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 24.726/24.937/25.149/0.211 ms
Отладка
Если не всё так радужно и в маршрутной таблице почти пусто, то идём к Lutoma, где myuserame - это название нашего соединения.
Также смотрим и со своей стороны:
birdc show protocols lutoma
birdc show route
Настройка DNS
Пинговать и трейсить IP-адреса - это хорошо, но быстро наскучит. В DN42 есть же куча сервисов, которые доступны только изнутри.
Так как зона .dn42 является внутренней и корневые DNS-сервера Интернета о ней не знают, то использовать тот же Cloudflare DNS или Google DNS не получится. Вместо это можно использовать локальный DNS-демон dnsmasq, который все запросы к dn42-доменам будет адресовать к корневому DN42-серверу, а остальное к Cloudflare/Google/Quad9.
Установка и конфигурация dnsmasq
pacman -S dnsmasq
vim /etc/dnsmasq.conf
/etc/dnsmasq.conf
# Listen on this standard DNS port port=53 # Never forward plain names (without a dot or domain part) domain-needed # Don't read /etc/hosts file no-hosts # Don't read /etc/resolv.conf or any other file. # Use only the configuration provided by this file. no-resolv # Don't poll changes from external files (like /etc/resolv.conf) no-poll # Upstream DNS servers server=2606:4700:4700::1111 server=2001:4860:4860::8844 server=1.1.1.1 server=8.8.8.8 # Force the upstream servers to be used in order strict-order # Increase the cachesize cache-size=1500 # Don't store in cache the invalid resolutions no-negcache # Forward DN42 rebind-domain-ok=dn42 server=/dn42/172.20.0.53 # Reverse Forwards for DN42 server=/10.in-addr.arpa/172.20.0.53 server=/20.172.in-addr.arpa/172.20.0.53 server=/21.172.in-addr.arpa/172.20.0.53 server=/23.172.in-addr.arpa/172.20.0.53
А ещё dnsmasq умеет блокировать рекламу, но это совсем другая история.
Остаётся запустить dnsmasq и прописать его в качестве DNS-сервера по умолчанию.
systemctl enable --now dnsmasq
vim /etc/resolv.conf
/etc/resolv.conf
nameserver ::1
nameserver 2606:4700:4700::1111
Проверяем.
ping -c 2 asm.dn42
ping asm.dn42
PING asm.dn42(asm.ax (fd21:3087::1)) 56 data bytes
64 bytes from asm.ax (fd21:3087::1): icmp_seq=1 ttl=63 time=11.7 ms
64 bytes from asm.ax (fd21:3087::1): icmp_seq=2 ttl=63 time=11.8 ms
--- asm.dn42 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 11.702/11.747/11.793/0.045 ms
На этом предлагаю остановиться. Неохваченными остались следующие темы:
Multi-homing (пиринг с несколькими пиринг-партнерами).
BGP communities
Создание своего домена в зоне
.dn42Создание организации
Различные типы пиринга:
Peer,Upsteam,ClientAnycast
Другие типы VPN (OpenVPN/GRE/ZeroTier)
2+ сервера в DN42 и внутренняя маршрутизация
IXP
Настройка всяких Mikrotik-ов.
Если кому-то это будет интересно и полезно, то могу написать статью-продолжение.
Ну и конечно, Пиринг со мной.
