# README-install-SRS.md ## Selektives SRS für Postfix – Installation und Integration **Stand:** 17.10.2026 **System:** `mx.warenform.de` **Betriebssystem:** Debian 13 **Ziel:** Selektives Sender Rewriting Scheme (SRS) nur für echte externe Alias-Weiterleitungen, ohne normale ausgehende Nachrichten, lokale Zustellungen oder intern erzeugte Benachrichtigungen unnötig umzuschreiben. --- ## 0. Das Grundproblem: Warum weitergeleitete E-Mails abgelehnt werden können Moderne Mailserver – insbesondere große Provider wie Google/Gmail, Microsoft, GMX oder Yahoo – prüfen eingehende E-Mails sehr streng auf die Authentizität des Absenders. Dabei spielen vor allem drei Verfahren eine Rolle: ```text SPF DKIM DMARC ``` Eine klassische E-Mail-Weiterleitung kann diese Prüfungen stören, obwohl die ursprüngliche E-Mail vollkommen legitim ist. ### 0.1 Beispiel einer normalen Weiterleitung Eine Nachricht wird ursprünglich von: ```text ckubu@gmx.de ``` an: ```text test@warenform.de ``` gesendet. Auf `mx.warenform.de` existiert für diese Adresse beispielsweise eine Weiterleitung: ```text test@warenform.de -> ckubu@gmail.com ``` Die ursprüngliche Nachricht kommt korrekt von einem GMX-Mailserver: ```text GMX | | MAIL FROM: | v mx.warenform.de ``` Bis hierhin ist alles in Ordnung. Der SPF-Test kann beispielsweise feststellen: ```text Absender-Domain: gmx.de sendender Server: GMX-Mailserver Ergebnis: SPF PASS ``` Das Problem entsteht bei der anschließenden Weiterleitung. Ohne besondere Maßnahmen würde `mx.warenform.de` dieselbe Nachricht weiterleiten als: ```text mx.warenform.de | | MAIL FROM: | v gmail.com ``` Für Gmail sieht die Situation nun so aus: ```text Envelope-Absender: ckubu@gmx.de sendender Server: mx.warenform.de ``` Gmail prüft deshalb den SPF-Eintrag von `gmx.de`. Die entscheidende Frage lautet: > Darf die IP-Adresse von `mx.warenform.de` E-Mails für `gmx.de` versenden? Die Antwort lautet: **nein**. `mx.warenform.de` gehört nicht zur Mail-Infrastruktur von GMX und ist deshalb nicht im SPF-Record von `gmx.de` autorisiert. Eine ursprünglich vollkommen legitime E-Mail kann durch die Weiterleitung daher plötzlich einen `SPF FAIL` oder zumindest einen ungünstigen SPF-Bewertungszustand erhalten. ### 0.2 Warum der empfangende Server die Weiterleitung nicht einfach „erkennen“ kann Aus Sicht des empfangenden Servers besteht zunächst kein grundlegender Unterschied zwischen einem legitimen Weiterleitungsserver und einem fremden Server, der vorgibt, Mail für `gmx.de` zu versenden. Beide Situationen sehen auf SMTP-Ebene zunächst ähnlich aus: ```text MAIL FROM: ``` aber die Verbindung kommt von einer IP-Adresse, die nicht zu GMX gehört. Der empfangende Server kann deshalb den ursprünglichen SPF-Erfolg nicht einfach übernehmen. Er muss die Nachricht anhand der Verbindung prüfen, über die sie **jetzt** zugestellt wird. ### 0.3 DKIM kann das Problem teilweise auffangen Neben SPF gibt es DKIM. GMX versieht eine Nachricht beispielsweise mit einer kryptographischen Signatur: ```text DKIM-Signature: d=gmx.de ``` Diese Signatur wird über bestimmte Header und Teile des Nachrichteninhalts gebildet. Wenn der Weiterleitungsserver die Nachricht nicht verändert, kann diese ursprüngliche DKIM-Signatur auch nach der Weiterleitung weiterhin gültig sein. Der Zielserver kann dann `DKIM PASS` feststellen, obwohl der SPF-Test des ursprünglichen Absenders durch die Weiterleitung problematisch geworden ist. Eine Weiterleitung darf deshalb möglichst keine Änderungen an den von DKIM signierten Bestandteilen der Nachricht vornehmen. Problematisch können zum Beispiel sein: ```text Änderung des Subject-Headers Hinzufügen von Text zum Body Änderung bestimmter signierter Header Umformatierung des Nachrichteninhalts ``` Solche Änderungen können die ursprüngliche DKIM-Signatur ungültig machen. ### 0.4 DMARC verschärft das Problem DMARC verbindet SPF und DKIM mit der sichtbaren Absenderadresse im `From:`-Header. Bei unserer Beispielmail steht dort weiterhin: ```text From: ckubu@gmx.de ``` DMARC verlangt vereinfacht, dass mindestens einer der beiden Mechanismen SPF oder DKIM erfolgreich ist und dabei zur Domain im sichtbaren `From:`-Header passt. Bei einer einfachen Weiterleitung kann folgende Situation entstehen: ```text From: ckubu@gmx.de SPF: FAIL DKIM: PASS DMARC: PASS ``` Das funktioniert, solange die ursprüngliche DKIM-Signatur erhalten bleibt. Wird dagegen auch DKIM durch die Weiterleitung beschädigt, kann das Ergebnis sein: ```text SPF: FAIL DKIM: FAIL DMARC: FAIL ``` Wenn die Domain des ursprünglichen Absenders beispielsweise eine strenge DMARC-Policy wie `p=reject` veröffentlicht, kann der Zielserver die Nachricht vollständig ablehnen. Auch ohne hartes `reject` verschlechtern fehlgeschlagene Authentifizierungsprüfungen die Bewertung einer Nachricht erheblich. Große Provider wie Gmail berücksichtigen zusätzlich Reputation, Nachrichtenhistorie und weitere Anti-Spam-Signale. Eine saubere SPF-/DKIM-/DMARC-Situation ist daher besonders wichtig. ### 0.5 Das Prinzip von SRS Das Sender Rewriting Scheme (SRS) löst das SPF-Problem der Weiterleitung, indem der **Envelope-Absender** beim Weiterleiten umgeschrieben wird. Aus: ```text MAIL FROM: ``` wird beispielsweise: ```text MAIL FROM: ``` Die sichtbare Absenderadresse der Nachricht bleibt dagegen unverändert: ```text From: ckubu@gmx.de ``` Der Zielserver prüft SPF nun nicht mehr für `gmx.de`, sondern für `srs.warenform.de`. Damit lautet die SPF-Frage jetzt: > Darf `mx.warenform.de` Mail für `srs.warenform.de` versenden? Diese Frage kann mit **ja** beantwortet werden. Das Ergebnis ist `SPF PASS`. ### 0.6 Warum DKIM trotz SRS weiterhin wichtig ist Nach der SRS-Umschreibung gehört der Envelope-Absender beispielsweise zu: ```text srs.warenform.de ``` Der sichtbare Absender bleibt aber: ```text From: ckubu@gmx.de ``` Damit ist SPF zwar technisch erfolgreich, aber die SPF-Domain ist nicht mehr identisch mit der sichtbaren `From:`-Domain. Für DMARC ist deshalb die weiterhin gültige ursprüngliche DKIM-Signatur besonders wichtig. Im Idealfall ergibt sich nach der Weiterleitung: ```text Envelope-From: SRS0=...@srs.warenform.de Header-From: ckubu@gmx.de SPF: PASS für srs.warenform.de DKIM: PASS für gmx.de DMARC: PASS über DKIM ``` Genau dieses Verhalten wurde bei der hier beschriebenen Installation im abschließenden End-to-End-Test bestätigt. ### 0.7 Warum SRS nicht einfach global eingesetzt wird SRS ist für diesen Zweck eine Lösung für **weitergeleitete Nachrichten**. Es gibt keinen Grund, beispielsweise eine normale eigene ausgehende Nachricht oder eine lokale Zustellung ebenfalls mit SRS umzuschreiben. Eine globale SRS-Umschreibung würde unnötige Komplexität erzeugen und könnte unerwünschte Nebenwirkungen haben. Das Ziel dieser Installation lautet daher ausdrücklich: ```text SRS nur dort einsetzen, wo eine fremde Nachricht tatsächlich an einen externen Empfänger weitergeleitet wird. ``` Daraus ergibt sich die im weiteren Verlauf beschriebene selektive SRS-Architektur. --- ## 1. Ausgangssituation Auf `mx.warenform.de` läuft ein produktives Mail-System mit: - Postfix - AmaViS - SpamAssassin - ClamAV - OpenDKIM - OpenDMARC - `postfix-policyd-spf-python` - Dovecot LMTP - virtuellen Domains und Aliasen über PostgreSQL/PostfixAdmin - lokalen Aliasen aus `/etc/aliases` - Dovecot/Sieve für lokale Zustellung und Benachrichtigungen Der normale eingehende Mailpfad ist vereinfacht: ```text Internet | v Postfix :25 | v AmaViS :10024 | v Postfix-Reinjection :10025 | +--> lokale/virtuelle Zustellung via Dovecot LMTP | +--> externe Alias-Weiterleitung ``` Vor Einführung von SRS wurden externe Weiterleitungen mit dem ursprünglichen Envelope-Sender weitergesendet. Beispiel: ```text MAIL FROM: RCPT TO: ``` `test@warenform.de` enthält unter anderem die externe Zieladresse: ```text ckubu@oopen.de ``` Ohne SRS würde `mx.warenform.de` die Nachricht an `ckubu@oopen.de` mit ```text MAIL FROM: ``` weiterleiten. Das ist heute problematisch, weil der empfangende Server dann SPF für `gmx.de` gegen die IP-Adresse von `mx.warenform.de` prüft. Diese IP ist natürlich nicht als GMX-Mailserver autorisiert. Die Weiterleitung kann dadurch einen SPF-Fehler erzeugen, obwohl die ursprüngliche Nachricht legitim war. --- ## 2. Warum die Lösung nicht einfach aus „PostSRSd einschalten“ besteht Auf diesem System reicht ein globales Umschreiben aller Absender nicht aus. SRS soll **nur dann** angewendet werden, wenn wirklich eine externe Alias-Weiterleitung stattfindet. Nicht mit SRS umgeschrieben werden sollen beispielsweise: - direkte ausgehende Nachrichten, - normale SMTP-Zustellungen, - lokale Alias-Zustellungen, - lokale Weiterleitungen aus `/etc/aliases`, - lokale virtuelle Mailboxen, - durch Dovecot/Sieve neu erzeugte Benachrichtigungen, - Nachrichten mit leerem Envelope-Sender (`<>`), - administrative Nachrichten wie `root -> argus@oopen.de`. Daraus ergeben sich mehrere technische Anforderungen: 1. Postfix muss für jeden einzelnen Ziel-Empfänger entscheiden können, ob SRS notwendig ist. 2. Der ursprüngliche Alias-Empfänger muss während der Verarbeitung erhalten bleiben. 3. Lokale und externe Ziele desselben Alias müssen unterschiedlich behandelt werden können. 4. Eingehende Bounces an SRS-Adressen müssen wieder auf die ursprüngliche Adresse zurückgeschrieben werden. 5. Die ursprüngliche DKIM-Signatur der weitergeleiteten Nachricht darf nicht unnötig beschädigt werden. 6. Das Ganze muss ohne `postmulti` funktionieren und nach einem Reboot automatisch starten. 7. Die Konfiguration muss später durch Enable-/Disable-/Update-Skripte reproduzierbar und reversibel sein. --- ## 3. Zielarchitektur Die produktive Architektur besteht aus vier SRS-Hilfsskripten, PostSRSd, einem Reverse-Socketmap-Dienst und einer separaten Postfix-Delivery-Instanz. ### 3.1 Komponenten ```text /usr/local/sbin/srs-forward.py /usr/local/sbin/srs-alias-decision.py /usr/local/sbin/srs-reverse-map.py /usr/local/sbin/srs-reverse-policy.py ``` PostSRSd: ```text /usr/local/postsrsd -> /usr/local/postsrsd-2.4.1 ``` Konfiguration: ```text /etc/postsrsd-srs/postsrsd.conf /etc/postsrsd-srs/secret ``` Systemd-Dienste: ```text postsrsd-srs.service srs-reverse-map.service postfix@srs-delivery.service postfix.service ``` SRS-Delivery-Konfiguration: ```text /etc/postfix-srs/delivery/main.cf /etc/postfix-srs/delivery/master.cf /etc/postfix-srs/delivery/transport /etc/postfix-srs/delivery/transport.db ``` --- ## 4. Verwendete Ports | Port | Dienst | Zweck | |---:|---|---| | 25 | Haupt-Postfix | normaler SMTP-Eingang | | 10003 | PostSRSd | SRS Forward + Reverse Socketmap | | 10004 | `srs-reverse-map.py` | eingeschränkte Reverse-Socketmap für Haupt-Postfix | | 10028 | SRS-Delivery-Postfix | Reinjection von selektiv verarbeiteten Nachrichten | | 10029 | SRS-Delivery-Postfix | Reverse-SRS-Reinjection für Bounces | Alle SRS-internen Dienste lauschen ausschließlich auf Loopback. --- ## 5. PostSRSd Installiert ist PostSRSd 2.4.1 unter: ```text /usr/local/postsrsd-2.4.1 ``` Der stabile Pfad lautet: ```text /usr/local/postsrsd ``` und ist ein Symlink auf die aktuell aktive Version. Das ermöglicht später ein versionsweises Update, z. B.: ```text /usr/local/postsrsd-2.4.1 /usr/local/postsrsd-2.5.0 /usr/local/postsrsd -> /usr/local/postsrsd-2.5.0 ``` ### 5.1 Systemd-Service ```text postsrsd-srs.service ``` Startkommando: ```text /usr/local/postsrsd/sbin/postsrsd -C /etc/postsrsd-srs/postsrsd.conf ``` ### 5.2 Produktive Konfiguration ```text domains = {} srs-domain = "srs.warenform.de" socketmap = inet:127.0.0.1:10003 secrets-file = "/etc/postsrsd-srs/secret" milter-rewrite-local = off original-envelope = embedded debug = off ``` PostSRSd stellt auf Port 10003 mindestens folgende Socketmap-Funktionen bereit: ```text forward reverse ``` Beispiel: ```bash postmap -q \ 'ckubu@gmx.de' \ 'socketmap:inet:127.0.0.1:10003:forward' ``` Ergebnis: ```text SRS0=...=gmx.de=ckubu@srs.warenform.de ``` Reverse: ```bash postmap -q \ 'SRS0=...=gmx.de=ckubu@srs.warenform.de' \ 'socketmap:inet:127.0.0.1:10003:reverse' ``` Ergebnis: ```text ckubu@gmx.de ``` --- ## 6. Warum das Debian-Paket `postsrsd` entfernt wurde Das Debian-Paket `postsrsd` Version 1.x war zusätzlich installiert. Es wurde nicht mehr benötigt, da die produktive Installation bewusst als eigene, versionierte Installation unter `/usr/local/postsrsd-*` betrieben wird. Das Debian-Paket wurde deshalb entfernt: ```bash apt-get purge postsrsd ``` Dadurch gibt es nur noch eine produktive PostSRSd-Implementierung und keine Verwechslungsgefahr zwischen: ```text /usr/sbin/postsrsd ``` und ```text /usr/local/postsrsd/sbin/postsrsd ``` --- ## 7. Selektive SRS-Entscheidung Die zentrale Logik liegt in: ```text /usr/local/sbin/srs-alias-decision.py ``` Sie entscheidet für jeden Empfänger: ```text SRS NO_SRS UNKNOWN ``` ### 7.1 Typische Fälle Lokaler Alias: ```text sender: root@mx.warenform.de recipient: argus@oopen.de original_recipient: root ``` Ergebnis: ```text NO_SRS: Lokaler Alias ``` Externe PostfixAdmin-Alias-Weiterleitung: ```text sender: ckubu@gmx.de recipient: ckubu@oopen.de original_recipient: test@warenform.de ``` Ergebnis: ```text SRS: PostfixAdmin-Alias-Kette mit SMTP-Zustellung ``` Direkte Nachricht: ```text recipient == original_recipient ``` Ergebnis: ```text NO_SRS: Keine Empfaengerumschreibung ``` Leerer Envelope-Sender: ```text MAIL FROM:<> ``` Ergebnis: ```text NO_SRS ``` --- ## 8. Warum `original_recipient` entscheidend ist Eine der wichtigsten Schwierigkeiten bei der Implementierung war, dass Postfix/AmaViS Alias-Umschreibungen zu früh durchführen kann. Für die Entscheidung ```text test@warenform.de -> ckubu@oopen.de ``` muss `srs-forward.py` beide Informationen kennen: ```text recipient = ckubu@oopen.de original_recipient = test@warenform.de ``` Wenn Postfix die Alias-Umschreibung bereits vor AmaViS endgültig durchgeführt hat, sieht die spätere SRS-Logik dagegen nur: ```text recipient = ckubu@oopen.de original_recipient = ckubu@oopen.de ``` Dann wäre nicht mehr erkennbar, dass es sich um eine Weiterleitung handelt. ### 8.1 Lösung `no_address_mappings` wurde deshalb auf den **eingehenden SMTP-Dienst auf Port 25** gelegt und nicht auf die Reinjection 10025. Relevant in `/etc/postfix/master.cf`: ```text smtp inet n - y - - smtpd -o content_filter=amavisfeed:[127.0.0.1]:10024 -o smtpd_sasl_auth_enable=no -o receive_override_options=no_address_mappings ``` Dadurch erhält AmaViS zunächst die ursprüngliche Alias-Adresse. Erst nach der Reinjection auf Port 10025 findet die eigentliche Alias-Expansion statt. Das war ein zentraler Punkt der funktionierenden Lösung. --- ## 9. Haupt-Postfix: `main.cf` Die produktiven SRS-Parameter befinden sich in einem eindeutig markierten, automatisch verwaltbaren Block: ```text # BEGIN OOPEN-SRS-MANAGED ... # END OOPEN-SRS-MANAGED ``` Dieser Block darf insbesondere an seinen Markern nicht manuell verändert werden. Aktive Parameter: ```text default_transport = srs-forward srs-forward_destination_recipient_limit = 1 recipient_canonical_maps = socketmap:inet:127.0.0.1:10004:reverse ``` ### 9.1 `default_transport = srs-forward` Nachrichten, die über den normalen Default-Transport zugestellt würden, werden zunächst an die Selektionslogik übergeben. Das bedeutet **nicht**, dass jede Nachricht SRS bekommt. `srs-forward.py` entscheidet anschließend zwischen: ```text SRS NO_SRS ``` Bei `NO_SRS` wird die Nachricht mit unverändertem Envelope-Sender an die SRS-Delivery-Instanz übergeben. ### 9.2 `srs-forward_destination_recipient_limit = 1` Diese Einstellung ist notwendig, weil ein Alias mehrere Ziele enthalten kann: ```text test@warenform.de -> chris@antimedia.de -> admin@warenform.de -> ckubu@oopen.de -> test@warenform.de ``` Einzelne Ziele können lokal sein, andere extern. Die SRS-Entscheidung muss deshalb pro Empfänger erfolgen. ### 9.3 `recipient_canonical_maps` ```text recipient_canonical_maps = socketmap:inet:127.0.0.1:10004:reverse ``` Dieser Dienst ist für eingehende SRS-Bounces zuständig. --- ## 10. Kein `postmulti` Während der Entwicklung wurde zunächst mit Postfix-Multi-Instance-Funktionen gearbeitet. Diese Lösung wurde bewusst verworfen. Der Haupt-Postfix verwendet heute wieder die Defaults: ```text multi_instance_enable = no multi_instance_wrapper = multi_instance_directories = ``` Die SRS-Delivery-Instanz wird stattdessen direkt über systemd betrieben: ```text postfix@srs-delivery.service ``` Konfiguration: ```text /etc/postfix-srs/delivery ``` Diese Architektur ist auch im SRS-Managed-Block der `main.cf` dokumentiert. Spätere Installations- oder Enable-Skripte dürfen für diese Installation **nicht** wieder `postmulti` aktivieren. --- ## 11. `srs-forward` in `master.cf` Produktiver Transport: ```text srs-forward unix - n n - - pipe flags=Rq null_sender= user=nobody argv=/usr/local/sbin/srs-forward.py ${sender} ${recipient} ${original_recipient} ${queue_id} envid=${envid} ``` Das Skript: ```text /usr/local/sbin/srs-forward.py ``` ruft intern auf: ```text /usr/local/sbin/srs-alias-decision.py ``` und verwendet für die SRS-Umschreibung: ```text socketmap:inet:127.0.0.1:10003:forward ``` Danach wird die Nachricht per SMTP an: ```text 127.0.0.1:10028 ``` übergeben. --- ## 12. Separate SRS-Delivery-Postfix-Instanz Die Instanz läuft unter: ```text postfix@srs-delivery.service ``` Konfigurationsverzeichnis: ```text /etc/postfix-srs/delivery ``` Queue: ```text /var/spool/postfix-srs-delivery ``` Data Directory: ```text /var/lib/postfix-srs-delivery ``` Wichtige Parameter: ```text multi_instance_name = postfix-srs-delivery multi_instance_enable = no inet_interfaces = loopback-only default_transport = smtp local_transport = error:SRS-LOCAL-DELIVERY-BLOCKED mailbox_transport = error:SRS-MAILBOX-DELIVERY-BLOCKED relay_transport = error:SRS-RELAY-DELIVERY-BLOCKED virtual_transport = srs-lmtp:unix:/var/spool/postfix/private/dovecot-lmtp transport_maps = btree:/etc/postfix-srs/delivery/transport ``` Die `error:`-Transporte sind absichtliche Schutzschranken. Die SRS-Delivery-Instanz soll nicht versehentlich Zustellpfade übernehmen, die für sie nicht vorgesehen sind. --- ## 13. Reinjection auf Port 10028 In `/etc/postfix-srs/delivery/master.cf`: ```text 127.0.0.1:10028 inet n - y - - smtpd -o syslog_name=postfix-srs-delivery/reinject -o receive_override_options=no_address_mappings,no_unknown_recipient_checks -o smtpd_recipient_restrictions=permit_mynetworks,reject -o mynetworks=127.0.0.0/8 ``` Hier landen Nachrichten aus `srs-forward.py`. Der Envelope-Sender kann dabei entweder: ```text unverändert ``` oder: ```text SRS0=...@srs.warenform.de ``` sein. --- ## 14. Reverse-SRS für Bounces SRS löst zwar das SPF-Problem bei der Weiterleitung, erzeugt aber eine neue Anforderung: Bounces werden an die SRS-Adresse geschickt. Beispiel: ```text SRS0=...=gmx.de=ckubu@srs.warenform.de ``` Diese Adresse muss wieder auf: ```text ckubu@gmx.de ``` zurückgeführt werden. Dazu gibt es zwei Ebenen. ### 14.1 Reverse-Socketmap Port 10004 Dienst: ```text srs-reverse-map.service ``` Programm: ```text /usr/local/sbin/srs-reverse-map.py ``` Listener: ```text 127.0.0.1:10004 ``` Upstream: ```text 127.0.0.1:10003 ``` Der Haupt-Postfix verwendet: ```text recipient_canonical_maps = socketmap:inet:127.0.0.1:10004:reverse ``` ### 14.2 Reverse-Reinjection Port 10029 Die SRS-Delivery-Instanz besitzt zusätzlich: ```text 127.0.0.1:10029 ``` mit eigener Recipient-Policy: ```text srs-reverse-policy ``` Programm: ```text /usr/local/sbin/srs-reverse-policy.py ``` und eigenem Cleanup-Dienst: ```text srs-reverse-cleanup ``` Dort gilt ausdrücklich: ```text recipient_canonical_classes=envelope_recipient ``` Damit wird nur der Envelope-Empfänger zurückgeschrieben, nicht unnötig der sichtbare Nachrichteninhalt. --- ## 15. Transport-Map der SRS-Delivery-Instanz Datei: ```text /etc/postfix-srs/delivery/transport ``` Produktiver Eintrag: ```text srs.warenform.de srs-reverse-smtp:[127.0.0.1]:10029 ``` Wichtig: Da in `main.cf` ausdrücklich ```text transport_maps = btree:/etc/postfix-srs/delivery/transport ``` konfiguriert ist, muss die Datenbank auch explizit als `btree:` erzeugt werden: ```bash postmap btree:/etc/postfix-srs/delivery/transport ``` Nicht: ```bash postmap /etc/postfix-srs/delivery/transport ``` Letzteres hatte während der Entwicklung eine inkompatible `transport.db` erzeugt und zu: ```text open database .../transport.db: Invalid argument ``` geführt. --- ## 16. Systemd-Abhängigkeiten ### 16.1 `postfix@srs-delivery.service` Drop-in: ```text /etc/systemd/system/postfix@srs-delivery.service.d/srs.conf ``` Inhalt: ```text [Unit] Wants=postsrsd-srs.service After=postsrsd-srs.service ``` ### 16.2 Haupt-Postfix Drop-in: ```text /etc/systemd/system/postfix.service.d/srs.conf ``` Inhalt: ```text [Unit] Wants=srs-reverse-map.service postfix@srs-delivery.service After=srs-reverse-map.service postfix@srs-delivery.service ``` Damit werden die benötigten SRS-Komponenten auch nach einem Reboot automatisch gestartet. --- ## 17. Wichtige Sonderfälle ### 17.1 Lokaler Alias `root` `/etc/aliases` enthält: ```text root: argus@oopen.de ``` Hier liefert Postfix als `original_recipient` nur: ```text root ``` und nicht: ```text root@mx.warenform.de ``` Die Decision-Logik muss deshalb einen unqualifizierten lokalen Alias korrekt erkennen. Ergebnis: ```text NO_SRS: Lokaler Alias ``` Das ist wichtig, weil administrative Nachrichten von `root` ihren Envelope-Sender behalten sollen. ### 17.2 Null-Sender Bounces verwenden: ```text MAIL FROM:<> ``` Ein Null-Sender wird niemals mit SRS umgeschrieben. ### 17.3 Sieve-Benachrichtigungen Durch Dovecot/Sieve neu erzeugte Benachrichtigungen sind keine Weiterleitung der ursprünglichen Nachricht. Sie werden deshalb korrekt als `NO_SRS` behandelt. --- ## 18. DKIM, SPF und DMARC Ein wichtiges Ziel war, die originale DKIM-Signatur nicht zu beschädigen. SRS verändert nur den Envelope-Sender. Der sichtbare Header: ```text From: ckubu@gmx.de ``` und die ursprüngliche GMX-DKIM-Signatur bleiben erhalten. Im abschließenden End-to-End-Test wurde am Ziel `a.mx.oopen.de` bestätigt: ```text Return-Path: ``` SPF: ```text Received-SPF: Pass client-ip=83.223.86.76 envelope-from=SRS0=...@srs.warenform.de ``` DKIM: ```text dkim=pass header.d=gmx.de ``` DMARC: ```text dmarc=pass header.from=gmx.de ``` Damit funktioniert das gewünschte Zusammenspiel: ```text Envelope-From -> SRS-Domain Header-From -> ursprüngliche Absenderdomain DKIM -> ursprüngliche Signatur bleibt gültig SPF -> besteht für die SRS-Domain DMARC -> besteht über die gültige DKIM-Ausrichtung ``` --- ## 19. Abschließender End-to-End-Test Test: ```text Absender: ckubu@gmx.de Empfänger: test@warenform.de ``` Alias-Ziel: ```text ckubu@oopen.de ``` Journal: ```text postsrsd: forwarded as ``` Danach: ```text to= orig_to= relay=srs-forward status=sent ``` SRS-Delivery: ```text from= ``` Final: ```text to= relay=a.mx.oopen.de status=sent ``` Der empfangende Server bestätigte: ```text SPF_PASS DKIM_VALID DMARC_PASS ``` --- ## 20. Reboot-Test Nach einem vollständigen Reboot wurden folgende Dienste automatisch gestartet: ```text postsrsd-srs.service enabled / active srs-reverse-map.service enabled / active postfix@srs-delivery.service enabled / active postfix.service enabled / active ``` Listener: ```text 25 10003 10004 10028 10029 ``` Forward-/Reverse-Test nach Reboot: ```text Forward: SRS0=...@srs.warenform.de Reverse: ckubu@gmx.de ``` Decision-Tests: ```text root -> argus@oopen.de NO_SRS: Lokaler Alias test@warenform.de -> ckubu@oopen.de SRS: PostfixAdmin-Alias-Kette mit SMTP-Zustellung ``` --- ## 21. Bekannte, nicht SRS-spezifische Warnungen `postfix check` endet mit: ```text check rc=0 ``` Es existieren jedoch bekannte Warnungen: ```text group or other writable: /etc/postfix/ssl/mailserver.key group or other writable: /etc/postfix/ssl/mailserver.crt not owned by root: /var/spool/postfix/etc/resolv.conf ``` Diese Warnungen sind unabhängig von SRS. Ebenfalls unabhängig von SRS: ```text DNSSEC validation may be unavailable ``` im SMTP-Client der SRS-Delivery-Instanz. Nach Reboot waren außerdem zeitweise: ```text networking.service openipmi.service ``` als fehlgeschlagen markiert. Auch dies ist kein SRS-Problem; Netzwerk und Maildienste liefen trotzdem. --- ## 22. Aufgeräumte produktive Struktur Produktive SRS-Skripte: ```text /usr/local/sbin/srs-alias-decision.py /usr/local/sbin/srs-forward.py /usr/local/sbin/srs-reverse-map.py /usr/local/sbin/srs-reverse-policy.py ``` Produktive SRS-Delivery-Konfiguration: ```text /etc/postfix-srs/delivery/main.cf /etc/postfix-srs/delivery/master.cf /etc/postfix-srs/delivery/transport /etc/postfix-srs/delivery/transport.db ``` PostSRSd: ```text /usr/local/postsrsd /etc/postsrsd-srs/postsrsd.conf /etc/postsrsd-srs/secret ``` Alte Test-/Entwicklungsdateien wurden aus den produktiven Verzeichnissen entfernt bzw. unter `/root` archiviert. --- ## 23. Anforderungen an spätere Installations-/Update-/Enable-/Disable-Skripte Die spätere Automatisierung soll nicht einfach alte komplette Postfix-Konfigurationsdateien zurückspielen. Stattdessen soll sie gezielt und reversibel arbeiten. ### Installation Ein Installationsskript soll: 1. PostSRSd versioniert installieren. 2. `/usr/local/postsrsd` auf die aktive Version verlinken. 3. Konfiguration und Secret anlegen. 4. die vier produktiven SRS-Skripte installieren. 5. SRS-Delivery-Postfix-Konfiguration anlegen. 6. systemd-Units/Drop-ins installieren. 7. den `OOPEN-SRS-MANAGED`-Block in `main.cf` erzeugen. 8. die benötigten `master.cf`-Erweiterungen reproduzierbar einfügen. 9. die notwendige `receive_override_options=no_address_mappings`-Änderung am SMTP-Eingang sicherstellen. 10. alle Konfigurationen prüfen. 11. Dienste starten. 12. Forward/Reverse- und Decision-Tests durchführen. ### Enable Vor der erstmaligen Aktivierung müssen die vorhandenen Werte der von SRS veränderten Parameter gesichert werden. Diese Sicherung soll strukturiert erfolgen, nicht durch Zurückspielen einer kompletten alten `main.cf`. ### Disable Ein Disable-Skript muss: 1. SRS-spezifische Routing-Parameter entfernen bzw. vorherige Werte wiederherstellen. 2. `master.cf` auf den Nicht-SRS-Zustand zurücksetzen. 3. die SRS-Dienste stoppen/deaktivieren. 4. die vorhandene Postfix-Konfiguration erhalten. 5. **kein** altes vollständiges Backup über die aktuelle Konfiguration kopieren. ### Update Updates von PostSRSd sollen über neue Versionsverzeichnisse erfolgen: ```text /usr/local/postsrsd- ``` und erst nach erfolgreicher Prüfung den Symlink: ```text /usr/local/postsrsd ``` umschalten. --- ## 24. Wichtige Designentscheidungen Die folgenden Punkte sind bewusst so umgesetzt und sollten nicht ohne erneute technische Prüfung geändert werden: - SRS ist selektiv, nicht global. - Entscheidungen erfolgen pro Empfänger. - `original_recipient` muss erhalten bleiben. - `no_address_mappings` gehört auf den Eingang vor AmaViS. - lokale Aliase erhalten kein SRS. - Null-Sender erhalten kein SRS. - originale DKIM-Signaturen werden nicht ersetzt. - Reverse-SRS ist getrennt abgesichert. - die SRS-Delivery-Instanz läuft nicht über `postmulti`. - interne SRS-Dienste lauschen nur auf Loopback. - aktive Produktionsnamen enthalten keine `test`, `v2`, `v3`, `v4` oder `prod`-Bezeichnungen. - `btree:`-Maps werden ausdrücklich mit `postmap btree:/...` erzeugt. - der `OOPEN-SRS-MANAGED`-Block ist eine stabile Schnittstelle für spätere Skripte. --- ## 25. Kurztests für den Betrieb Dienste: ```bash systemctl is-active \ postsrsd-srs.service \ srs-reverse-map.service \ postfix@srs-delivery.service \ postfix.service ``` Listener: ```bash ss -ltnp | grep -E ':(25|10003|10004|10028|10029)\b' ``` Forward: ```bash postmap -q \ 'ckubu@gmx.de' \ 'socketmap:inet:127.0.0.1:10003:forward' ``` Reverse: ```bash postmap -q \ 'SRS0=...' \ 'socketmap:inet:127.0.0.1:10003:reverse' ``` Reverse über Haupt-Postfix-Map: ```bash postmap -q \ 'SRS0=...' \ 'socketmap:inet:127.0.0.1:10004:reverse' ``` Konfiguration: ```bash postfix check ``` E2E-Journal: ```bash journalctl --since "5 minutes ago" --no-pager | \ grep -E 'test@warenform\.de|ckubu@oopen\.de|SRS0=|srs-forward|postfix-srs-delivery' ``` --- ## 26. Ergebnis Die produktive Installation erreicht das gewünschte Ziel: - echte externe Alias-Weiterleitungen verwenden SRS, - lokale oder direkte Zustellungen bleiben unverändert, - SPF besteht beim weitergeleiteten Ziel, - die ursprüngliche DKIM-Signatur bleibt gültig, - DMARC besteht, - Bounces können zurückgeführt werden, - die komplette SRS-Kette startet automatisch nach einem Reboot, - die Konfiguration ist für spätere Automatisierung vorbereitet.