Files
mailsystem/archive/selective-srs-2026/README-install-SRS.md
T

1450 lines
29 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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:<ckubu@gmx.de>
|
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:<ckubu@gmx.de>
|
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:<ckubu@gmx.de>
```
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:<ckubu@gmx.de>
```
wird beispielsweise:
```text
MAIL FROM:<SRS0=...=gmx.de=ckubu@srs.warenform.de>
```
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: <ckubu@gmx.de>
RCPT TO: <test@warenform.de>
```
`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: <ckubu@gmx.de>
```
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: <SRS0=...@srs.warenform.de>
```
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:
<ckubu@gmx.de>
forwarded as
<SRS0=...=gmx.de=ckubu@srs.warenform.de>
```
Danach:
```text
to=<ckubu@oopen.de>
orig_to=<test@warenform.de>
relay=srs-forward
status=sent
```
SRS-Delivery:
```text
from=<SRS0=...=gmx.de=ckubu@srs.warenform.de>
```
Final:
```text
to=<ckubu@oopen.de>
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-<version>
```
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.