Просмотр исходного кода

Fixed the comparison of iptables filters. Now the order of the elements is ignored.

root 1 день назад
Родитель
Сommit
fcbda770cd
1 измененных файлов с 36 добавлено и 3 удалено
  1. 36 3
      scripts/sync_iptables.pl

+ 36 - 3
scripts/sync_iptables.pl

@@ -531,14 +531,16 @@ if ($gate->{user_acl}) {
             # Проверка текущих правил
             for (my $f_index=0; $f_index<scalar(@cur_filter); $f_index++) {
                 my $filter_str = trim($cur_filter[$f_index]);
-                if (!$chain_rules{$group_name}[$f_index] or $filter_str !~ /$chain_rules{$group_name}[$f_index]/i) {
+                my $expected = $chain_rules{$group_name}[$f_index];
+                my $rules_ok = compare_iptables_rules($expected, $filter_str);
+                if (!$rules_ok) {
                     log_error($gate_ident."Check chain $chain_name error! Rule mismatch at position $f_index");
-                    log_verbose($gate_ident."Expected: $chain_rules{$group_name}[$f_index]");
+                    log_verbose($gate_ident."Expected: $expected");
                     log_verbose($gate_ident."Current: $filter_str");
                     $chain_ok = 0;
                     last;
+                    }
                 }
-            }
         }
 
         if (!$chain_ok) {
@@ -697,3 +699,34 @@ sub save_ipsets_to_files {
     }
     log_verbose($gate_ident."Saved $files_saved ipset configuration files");
 }
+
+sub compare_iptables_rules {
+    my ($r1, $r2) = @_;
+    return 1 if $r1 eq $r2;
+    return 0 if !defined $r1;
+    return 0 if !defined $r2;
+
+    # Нормализация: правило -> отсортированный массив "флаг=значение"
+    my $normalize = sub {
+        my $rule = shift;
+        my @parts;
+        # Режем строго перед флагами, не ломая значения с пробелами/дефисами
+        for my $block (grep { $_ } split(/\s+(?=-(?:-)?[a-z])/i, $rule)) {
+            $block =~ s/^\s+|\s+$//g;
+            $block = lc($block);
+            if ($block =~ /^(!?\s*-[\w-]+)\s*(.*)/) {
+                my ($flag, $val) = ($1, $2);
+                $flag =~ s/\s+//g;   # ! -s -> !-s
+                $val  =~ s/\s+/ /g;  # схлопываем пробелы внутри значения
+                push @parts, "$flag=$val";
+            }
+        }
+        return sort @parts;
+    };
+
+    my @n1 = $normalize->($r1);
+    my @n2 = $normalize->($r2);
+
+    # Длина массивов должна совпадать + посимвольное равенство отсортированных списков
+    return @n1 == @n2 && join(' ', @n1) eq join(' ', @n2);
+}