Disassembler

Artificial intelligence is no match for natural stupidity.
03listopadu2011

Spamující SpamAssassin (bug v NetAddr::IP)


V jisté firmě, která vlastní jedu z mých Debianových instalací mailserveru, mi po včerejším updatu začal Amavis rozesílat obskurní hlášku

netset: cannot include 0:0:0:0:0:0:0:1/128 as it has already been included

Nutno podotknout, že tento server běží na Debianu Wheezy a nejnovějších balíčcích z Wheezy repozitářů a používám jej jako pokusného králíka. Firma si, vzhledem ke své platební morálce, stabilní a vyladěný server nezaslouží a já se alespoň pod záminkou aktualizací mohu oddávat konfiguračním orgiím.

Implicitní věřitel


Po chvíli zkoumání, odkud hláška pochází, jsem identifikoval SpamAssassina a jeho sa-update rutinu jako zdroj. Samozřejmě jsem nebyl první, kdo se s touto hláškou setkal a tak mi strýček Google poradil vyhodit z nastavení internal nebo trusted network localhosta, protože od verze 3.2.0 je localhost nastaven jako internal a trusted implicitně (v předchozích verzích jej bylo nutno konfigurovat ručně). To je samozřejmě v pořádku, protože když člověk (nebo počítač) nevěří ani sám sobě, tak komu pak věřit může? I prohrábnul jsem tedy /etc/spamassassin/local.cf a zjistil, že ani tam, ani jinde, ba ani v konfiguracích Amavisu žádné takové sítě nastaveny nemám. Tak co teď?

Móda zkracování


Vystopoval jsem tedy, kdo tyto implicitní sítě přidává. Naštěstí to nebylo tak těžké, protože SpamAssassin sedí na Perlu a jeho Perlové skripty jsou psány relativně slušně. V modulu /usr/share/perl5/Mail/SpamAssassin/Conf.pm na mě na řádku 3986 smutně hleděla tato funkce

sub new_netset {
  my ($self) = @_;
  my $set = Mail::SpamAssassin::NetSet->new();
  $set->add_cidr ('127/8');
  $set->add_cidr ('::1');
  return $set;
}

Funkce samotná je správně, ale NetAddr::IP, tedy součást zodpovědná za správný překlad na IPv6, už ne. Ve verzi 4.034 totiž proběhla změna popsaná jako

Updated Lite::_xnew v1.20 to properly handle ipV6 notation of the form
        xxxx:xxxx:xxxx:xxxx:xxxx:xxxx, DDD

A pokus o přeložení výše zmíněného subnetu 127/8 místo

root@mail:~# perl -le 'use NetAddr::IP; print NetAddr::IP->new6("127/8")'
0:0:0:0:0:0:7F00:0/104

dopadne následovně

root@mail:~# perl -le 'use NetAddr::IP; print NetAddr::IP->new6("127/8")'
0:0:0:0:0:0:7F00:0/8

Oprava překladu IPv6 notace dodrbala překlad IPv4 notace. Jak prosté, milý Watsone.

Co s tím?


Jednoduchým workaroundem tedy je, změnit 127/8 na 127.0.0.0/8, protože pak se subnet přeloží správně.

root@mail:~# perl -le 'use NetAddr::IP; print NetAddr::IP->new6("127.0.0.0/8")'
0:0:0:0:0:0:7F00:0/104

Úprava Conf.pm bude tedy následující

--- Mail/SpamAssassin/Conf.pm.old
+++ Mail/SpamAssassin/Conf.pm
@@ -3972,7 +3972,7 @@
 sub new_netset {
   my ($self) = @_;
   my $set = Mail::SpamAssassin::NetSet->new();
-  $set->add_cidr ('127/8');
+  $set->add_cidr ('127.0.0.0/8');
   $set->add_cidr ('::1');

Chyba překladu IPv4 notace by již měla být v NetAddr::IP 4.036 opravena. Těším se na push do downstreamu.