samba-winbind-dnsupdate-0.5-alt2 Стенды (обновлены до сизифа): Workstation 10.2 x86-64 - клиент Server 10.2 office x86-64 - dc Предусловия: Развернут Samba домен, клиенты введены в домен. На клиенте имеется несколько ip адресов на одном интерфейсе: # ip a ... 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 ... inet <ipv4-1> brd <brd-adr> scope global dynamic noprefixroute eth0 valid_lft 1320sec preferred_lft 1320sec inet <ipv4-2> scope global secondary eth0 valid_lft forever preferred_lft forever inet6 <ipv6-1> scope global dynamic mngtmpaddr proto kernel_ra valid_lft 86393sec preferred_lft 14393sec inet6 <ipv6-2> scope link proto kernel_ll valid_lft forever preferred_lft forever Шаги (выполнять на клиенте): 1. # winbind-dnsupdate или # winbind-dnsupdate --disable-dconf -6 (для ipv6) Ожидаемый результат: Корректное обновление dns записей для dc Фактический результат: Ошибка обновление dns записей : [INFO]: Current IPv4 address: <ipv4-1> <ipv4-2> [INFO]: IPv4 address in DNS server: <dc-ipv4> [INFO]: The IPv4 address of interface eth0 has been changed. [INFO]: Start the A record update. [ERROR]: Nsupdate error: [ERROR]: incorrect section name: <ipv4-2> syntax error [ERROR]: A record update failed. (Для ipv6) : [INFO]: Current IPv6 address: <ipv6-1> <ipv6-2> [INFO]: IPv6 address in DNS server: <dc-ipv6> [INFO]: The IPv6 address of interface eth0 has been changed. [INFO]: Start the AAAA record update. [ERROR]: Nsupdate error: [ERROR]: incorrect section name: <ipv6-2> syntax error [ERROR]: A record update failed.
https://git.altlinux.org/gears/s/..git?p=samba-winbind-dnsupdate.git;a=blob;f=winbind-dnsupdate;hb=0.7.1-alt1 На строках 585 и 608 глючные функции; они при наличии нескольких адресов на интерфейсе дампят их все через LF. А потом validate_ipv{4,6} ничего по факту не валидируют.
Далее рекомендации тем, кто будет фиксить: 1) Не надо парсить обычный вывод `ip(8)`. Легко ошибиться, легко словить регрессию. Варианты: * ip -br a ... * ip -j a ... Если возьмёте последний, лучше покройте его тестами своими; апстрим iproute2 системно таким не занимается, там бывают регрессии и не все команды умеют выдавать json-данные. Апстрим будет рад, конечно, увидеть патчи. 2) Не надо регулярками парсить текстовое представление адреса, это смерть. IPv6 в этом плане, кстати, проще, чем IPv4. Нужно применить алгоритм inet_pton(3), что на шелле нелегко. Правда, поговорить с ядром по RTNL и получить оттуда адреса в бинарном network byte order виде ещё сложнее. 3) Не надо хавать какие попало адреса. Понятно, что ряд адресов выпадают из множ-ва тех, которые имеет смысл регистрировать в домене. Этот ряд — подмножество вот этих двух списков: https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml * Локалхост (::1/128, 127.0.0.0/8) * IPv4-mapped IPv6 (::ffff:0:0/96) * Link-local (fe80::/10, 169.254.0.0/16) * 6to4 (2002::/16) * ... Вот это и нужно валидировать. IPv4-mapped и link-local надо обязательно отрывать. Скрыть link-local можно, передав ip(8) фильтр `scope global`. Кроме того, для IPv6 нужна политика, какие адреса предпочтительно там регистрировать, здесь нужен экспертный совет по домен-решению. Primary/non-temporary или secondary/temporary? Если temporary, то надо брать valid и preferred lifetime в рассмотрение (подозреваю, что и для IPv4 DHCP-клиент их выставляет). В любом случае надо протухшие адреса убирать. Вот так выглядит результат в неплохом приближении: # ip -br -f $family addr show scope global -tentative -deprecated Но тут всё равно адресов может оказаться несколько, PTR для них всех нужно прописывать. Что приводит нас к пункту 4...
4) Не должна ли эта программа быть даймоном и реагировать на события, например, от `ip monitor`? Адрес появился (add), у адреса изменились флаги либо другое состояние (он по-change-ился), адрес пропал (delete). Или не быть даймоном, а запускаться этим даймоном по событию (fork-exec на событие, конечно, но хоть что-то). Может быть, уже так и есть, а я не в курсе; тогда хорошо.
(Ответ для Arseny Maslennikov на комментарий #3) > 4) Не должна ли эта программа быть даймоном и реагировать на события, > например, от `ip monitor`? Адрес появился (add), у адреса изменились флаги > либо другое состояние (он по-change-ился), адрес пропал (delete). > Или не быть даймоном, а запускаться этим даймоном по событию (fork-exec на > событие, конечно, но хоть что-то). > > Может быть, уже так и есть, а я не в курсе; тогда хорошо. В samba-winbind-dnsupdate-0.7.1-alt1.noarch есть .service и .timer: /usr/lib/systemd/system/winbind-dnsupdate.service /usr/lib/systemd/system/winbind-dnsupdate.timer # /usr/lib/systemd/system/winbind-dnsupdate.service [Unit] Description=Update dns record service After=network.target network-online.target [Service] Type=oneshot EnvironmentFile=-/etc/sysconfig/winbind-dnsupdate ExecStart=/usr/bin/winbind-dnsupdate $OPTIONS [Install] WantedBy=multi-user.targe # /usr/lib/systemd/system/winbind-dnsupdate.timer [Unit] Description=Update dns record Daily and on boot [Timer] OnBootSec=5min OnUnitActiveSec=60min [Install] WantedBy=timers.target
(In reply to Artem Varaksa from comment #4) > (Ответ для Arseny Maslennikov на комментарий #3) > > 4) Не должна ли эта программа быть даймоном и реагировать на события, > > например, от `ip monitor`? Адрес появился (add), у адреса изменились флаги > > либо другое состояние (он по-change-ился), адрес пропал (delete). > > Или не быть даймоном, а запускаться этим даймоном по событию (fork-exec на > > событие, конечно, но хоть что-то). > > > > Может быть, уже так и есть, а я не в курсе; тогда хорошо. > > В samba-winbind-dnsupdate-0.7.1-alt1.noarch есть .service и .timer: > > /usr/lib/systemd/system/winbind-dnsupdate.service > /usr/lib/systemd/system/winbind-dnsupdate.timer Благодарю за инфо. :) > # /usr/lib/systemd/system/winbind-dnsupdate.service > <...> > > # /usr/lib/systemd/system/winbind-dnsupdate.timer > [Unit] > Description=Update dns record Daily and on boot > > [Timer] > OnBootSec=5min > OnUnitActiveSec=60min > > [Install] > WantedBy=timers.target Обновление раз в 60 минут — это, если честно, паллиатив. Оно должно срабатывать по событию изменения множества адресов на интерфейсе (и у главного конкурента, чудаков на букву М, именно так), потому что такое изменение — это преждевременно протухшие записи. Но просто изменить в таймере промежуток или привязать её к выхлопу `ip monitor addr` — тоже не то, потому что: — программа, видимо, при работе ещё и выясняет, где сервер, на который слать nsupdate; это несколько DNS-запросов с зависимостью по данным; — из-за этого слишком часто (в случае флапа адресов на интерфейсе, последовательности мгновенных появлений-пропаданий) её дёргать нельзя, нужен grace period, я бы предложил сделать его сравнимым с neighbour reachability timer, по умолчанию 1,5 секунды. https://datatracker.ietf.org/doc/html/rfc4861#section-6.3.2, "ReachableTime"