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-DN42
person: username e-mail: me@domain.tld nic-hdl: USERNAME-DN42 mnt-by: USERNAME-MNT source: DN42
person — ваше имя пользователя (aka ник),
email — адрес электропочты (желательно, тот который указан в PGP‑ключе),
nic‑hdl — должно совпадать с названием файла,
mnt‑by — ссылка на объект mntner (его мы сделаем следующим),
source — DN42.Создаём объект mntner.
vim data/mntner/USERNAME-MNT
mntner: 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/AS4242422076
aut-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: DN42
as-name - название нашей автономной системы;
descr - описание (для людей);
admin-c, tech-c и mnt-by - ссылки на mntner-объект;
remarks - необязательное поле для заметок (Обычно там указывается информации о способах peering);
source - как и везде DN42.Дальше описываем блоки
vim data/inetnum/172.23.109.240_28
inetnum: 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::_48
inet6num: 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_28
route: 172.23.109.240/28 origin: AS4242422076 mnt-by: USERNAME-MNT source: DN42
Тут тоже всё понятно. Единственное, в официальной инструкции сказано, что ещё нужен атрибут
max-length
, который должен быть равен маске сети. Этот атрибут говорит другим роутерам, что максимально возможный блок будет именно /28, а если мы попробуем анонсировать /29, то этот анонс не пройдёт валидацию.Я не советую его указывать, ибо если появится желание анонсировать свою сеть частями, то этот атрибут придётся убрать. Как показала практика - это совсем не просто, так как основные пользователи против роста маршрутной таблицы.
vim data/route6/fd46:b10:16::_48
route6: 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
,Client
Anycast
Другие типы VPN (OpenVPN/GRE/ZeroTier)
2+ сервера в DN42 и внутренняя маршрутизация
IXP
Настройка всяких Mikrotik-ов.
Если кому-то это будет интересно и полезно, то могу написать статью-продолжение.
Ну и конечно, Пиринг со мной.