70.1.5. pepsi-stage-srs

rewrite the envelope sender with the Sender Rewriting Scheme

Manual section:

1

70.1.5.1.1. Name

pepsi-stage-srs - SRS envelope-sender rewriting stage of the Pepsi pipeline.

70.1.5.1.2. Synopsis

pepsi-stage-srs [GLOBAL-OPTIONS] worker

pepsi-stage-srs [GLOBAL-OPTIONS] forward ADDRESS

pepsi-stage-srs [GLOBAL-OPTIONS] reverse ADDRESS

70.1.5.1.3. Description

This stage defaults to FUSION = yes: when stage fusion is enabled ([pepsi] ALLOW_FUSION, the default) and this stage is folded into the unified pepsi binary, a predecessor may run it in its own worker process instead of dispatching it separately. See pepsi-dispatch(1) and pepsi.conf(5).

pepsi-stage-srs is a stage program run by pepsi-dispatch(1) as a persistent worker reading message ids on standard input. It implements the Sender Rewriting Scheme (SRS).

When Pepsi forwards a message it keeps the body intact but relays it from its own IP addresses. The next hop’s SPF check then sees Pepsi sending mail whose envelope sender is still the original sender’s domain, which does not authorise Pepsi’s IPs, and the check fails. SRS solves this by rewriting the envelope sender (MAIL FROM) into a local address of a Pepsi-controlled domain (SRS_DOMAIN) that encodes — and HMAC-signs — the original sender:

SRS0=HHHH=TT=origin.example=alice@srs.example.org

SPF at the next hop now checks srs.example.org, which legitimately sends from Pepsi’s IPs. The body and its DKIM signatures are untouched. The stage then advances the message to its NEXT_STAGE (the delivery stage). It changes only the envelope sender, leaving the row’s state — including any RFC 3461 state.dsn parameters — untouched for later stages to honour.

The null sender (<>, i.e. a returning bounce) is never rewritten, and a sender already in SRS_DOMAIN is left unchanged (rewriting is idempotent). A sender that is already an SRS address — the message reached Pepsi through another forwarder — is re-signed in the compact SRS1 form rather than being nested, so a bounce hops back one forwarder at a time.

70.1.5.1.3.1. Reverse direction

The other half of SRS — recognising a bounce returned to an SRS address, verifying its signature and timestamp, decoding the original sender and relaying the bounce there — is performed by pepsi-ingress(1) at RCPT time, not by this program. A recipient in SRS_DOMAIN whose local-part is a valid SRS token is accepted and rewritten back to the original sender (even though that sender’s domain is not one Pepsi serves — the valid signature authorises the relay); a forged or expired token is rejected with 550. Both directions read the same shared [pepsi-srs] configuration, so the secret and domain match.

70.1.5.1.4. Configuration

The stage needs only a NEXT_STAGE in its own [stage-<name>] section (PROGRAM = pepsi-stage-srs); the SRS parameters (SRS_DOMAIN, SECRET/SECRET_FILE, MAX_AGE_DAYS) live in the shared [pepsi-srs] section it shares with pepsi-ingress(1). All are documented in pepsi.conf(5). Omitting [pepsi-srs] disables SRS: the stage refuses to run and pepsi-ingress(1) treats SRS-looking recipients as ordinary addresses.

70.1.5.1.5. State

Inputs: none — the stage operates on the mail_from column, not on state.

Outputs: state.srs.original, the envelope sender the rewrite replaced. Nothing else in state is touched — state.dsn and the rest are preserved unchanged. The state layout is described in pepsi.state(7).

That one key exists for a DSN Pepsi originates after this stage has run, which is every DSN on a relaying path: this stage necessarily precedes the delivery stage, so pepsi-stage-bounce(1) would otherwise address the report to our own SRS alias and make it take a round trip out to the next hop and back in through our MX to be decoded. The bounce stage reads this instead of reversing the alias, which keeps the SRS secret out of a stage that only composes mail. It is written only when absent, so a message rewritten twice keeps the address that names a real correspondent rather than the intermediate alias.

Transitions: always advances to NEXT_STAGE, whether the envelope sender was SRS-rewritten or passed through unchanged (a null sender, or one already in SRS_DOMAIN). There is no branch; the stage never pauses, fails, reroutes or finishes.

70.1.5.1.6. Commands

Run as a worker, the program rewrites each message’s envelope sender and advances it. The subcommands are operator tools:

forward ADDRESS

Print the SRS rewrite of ADDRESS (the forward direction) and exit. Useful for inspecting what a given sender becomes.

reverse ADDRESS

Decode and verify ADDRESS (an SRS address or bare local-part) and print the original sender, or fail if it is not a valid SRS address.

70.1.5.1.7. Global Options

-c FILE, –config FILE

Read the configuration from FILE instead of the default search path.

-L LOGLEVEL, –log LOGLEVEL

Set the logging verbosity (error, warn, info, debug, trace; default info).

-h, –help

Print a usage summary and exit.

-V, –version

Print the version and exit.

70.1.5.1.8. Exit Status

0

The message was rewritten and advanced (or the subcommand succeeded).

1

An error occurred (misconfiguration, the message is not in the expected state, or a database error). The reason is written to the log.

70.1.5.1.9. Examples

Show what a sender is rewritten to:

pepsi-stage-srs -c /etc/pepsi/pepsi.conf forward alice@origin.example

Decode a returned bounce address:

pepsi-stage-srs -c /etc/pepsi/pepsi.conf reverse 'SRS0=HHHH=TT=origin.example=alice@srs.example.org'

70.1.5.1.10. See Also

pepsi-config(1), pepsi-stage-relay-to-smarthost(1), pepsi-stage-relay-to-internet(1), pepsi-stage-bounce(1), pepsi-stage-dkim-sign(1), pepsi-dispatch(1), pepsi-ingress(1), pepsi.conf(5), pepsi.state(7), pepsi-setup(1)

70.1.5.1.11. Bugs

Report bugs to the Pepsi issue tracker.