NetworkManager не правильно работает с IPv6 (через SLAAC)

Имеем: 1. роутер получающий от провайдера (rt) по dhcp IPv4 (частные адреса 100.64.0.0/10) и IPv6 условно 1:2:3:4::/56 со сроком аренды чуть больше двух суток. Далее роутер IPv4 NAT-тит в локалку, а IPv6 раздаёт по SLAAC. Одна из машин получающих IPv6 OS:FC37 ядро:6.5.12-100 + работает NetworkManager. Проблема возникает, когда роутер по каким либо причинам переподключается к провайдеру (перезагрузка, сбой сессии, итп), при этом со стороны WAN меняется IPv4 и IPv6. На узлах с Linux + NetworkManager остаётся старый IPv6 + устанавливается новый, т.е. на интерфейсе смотрящем к роутеру, может быть больше одного адреса, и после каждой перезагрузки добавляется новый IPv6, старые не удаляются. Из-за чего доступ к IPv6 сети пропадает, т.к. при маршрутизации адрес источника используется старый. После ручного удаления старых IPv6 адресов, они спустя минуты возвращаются на интерфейс, как я понял, это делает глючный NetworkManager, потому что если перед удалением его остановить, то возвращения не произойдёт.

Подскажите участок кода NetworkManager отвечающего за этот дефект? хочу его для себя пропатчить, самостоятельно найти не в сотоянии, "говнокод". Или, как отключить обслуживание IPv6 демоном NetworkManager, не отключая его полностью.


Ответы (1 шт):

Автор решения: balbes

Не стал разбираться в чужом говнокоде, породил свой, скриптик-костыль, который чистит "нерабочие" IPv6 адреса:

#!/usr/bin/perl

my $numArgs = $#ARGV + 1;

if($numArgs != 1) {
    print "Error Args ... \n";
    exit 1;
}

$dev = $ARGV[0];
print "DEV=$dev\n";

my $sip = `ip -6 a s dynamic dev $dev`;
my $srt = ` ip -6 r s dev $dev`;
my $scmd = "";

my @rt6 = ($srt =~ /.*?([0-9a-fA-F:]+\/[0-9]+)\s+(?=proto\sra\s).*?/gs);

my @ipv6 = split /inet6/, $sip;

for (my $i = 1; $i <= $#ipv6; $i++) {
    my @rs = ($ipv6[$i] =~ /\s*(\S+)\s+.*?valid_lft\s+(\d+)/gs);
    if (defined $rs[0]) {
        my %h;
        %h=('ip6'=>$rs[0],'tmo'=>$rs[1]);
        push (@ip6a,{%h});
    }
}


for (my $i = 0; $i <= $#ip6a; $i++) {
    my $ip6 = $ip6a[$i]->{ip6};
    my $cmp;
    foreach my $it (@rt6) {
    $cmp = $it;
    $cmp =~ s/:\/[0-9]+//;
    if (index($ip6, $cmp) != -1) {
        $ip6a[$i]->{rt} = $it;
        }
    }
    my $rt = $ip6a[$i]->{rt};
    $ip6 =~ s/\/[0-9]+//;
    my $res = `traceroute -6 -n -m1 -w1,1,1 2600:: -s $ip6 | grep $cmp`;
    my $ipv6 = $ip6a[$i]->{ip6};
    if (index($res, $cmp) != -1) {
        print "Test OK ip=$ipv6  rt=$rt\n";
    }else{
        print "For del ip=$ipv6  rt=$rt\n";
        $scmd = $scmd . "ip a del $ipv6 dev $dev ; ";
        $scmd = $scmd . "ip r del $rt dev $dev ; ";
    }
}

my $res = "";
if($scmd ne '') {
    $scmd = "systemctl stop NetworkManager ; ".$scmd."systemctl start NetworkManager ;";
    $res = `$scmd`;
    }

Можно по cron-у запускать.

→ Ссылка