Версия 6 протокола IP изначально разрабатывалась с расчётом на множественные подключения к Интернету и множественные IP-адреса у одного хоста. Что может быть полезным в месте, где отсутствует «хороший» доступ к Интернету по IPv6. Увы, всё ещё возможно вести бизнес предоставления доступа, не предоставляя в меню IPv6. Это вынуждает админов на местах пользоваться различными суррогатами. Представьте, например, что первый суррогат надёжен, но является медленным, а второй быстр, но особого доверия к нему нет. Разумно «на всякий случай» держать включенными оба. Но если два диапазона IPv6 маршрутизованы через одну и ту же машину-шлюз, то как не дать ей запутаться, каким пакетам куда идти? Обычные правила маршрутизации, основанные на IP-адресах получателя, тут не годятся.

Что решается

Данная статья описывает решение проблемы маршрутизации IPv6 в случае, когда локальная сеть наделяется двумя источниками IPv6, работающими через один маршрутизатор. Конкретно, чтобы пакет IPv6 из локальной сети уходил в Интернет через тот интерфейс, к которому приписан его исходящий адрес.

Что не решается

В данной статье не рассматривается, как прикладные программы выбирают, каким подключением к Интернету им пользоваться. В частности, как выбирать между двумя глобальными «своими» адресами IPv6 (или слать по IPv4).

Статья не делает акцент на вопросы подключения IPv6, полагая их решение доступным самостоятельным усилиям администратора.

Описание условий

В приводимом ниже примере в распоряжении администратора локальной сети имеются два блока (глобального) IPv6-пространства, и оба реализованы через 6in4 (инкапсуляция v6 в пакетах IPv4). Первый — 6to4, отображающий диапазон IPv6-адресов 2002::/16 на Интернет v4. Если провайдер выделяет вам белый IP-адрес, имеет маршрут на anycast-адрес 192.88.99.1 и в целом не слишком крив, то FreeBSD сама поднимет его (под именем stf0) при указании в /etc/rc.conf:

ipv6_enable="YES"
stf_interface_ipv4addr="▀▀.▄▄.◥◥.◣◣"  # Здесь должен быть записан белый IP
ipv6_defaultrouter="2002:c058:6301::"

Этот способ с 2015 года считается устаревшим, однако его преимуществом является привязка диапазона IPv6 к публичному адресу IPv4 (который, в моём случае, постоянен). Даже если в сетевой инфраструктуре, обеспечивающей 6to4, что-то поменяется, то на адресах, назначенных устройствам в локальной сети, это не отразится. Важнейшим недостатком 6to4 в современных условиях является низкая пропускная способность. Также, мой 6to4 гоняет IPv6 из локалки в европейской России через шлюз в Амстердаме, что добавляет около 40 мс задержки.

Второй источник моего IPv6 в диапазоне 2001:470::/32 расположен поближе и пропускная способность у него побольше, поскольку делает его компания Hurricane Electric (под брэндом tunnelbroker.net). Это — туннель, интерфейс которого ядро называет gif0 и поднимаю я его особым системным скриптом, изготовление и установка которого выходит за рамки статьи; потребные для включения tunnelbroker команды перечислены здесь. Его недостатком являются блок IPv6 без особого запаса по размеру (/64), а также зависимость от коммерческой фирмы, с которой не имеешь договора.

Описание pf(4)

Файл /etc/pf.conf содержит текст программы для пакетного фильтра pf(4), входящего в поставку BSD-систем. Текст состоит из определений (макросов) и последовательности правил вида «для такого-то пакета оттуда-то и туда-то делай то-то». При указании pf_enable="YES" в /etc/rc.conf подача правил на выполнение включается автоматически во время инициализации FreeBSD. Вручную можно включить (новый) свод правил командой

pfctl -e -f /etc/pf.conf

Если pf уже включен, то указывать ключ «-e» не обязательно.

Решение

Предполагаем, что наш /etc/pf.conf содержит следующие определения:

myv6_6to4 = "2002:▀▀▄▄:◥◥◣◣::/48"
myv6_he   = "2001:470:◆◆:●●●::/64"
v6_noglobal = "fc00::/6"

Это позволяет решить поставленную задачу двумя правилами:

# routing related to tunnels
pass quick from $myv6_he to {$myv6_6to4, $myv6_he, $v6_noglobal}
pass out route-to gif0 from $myv6_he to any

Основная работа делается правилом «pass out route-to ⋯», предписывающим исходящим (out) пакетам идти (pass) в интерфейс gif0 невзирая на таблицу маршрутов (где, как мы вспоминаем, присутствует default на stf0).

Правило «pass quick ⋯» досрочно (quick) прекращает проверку фильтром пакетов, идущих из диапазона на адреса в том же диапазоне ($myv6_he), либо в другом принадлежащем сети диапазоне ($myv6_6to4), а также на разные адреса ($v6_noglobal), не являющиеся глобальными. Этот трафик не надо принудительно направлять в gif0.

Важно: в pf.conf правила pass должны идти после определений и правил переназначения адреса (rdr, nat).

Замечания

Если вместо «pass out route-to ⋯» поставить «pass in route-to ⋯», то правило будет обслуживать трафик, проходящий через шлюз, но не сработает для пакетов, создаваемых на машине FreeBSD локально.

Поскольку канала для IPv6 только два, маршрутизацию 6to4 мы смогли сделать «исключением альтернатив», на основании стандартной таблицы маршрутов ядра. Что, если канала станет три и понадобится маршрутизировать 6to4 явно? В принципе, можно было бы добавить аналогичные правила для stf0:

pass quick from $myv6_6to4 to {$myv6_6to4, $myv6_he, $v6_noglobal}
pass out route-to stf0 from $myv6_6to4 to any

Препятствие заключается в том, что протокол 6to4 устроен сложнее, чем «просто» туннель gif0 (в котором не имеется выбора, через которую точку послать пакет). А мы предположили, что маршрут по умолчанию ведёт не в stf0. Хотя pf(4) понимает непосредственного получателя пакета с опцией «route-to (interface, gateway)», в 6to4 этот gateway надо включать лишь если адрес назначения не лежит в диапазоне 2002::/16. Можно попытаться заменить один «pass out route-to ⋯» двухходовкой

pass out quick route-to stf0 from $myv6_6to4 to 2002::/16
pass out route-to (stf0, 2002:c058:6301::) from $myv6_6to4 to any

но лично мне как-то пробовать уже не интересно…

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


  1. FotoHunter
    05.11.2021 22:49

    У меня это реализовано на Linux, 2 канала до hurnicate electric (Швеция и Нидерланды) через 2 физических провайдеров. Для клиентов подняты 2 подсети маршрутизируемые 2мя разными роутерами. Выбор маршрута происходит автоматически на уровне клиента. Yandex через 1го, Google через 2го.


  1. dragoangel
    07.11.2021 11:24

    Такая же схема с pfsense: 2 HE туннеля, по одному на WAN, с разными HE endpoint через NATPt. Клиенты в сети получают IPv6 с подсети основного WAN, и транслируются через резервный канал когда основной не доступен. Минус: на момент переключения мы теряем преимущество IPv6: прозрачную маршрутизацию, но без своей ASN я другого решения не вижу. Схема в работе больше 3 лет, работает отлично.

    Ну и есть два минуса в самом использовании туннеля:

    1. увы, но в интернетах до сих пор встречаются сервисы которые не понимая важность ICMP трафика банят то что банить нельзя (destination unreachable/package too big) ломая PMTUD и этим ломая HE туннель так как из-за 5 калек вешать на всю intranet MTU 1480 не охота, а без этого они не доступны через туннель.

    2. приходится пройтись по многим geoip db и откорректировать данные о тех подсетях что вы используете для того чтобы бы сервисы которые их используют корректнее работали. Увы война с корпорацией добра (Google) у меня так и не увенчалась успехом, что я не делал, они не меняют geoip информацию на мои 2*/48 подсети на протяжении всех лет. Не понимаю я их если честно - у них в руках их личная geoip, данные геолокации с телефонов и они не могут даже их сопоставить, и форму заявки для ipv6 адаптировать не могут, как и человеко-саппорт добавить.

      Разруливаю оба этих недостатка через unbound python модуль (раньше свой личный, а теперь тот что в pfBlockerNG): делаю strip AAAA для таких нехороших сервисов в DNS resolving. К слову снова с Google пришлось снова повоевать, нужно было обрезать AAAA сразу для нескольких их доменов, видители они в токены авторизации зашивают IP, и выдают свои токены на разные сервисы. Выходит: пришел на google.com по ipv4 - значит иди и на googleusercontent и на youtube, и т.д. Не знаю как у них это вообще работает даже с нормальным резолвингом, ибо любой браузер умеет и сам делать downgrade на запросы с ipv6 на ipv4, если при этом есть выигрыш в производительности.


    1. FotoHunter
      09.11.2021 04:25

      Я чуть дольше в этой теме у "вконтакте" сервер с картинками отваливался на ipv6, потом поправили :))) У меня оба he канала паралельно работают, но один из них время от времени падает из за падения их ipv4 шлюза. По поводу mtu не понял, у меня 1480 на ipv6 нормально работает. Есть лишь сложности с некоторыми клиентскими машинами в частности на Ubuntu 20.04 netplan настроил на 2 шлюза, а после обновления он вылетел с ошибкой, оказалось больше не держит 2 ipv6 шлюза, а при получении шлюза автоматически другие проблемы вылезают. Поэтому маршрутизатор крутится на SlackWare и все настройки жёстко прописаны.


      1. dragoangel
        09.11.2021 04:28

        не понял причем там ВК :).

        По MTU - прочитайте еще раз, проблем нет пока вы не наткнетесь на сервер у которого не функционирует PMTUD из-за неверного firewall на его стороне.


        1. FotoHunter
          10.11.2021 07:14

          у ВК, по крайней мере на момент, когда я ipv6 начал осваивать, часть серваков не умело в ipv6 и когда клиент заходил по v6 - текстовая часть сайта грузилась, а фотки нет. Сейчас там всё работает в полном объёме, но сам факт, что некоторые сайты могут криво работать с ipv6 забавляет :) А с mtu и icmp мне видимо везло или я не рассматривал с этой точки зрения неработающие сайты.


          1. dragoangel
            10.11.2021 12:03

            В смысле в полном обьеме? ВК вообще вырубили IPv6, еще давным давно, еще до того как его в Украине забанили...

            >> но сам факт, что некоторые сайты могут криво работать с ipv6 забавляет :)

            Скажем так - чем сайты которые работают по IPv6 могут делать что то криво? Разве что:geoip, rate limiting, brute force protection, ip restrictions. Тоесть все логические взяви с IP, их в системах не так уж и много. А то что не отображась картинки - это уже проблема из ряда DNS который указывает не на тот сервер или мисконфигурации самого веб сервера..., на прямую к IPv6 не имеющего отношения, просто те кто тестил работу сервиса могли банально забыть что у них еще есть IPv6. Видел одного клиента у которого "заводские" настройки DNS у регистратора имели АААА на парковочные IPv6. Их админ не понимая что такое АААА и почему он там - не стал его убирать, а А запись он конечно поправил. Вышла картина: сайт у них работает "для них", потому что у них нет IPv6, но для нас и для всех нормальных поисковых систем их сайт это что? Правильно - просто заглушка. А потом они удивлялись почему их в поисковиках никто найти не может... Ахаха...

            По PMTUD - запустите Microsoft Skype for Business или Lync, и поймете :P