Приветствую сообщество.

В этой заметке я хотел бы поделиться своим велосипедом по настройке ipv6 в локациях где невозможно это сделать нормальным способом (провайдер не умеет/может/хочет ipv6).

На входе у нас есть локация где есть ipv4 интернет (дача, регион, офис), oracle VM instance и роутер на базе openwrt обслуживающий сеть в нашей локации.

На выходе мы хотим получить нормально (насколько это возможно в рамках наших ограничений) работающий ipv6 там, где не удалось настроить правильным/ровным способом через провайдера.

Мы будем решать 2 задачи, а именно:

1) Все устройства в нашей локальной сети должны иметь доступ к ipv6 ресурсам в интернете

2) Из интернета мы хотим иметь возможность достучаться до устройств внутри нашей локальной сети по прямому ipv6 адресу.

Это удобно когда, например, на даче у нас есть камеры/хабы/NAS/итд и мы хотим обращаться к ним напрямую по ipv6 адресу.

Теория

Для того чтобы реализовать задачу №1 нам нужен хотя бы один роутер  у которого есть ipv6 адрес и который умеет выходить в мир. Все остальные устройства мы спрячем за NAT'ом. Да-да, вы не ослышались, технология которая была придумана чтобы избавить мир от этого ужасного зла, сама будет его использовать :(
Увы, таковы ограничения oracle free tier instances.

Технически это будет выглядеть так.

У нас есть oracle compute instance (далее просто VM) на котором мы настроим global ipv6 address. На этой машине поднимем wireguard vpn, подключим к ней все наши локации и сделаем ip6tables masquerade. Таким образом все наши устройства внутри конкретной локации смогут достучаться до любых ipv6 ресурсов.
Криво ? Да ! Костыльно ? Снова, да ! Есть идеи получше ? Пишите в комментариях.

Для решения задачи №2 нам снова понадобятся костыли но уже иного рода.

Чтобы какое-то устройство было видно из интернета ему нужен global ipv6 address.
А где ж его взять когда его нет ? Ответ: ip6tables DNAT.

Мы настроим на нашей VM еще пачку global ipv6 адресов и будем пробрасывать их на устройства внутри локаций через ip6tables DNAT.

Криво ? Да ! Костыльно ? Снова, да ! Есть идеи получше ? Пишите в комментариях.

Внимательный читатель спросит: а почему бы просто не нарезать и зароутить ipv6 /64 подсеть через wireguard vpn в нужную локацию ?

Увы, oracle free tier не маршрутизирует выделенную подсеть /64 на нашу VM.
Адреса из подсети /64 нужно назначать ручками (ohh, shit) и поштучно (ohh, shit !) c лимитом не более 32 адресов (ohhh, shit ?!) на одну VM :(
Вот такие пироги... С практической точки зрения это означает что мы сможем достучаться не более чем до 32 устройств во всех наших локациях.

Практика

В практической части настройку мы будем делать в трех местах:

  1. роутер на базе прошивки openwrt

  2. oracle cloud interface 

  3. внутри oracle VM 

В этой заметке предполагается что читатель уже обзавелся oracle cloud free tier account ом (как его получить можно почитать например тут) и уже поднял/настроил wireguard vpn на oracle VM.

Пошаговая инструкция

Шаг 1: Настройка ipv6 на oracle VM

Сначала включаем/настраиваем ipv6 на VM, подробный гайд на эту тему можно почитать тут.

Теперь добавим нашей VM global unique ipv6 адрес.
Это нужно для того чтобы решить задачу №1, именно под этим адресом все устройства из наших локаций будут ходить на ipv6 ресурсы в интернете.

Для этого в интерфейсе oracle cloud:

  1. Идем в Compute → Instances → <выбираем нашу VM> → Attached VNICs → <выбираем Primary VNIC> → IPv6 Addresses → Assign IPv6 Address

  2. В открывшемся блоке Subnet IPv6 Prefix выбираем ранее созданный subnet → Manually assign IPv6 addresses from prefix → <задаем ipv6 адрес> →  Assign.
    Во всех примерах далее будет использоваться адрес 2603:a:b:c::100

  3. Теперь заходим на нашу  VM по ssh и добавляем этот адрес на внешний интерфейс

ip a a 2603:a:b:c::100 dev enp0s3

  1. Проверяем

enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 9000
        inet 10.0.0.33  netmask 255.255.255.0  broadcast 10.0.0.255
        inet6 2603:a:b:c::100  prefixlen 128  scopeid 0x0<global>
        inet6 fe80::200:17ff:fe02:874a  prefixlen 64  scopeid 0x20<link>
        ether 00:00:17:02:87:4a  txqueuelen 1000  (Ethernet)

  1. Видим что все в порядке, теперь попробуем попинговать его из интернета (не забываем включить соответствующее правило в файерволе если вы его не отключили в oracle cloud interface). Сделать это можно например так.

  2. Если пинг прошел успешно можно вас поздравить и переходить к следующему шагу ?

Шаг 2: Настройка ipv6 в локальной сети нужной локации

Для нормально функционирующего ipv6 на роутере нам необходимо поднять /64 подсеть. Учитывая то, что link-local адреса не маршрутизируются, а global адресов у нас нету мы поднимем ULA подсеть. Эти адреса не глобальные но они маршрутизируются, и этого достаточно для решений обеих задач. 

ULA адреса берутся из специально выделенного диапазона fc00::/7.
Мы для удобства будет использовать fd01::/16 для первой локации, fd02::/16 для второй, fd03::/16 для третьей, итд.

На роутере с  openwrt это делается очень просто

  1. Идем в Network → Interfaces → Global network options и задаем там желаемую подсеть

  1. Идем в Network → Interfaces и в интерфейсе который обслуживает наш LAN, проверяем что Delegate IPv6 prefixes (checked) и IPv6 assignment length 64 (вкладка Advanced Settings)

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

  1. Настраиваем DHCPv6 на роутере так, чтобы устройства в нашей сети начали получать адреса вида fd01::/64 (нам понадобятся дальше статические ipv6 адреса когда мы будем настраивать доступ к конкретным устройствам из интернета).

Для этого идем в Network → Interfaces и в интерфейсе который обслуживает наш LAN

  1. Проверяем что устройства внутри нашей локальной сети начали получать адреса вида fd01::a:b:c:d/128

    Шаг 3: Настройка wireguard server/client

Шаг 3: Настройка wireguard server/client

Тут нет никаких особых премудростей, подойдет любая инструкция.
Ниже я опишу только самые важные моменты.

  1. На сервере (oracle VM) в конфиге wireguard не забываем добавить подсети вида fd01::/64, fd02::/64 итд в AllowedIPs соответствующих секций и перезапустить server

[Peer]
# location 1
PublicKey = <public key here>
AllowedIPs = 192.168.16.1/32,192.168.1.0/24,fd01::1/64

[Peer]
# location 2
PublicKey = <public key here>
AllowedIPs = 192.168.16.2/32,192.168.2.0/24,fd02::1/64

[Peer]
# location 3
PublicKey = <public key here>
AllowedIPs = 192.168.16.3/32,192.168.3.0/24,fd03::1/64

  1. На клиенте (openwrt router) не забываем в настройки peer в AllowedIPs добавить подсеть →  ::/0 и перезапустить интерфейс

  2. На клиенте заворачиваем весь ipv6 трафик на wireguard интерфейс

ip -6 r a default dev wgoracle

  1. Проверяем пингуется ли ipv6 global адрес из шага 1 с любого устройства из локальной сети.

ping -c 4 2603:a:b:c::100
PING 2603:a:b:c::100 (2603:a:b:c::100): 56 data bytes
64 bytes from 2603:a:b:c::100: seq=0 ttl=64 time=107.419 ms
64 bytes from 2603:a:b:c::100: seq=1 ttl=64 time=74.966 ms
64 bytes from 2603:a:b:c::100: seq=2 ttl=64 time=307.784 ms
64 bytes from 2603:a:b:c::100: seq=3 ttl=64 time=318.498 ms
--- 2603:a:b:c::100 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 74.966/202.166/318.498 ms

Ну что ж отлично, полпути уже проделано.

  1. На сервере включаем ipv6 forwarding

sysctl -w net.ipv6.conf.all.forwarding=1

  1. Ну а теперь самый важный шаг: на сервере настраиваем ipv6 маскарад

ip6tables -t nat -A POSTROUTING -o enp0s3 -s fd01::1/64 -j MASQUERADE

Это правило говорит о том, что весь трафик из локальной сети fd01::1/64 будет NAT ится в oracle VM global ip из шага 1 (в нашем примере это 2603:a:b:c::100)

  1. С любого устройства из локальной сети пробуем пингануть какой-нибудь внешний ipv6 ресурс

ping6 -c 4 ipv6.ya.ru
PING ipv6.ya.ru(any.yandex.ru (2a02:6b8::242)) 56 data bytes
64 bytes from any.yandex.ru (2a02:6b8::242): icmp_seq=1 ttl=53 time=169 ms
64 bytes from any.yandex.ru (2a02:6b8::242): icmp_seq=2 ttl=53 time=157 ms
64 bytes from any.yandex.ru (2a02:6b8::242): icmp_seq=3 ttl=53 time=125 ms
64 bytes from any.yandex.ru (2a02:6b8::242): icmp_seq=4 ttl=53 time=133 ms

--- ipv6.ya.ru ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 7ms
rtt min/avg/max/mdev = 125.248/145.841/168.632/17.488 ms

Ура ! Работает ! :)  На этом шаге задача №1 успешно решена.
Любые ipv6 ресурсы нам теперь доступны через самопальный ipv6-in-ipv4 туннель :) 

Шаг 4: Настраиваем доступ к конкретным устройства внутри LAN из интернета.

Предположим что у нас внутри LAN есть устройства к которым мы хотим достучаться (камера, smart home hub, NAS). И у этих устройств уже есть статические ULA ipv6 адреса которые они получают через dhcpv6 которые мы настроили на шаге 2.

Ниже мы настроим прямой доступ из интернета к устройству fd01::10.
Для всех остальных устройств шаги аналогичные. Приступаем:

  1. На сервере (oracle VM) убеждаемся что устройство доступно по ULA адресу

  2. Далее заходим в oracle cloud interface (как мы делали это на шаге 1) и добавляем адрес 2603:a:b:c::1:10.

Тут хочу замечу что такая нотация удобна лично мне, вы можете выбрать любую другую. 

Внешний адрес 2603:a:b:c::1:10 будет мапиться на внутренний fd01::10.
Другой внешний адрес, например, 2603:a:b:c::2:15 будет мапиться в fd02::15.
И так далее.

  1. Самый важный шаг: на сервере настраиваем IPv6 DNAT (по сути маппинг внешнего адреса во внутренний)

ip6tables -t nat -A PREROUTING -d 2603:a:b:c::1:10 -j DNAT --to-destination fd01::10

  1. Проверяем через пинг (не забываем настроить правило в файерволе локальной сети) с какого-нибудь внешнего ресурса.

ping -c 4 2603:a:b:c::1:10
PING 2603:a:b:c::1:10 (2603:a:b:c::1:10): 56 data bytes
64 bytes from 2603:a:b:c::1:10: seq=0 ttl=64 time=17.419 ms
64 bytes from 2603:a:b:c::1:100: seq=1 ttl=64 time=74.966 ms
64 bytes from 2603:a:b:c::1:10: seq=2 ttl=64 time=37.784 ms
64 bytes from 2603:a:b:c::1:10: seq=3 ttl=64 time=31.498 ms
--- 2603:a:b:c::100 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss

Ура ! Заработало ! Трафик действительно дошел до нашего устройства :)

Заключение

Ну что ж, обе задачи нами успешно решены через набор подпорок и костылей.
Автор полностью осознает ущербность, неправильность и костыльность предложенных решений и посыпает голову пеплом.

Но, увы, других (более “ровных”)  вариантов пока отыскать не удалось.
В комментариях предлагаю забросать автора помидорами и указать правильные способы решения вышеупомянутых задач :)

Успехов !

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


  1. litos
    11.05.2024 15:05

    Сейчас дистрибутивы Linux начинают переходить с iptables на nftables, хорошо бы было попробовать использовать его


    1. sirj Автор
      11.05.2024 15:05

      В принципе можно, принципиально ничего не поменяется, только команды DNAT/MASQUERADE будут другими.
      Думаю что через различного рода "конвертеры" iptables <-> nftables можно легко их себе нагенерить.


  1. olegtsss
    11.05.2024 15:05

    Но, увы, других (более “ровных”)  вариантов пока отыскать не удалось - относительно недавно достаточно подробно рассматривал вашу проблему через интеграцию с ipv6 брокером: https://habr.com/ru/companies/ruvds/articles/760338/


    1. sirj Автор
      11.05.2024 15:05

      Годное решение.
      Когда я пробовал играться с туннелями от hurrican electric меня смущало то, что они периодически отваливались если через них не шел трафик (просто моя догадка, на самом деле не знаю в чем проблема) и приходилось прикручивать костыли чтобы их периодически перезапускать.
      Если эти болячки уже починились то выглядит как более "ровный" способ если не смущает лишний hop в цепочке маршрутов (lan -> vps -> broker -> internet)


    1. AlexHighTower
      11.05.2024 15:05

      а это способ случаем не подразумевает обязательное наличие публичного ipv4 адреса на который будут лететь пакеты? т.е. если провайдер не даёт тебе публичный адрес, то ой...


  1. DaemonGloom
    11.05.2024 15:05
    +4

    Один из простых и разумных вариантов - тоннель от hurricane electric (https://tunnelbroker.net).


    1. Sly_tom_cat
      11.05.2024 15:05

      И на том же OpenWRT настраивается довольно просто.


    1. mrSnyaify
      11.05.2024 15:05

      И постоянно ловить капчи от Гугла и Яндекса :(


    1. sirj Автор
      11.05.2024 15:05

      Я когда-то пробовал это решение.
      Да, там все просто и оно даже работает, но нужен внешний белый IPv4 (либо я что-то недопонял).
      С моим велосипедом этого не требуется.


    1. BjLomax
      11.05.2024 15:05

  1. haga777
    11.05.2024 15:05

    а если у меня есть ipv6  на микроте? 
    как подсесть /64 кинут  через впн на другой микрок с который за нат? 


  1. Chupaka
    11.05.2024 15:05
    +1

    Инструкция по получению Oracle Cloud уже не первый год неактуальна для значительной аудитории Хабра? Я уж понадеялся, что что-то новое открыли...


    1. sirj Автор
      11.05.2024 15:05

      Статья про возможность поднять ipv6 там где его не выдает провайдер.
      У меня под рукой был oracle cloud поэтому решение основано на нем.
      Теоретически можно все это повторить на любом другом клауде, надо только понять какие там ограничение по ipv6 адресам/подсетям


    1. ciuafm
      11.05.2024 15:05

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

      Неужели у вас нет знакомых за границей?


      1. osj
        11.05.2024 15:05

        Вы удивитесь, но не все так просто. Большинство дебетовок пластиковых откидывается. We accept credit cards and debit cards that function like credit cards. We do not accept debit cards with a PIN or virtual, single-use, or prepaid cards.


  1. CCNPengineer
    11.05.2024 15:05

    а зачем IPv6 ? можно же на IPv4 адрес Оракл и на далее NAT с разных портов на разные устройства.


    1. sirj Автор
      11.05.2024 15:05

      Это да, но port mapping это тот еще геморрой, яркий пример это NATить наружу FTP.
      Когда у нас устройство доступно по IP адресу, проблем гораздо меньше (сугубо имхо).


      1. CCNPengineer
        11.05.2024 15:05

        разве кто то использует сейчас нешифрованый FTP ? и открывает динамические порты? сейчас думаю все используют SCP шифрованый протокол передачи файлов поверх SSH на порту TCP 22


        1. sirj Автор
          11.05.2024 15:05

          Если у вас нет проблем с NAT и пробросом портов и вы умеете управлять всем этим "зоопарком" вам этот велосипед не нужен :)


  1. Hinedes
    11.05.2024 15:05

    Статья прикольная так-то, просто я не знаю зачем использовать Ipv6..


    1. sirj Автор
      11.05.2024 15:05

      Основное преимущество для меня это возможность напрямую работать с устройствами внутри сети (у каждого устройства свой "белый" IP).
      Никакого геморроя с пробросом портом и сопуствующими проблемами.


      1. enamchuk
        11.05.2024 15:05

        Если нужна "внутрисеть", то советую присмотреться к ZeroTier, Tailscale, Netbird.
        При желании можно и пробросы портов сделать, или использовать как VPN, выходя в сеть через любой (заранее настроенный) узел сети.
        Внутри сети используются IPv4, IPv6, а связь между узлами, зачастую идёт напрямую, минуя релеи.