Postfix - amavisd-new ohne localhost oder Mailserver auf neue Weise

Es gibt viele Anweisungen, wie Sie den Mailserver auf einer Reihe von Postfix - amavisd-new - dovecot erhöhen können. Und die überwiegende Mehrheit von ihnen wiederholt sich fast wörtlich, einschließlich Fehlern und Ungenauigkeiten.

Es scheint mir langweilig, gedankenlos Tasten zu drücken, deshalb habe ich beschlossen, die Standardkonfiguration zu optimieren: Was ist, wenn ich die Interaktion von Postfix und amavisd-new nicht über localhost, sondern auf einem Unix-Socket aufbaue?

Wie sich herausstellte, ist nicht alles so einfach, aber ich habe es geschafft! Anleitung und Patch unter dem Schnitt.

Ehrlich gesagt mag ich im Allgemeinen keine Interaktion durch localhost innerhalb derselben Maschine. Wenn Sie den Datenaustausch zwischen zwei Anwendungen organisieren möchten, ist dies viel korrekter, sicherer und weniger ressourcenintensiv, wenn Sie dies über einen Unix-Socket im Dateisystem tun. Darüber hinaus können Sie auf diese Weise den Schutz (mithilfe von Rechten im Dateisystem) auch dann organisieren, wenn er auf Anwendungs- oder Protokollebene nicht vorhanden ist.

Der E-Mail-Pfad in der besprochenen Gruppe sieht also folgendermaßen aus:



Es stellt sich heraus, dass wir zwei Verbindungen organisieren müssen: beim Übertragen zur Filterung und bei der Rückkehr zum MTA. Da der Socket vom Listener erstellt wird, ist er im ersten Fall amavisd und im zweiten - postfix.

Beginnen wir mit dem zweiten, weil er einfacher und besser beschrieben ist. Damit postfix einen Listening-Socket erstellen kann, müssen Sie in der zweiten Spalte von master.cf (Typenspalte) nur Unix und nicht Inet angeben. In diesem Fall definiert die erste Spalte den Pfad und den Dateinamen des Sockets.

Da Postfix-Prozesse in Chroot funktionieren (dies kann für einen bestimmten Prozess deaktiviert werden, ist es aber nicht wert), müssen Sie einen Ordner im Postfix-Ausgangsverzeichnis erstellen: / var / spool / postfix. Es wird beide Steckdosen haben:

mkdir /var/spool/postfix/amavis chown amavis:postfix /var/spool/postfix/amavis chmod 770 /var/spool/postfix/amavis 

Gut und Postfix Konfiguration:

 amavis/postfix-in unix y - y - - smtpd -o smtpd_client_restrictions=$local_clients_only -o smtpd_helo_restrictions= -o smtpd_sender_restrictions= -o smtpd_recipient_restrictions= -o smtpd_milters= 

Die spezifischen Optionen hängen von Ihrer Einstellung ab. Dies ist meine Option.

Es gibt zwei Probleme:

  1. Der Pfad ist relativ zu / var / spool / postfix / private, für das sehr strenge Berechtigungen gelten.
  2. Ich bin mir nicht sicher, ob dies für alle Distributionen zutrifft, aber für Ubuntu. Es ist besser, die Rechte an dem Ordner nicht zu berühren (die Sockets aller Postfix-Dienste sind vorhanden), sondern nur einen Symlink zu erstellen.
  3. Zusätzlich zum Socket erstellt postfix auch eine PID-Datei für den Prozess, deren Name automatisch von der Maske vom Typ $ generiert wird. $ Name. Wobei Typ gleich Unix ist und der Name aus der ersten Spalte von master.cf stammt. Es stellt sich heraus, dass unux.amavis / postfix-in, d.h. Datei in einem Unterordner. Er selbst wird es nicht schaffen und mit einem Fehler fallen.

Also ersetzen wir Krücken:

 cd /var/spool/postfix/private ln -s ../amavis . mkdir /var/spool/postfix/pid/unix.amavis 

Nicht sehr schön, aber nicht destruktiv für die reguläre Ordnerstruktur des Pakets.

Wir starten postfix neu und stellen sicher, dass die Socket-Datei im Ordner amavis und die PID-Datei in pid / unix.amavis angezeigt wird. Leider sind die Rechte für den Socket 666, aber die Rechte für den Ordner, den Sie zuvor erstellt haben, schützen die Datei vor unnötigen Augen.

Sie können die Arbeit mit dem Befehl überprüfen:

 netcat -U /var/spool/postfix/amavis/postfix-in 220 mail.example.ru ESMTP Postfix 

Nun, sie haben es geschafft. Nun zu amavisd.

Konfigurieren Sie zunächst den E-Mail-Rückgabepfad über den Unix-Socket von Postfix. Dies funktioniert sofort:

 $forward_method = 'smtp:/var/spool/postfix/amavis/postfix-in'; $notify_method = \$forward_method; 

Nun, jetzt ist es am schwierigsten, Steckdosen in amavisd einzurichten. Die Lösung kann im Internet gefunden werden , dort wird jedoch vorgeschlagen, einen einzelnen Socket zu verwenden, der durch den Parameter $ unix_socketname angegeben wird. Ich wollte auch mein eigenes amavisd-neues Protokoll (AM.PDP) und E-Mail-Empfang über Sockets.

Die Standardkonfigurationsdatei enthält einen Verweis auf die Direktive @listen_sockets, es gibt jedoch keine Beschreibung dafür. Aber es ist in Versionshinweisen , auch mit Beispielen! Es gibt zwar nur eine Steckdose, aber was hindert Sie daran, es zu versuchen?

OK, aber wie wird das Protokoll für den Socket festgelegt (das in der Richtlinienbank angegeben ist)? In allen Beispielen schreiben sie einfach SOCK. In Analogie zu Inet-Sockets (Sie können dort den Host-Port angeben) schlug ich vor, den vollständigen Pfad zur Socket-Datei anzugeben. Folgendes ist passiert:

 $unix_socketname = undef; $inet_socket_bind = undef; $inet_socket_port = undef; @listen_sockets = ('/var/lib/amavis/amavisd.sock', '/var/spool/postfix/amavis/amavis-in.sock'); $unix_socket_mode = 0660; %interface_policy = ( '/var/lib/amavis/amavisd.sock' => 'AM.PDP-SOCK', '/var/spool/postfix/amavis/amavis-in.sock' => 'LMTP-SOCK' ); $policy_bank{'LMTP-SOCK'} = { protocol => 'LMTP' }; $policy_bank{'AM.PDP-SOCK'} = { protocol => 'AM.PDP', auth_required_release => 0, # don't require secret-id for release }; 

Neustart, Überprüfung - tatsächlich wurden beide Sockets erstellt! Sieg Nicht wirklich, wenn Sie versuchen, eine Verbindung zum Socket herzustellen, passiert nichts und es wird ein Fehler in das Protokoll geschrieben, dass das Protokoll nicht dafür definiert ist. Es stellt sich heraus, dass die Policenbank für sie nicht gilt.

Wie so? Ich musste zum Code gehen.

Diese Kampagne brachte zwei Neuigkeiten - wie immer, gut und schlecht. Das Gute ist, dass die Annahme bezüglich% interface_policy richtig war:

 # load policy banks according to my socket (destination), # then check for allowed access from the peer (client/source) # sub access_is_allowed($;$$$$) { my($unix_socket_path, $src_addr, $src_port, $dst_addr, $dst_port) = @_; my(@bank_names); if (defined $unix_socket_path) { push(@bank_names, $interface_policy{"SOCK"}); push(@bank_names, $interface_policy{$unix_socket_path}); } elsif (defined $dst_addr && defined $dst_port) { $dst_addr = '['.lc($dst_addr).']' if $dst_addr =~ /:[0-9a-f]*:/i; # IPv6? push(@bank_names, $interface_policy{$dst_port}); push(@bank_names, $interface_policy{"$dst_addr:$dst_port"}); } load_policy_bank($_) for @bank_names; 

Das Schlimme ist, dass $ unix_socket_path leer in diese Funktion kommt. Es wird wie folgt gefüllt:

 my $is_ux = $sock && $sock->UNIVERSAL::can('NS_proto') && $sock->NS_proto eq 'UNIX'; 

Und beide Eigenschaften sind dort leer.

Eine Untersuchung der Dokumentation schlug diese Option vor:

 my $unix_socket_path = $sock->hostpath(); 

Und es hat funktioniert! Ready .patch kann hier gesagt werden .

Da ist der letzte Schliff. Da amavisd einen eigenen Socket mit Rechten nur für sich selbst erstellt und wir den Zugriff auf den Rest verweigert haben (was wahr ist), müssen wir der amavis-Gruppe Postfix hinzufügen, damit sie in den Socket schreiben kann:

 gpasswd -a postfix amavis 

Fertig.

PS: Ich habe den Patch und die Beschreibung des Problems von Mark Martinec per E-Mail gesendet, da ich auf der Website keine Erwähnung des Bug-Trackers gefunden habe. Ich habe noch keine Antwort erhalten, aber ich zähle nicht wirklich darauf - das Projekt sieht aufgegeben aus (die letzte Veröffentlichung vor mehr als zwei Jahren).

Source: https://habr.com/ru/post/de415597/


All Articles