Форум OlegON > Компьютеры и Программное обеспечение > Сеть

IPv6: настройка локалки с учетом динамического префикса провайдера (Ростелеком) : Сеть

16.04.2024 11:54


12.03.2018 12:17
OlegON
 
Несмотря на то, что вопросы IPv6 я уже поднимал здесь, все же решил выделить в отдельную тему, чтобы не получилась полная каша.

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

Топология следующая:
ISP - Linux router - Mikrotik - LAN

Самая конфетка в данных условиях - произвольное изменение провайдером адреса IPv6 и его же префикса. Закономерности не выявлял (и не пытался), но, как факт, пока игрался с серверами, клиенты получали иногда по 5 адресов из разных префиксов, что в итоге заворачивало пакеты в никуда. Просто стал исходить из того, что адрес и префикс динамические.

Хрустящим фантиком конфетки являлось полное игнорирование Mikrotik (ROS) RA-пакетов. Т.е. Linux ему шлет RA, а на ROS адреса не назначаются. На форуме по Mikrotik пообщался - посоветовали ставить DHCP-сервер. Радости, конечно, это сильно не прибавило.

Нюанс еще один - из клиент-серверных пакетов в репозиториях есть wide-dhcp6 и dibbler. Оба сильно лохматой давности. Сначала я взял именно wide, поскольку Network manager его поддерживает, но со временем пришлось от него отказаться - возможности скриптования у dhcp6s достаточно скудные или я так и не нашел, как получить наружу в скрипт полученный префикс. В общем, поменял я все на dibbler. В нем все прозрачно и просто, за исключением того, что сервер разок минимум засегфолтился. И, да, ни один из сервисов не был оформлен демоном. Я тоже не стал под них писать юниты.

Итого, на Линукс-рутере поднят dibbler-client, который запрашивает префиксы и адрес на внешний и внутренний интерфейс, скриптом изменения дергаются dibbler-server и radvd, которые перезапускается при каких-либо сетевых изменениях с новыми конфигами, в качестве бонуса - перезапускается DNS-сервер unbound, пересаживающийся на новый адрес при его изменении. Пока работает.

Из известных багов схемы - сраный dibbler-client за каким-то хреном подтягивает DNS-сервера с ISP, хотя я его об этом не просил и специально не включал опцию запроса, даже убрал ее. Видимо, это хардкод где-то. Второй прикол в том, что клиенты получают адрес IPv6 совсем не сразу после поднятия интерфейса, а по аннонсу RA с Микротика, поскольку DHCP6 на нем нет. Поэтому могут получаться условия, когда софт вообще не в курсе существования IPv6 и не пытается по нему работать. Это несмотря на то, что local адрес на интерфейсе появляется сразу. У меня несколько раз так затыкался Transmission.
Перехожу к конфигам (привожу только то, что относится к описываемой схеме):

/etc/sysconfig/network-scripts/ifcfg-enp3s0 (LAN)
Цитата:
IPV6INIT=yes
IPV6_AUTOCONF=no
инициализацию интерфейса надо производить и на сервере и на клиентах, поскольку иначе не получите локальный адрес, а без него не работает все остальное. Однако, для WAN-интерфейса работает и без этого

/etc/sysconfig/network-scripts/ifcfg-enp1s0 (WAN)
Цитата:
IPV6INIT=no
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
IPV6FORWARDING=yes
/etc/sysctl.conf
Цитата:
net.ipv6.conf.all.forwarding=1
net.ipv6.conf.default.forwarding=1
net.ipv6.conf.enp1s0.accept_ra=2
net.ipv6.conf.enp3s0.accept_ra=2
по умолчанию, если включить форвард, то отключается прием RA.

/etc/dibbler/client.conf
Цитата:
log-mode syslog
reconfigure-accept 1
log-level 2
inactive-mode
script "/etc/dibbler/script"
iface enp3s0 {
ia
pd
routing 1
option dns-server
}
iface enp1s0 {
ia
pd
routing 1
}
тут все просто, запрашиваем адрес (ia) и префикс (pd). Самый сок в скрипте обновления
/etc/dibbler/script
Код:
#!/bin/bash
set >/etc/dibbler/set
export PREFIX1
export ADDR1
PREFIX=`cat /etc/dibbler/prefix`
ip -6 r del $PREFIX/56 via fe80::6e3b:6bff:fe12:29f8 dev enp3s0 metric 256 pref medium
if [ ! -z "$PREFIX1" ];
then
echo "$PREFIX1">/etc/dibbler/prefix
fi
if [ ! -z "$ADDR1" ];
then
echo "$ADDR1">/etc/dibbler/addr
fi
PREFIX=`cat /etc/dibbler/prefix`
ADDR=`cat /etc/dibbler/addr`
export PREFIX
export ADDR
ip -6 r add $PREFIX/56 via fe80::6e3b:6bff:fe12:29f8 dev enp3s0 metric 256 pref medium
cat /etc/dibbler/radvd.tpl | envsubst>/etc/radvd.conf
cat /etc/dibbler/server.tpl | envsubst>/etc/dibbler/server.conf
/usr/sbin/dibbler-server stop
sleep 5
pkill -9 dibbler-server
/usr/sbin/dibbler-server start
sleep 5
systemctl restart radvd
systemctl reload unbound
/etc/dibbler/radvd.tpl
Цитата:
interface enp3s0
{
AdvSendAdvert on;
AdvManagedFlag on;
AdvOtherConfigFlag on;
AdvReachableTime 0;
AdvRetransTimer 0;
AdvCurHopLimit 64;
MaxRtrAdvInterval 120;
AdvDefaultLifetime 800;
AdvDefaultPreference medium;
AdvSourceLLAddress on;
prefix $PREFIX/64
{
AdvValidLifetime 7300;
AdvPreferredLifetime 7300;
AdvOnLink on;
AdvAutonomous on;
AdvRouterAddr off;
DeprecatePrefix off;
};
};
/etc/dibbler/server.tpl
Цитата:
log-level 2
log-mode syslog
preference 255
iface enp3s0 {
prefered-lifetime 3600
valid-lifetime 7200
class {
pool $PREFIX/56
}
pd-class {
pd-pool $PREFIX/56
pd-length 64
}
option dns-server $ADDR
option domain olegon.ru
option lifetime 600
option ntp-server $ADDR
}
Тут немного сложнее. При изменении сетевых настроек клиент не получает адрес и префикс одновременно. Однако, в шаблонах они прописываются сразу оба. Поэтому пришлось скидывать то, что дали в файл, если пришло не пустое и потом подбирать из файла, получая таким образом последние настройки. Да, особый момент в том, что несмотря на появление префикса, не появлялся рутинг до клиентов. Точнее, по умолчанию добавлялся
Код:
ip -6 r add $PREFIX/56 dev enp3s0 metric 256 pref medium
и в итоге ни хрена не работало, пока не указывал явно local адрес следующего хопа, т.е. интерфейс микротика
Код:
ip -6 r add $PREFIX/56 via fe80::6e3b:6bff:fe12:29f8 dev enp3s0 metric 256 pref medium
Да, не очень красивое решение, поскольку в момент работы скрипта рутинг пропадает на какое-то очень короткое время, но, заморачиваться с проверкой текущего очень не хотелось, хотя это и недолго сделать, отгрепав про префиксу.

Ну и по Mikrotik
Код:
/ipv6 export verbose
# mar/12/2018 12:03:20 by RouterOS 6.41.2
# model = RouterBOARD 962UiGS-5HacT2HnT
/ipv6 address
add address=::100/64 advertise=yes disabled=no eui-64=no from-pool=pool6 interface=bridge no-dad=no
/ipv6 dhcp-client
add add-default-route=yes disabled=no interface=wan pool-name=pool6 pool-prefix-length=64 prefix-hint=::/0 request=\
    address,prefix use-peer-dns=yes
/ipv6 nd
set [ find default=yes ] advertise-dns=yes advertise-mac-address=yes disabled=no hop-limit=unspecified interface=all \
    managed-address-configuration=no mtu=unspecified other-configuration=yes ra-delay=3s ra-interval=30s-1m20s ra-lifetime=30m \
    reachable-time=unspecified retransmit-interval=unspecified
/ipv6 nd prefix default
set autonomous=yes preferred-lifetime=6h valid-lifetime=6h
/ipv6 settings
set accept-redirects=yes-if-forwarding-disabled accept-router-advertisements=yes forward=yes max-neighbor-entries=1024
суть настроек в том, чтобы принимать RA, однако, одновременно и назначать себе адрес через DHCP6. Подчеркну свою основную ошибку, над которой бился некоторое время - pool6 создавать НЕ надо, он создастся сам, как только DHCP6 получит lease. Самому создать пул, удовлетворяющий динамике префиксов, не удастся. Соответственно на бридже (для клиентов) необходимо создать какой-то адрес с указанием from-pool, т.е. чтобы заработала цепочка: клиент DHCP получает адрес, создает пул, появляется адрес из пула на интерфейсе, заработал RA на интерфейсе. Маленькие сроки жизни и анонсов RA на Mikrotik объясняются каким-то текущим багом, который обещали поправить в следующей версии.

Вот, как-то так… Работает несколько дней, в т.ч. специально ребутнул всех. Если у кого-то замечания и дополнения - прошу отписаться ниже. Я ни разу не сетевой спец, но задачу хотелось решить. Даже не догадываюсь, сколько косяков оставил, поскольку достаточно неважно все документировано по софту. Ну, если вопросы - задавайте.
03.05.2018 12:08
OlegON
 
В общем, предложенный выше вариант накрылся медным тазом. Поделие польских товарищей (dibbler-*) почему-то стало валиться в корку, оставляя меня без столь нужного в последнее время IPv6. Пришлось все переделать для софта от ISC, попутно еще озадачиться и выкинуть radvd, поскольку он при наличии dhcp-server не нужен. Итак, результат для dhcp-server и dhcp-client от ISC

/etc/dhcp/dhclient.conf
Код:
timeout 15;
retry 60;
interface "enp1s0" {
 supersede dhcp6.name-servers ::1;
 request;
}
собственно, пояснять нечего, кроме того, что я игнорирую DNS-серверы от провайдера, поскольку у меня есть свой unbound. Самый сок в скрипте dhclient-enter-hooks, который вызывается dhclient при изменениях конфигурации, полученной от провайдера.
/etc/dhcp/dhclient-enter-hooks
Код:
#!/bin/bash
function make_resolv_conf {
touch /etc/dhcp/dhclient.conf
}

SERVER=`grep 'Reply message on enp1s0 from ' /var/log/messages | sed -r 's/.*from (.*)\.$/\1/' | tail -n1`

if [ ! -z "$SERVER" ];
then
echo "$SERVER">/etc/dhcp/server
fi

PREFIX=$new_ip6_prefix

if [ ! -z "$PREFIX" ];
then
echo "$PREFIX">/etc/dhcp/prefix
fi

ADDR=$new_ip6_address

if [ ! -z "$ADDR" ];
then
echo "$ADDR">/etc/dhcp/addr
fi

export SERVER=`cat /etc/dhcp/server`
export PREFIX=`cat /etc/dhcp/prefix`
export ADDR=`cat /etc/dhcp/addr`
export LADDR=`cat /etc/dhcp/prefix|sed -e 's#/56#1#'`
export LPREFIX=`cat /etc/dhcp/prefix|sed -e 's#/56#/64#'`
export LRANGE=`cat /etc/dhcp/prefix|sed -e 's#/56##'`

if ! ip -6 r s dev enp3s0 | grep "$PREFIX" &>/dev/null ; then
echo Change route
ip -6 r flush table main
ip -6 r add default via $SERVER dev enp1s0 proto static metric 512 pref medium
ip -6 r add $PREFIX via fe80::6e3b:6bff:fe22:29f8 dev enp3s0 metric 256 pref medium
ip -6 r add fe80::6e3b:6bff:fe12:29f8 dev enp3s0 metric 100
fi

if ! ip -6 a s dev enp3s0 | grep "$LADDR" &>/dev/null; then
echo Change secondary address
ip -6 a flush dev enp3s0 scope global
ip -6 a add $LADDR dev enp3s0
sleep 10
cat /etc/dhcp/unbound.tpl | envsubst>/etc/unbound/unbound.conf
systemctl restart unbound.service
cat /etc/dhcp/server.tpl | envsubst>/etc/dhcp/dhcpd6.conf
pkill -9 dhcpd
/usr/sbin/dhcpd -6 -cf /etc/dhcp/dhcpd6.conf enp3s0
fi
Поясню... make_resolv_conf надо переопределять, чтобы не трогал resolv.conf, хотя, мне кажется, он его и так не трогает.
Ловлю "Reply message on enp1s0" по логу, чтобы если вдруг аплинк, раздающий адреса, изменится, для меня это не было сюрпризом. Он нужен для дефолтового рутинга. Скрипт вызывается по поводу любого изменения конфигурации, поэтому иногда бывает, что каких-то переменных в нем нет. Чтобы не мучиться, я просто скидываю их в файл, если переменные не пустые, а потом оттуда достаю. Соответственно, создаю таблицы рутинга, назначаю адреса и создаю конфиги зависимых сервисов. Обращаю внимание на unbound. Прикол с ним в том, что при запуске на ::1, он начинает перехватывать транзитные пакеты и откликаться с совсем не тех адресов, куда был послан запрос. Это крайне не нравилось штатному клиенту, пришлось отучить. Вот набор tpl

/etc/dhcp/server.tpl
Код:
default-lease-time 1800;
max-lease-time 7200;
log-facility local7;
subnet6 $LPREFIX {
        range6 $LPREFIX;
        option dhcp6.name-servers $ADDR;
        option dhcp6.domain-search "olegon.ru";
        prefix6 $LRANGE $LRANGE /64;
}
/etc/dhcp/unbound.tpl
Код:
server:
        verbosity: 0
        statistics-interval: 0
        statistics-cumulative: yes
        extended-statistics: no
        num-threads: 2
        interface: 0.0.0.0
        interface: $ADDR
        outgoing-interface: 77.37.240.57
        outgoing-interface: $ADDR
        prefer-ip6: no
        outgoing-range: 256
        outgoing-num-tcp: 128
        incoming-num-tcp: 128
        so-rcvbuf: 1m
        so-sndbuf: 1m
        so-reuseport: yes
        edns-buffer-size: 1480
        msg-cache-size: 50m
        msg-cache-slabs: 4
        num-queries-per-thread: 128
        rrset-cache-size: 100m
        rrset-cache-slabs: 4
        cache-min-ttl: 3600
        cache-max-ttl: 86400
        cache-max-negative-ttl: 300
        infra-host-ttl: 1800
        infra-cache-slabs: 2
        infra-cache-numhosts: 1000000
        do-ip4: yes
        do-ip6: yes
        do-udp: yes
        do-tcp: yes
        use-syslog: yes
        root-hints: "/etc/unbound/root.hints"
        prefetch: yes
        prefetch-key: yes
        rrset-roundrobin: yes
        minimal-responses: yes
        module-config: "iterator"
        key-cache-size: 128m
        key-cache-slabs: 4
        neg-cache-size: 256k
определения локальных зон и access-control я не буду светить... суть в outgoing-interface
Поскольку иногда адреса меняются и сервисы не могут запуститься, я раз в минуту проверяю их и перезапускаю
Код:
ps -ef | grep -v grep | grep '/usr/sbin/dhclient -6 -P -N -R enp1s0' &>/dev/null || /scripts/run_dhcp6.sh &>/dev/null
pgrep dhcpd>/dev/null || /usr/sbin/dhcpd -6 -cf /etc/dhcp/dhcpd6.conf enp3s0 &>/dev/null
pgrep master>/dev/null || systemctl restart postfix.service &
pgrep tor>/dev/null || systemctl restart tor.service &
pgrep ntpd>/dev/null || systemctl restart ntpd.service &
pgrep unbound>/dev/null || systemctl restart unbound.service &
а раз в сутки проверяю вообще живость IPv6
Код:
ping -c3 ipv6.google.com &>/dev/null || ( pkill -9 dhclient ; ip -6 r flush table main ; ip -6 a flush dev enp3s0 scope global )
часто этот скрипт гонять не стоит, иногда гугл почему-то не отвечает сам по себе, хотя IPv6 работает.
Часовой пояс GMT +3, время: 11:54.

Форум на базе vBulletin®
Copyright © Jelsoft Enterprises Ltd.
В случае заимствования информации гипертекстовая индексируемая ссылка на Форум обязательна.