Discussion:
sender rewrining advice
(too old to reply)
none
2024-03-17 16:29:00 UTC
Permalink
receive
email
|
|
|
|
V
+------------+ +------------+ +------------+
| MX | | OUTGOING | | MX |
| +------>| |----->| |
| accessmap | | | | EXTERNAL |
| | | | | |
+------+-----+ +------------+ +------------+
|
|
V
+------+-----+
| LOCAL |
| |
| virtuser |
| |
+------------+

I would like to forward messages to external email addresses and apply
sender rewriting. I don't have any experience with this, and was
wondering what a default best practice is.

- on the mx server I want to decide what messages are for local delivery
and what go to external.

Normally I have to first relay the message to a local host, where in the
virtualuser table I have an entry to deliver to an email address.
I prefer to skip this. What could I use on the MX host? LDAPRoute?


- I prefer the messages to be routed via the 'OUTGOING' service
Because the MX are not specified in spf records. Assuming that such
envolopes 'SRS0=HHH=TT=example.org=***@example.com' are still being
checked on spf.


- on the 'OUTGOING' I only have dkim signing

I guess best would be to first do some routing and then on the
'OUTGOING' do the sender rewriting. Anyone already doing something like
this?
Grant Taylor
2024-03-17 20:12:54 UTC
Permalink
Nice ASCII diagram, which successfully made it through unscathed. :-)
Post by none
I would like to forward messages to external email addresses and apply
sender rewriting. I don't have any experience with this, and was
wondering what a default best practice is.
I don't know what the best practice is per se. But I'm doing sender
rewriting (SRS) on my two public facing Sendmail systems.

I do SRS on recipients that aren't in class w. So the method I'm using
wouldn't work for you as things going from MX to LOCAL would be
re-written using the method that I'm using. Though there is a chance
that LDAP routing might change this.
Post by none
- on the mx server I want to decide what messages are for local delivery
and what go to external.
I'm going to assume that you have an email route (mailertable?) for
things going to LOCAL and a fall back smart host configuration going to
OUTGOING.

How are you dealing with the routing to LOCAL today? mailertable and /
or LDAP routing and / or something else?
Post by none
Normally I have to first relay the message to a local host, where in the
virtualuser table I have an entry to deliver to an email address.
I prefer to skip this. What could I use on the MX host? LDAPRoute?
Please elaborate on what you are doing today.
Post by none
- I prefer the messages to be routed via the 'OUTGOING' service
Because the MX are not specified in spf records. Assuming that such
checked on spf.
I don't see any problem with sending all messages leaving your
environment via OUTGOING. I'd have to look up to see which is the
better way to do that; fall back smart host or smart host or something else.
Post by none
- on the 'OUTGOING' I only have dkim signing
I guess best would be to first do some routing and then on the
'OUTGOING' do the sender rewriting. Anyone already doing something like
this?
You could apply the same type of sender rewriting that I'm doing on your
OUTGOING host. Assuming that there is exceedingly little that is
delivered locally while everything else is going off host.

Even if .forward type activity for root et al. on OUTGOING going back to
MX -> LOCAL shouldn't be a problem if it's rewritten via SRS.
--
Grant. . . .
none
2024-03-18 20:25:57 UTC
Permalink
I do SRS on recipients that aren't in class w.  So the method I'm using
wouldn't work for you as things going from MX to LOCAL would be
re-written using the method that I'm using.  Though there is a chance
that LDAP routing might change this.
Post by none
- on the mx server I want to decide what messages are for local
delivery and what go to external.
I'm going to assume that you have an email route (mailertable?) for
things going to LOCAL and a fall back smart host configuration going to
OUTGOING.
yes mailertable, but no fall back at all.
How are you dealing with the routing to LOCAL today?  mailertable and /
or LDAP routing and / or something else?
mailertable, only a few entries in LDAP routing
Post by none
Normally I have to first relay the message to a local host, where in
the virtualuser table I have an entry to deliver to an email address.
I prefer to skip this. What could I use on the MX host? LDAPRoute?
Please elaborate on what you are doing today.
I am not really doing anything yet. I have some people on LOCAL using
forwarding, which are starting to generate spf bounces.

But in the near future I would like to offer an email address that is
forwarded, that I configure and not some users turning it off/on.
I tested a bit with ldap routing. I would be able to forward remotely
via MailLocalAdress and MailRoutingAddress

***@gmail.com -> ***@me.com received at MX -> ***@guerrillamail.com

I think it would be nicer if I could skip processing on LOCAL.

There will be email addresses on this @me.com that are just delivered to
regular mailboxes on LOCAL.
Post by none
- I prefer the messages to be routed via the 'OUTGOING' service
Because the MX are not specified in spf records. Assuming that such
checked on spf.
I don't see any problem with sending all messages leaving your
environment via OUTGOING.  I'd have to look up to see which is the
better way to do that; fall back smart host or smart host or something else.
I have limited experience with smart hosts. Only used in situations
where all traffic is forwarded.
Post by none
- on the 'OUTGOING' I only have dkim signing
I guess best would be to first do some routing and then on the
'OUTGOING' do the sender rewriting. Anyone already doing something
like this?
You could apply the same type of sender rewriting that I'm doing on your
OUTGOING host.  Assuming that there is exceedingly little that is
delivered locally while everything else is going off host.
I think I have fair amount of local deliveries also on OUTGOING. What is
the problem with local delivery and SRS? I thought the SRS milters could
be given something like ip ranges to determine what is local and not?
Even if .forward type activity for root et al. on OUTGOING going back to
MX -> LOCAL shouldn't be a problem if it's rewritten via SRS.
Yes that would be my 2nd point of attention. Handling these user
forwards correctly. But I thought focussing on just forwarding at the MX
would be easier for now.
Grant Taylor
2024-03-20 01:56:52 UTC
Permalink
Post by none
yes mailertable, but no fall back at all.
ACK
Post by none
mailertable, only a few entries in LDAP routing
Please elaborate on which you're using when and why.

My experience and understanding is that mailertable routes at the domain
level while LDAP routing can route at the address level.
Post by none
I am not really doing anything yet. I have some people on LOCAL using
forwarding, which are starting to generate spf bounces.
ACK
Post by none
But in the near future I would like to offer an email address that is
forwarded, that I configure and not some users turning it off/on.
Okay.

N.B. IMHO there is very little difference between how the forwarding is
done when it comes to SRS.
Post by none
I tested a bit with ldap routing. I would be able to forward remotely
via MailLocalAdress and MailRoutingAddress
Nomenclature becomes extremely important and we quickly get into minutia.
Is me.com one of your addresses or Apple's iCloud?
Post by none
I think it would be nicer if I could skip processing on LOCAL.
You should be able to forward directly on MX without needing to loop
through LOCAL.
Post by none
regular mailboxes on LOCAL.
It looks like you are using @me.com as a reference to your own domain,
not Apple's iCloud me.com.

Which system thinks that it is responsible for -- I'm going to say --
@example.com? MX or LOCAL?

If you are using LDAP routing, you can have MX think that @example.com
is local to it. -- I think, based on my understanding.

If you aren't using LDAP routing then you would probably need to make MX
relay @example.com over to LOCAL and LOCAL would think that @example.com
is local to it.
Post by none
I have limited experience with smart hosts. Only used in situations
where all traffic is forwarded.
ACK
Post by none
I think I have fair amount of local deliveries also on OUTGOING. What is
the problem with local delivery and SRS?
SRS doesn't interfere with delivery. SRS alters the SMTP envelope
/from/ address. SRS could happen at each SMTP hop along the way and it
shouldn't adversely impact delivery.
Post by none
I thought the SRS milters could be given something like ip ranges to
determine what is local and not?
I don't know how an SRS milter would work. As such I can't speak to how
they do and don't operate.

I'm not using a milter to do SRS. I've got SRS hooked into Sendmail as
part of one of it's rule sets.
Post by none
Yes that would be my 2nd point of attention. Handling these user
forwards correctly. But I thought focussing on just forwarding at the MX
would be easier for now.
The way that I'm using SRS, Sendmail looks to see if the recipient email
domain is local to itself or if it's to be sent somewhere off box. If
the email is to be sent somewhere off box, then SRS is used. Thus email
from LOCAL (via .forward files thereon) going anywhere not on LOCAL
(assuming SRS is done on LOCAL) will be rewritten.

If you would, please change the example names that you have used to
something that doesn't collide with other functions; e.g.

- MX is a function, not a host name
- LOCAL is a definition for addresses, much like loopback / 127.0.0.1
in IPv4
- @me.com is an often used domain name that is registered to Apple for
their iCloud.

I think that clearer names / identifiers would help this discussion.

Also, please provide the name(s) that Sendmail things are local to each
system. Feel free to redact part of them if you want to, but something
like a.example is on ${HOST_PREVIOUSLY_CALLED_MX}, b.example is local to
${HOST_PREVIOUSLY_CALLED_LOCAL}, and c.example is local to
${HOST_PREVIOUSLY_CALLED_OUTGOING}. I think these (place holder) names
are going to quickly become extremely important.
--
Grant. . . .
none
2024-03-20 14:38:25 UTC
Permalink
Post by Grant Taylor
Post by none
mailertable, only a few entries in LDAP routing
Please elaborate on which you're using when and why.
both on MX. LDAP routing when an email destined for host B, should
temporary go to host A.
Post by Grant Taylor
Post by none
I think it would be nicer if I could skip processing on LOCAL.
You should be able to forward directly on MX without needing to loop
through LOCAL.
Post by none
to regular mailboxes on LOCAL.
not Apple's iCloud me.com.
correct
Post by Grant Taylor
Which system thinks that it is responsible for -- I'm going to say --
@example.com?  MX or LOCAL?
LOCAL
Post by Grant Taylor
is local to it.  --  I think, based on my understanding.
Ok so for this setup I should create Ldap routing entries like this.

mailLocalAddress: ***@me.com / ***@example.com
mailHost: (OUTGOING server)
mailRoutingAddress: ***@guerrillamail.com

but I have to allow relaying on OUTGOING with something like this in the
access map

Connect:(MX server) RELAY

Is it wise to maybe reduce this to only the me.com/example.com or is
there something different.
Would this be possible/better

FEATURE(`blacklist_recipients')

@me.com RELAY
@example.com RELAY


Is this what you had in mind?
Post by Grant Taylor
I'm not using a milter to do SRS.  I've got SRS hooked into Sendmail as
part of one of it's rule sets.
Can you specify ip ranges there or host domains, so you do not do
envelope rewriting when it is not necessary?
Do these sendmail rules get MX hosts for ***@guerrillamail.com compare
them with some configured/identified local network and everything not in
the local network is rewritten?
Post by Grant Taylor
 - MX is a function, not a host name
 - LOCAL is a definition for addresses, much like loopback / 127.0.0.1
in IPv4
I know, I thought referring to their function would be more clear.
Post by Grant Taylor
their iCloud.
Yes indeed not nice, I have asked them to change it to ime.com. That
fits better with the rest of their stuff.
Post by Grant Taylor
I think that clearer names / identifiers would help this discussion.
Also, please provide the name(s) that Sendmail things are local to each
system.  Feel free to redact part of them if you want to, but something
like a.example is on ${HOST_PREVIOUSLY_CALLED_MX}, b.example is local to
${HOST_PREVIOUSLY_CALLED_LOCAL}, and c.example is local to
${HOST_PREVIOUSLY_CALLED_OUTGOING}.  I think these (place holder) names
are going to quickly become extremely important.
ok
Grant Taylor
2024-03-21 02:01:34 UTC
Permalink
Post by none
both on MX. LDAP routing when an email destined for host B, should
temporary go to host A.
I assume by "should temporary go to host A" to mean while the message is
relayed through host A? As in host A is the MX the world sends to and
host A then relays it to host B? -- Or have I completely lost track?
Post by none
correct
Okay.
Post by none
LOCAL
Okay.

Does MX (host A?) have @example.com in it's relay-domains file (or
somehow otherwise in class R)?
Post by none
Ok so for this setup I should create Ldap routing entries like this.
I'm going to have to refresh myself on LDAP routing as it's been a LONG
time.
Post by none
mailHost: (OUTGOING server)
If I'm correctly picking up what you're putting down you are trying to
say that mail to ***@example.com should be forwarded to
***@guerrillamail.com and go out via the OUTGOING server?

I believe you also said that you wanted MX to send the message to
OUTGOING directly and not send it to LOCAL which would then send it back
to MX on it's way to OUTGOING.

In this case MX is going to need some knowledge of how to do the routing
for a non-local domain.

I'm going to have to dig out the Bat book and re-read about LDAP routing.

---

I'm confident that MX could relay @example.com to LOCAL and where LOCAL
could forward the message to @guerrillamail.com and send it back out.

Aside: LOCAL could send the email via MX which would send it on to
OUTGOING or perhaps LOCAL could send it directly to OUTGOING.
Post by none
but I have to allow relaying on OUTGOING with something like this in the
access map
Connect:(MX server)    RELAY
I think that you can add MX's hostname or IP address to the
/etc/mail/relay-domains file.

N.B. you might should put the hostname in square brackets so that
Sendmail doesn't do an Mail eXchanger lookup on MX's hostname.
(Expanding action to differentiate from a colliding host reference.)
Post by none
Is it wise to maybe reduce this to only the me.com/example.com or is
there something different.
I don't know.
Post by none
Would this be possible/better
FEATURE(`blacklist_recipients')
@me.com            RELAY
@example.com        RELAY
I'm not convinced that you need, much less what that. At least not yet.
Post by none
Is this what you had in mind?
No.

When I made the statement "you can have MX think that @example.com is
local to it" I was thinking that MX would think that it's responsible
for @example.com email addresses and that LDAP routing would be used to
route some messages to LOCAL and other messages elsewhere, possibly
forwarding them to guerrillamail.com.
Post by none
Can you specify ip ranges there or host domains, so you do not do
envelope rewriting when it is not necessary?
The method that I'm using -- I need to log in and copy some files to
provide examples -- simply applies sender rewriting to any envelope that
is not from a domain that Sendmail is responsible for;
/etc/mail/local-host-names (class w).

I don't know how that would expand out with LDAP routing.

I do think that the config is relatively simple to change to have it
read a different class that isn't used for anything else so that you
could have it be something like dont-srs-domains type thing.
Post by none
them with some configured/identified local network and everything not in
the local network is rewritten?
No.

They look at the sending envelope address and compare it to the
/etc/mail/local-host-names (class w).
Post by none
I know, I thought referring to their function would be more clear.
Sometimes yes and sometimes no.
Post by none
Yes indeed not nice, I have asked them to change it to ime.com. That
fits better with the rest of their stuff.
LOL
--
Grant. . . .
none
2024-03-21 12:12:58 UTC
Permalink
internet internet
recv. email
| ^
| |
| |
V |
+------------+ +------+-----+
| A | | B |
| mailert +---1-->| auth |
| accessmap | | |
| ldapr | | |
+------+-----+ +------------+
|
|
|
V
+------+-----+
| C |
| |
| virtuser |
| |
+------------+



host a: incomming, mx
host b: outgoing, smtp with user auth
Post by Grant Taylor
somehow otherwise in class R)?
Indeed. I am trying to use email addresses here and not domains. So NDR
are generated on host A / mx server.

I have there, access:
to:***@example.com RELAY

mailertable:
example.com esmtp:[c.local]
Post by Grant Taylor
mailHost: B
This ldap entry currently makes emails being routed from the mx server A
to the outgoing server B
Post by Grant Taylor
If I'm correctly picking up what you're putting down you are trying to
correct
Post by Grant Taylor
I'm going to have to dig out the Bat book and re-read about LDAP routing.
Yes the above does this currently with ldap routing. But I don't know if
this is the best way to do it.
Post by Grant Taylor
---
host C, LOCAL is not in the spf records. I think external access is even
blocked. I had spammers by passing spam blocking on the mx / host a and
delivering directly to C
Post by Grant Taylor
Aside:  LOCAL could send the email via MX which would send it on to
OUTGOING or perhaps LOCAL could send it directly to OUTGOING.
but I have to allow relaying on OUTGOING with something like this in
the access map
Connect:(MX server)    RELAY
I think that you can add MX's hostname or IP address to the
/etc/mail/relay-domains file.
ok I made note of this, I will enhance this later.
Post by Grant Taylor
Can you specify ip ranges there or host domains, so you do not do
envelope rewriting when it is not necessary?
The method that I'm using -- I need to log in and copy some files to
provide examples -- simply applies sender rewriting to any envelope that
is not from a domain that Sendmail is responsible for;
/etc/mail/local-host-names (class w).
I am not sure if my outgoing, host b, has access to the
local-host-names. It is still using the same clusterid as host c and can
probably access the local-host-names.
But I think in the near future I will create a separate clusterid for
the outgoing, host b.
(Used to have everything in one host)

At some point in the future I would like to secure host b more, so
authenticated users can only send out email with their assigned address.
Post by Grant Taylor
They look at the sending envelope address and compare it to the
/etc/mail/local-host-names (class w).
So currently I am able to route from host a to host b the emails send to
***@example.com.
How should I go about to enable SRS for senders to ***@example.com on
host b?
Grant Taylor
2024-03-23 04:10:54 UTC
Permalink
      internet             internet
    recv. email
         |                    ^
         |                    |
         |                    |
         V                    |
  +------------+       +------+-----+
  |      A     |       |      B     |
  |  mailert   +---1-->|    auth    |
  |  accessmap |       |            |
  |  ldapr     |       |            |
  +------+-----+       +------------+
         |
         |
         |
         V
  +------+-----+
  |      C     |
  |            |
  |  virtuser  |
  |            |
  +------------+
host a: incomming, mx
host b: outgoing, smtp with user auth
Indeed. I am trying to use email addresses here and not domains. So NDR
are generated on host A / mx server.
I take it that host A is not fully aware of the recipient addresses that
are on host B. Thus why host A needs to bounce / DSN / NDR a message
that it accepted responsibility for.

If host A was fully aware of the recipient addresses that are on host B,
then host A could have rejected the inbound message and not need to send
a bounce / DSN / NDR. The bounce / DSN / NDR would be the
responsibility of the system trying to send to host A.
Do you also have a corresponding REJECT?

to:@example.com REJECT

Without the REJECT I would expect Sendmail to accept the message as part
of the relay-domains configuration.
This ldap entry currently makes emails being routed from the mx server A
to the outgoing server B
That's what I thought.
correct
Thank you for confirming.

I'll have to go Read The Fine Manual again to see how LDAP routing comes
into play for relayed / non-local domains.
Yes the above does this currently with ldap routing. But I don't know if
this is the best way to do it.
My dusty understanding of LDAP routing is that it's intended for
multiple servers to share the same domain name(s); e.g. @example.com,
and know which server hosts specific mailboxes. Meaning that both host
A and host C would be configured with @example.com in their
local-host-names file.
host C, LOCAL is not in the spf records. I think external access is even
blocked. I had spammers by passing spam blocking on the mx / host a and
delivering directly to C
SPF is about the connecting host.

As such, GuerrillaMail.com will see host B as the connecting host and
check it's IP against SPF records.

Depending on your configuration, hosts A, B, and C may need to either
have allow list entries or valid SPF information for each other.
ok I made note of this, I will enhance this later.
:-)
I am not sure if my outgoing, host b, has access to the
local-host-names. It is still using the same clusterid as host c and can
probably access the local-host-names.
Even if it doesn't have access to the local-host-names file on hosts A
or C, you could probably copy the contents to a similar file and
configure the methodology to use that file in lieu of the
local-host-names file.
But I think in the near future I will create a separate clusterid for
the outgoing, host b.
Okay.
(Used to have everything in one host)
ACK
At some point in the future I would like to secure host b more, so
authenticated users can only send out email with their assigned address.
I'm aware that such is done by some MTAs. I've wondered about doing
that with Sendmail. But then I realized that users were authenticating,
thus I would have a good idea (but no guarantee) who, or at least which
account, was being used to abuse things. I've not needed to actually go
down this path (yet).
So currently I am able to route from host a to host b the emails send to
host b?
You could SRS /everything/ leaving host B. It won't actually hurt anything.

SRS your own envelopes is a little silly and maybe even questionable.

From memory -- I'll look some time this weekend -- the SRS routine that
I'm using uses the local-host-names file (class w) as part of the test
to determine if envelope senders should be rewritten or not.

I don't think that it /must/ /be/ the local-host-names file (class w).
I naively assume that you could use any file name you wanted and declare
a new class to be used for this test. It would be a minor change to the
rules to look at that alternate named file / class.
--
Grant. . . .
Grant Taylor
2024-03-23 04:41:42 UTC
Permalink
Post by Grant Taylor
From memory -- I'll look some time this weekend -- the SRS routine that
I'm using uses the local-host-names file (class w) as part of the test
to determine if envelope senders should be rewritten or not.
What I have is based off of the following, which is now available via
Archive.org

Link - SRS integration with sendmail
-
https://web.archive.org/web/20051221183047/http://srs-socketmap.info/sendmailsrs.htm

The collection of files is basically two versions of very similar
solutions. I've used both.

N.B. I originally drafted this reply with the files attached, but I've
since removed them and will send them in a follow up. They /should/ be
forthcoming shortly.

I have sym-links in /usr/share/sendmail/cf/hack directory pointing to
the m4 files in the /etc/mail/srs directory.

Towards the end of my sendmail.mc file I have the following line:

I'm currently using the perlsrs-old.m4.

HACK(`perlsrs-old')dnl

Both perlsrs.m4 and socketmap.m4 rely on the socketmapd.0.31.pl file
running as a daemon listening on a local Unix socket. -- I used this
for a while, but abandoned it because I got tired of needing to manually
start it after updates. I should have written an init script, but c'est
la vie.

So I switched to perlsrs-old.m4 which forks a copy of envfrom2srs.pl or
srs2envto.pl as necessary.

I've never had any problems with the overhead of forking the Perl
processes. SpamAssassin, ClamAV, and the IMAP daemon take up FAR more
resources than the SRS solution.

It looks like line 37 of the perlsrs-old.m4 is what references the class
w map (where local-host-names gets loaded into). So I would think that
you could create a new class and load contents of a different file into
the class and for reference.

I don't remember the specifics about the socketmapd solutions
(perlsrs.m4 and socketmap.m4) but I know that they did work and that I
didn't notice any less overhead with the long running daemon vs forking.

According to mailstats, my server has been averaging 15.5 k messages a
day for the last month (10k min and 19k max). I'm on a small Linode w/
2 GB of memory. -- This really doesn't make an impact and it's not
like it's a big system.
--
Grant. . . .
Grant Taylor
2024-03-23 04:43:13 UTC
Permalink
Post by Grant Taylor
N.B. I originally drafted this reply with the files attached, but I've
since removed them and will send them in a follow up.  They should be
forthcoming shortly.
I have all of the attached files in the /etc/mail/srs directory.

Let's see if 14 kB of attachments make it through Usenet. }:-) They're
text. :-D

Here goes nothing.
--
Grant. . . .
Grant Taylor
2024-03-23 04:44:11 UTC
Permalink
Post by Grant Taylor
I have all of the attached files in the /etc/mail/srs directory.
Let's see if 14 kB of attachments make it through Usenet.  }:-)  They're
text.  :-D
Here goes nothing.
If the message with the attachments that I'm replying to didn't make it
to your news server, let me know.
--
Grant. . . .
none
2024-03-23 09:31:04 UTC
Permalink
Post by Grant Taylor
Post by Grant Taylor
I have all of the attached files in the /etc/mail/srs directory.
Let's see if 14 kB of attachments make it through Usenet.  }:-)
They're text.  :-D
Here goes nothing.
If the message with the attachments that I'm replying to didn't make it
to your news server, let me know.
:/ No they seem to have stripped it.
Grant Taylor
2024-03-23 17:48:36 UTC
Permalink
Post by none
:/ No they seem to have stripped it.
:-(

I can't say that I'm surprised. Hoping. Wishful thinking.

Let's see if this comes through.



cat envfrom2srs.pl
--8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<--
#!/usr/bin/perl
#
# Sendmail "program" map script to rewrite envelope-from
# address to SRS0 address. Called from macro EnvFromSMTP.
#
# Code by Mark Kramer <***@asarian-host.net>
#
# Version 0.30
#
# Last revision: March 24, 2004
#
# Licensed under GPL
#
# For detailed installation notes, read:
#
# http://asarian-host.net/srs/sendmailsrs.htm
#
# See also: http://www.anarres.org/projects/srs/
# http://spf.pobox.com/
#
# This version requires at least Sendmail 8.12.10 + Mail::SRS 0.30



use Mail::SRS;
use strict;

# No funny business in our output, please

close (STDERR);

my $old_address = $ARGV[0];
my $secret = 'REDACTED';
my ($new_address, $use_address);
my $fwdomain = 'REDACTED';
my $srs = new Mail::SRS (Secret => $secret, HashLength => 8,
AlwaysRewrite => 1);

###
open(my $fh, '>>', '/tmp/mylog.txt');
print $fh "$old_address\n";
close $fh;
###

# Our original envelope-from may look funny on entry
# of this Ruleset:
#
# admin<@asarian-host.net.>
#
# We need to preprocess it some:

($use_address = $old_address) =~ s/[<>]//g;
$use_address =~ s/\.$//g;

# Here, at EnvFromSMTP, we do not loop our address through an
# extra IsSrs macro: we want SRS1 forwarding functionality!
# (relaying reversed third-party SRS1 addresses is a
# different story, though; but here we just allow for SRS0
# addresses to be promoted to SRS1 ones).
#
# Ok, first check whether we already have a signed SRS address;
# if so, just return the old address: we do not want to double-sign
# by accident! (Non-locally generated SRS0 addresses, by nature
# of the protocol, will not 'eval'; so, they will simply become
# SRS1 addresses. Thus, only locally generated SRS0 addresses are
# exempted from double-signing.)
#
# Else, gimme a valid SRS signed address, munge it back the way
# sendmail wants it at this point; or just return the old address,
# in case nothing went.

if (eval {$new_address = $srs -> reverse ($use_address)}) {
print "$old_address\n";
} elsif (eval {$new_address = $srs -> forward ($use_address, $fwdomain)}) {
$new_address .= '.>';
$new_address =~ s/\@/<@/;
print "$new_address\n";
} else {
print "$old_address\n";
}

exit 0;
-->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8--



perlsrs.m4
--8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<--
divert(-1)

# Copyright (c) 2004 by Mark Kramer <***@asarian-host.net>
# All rights reserved.
# Copyright (c) 1988, 1993
# The Regents of the University of California. All rights reserved.
#
# By using this file, you agree to the terms and conditions set
# forth in the LICENSE file which can be found at the top level of
# the sendmail distribution.
#
#

divert(0)

VERSIONID(`$Id: 8.13.perlsrs.m4,v 1.0 2004/08/21 13:15:43 mkramer Exp $')

ifdef(`_MAILER_DEFINED_',,`errprint(`*** WARNING: MAILER() should be
before HACK(perlsrs)')')

LOCAL_CONFIG

# SRS socket maps

Kreverse_srs socket local:/var/run/socketmapd.sock
Kmake_srs socket local:/var/run/socketmapd.sock

# SRS regex map

Kis_srs regex ^<?SRS[01][=+-].*

MAILER_DEFINITIONS

SEnvFromSMTP
R$* $: $(make_srs $1 $)

LOCAL_RULESETS

###################################################################
### Local SRS Macros ###
###################################################################

SIsSrs
R$* $: $(is_srs $1 $)
R$@ $@ YES
R$* $@ NO

SReverseSrs
R$* $: $1 $>IsSrs $1
R$* NO $@ $1
R$* YES $@ $(reverse_srs $1 $)

LOCAL_RULE_0

# Do we need to reverse SRS address?

R$* $: $>ReverseSrs $1
-->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8--



perlsrs-old.m4
--8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<--
divert(-1)

# Copyright (c) 2004 by Mark Kramer <***@asarian-host.net>
# All rights reserved.
# Copyright (c) 1988, 1993
# The Regents of the University of California. All rights reserved.
#
# By using this file, you agree to the terms and conditions set
# forth in the LICENSE file which can be found at the top level of
# the sendmail distribution.
#
#

divert(0)

VERSIONID(`$Id: perlsrs.m4,v 1.2 2004/04/01 20:37:09 mkramer Exp $')

ifdef(`_MAILER_DEFINED_',,`errprint(`*** WARNING: MAILER() should be
before HACK(perlsrs)')')

LOCAL_CONFIG

# Forward SRS program map

Kenvfrom2srs program /etc/mail/srs/envfrom2srs.pl

# Reverse SRS program map

Ksrs2envto program /etc/mail/srs/srs2envto.pl

# SRS regex map

Kis_srs regex ^<?SRS[01][=+-].*

MAILER_DEFINITIONS

SEnvFromSMTP
R$*@$=w$* $@ $1@$2$3 Don't SRS rewrite local (class w) sending domains.
R$* $: $(envfrom2srs $1 $) SRS rewrite non-local (!class w) sending
domains.

LOCAL_RULESETS

###################################################################
### Local SRS Macros ###
###################################################################

SIsSRS
R$* $: $(is_srs $1 $)
R$@ $@ YES
R$* $@ NO

SReverseSrs
R$* $: $1 $>IsSRS $1
R$* NO $@ $1
R$* YES $@ $(srs2envto $1 $)

LOCAL_RULE_0

# Do we need to reverse SRS address?

R$* $: $>ReverseSrs $1
-->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8--



socketmapd.0.31.pl
--8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<--
#!/usr/bin/perl

# Sendmail "socket" map script to perform SRS functions.
#
# Code by Mark Kramer <***@asarian-host.net>
#
# Version 0.31
#
# Last revision: November 2, 2004
#
# With thanks to Jim Allen for pointing out a missing
# "while (!eof($client))" loop, causing BROKEN PIPE errors
# on concurrent connections.
#
# Licensed under GPL
#
# For detailed installation notes, read:
#
# http://asarian-host.net/srs/sendmailsrs.htm
#
# See also: http://www.anarres.org/projects/srs/
# http://spf.pobox.com/
#
# This version requires at least Sendmail 8.13.0 + Mail::SRS 0.30

use IO::Socket;
use POSIX qw (:sys_wait_h);
use Sys::Syslog qw (:DEFAULT setlogsock);
use Mail::SRS;
use strict;

my ($user, $login, $pass, $uid, $gid, $data, $socket_map, $old_address,
$new_address, $use_address, $client, $sock);
my $secret = 'REDACTED';
my $fwdomain = 'REDACTED';
my $srs = new Mail::SRS (Secret => $secret, MaxAge => 8, HashLength =>
8, AlwaysRewrite => 1);

sub write_syslog {
setlogsock ('unix');
openlog ('socketmapd', 'pid,cons', 'lpr') or exit 1;
syslog ('info', @_);
closelog ();
}

sub log_error_and_exit {
write_syslog (@_);
exit 1;
}

sub netstringRead {
my $sock = shift;
my $saveSeparator = $/;
$/ = ':';
my $dataLength = <$sock>;
write_syslog ("WARNING: cannot read netstring length") unless
defined ($dataLength);
chomp ($dataLength);
my $data;
if ($sock -> read ($data, $dataLength) == $dataLength) {
($sock -> getc () eq ',') or write_syslog ("WARNING: data
misses closing ,");
} else {
write_syslog ("WARNING: received only " . length ($data) . " of
$dataLength bytes");
}
$/ = $saveSeparator;
return $data;
}

sub netstringWrite {
my $sock = shift;
my $data = "OK " . shift;
write_syslog ("WARNING: $@") if (not eval {print $sock length
($data) . ':' . $data . ','});
}

sub handleChildConnection {
my $client = shift;
while (not eval {eof ($client)}) {
if (eval {$data = netstringRead ($client)}) {
if ($data =~ /^(\S+) (\S+)$/) {
$socket_map = $1;
$old_address = $2;
($use_address = $old_address) =~ s/[<>]//g;
$use_address =~ s/\.$//g;
if ($socket_map eq 'reverse_srs') {
if ($use_address =~ /^SRS[01][-+=]/i) {
$use_address = $_ while (eval {$_ = $srs ->
reverse ($use_address)});
$use_address .= '.>';
$use_address =~ s/\@/<@/;
netstringWrite ($client, $use_address);
} elsif ($use_address =~ /^\|/) {
netstringWrite ($client, "\"$old_address\"");
} else {
netstringWrite ($client, $old_address);
}
} elsif ($socket_map eq 'make_srs') {
if (eval {$new_address = $srs -> reverse
($use_address)}) {
netstringWrite ($client, $old_address);
} elsif (eval {$new_address = $srs -> forward
($use_address, $fwdomain)}) {
$new_address .= '.>';
$new_address =~ s/\@/<@/;
netstringWrite ($client, $new_address);
} else {
netstringWrite ($client, $old_address);
}
} else {
write_syslog ("WARNING: unknown socketmap,
'$socket_map'");
}
} else {
write_syslog ("WARNING: incomplete data, '$data'");
}
} else {
write_syslog ("WARNING: unable to read from client");
}
}
}

if (not $user = lc ($ARGV[0])) {
print STDERR "Missing user\n";
print STDERR "Usage: $0 <user to run as>\n";
exit 1;
} elsif ($>) {
print STDERR "You need to start socketmapd as root!\n";
exit 1;
} else {
($login, $pass, $uid, $gid) = getpwnam ($user);
if (not defined ($uid)) {
log_error_and_exit ("$user is not a valid user on this system!");
} elsif (not $uid) {
log_error_and_exit ("You cannot run socketmapd as root!");
}
}

open (STDIN, '/dev/null');
open (STDOUT, '>/dev/null');
open (STDERR, '>&STDOUT');

umask (0027);

unlink ('/var/run/socketmapd.pid');
unlink ('/var/run/socketmapd.sock');

if ($_ = fork ()) {
open (USERLOG, ">".'/var/run/socketmapd.pid') or exit 1;
flock (USERLOG, 2);
seek (USERLOG, 0, 0);
print USERLOG " $_";
close (USERLOG);
exit 0;
}

POSIX::setsid () || exit 1;

if (not (eval {$sock = new IO::Socket::UNIX (
Listen => SOMAXCONN,
Type => SOCK_STREAM,
Local => '/var/run/socketmapd.sock')})) {
log_error_and_exit ("ERROR: Unable to create UNIX domain socket!");
}

chown $uid, $gid, '/var/run/socketmapd.sock';

$0 = 'socketmapd';

$) = $gid;
$( = $gid;
$> = $uid;
$< = $uid;

write_syslog ("Dropped privileges on socketmap daemon");

while (eval {$client = $sock -> accept ()}) {
if (fork) {
eval {$client -> close ()};
wait;
} elsif (fork) {
exit 0;
} else {
eval {$sock -> close ()};
eval {handleChildConnection ($client)};
eval {$client -> close ()};
exit 0;
}
}

write_syslog ("Unsuccessful exit from the socketmap daemon: $!");

eval {$sock -> close ()};

exit 0;
-->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8--



socketmap.m4
--8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<--
divert(-1)

# Copyright (c) 2004 by Mark Kramer <***@asarian-host.net>
# All rights reserved.
# Copyright (c) 1988, 1993
# The Regents of the University of California. All rights reserved.
#
# By using this file, you agree to the terms and conditions set
# forth in the LICENSE file which can be found at the top level of
# the sendmail distribution.
#
#

divert(0)

VERSIONID(`$Id: socketmap.m4,v 1.0 2004/11/09 13:15:43 mkramer Exp $')

ifdef(`_MAILER_DEFINED_',,`errprint(`*** WARNING: MAILER() should be
before HACK(socketmap)')')

LOCAL_CONFIG

# SRS socket maps

Kreverse_srs socket local:/var/run/socketmapd.sock
Kmake_srs socket local:/var/run/socketmapd.sock

# SRS regex map

Kis_srs regex ^<?SRS[01][-+=].*

MAILER_DEFINITIONS

SEnvFromSMTP
R$*@$=w$* $@ $1@$2$3 Don't SRS rewrite local (class w) sending domains.
R$* $: $(make_srs $1 $) SRS rewrite non-local (!class w) sending domains.

LOCAL_RULESETS

###################################################################
### Local SRS Macros ###
###################################################################

SIsSrs
R$* $: $(is_srs $1 $)
R$@ $@ YES
R$* $@ NO

SReverseSrs
R$* $: $1 $>IsSrs $1
R$* NO $@ $1
R$* YES $@ $(reverse_srs $1 $)

LOCAL_RULE_0

# Do we need to reverse SRS address?

R$* $: $>ReverseSrs $1
-->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8--



srs2envto.pl
--8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<--
#!/usr/bin/perl
#
# Sendmail "program" map script to revert SRS0 or SRS1 address
# back to regular recipient. Called from macro ParseLocal.
#
# Code by Mark Kramer <***@asarian-host.net>
#
# Version 0.30
#
# Last revision: March 24, 2004
#
# Licensed under GPL
#
# For detailed installation notes, read:
#
# http://asarian-host.net/srs/sendmailsrs.htm
#
# See also: http://www.anarres.org/projects/srs/
# http://spf.pobox.com/
#
# This version requires at least Sendmail 8.12.10 + Mail::SRS 0.30


use Mail::SRS;
use strict;

# No funny business in our output, please

close (STDERR);

my $old_address = $ARGV[0];
my $secret = 'REDACTED';
my $use_address;
my $srs = new Mail::SRS (Secret => $secret, HashLength => 8,
AlwaysRewrite => 1);

# Munge ParseLocal recipient in the same manner as required
# in EnvFromSMTP.

($use_address = $old_address) =~ s/[<>]//g;
$use_address =~ s/\.$//g;

# Just try and reverse the address. If we succeed, return this
# new address; else, return the old address (quoted if it was
# a piped alias).
#
# We do an exhaustive while loop, so that SRS1 address may
# become SRS0, which, in turn, may become reverted to
# a local recipient.
#
# Mail:SRS, as of 0.30, is now case-insensitive. Added the
# /i switch to accomodate for the change.

if ($use_address =~ /^SRS[01][=+-]/i) {
$use_address = $_ while (eval {$_ = $srs -> reverse ($use_address)});
$use_address .= '.>';
$use_address =~ s/\@/<@/;
print "$use_address\n";
} elsif ($use_address =~ /^\|/) {
print "\"$old_address\"\n";
} else {
print "$old_address\n";
}

exit 0;
-->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8--
--
Grant. . . .
Grant Taylor
2024-03-23 17:48:53 UTC
Permalink
I can't say that I'm surprised.  Hoping.  Wishful thinking.
Let's see if this comes through.
Did those make it through?
--
Grant. . . .
none
2024-03-23 23:33:43 UTC
Permalink
Post by Grant Taylor
I can't say that I'm surprised.  Hoping.  Wishful thinking.
Let's see if this comes through.
Did those make it through?
Yes I have this. Don't I need to change the spaces to tabs in the m4 files?

envfrom2srs.pl
perlsrs.m4
perlsrs-old.m4
socketmapd.0.31.pl
socketmap.m4
srs2envto.pl
Grant Taylor
2024-03-23 23:41:06 UTC
Permalink
Post by none
Yes I have this.
Good!
Post by none
Don't I need to change the spaces to tabs in the m4 files?
Yes. Yes you do. Good catch -> call.

Hopefully the `cat -t` variant makes that a little bit easier to do.
Tabs will show up as `^I`. Hopefully this will be clean enough that you
can make them work.



cat -t perlsrs.m4
--8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<--

divert(-1)

# Copyright (c) 2004 by Mark Kramer <***@asarian-host.net>
#^IAll rights reserved.
# Copyright (c) 1988, 1993
#^IThe Regents of the University of California. All rights reserved.
#
# By using this file, you agree to the terms and conditions set
# forth in the LICENSE file which can be found at the top level of
# the sendmail distribution.
#
#

divert(0)

VERSIONID(`$Id: 8.13.perlsrs.m4,v 1.0 2004/08/21 13:15:43 mkramer Exp $')

ifdef(`_MAILER_DEFINED_',,`errprint(`*** WARNING: MAILER() should be
before HACK(perlsrs)')')

LOCAL_CONFIG

# SRS socket maps

Kreverse_srs socket local:/var/run/socketmapd.sock
Kmake_srs socket local:/var/run/socketmapd.sock

# SRS regex map

Kis_srs regex ^<?SRS[01][=+-].*

MAILER_DEFINITIONS

SEnvFromSMTP
R$*^I^I$: $(make_srs $1 $)

LOCAL_RULESETS

###################################################################
### Local SRS Macros^I^I^I^I^I^I###
###################################################################

SIsSrs
R$*^I^I^I^I$: $(is_srs $1 $)
R$@^I^I^I^I$@ YES
R$*^I^I^I^I$@ NO

SReverseSrs
R$*^I^I^I^I$: $1 $>IsSrs $1
R$* NO^I^I^I^I$@ $1
R$* YES^I^I^I^I$@ $(reverse_srs $1 $)

LOCAL_RULE_0

# Do we need to reverse SRS address?

R$*^I^I^I^I$: $>ReverseSrs $1
-->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8--



cat -t perlsrs-old.m4
--8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<--

divert(-1)

# Copyright (c) 2004 by Mark Kramer <***@asarian-host.net>
#^IAll rights reserved.
# Copyright (c) 1988, 1993
#^IThe Regents of the University of California. All rights reserved.
#
# By using this file, you agree to the terms and conditions set
# forth in the LICENSE file which can be found at the top level of
# the sendmail distribution.
#
#

divert(0)

VERSIONID(`$Id: perlsrs.m4,v 1.2 2004/04/01 20:37:09 mkramer Exp $')

ifdef(`_MAILER_DEFINED_',,`errprint(`*** WARNING: MAILER() should be
before HACK(perlsrs)')')

LOCAL_CONFIG

# Forward SRS program map

Kenvfrom2srs program /etc/mail/srs/envfrom2srs.pl

# Reverse SRS program map

Ksrs2envto program /etc/mail/srs/srs2envto.pl

# SRS regex map

Kis_srs regex ^<?SRS[01][=+-].*

MAILER_DEFINITIONS

SEnvFromSMTP
R$*@$=w$*^I^I$@ $1@$2$3^I^I^IDon't SRS rewrite local (class w) sending
domains.
R$*^I^I^I$: $(envfrom2srs $1 $)^I^ISRS rewrite non-local (!class w)
sending domains.

LOCAL_RULESETS

###################################################################
### Local SRS Macros^I^I^I^I^I^I###
###################################################################

SIsSRS
R$*^I^I^I^I$: $(is_srs $1 $)
R$@^I^I^I^I$@ YES
R$*^I^I^I^I$@ NO

SReverseSrs
R$*^I^I^I^I$: $1 $>IsSRS $1
R$* NO^I^I^I^I$@ $1
R$* YES^I^I^I^I$@ $(srs2envto $1 $)

LOCAL_RULE_0

# Do we need to reverse SRS address?

R$*^I^I^I^I$: $>ReverseSrs $1
-->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8--



cat -t socketmap.m4
--8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<--

divert(-1)

# Copyright (c) 2004 by Mark Kramer <***@asarian-host.net>
#^IAll rights reserved.
# Copyright (c) 1988, 1993
#^IThe Regents of the University of California. All rights reserved.
#
# By using this file, you agree to the terms and conditions set
# forth in the LICENSE file which can be found at the top level of
# the sendmail distribution.
#
#

divert(0)

VERSIONID(`$Id: socketmap.m4,v 1.0 2004/11/09 13:15:43 mkramer Exp $')

ifdef(`_MAILER_DEFINED_',,`errprint(`*** WARNING: MAILER() should be
before HACK(socketmap)')')

LOCAL_CONFIG

# SRS socket maps

Kreverse_srs socket local:/var/run/socketmapd.sock
Kmake_srs socket local:/var/run/socketmapd.sock

# SRS regex map

Kis_srs regex ^<?SRS[01][-+=].*

MAILER_DEFINITIONS

SEnvFromSMTP
R$*@$=w$*^I$@ $1@$2$3^I^IDon't SRS rewrite local (class w) sending domains.
R$*^I^I$: $(make_srs $1 $)^ISRS rewrite non-local (!class w) sending
domains.

LOCAL_RULESETS

###################################################################
### Local SRS Macros^I^I^I^I^I^I###
###################################################################

SIsSrs
R$*^I^I^I^I$: $(is_srs $1 $)
R$@^I^I^I^I$@ YES
R$*^I^I^I^I$@ NO

SReverseSrs
R$*^I^I^I^I$: $1 $>IsSrs $1
R$* NO^I^I^I^I$@ $1
R$* YES^I^I^I^I$@ $(reverse_srs $1 $)

LOCAL_RULE_0

# Do we need to reverse SRS address?

R$*^I^I^I^I$: $>ReverseSrs $1
-->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8--
--
Grant. . . .
none
2024-03-23 11:26:09 UTC
Permalink
Post by Grant Taylor
According to mailstats, my server has been averaging 15.5 k messages a
day for the last month (10k min and 19k max).  I'm on a small Linode w/
2 GB of memory.  --  This really doesn't make an impact and it's not
like it's a big system.
That is good to hear. I am not processing that much yet, but looking
forward in doing so.

If you like stats, maybe have a look at mailfromd as a milter. I asked
them (Sergey) to add exporter for prometheus, which they did after a
year. Now you can practically log now anything you want.
Grant Taylor
2024-03-23 17:50:27 UTC
Permalink
Post by none
That is good to hear. I am not processing that much yet, but looking
forward in doing so.
:-)
Post by none
If you like stats, maybe have a look at mailfromd as a milter. I asked
them (Sergey) to add exporter for prometheus, which they did after a
year. Now you can practically log now anything you want.
I'm curious what mailfromd offers that I can't get out of mail logs.

I sort of keep an eye on it, but don't actually obsess over things.

I mostly said the numbers to dissuade you from worrying about forking
Perl processes per message.
--
Grant. . . .
none
2024-03-23 12:53:09 UTC
Permalink
Post by Grant Taylor
What I have is based off of the following, which is now available via
Archive.org
Link - SRS integration with sendmail
 -
https://web.archive.org/web/20051221183047/http://srs-socketmap.info/sendmailsrs.htm
Yes that is helpful. I have been reading them already quite a few times.
I am little surprised that this rewriting requires external support. I
thought some functions would be compiled in with sendmail.
Post by Grant Taylor
I have sym-links in /usr/share/sendmail/cf/hack directory pointing to
the m4 files in the /etc/mail/srs directory.
I'm currently using the perlsrs-old.m4.
   HACK(`perlsrs-old')dnl
Both perlsrs.m4 and socketmap.m4 rely on the socketmapd.0.31.pl file
running as a daemon listening on a local Unix socket.  --  I used this
for a while, but abandoned it because I got tired of needing to manually
start it after updates.  I should have written an init script, but c'est
la vie.
So I switched to perlsrs-old.m4 which forks a copy of envfrom2srs.pl or
srs2envto.pl as necessary.
I've never had any problems with the overhead of forking the Perl
processes.  SpamAssassin, ClamAV, and the IMAP daemon take up FAR more
resources than the SRS solution.
I am really surprised there is still so little native support for srs in
sendmail or existing milters. Especially when I see you are already
addressing this since 2004.
Do you know if milters are allowed access to rewrite the envelope?

new Mail::SRS (Secret => $secret, HashLength => 8, AlwaysRewrite => 1);

Does this make a unique envelope every time? I am using a whitelist,
where I can add email addresses. Rewriting constantly with a unique
sender would make this useles.
I don't really get why you even need to hash this, aside from trying to
make the envelope shorter.
Post by Grant Taylor
It looks like line 37 of the perlsrs-old.m4 is what references the class
w map (where local-host-names gets loaded into).  So I would think that
you could create a new class and load contents of a different file into
the class and for reference.
I think I would change this to something like identifying my local ip
ranges/network. I think that is easier to maintain.
This way you already prevent local email from being rewritten.
More efficient would be not to have every envelope send external but
have sendmail already select which ones need to be rewritten.
Another way would be use the results from an earlier done spf test

Seeing this webarchive page also made me think more in general about
this. Eg. with bounces, where should these go. I am not really
maintaining a local mailbox for this (yet). If they should return to the
original sender, would I include possible information that discloses the
forward email address or should I filter this out somehow.

I am also rethinking maybe doing something on host A, the mx servers.
Maybe instead configuring host B, configure A local. And then have some
local rules applied that do the sender rewriting? Forget about DKIM
signing these forwards.

mailLocalAddress: ***@me.com / ***@example.com
mailHost: LOCAL / A.local
mailRoutingAddress: ***@guerrillamail.com
Grant Taylor
2024-03-23 18:09:06 UTC
Permalink
Post by none
Yes that is helpful. I have been reading them already quite a few times.
I am little surprised that this rewriting requires external support. I
thought some functions would be compiled in with sendmail.
Well, pause for a moment and remember how SRS was(n't) received by the
email community at large.

Many poo poo SPF, especially -all, and most people poo poo SRS as a
retroactive hack and evidence that SPF is broken.

I'm from a different camp wherein forwarding an email list are SMTP
terminations and that a different message leaves those entities.
Post by none
I am really surprised there is still so little native support for srs in
sendmail or existing milters. Especially when I see you are already
addressing this since 2004.
I think this is a reflection of what the community thinks of SRS. It
wasn't until the last 3-5 years that people have started to realize that
ya, rewriting sort of is needed after all.
Post by none
Do you know if milters are allowed access to rewrite the envelope?
I don't know. I believe so. I know of a milter that can silently add a
BCC. That's part of the envelope.
Post by none
new Mail::SRS (Secret => $secret, HashLength => 8, AlwaysRewrite => 1);
Does this make a unique envelope every time? I am using a whitelist,
where I can add email addresses. Rewriting constantly with a unique
sender would make this useles.
I don't know. The label on the tin indicates that it would be
re-written. But I suspect that's once per envelope. As such I'd think
that the message would be queued and delivery re-tried using the same
address (for that given envelope) if something like grey listing or
communications failure happened.
Post by none
I don't really get why you even need to hash this, aside from trying to
make the envelope shorter.
My understanding is that the hash offers a modicum of security to
prevent (for some value) someone reversing your SRS mechanism and
sending messages to your server that your server would end up sending
back out as spam. I think that it's mostly anti-abuse / anti-reply.

If I know your secret hash seed I could use that to generate an SRS that
your system would trust, reverse the SRS and pass the message on to the
intended destination as if it originated from your server.
Post by none
I think I would change this to something like identifying my local ip
ranges/network. I think that is easier to maintain.
I think that you are thinking something different.
Post by none
This way you already prevent local email from being rewritten.
I don't think so. The email that originates from my server is using
envelope domains that are authorized to do so from my server. I don't
/need/ to rewrite them. I could rewrite them from <user>@example.net to
<SRS...>@example.net, but that's unnecessary. There's also the
possibility of ending up with a loop if you're not careful how you code
things.
Post by none
More efficient would be not to have every envelope send external but
have sendmail already select which ones need to be rewritten.
That's what the rule I called out using class w does. If the email is
not being delivered locally, then it is being delivered remotely. If
the envelope from isn't us, it needs to be rewritten.
Post by none
Another way would be use the results from an earlier done spf test
That would imply more state and be more complex code. Conversely the
"if the destination isn't local and the source isn't local, then rewrite
the source" logic is relatively simple to do in Sendmail rules.

N.B. that no state about previous tests needs to be referenced.
Especially if the tests are done outside of Sendmail proper via a milter.
Post by none
Seeing this webarchive page also made me think more in general about
this. Eg. with bounces, where should these go. I am not really
maintaining a local mailbox for this (yet).
Bounces end up at the original sender. It's just that the bounce comes
back to your server and your server forwards the bounce to the original
sender.

This is also why there is a seed in the hash, to make sure that only
email that your server rewrites pass the hash test and thus passed
through your server. -- Prevent your server from being used as a relay.
Post by none
If they should return to the original sender, would I include possible
information that discloses the forward email address or should I
filter this out somehow.
That would be an information disclosure leak.

There is also no standard way for this to be disclosed.

What's more, with no standard, there is no software to extract that
non-existent standard and send the bounce directly.

Aside: Do some reading on SRS as it's my understanding that SRS0 vs
SRS1 (or maybe SRS1 vs SRS2 -- I need more caffeine) as a short cut to
avoid some of the rewriting. -- That being said, I don't think I've
ever seen the SRS1 (or SRS2) used in the wild. Usually one set of
rewriting is sufficient for delivery based on what I've seen.
Post by none
I am also rethinking maybe doing something on host A, the mx servers.
Maybe instead configuring host B, configure A local. And then have some
local rules applied that do the sender rewriting? Forget about DKIM
signing these forwards.
My recollection of LDAP routing is that all hosts in the cluster would
consider example.com to be local and that they would know via LDAP
routing, which cluster member hosts which mailboxes.
--
Grant. . . .
none
2024-03-23 23:59:40 UTC
Permalink
Post by Grant Taylor
My understanding is that the hash offers a modicum of security to
prevent (for some value) someone reversing your SRS mechanism and
sending messages to your server that your server would end up sending
back out as spam.  I think that it's mostly anti-abuse / anti-reply.
If I know your secret hash seed I could use that to generate an SRS that
your system would trust, reverse the SRS and pass the message on to the
intended destination as if it originated from your server.
Hmmm, I don't really get this. My spf (and maybe even dkim) are still
applied not?

If I am processing the message

***@gmail.com -> ***@example.com forwarded to ***@guerrillamail.com

then my host B (outgoing) will create a new envelope, something like:

SRS0=HHH=TT=example.org=***@example.com

Any receiving host will still check the same example.com spf, as if it
would be a 'regular' envelope.
Grant Taylor
2024-03-24 04:48:20 UTC
Permalink
Post by none
Hmmm, I don't really get this. My spf (and maybe even dkim) are still
applied not?
Yes.
Post by none
Any receiving host will still check the same example.com spf, as if it
would be a 'regular' envelope.
Yes.

But that's not the spam path I was talking about.

There are fundamentally two SMTP envelopes / paths in the end to end
message delivery path.

Sender sends a message to the forwarder
mail from <***@sender.example>
rcpt to <***@forwarder.example>

Then the forwarder forwards the message and applies SRS.

mail from <srs0=hash=user1=***@forwarder.example>
rcpt to <***@receiver.example>

The catch that is not well understood is that the reverse path works too.

mail from <***@receiver.example@forwarder.example>
rcpt to <srs0=hash=user1=***@forwarder.example>

Your system will then (both) undo the SRS and send the message out (and
do another SRS):

mail from <srs0=hash=user3=***@forwarder.example>
rcpt to <***@sender.example>

SO the forwarded recipient; <***@receiver.example> can use your
forwarding server to send a message to the original sender;
<***@sender.example>.

Or said another way, someone can use your forwarding server's SRS
capability to cause you to send an email on their behalf to whomever
they want to by leveraging your handling of SRS.

A malicious sender can abuse your SRS support to spam recipients. Full
stop.

...

Or at least they could if they knew the seed to your hash.

The seeded hash is what validates SRS messages coming into your server.
Your server will only undo the SRS and forward things on /if/ the
inbound hash validates with the hash that you would generate.

As for SPF, DKIM, and DMARC, none of those matter much because 1)
messages leaving your forwarding server have envelopes that match your
forwarding server and it's SPF record. 2) If you aren't modifying
message that you forward, DKIM will still validate. 3) Malicious
senders can make sure that messages that you would send, or proxy, on
their behalf would pass any SPF, DKIM, and DMARC tests.

The strength of the secret used to seed the hash is what protects your
server's SRS support from becoming a spam spewing proxy.

Does that make sense?
--
Grant. . . .
none
2024-03-24 18:23:29 UTC
Permalink
Post by Grant Taylor
So I switched to perlsrs-old.m4 which forks a copy of envfrom2srs.pl or
srs2envto.pl as necessary.
Ok so I have now a bit of 'test' environment, build an el9 rpm for perl
SRS.

So I need to rewrite ***@gmail.com to ***@example.com in order to have
the email accepted by guerrillamail

***@gmail.com -> ***@example.com forwarded to ***@guerrillamail.com

I assume I can test like this:

[@srs]# perl envfrom2srs.pl ***@gmail.com
SRS0=Q8cgq6jj=K6=gmail.com=test<@REDACTED.>

This fromdomain/forward domain seems to be hard coded

my $fwdomain = 'REDACTED';

I prefer this to stay on the domain that is being forwarded. I like to
process messages like this

***@gmail.com -> ***@example.com forwarded to ***@guerrillamail.com
SRS0=Q8cgq6jj=K6=gmail.com=test<@example.com.>

***@gmail.com -> ***@example2.com forwarded to ***@guerrillamail.com
SRS0=Q8cgq6jj=K6=gmail.com=test<@example2.com.>
Grant Taylor
2024-03-24 18:44:10 UTC
Permalink
Post by none
Ok so I have now a bit of 'test' environment, build an el9 rpm for perl
SRS.
:-)
Post by none
the email accepted by guerrillamail
I don't remember. Probably.
Post by none
This fromdomain/forward domain seems to be hard coded
Yes?

You aren't providing example vs example2 information to the
envfrom2srs.pl script. So it has no knowledge of what to use other than
what is configured in it.
Post by none
I prefer this to stay on the domain that is being forwarded. I like to
process messages like this
Okay.

The scripts weren't written with that functionality in mind.

You may be able to extend the script to take a forwarding source domain
option and modify the rules referencing the maps accordingly.

You could probably also run multiple maps, one for each forwarding
source domain configured therein and intelligently choose which map you use.

I actually used the host's FQDN as the forwarding domain.
--
Grant. . . .
none
2024-03-24 19:51:16 UTC
Permalink
Post by Grant Taylor
 -
https://web.archive.org/web/20051221183047/http://srs-socketmap.info/sendmailsrs.htm
this from the webarchive, was always executing the srs rewriting not?

SEnvFromSMTP
R$+ $: $>PseudoToReal $1 sender/recipient common
R$* :; <@> $@ list:; special case
R$* $: $>MasqSMTP $1 qualify unqual'ed names
R$+ $: $>MasqEnv $1 do masquerading
R$* $: $(make_srs $1 $)
Post by Grant Taylor
The collection of files is basically two versions of very similar
solutions.  I've used both.
I'm currently using the perlsrs-old.m4.
   HACK(`perlsrs-old')dnl
It looks like line 37 of the perlsrs-old.m4 is what references the class
w map (where local-host-names gets loaded into).  So I would think that
you could create a new class and load contents of a different file into
the class and for reference.
:) I am not really experienced with m4 nor sendmail. Could that be
something like modifying this?

define(`confCW_FILE', `@LDAP')dnl
FEATURE(use_cw_file, `LDAP')dnl

Would it not be an easy sendmail hack to only allow messages going out
that have an envelope domain that matches a domain in this map?
Grant Taylor
2024-03-25 00:42:13 UTC
Permalink
Post by none
this from the webarchive, was always executing the srs rewriting not?
SEnvFromSMTP
R$+                     $: $>PseudoToReal $1    sender/recipient common
R$*                     $: $>MasqSMTP $1        qualify unqual'ed names
R$+                     $: $>MasqEnv $1         do masquerading
R$*                     $: $(make_srs $1 $)
I've not looked at what was in the archive in detail in a very long time.

My understanding is that what I saw 15+ years ago and what I'm using
checks to see if the envelope from is a local address or not and that it
only re-writes the envelope if it's not from a local sender.

I assume that the $(make_srs $1 $) is what's doing the rewriting there.
But I believe there was logic elsewhere controlling it.
Post by none
:) I am not really experienced with m4 nor sendmail. Could that be
something like modifying this?
The following are unrelated to SRS.
I believe `confCW_FILE' is how you specify the file to use for defining
the w class which is local host names.

I don't know how the `@LDAP' will fit into that mix. I assume that
there is a way to make that work but I have no idea what it is.
Post by none
FEATURE(use_cw_file, `LDAP')dnl
This tells Sendmail to look for local host names in a file. (The
confCW_FILE option above specifies what file.)
Post by none
Would it not be an easy sendmail hack to only allow messages going out
that have an envelope domain that matches a domain in this map?
I don't know how easy it would be. But I do believe that it should be
possible to do.

N.B. there is a difference in restricting senders to specified domains
vs restricting senders to specified addresses.

The former would still allow ***@example.net to send email as
***@example.net.
--
Grant. . . .
Grant Taylor
2024-03-25 00:43:53 UTC
Permalink
🙂 I am not really experienced with m4 nor sendmail.
I highly recommend that you skim the README files that are in the
Sendmail source tarball. Particularly those in the cf directory.

The following is also likely of some use.

Link - Sendmail 8.12.3 cf/README - Sendmail Configuration Files
- https://www.sendmail.org/~ca/email/doc8.12/cf/m4/
--
Grant. . . .
none
2024-03-23 10:00:28 UTC
Permalink
Post by none
At some point in the future I would like to secure host b more, so
authenticated users can only send out email with their assigned address.
I'm aware that such is done by some MTAs.  I've wondered about doing
that with Sendmail.  But then I realized that users were authenticating,
thus I would have a good idea (but no guarantee) who, or at least which
account, was being used to abuse things.  I've not needed to actually go
down this path (yet).
I think this is a selling point of services like sendgrid and the likes.
There are even banks using such services. So I assume they check this,
otherwise it would be very easy for scammers to send out phishing emails.

Since I am thinking of developing/adding a business to consumer service,
I am getting a little more interested in this.
Grant Taylor
2024-03-23 18:12:43 UTC
Permalink
Post by none
I think this is a selling point of services like sendgrid and the likes.
There are even banks using such services. So I assume they check this,
otherwise it would be very easy for scammers to send out phishing emails.
I think that SendGrid's point of services is that most people don't want
to or can't run a bulk mailing service, at least not properly.

So they outsource such bulk mailing to Email Service Providers (ESPs)
like SendGrid and Mailchimp.

There are also people that want to not have their own email services on
the front line, so they route both outbound and inbound email through an
ESP.

There are also the people that feel the need / obligation to route their
email through specialized ESPs for compliance / legal obligation reasons.
Post by none
Since I am thinking of developing/adding a business to consumer service,
I am getting a little more interested in this.
Good luck to you. -- As in fair water, not luck as in you'll need it.
--
Grant. . . .
none
2024-03-23 10:44:53 UTC
Permalink
Post by Grant Taylor
Do you also have a corresponding REJECT?
Without the REJECT I would expect Sendmail to accept the message as part
of the relay-domains configuration.
Afaik it is currently like this, I have to put something in the access
Post by Grant Taylor
Post by none
host C, LOCAL is not in the spf records. I think external access is
even blocked. I had spammers by passing spam blocking on the mx / host
a and delivering directly to C
SPF is about the connecting host.
As such, GuerrillaMail.com will see host B as the connecting host and
check it's IP against SPF records.
Depending on your configuration, hosts A, B, and C may need to either
have allow list entries or valid SPF information for each other.
I want to prevent as much as possible hosts that are allowed to send out
email.
Grant Taylor
2024-03-23 18:14:16 UTC
Permalink
Post by none
Afaik it is currently like this, I have to put something in the access
Hum.

Maybe we have different default configurations. Sendmail can be
configured a LOT of different ways.
Post by none
I want to prevent as much as possible hosts that are allowed to send out
email.
Understood.
--
Grant. . . .
none
2024-04-09 22:23:45 UTC
Permalink
      receive
       email
         |
         |
         |
         |
         V
  +------------+       +------------+      +------------+
  |     MX     |       |  OUTGOING  |      |     MX     |
  |            +------>|            |----->|            |
  |  accessmap |       |            |      |  EXTERNAL  |
  |            |       |            |      |            |
  +------+-----+       +------------+      +------------+
         |
         |
         V
  +------+-----+
  |    LOCAL   |
  |            |
  |  virtuser  |
  |            |
  +------------+
Hi Grant,

I just wanted to let you know I got this forwarding now working on mx
and do not need to route first to out any more.
I have removed the mailhost from ldap routing.

mailLocalAddress: ***@me.com / ***@example.com
mailHost:
mailRoutingAddress: ***@guerrillamail.com

Currently I am only rewriting the envelope. If I forward to an address
of https://appmaildev.com/en/dkim
The test results show nicely everything green for spf, dkim etc.

I am doing this in the milter available on mx and the only extra
overhead I have, is having to do an mx lookup to determine if the email
is to be delivered external.

Would you know of something I could pass as a macro to the milter that
would show if ldap routing is applied/active? If I know this, I could
limit the amount duplicate dns lookups quite a lot.
Grant Taylor
2024-04-18 03:34:01 UTC
Permalink
Post by none
Hi Grant,
Hi,
Post by none
I just wanted to let you know I got this forwarding now working on mx
and do not need to route first to out any more.
I have removed the mailhost from ldap routing.
Nice work. :-)
Post by none
Would you know of something I could pass as a macro to the milter that
would show if ldap routing is applied/active? If I know this, I could
limit the amount duplicate dns lookups quite a lot.
Sorry, I don't know off hand.

I will say that I would think a local caching recursive name server;
BIND and NSCD come to mind, should be able to mitigate a lot of the
impact on the DNS server and probably speed up subsequent queries on the
local system.
--
Grant. . . .
Loading...