Postfix - blocking by From rather than sender

I have a ton of incoming spam that masquerades as being sent by me, but has a sender at some arbitrary spammer domain. e.g.

Return-Path: <[email protected]>
... (stuff elided, etc.)
Received: from [static-93.0.72.177-ttvi.com.br] (unknown [177.72.0.158])
    (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))
    (No client certificate requested)
    (Authenticated sender: [email protected])
    by Server22.lejj.com (Postfix) with ESMTPSA id B527943151
...
To: [email protected]
From: <[email protected]>

The sender to postfix is [email protected], but by the time it's handed off to Cyrus-IMAP, it appears to be sent by me, and that means it's deposited into my recognized sender inbox.

I'd like to block all incoming mail from my domain (outgoing uses TLS + SMTP AUTH, and bypasses the checks, so I'm not worried about blocking myself), but since the sender address is not from my domain, I can't do that using sender rejection rules or SPF - these act on aiuw.com, not example.com.

I'm guessing there's no way to make Postfix handle the From line as part of the envelope information. Is that right, or am I missing something?

If not, what about a filter between Postfix and Cyrus-IMAP that could capture both the sender and From addresses and reject mismatches? Or, finally, a way of checking the sender address in a Sieve script, though I think that would get ugly quickly.

Apologies if this is a duplicate. I found several hits, but everything I saw was based on envelope sender, not From.


Solution 1:

----- START EDIT (2021-12-04) -----

While my previous answer does work, it will be better if you set up OpenDKIM and OpenDMARC, and give your domain a strict DMARC policy which instructs everyone (as well as yourself) to reject all "fraudulent" mail. That way, you will prevent other people from impersonating you and ensure the same protection from others with strict DMARC policies.

This will stop fraudulent From: headers because DKIM is a thing which cryptographically signs specific header values and the message body, with the pubkey being located in DNS, ensuring the message content does indeed come from the specified domain.

Even without DKIM, you can set a DMARC policy which tells everyone that the From: header should also follow SPF checks, and use the OpenDMARC milter to enforce that yourself.

Relevant reading:

https://mxtoolbox.com/dmarc/details/dmarc-tags

https://petermolnar.net/article/howto-spf-dkim-dmarc-postfix/

https://www.cyberpunk.rs/dmarc-postfix-setup

http://www.trusteddomain.org/opendmarc/opendmarc.conf.5.html

http://www.opendkim.org/opendkim.conf.5.html

Note that if your postfix runs in chroot mode (as is apparantly the case in ubuntu) the unix sockets must be located in /var/spool/postfix

----- END EDIT (2021-12-04) -----

I've been doing some research on this myself, and I found some ways to attack this from the "pre-inbox" angle.

If your receiving SMTP server is the same servers users submit their outgoing mail to, then first, we've got the header_checks postfix config. If we set it to pcre:/etc/postfix/header_checks, It'll check each header line against the regexps in that file. Here's what I in that file:

/^(From|Sender|Reply-To)\: .*\@domain1\.com/ REJECT stop impersonating me
/^(From|Sender|Reply-To)\: .*\@domain2\.com/ REJECT stop impersonating me

Since my SMTP server receives mail for domain1.com and domain2.com, it'll reject all incoming mail with those domains. Though you only want to do this for the SMTP port, (25) not the submission port (587) otherwise it'll prevent legitimate use of your domain. To do this, edit your master.cf, and add -o header_checks=regexp:/etc/postfix/header_checks under the line which starts with smtp. You can also specify a different header_checks file under your submission port settings to enforce different header rules for authenticated users.

The main issue with header_checks is that it only checks one header at a time. Another solution is to use content_filter, which looks at the message as a whole. I first discovered this while attempting to mitigate against From: header fraud for all incoming mail, which lead me to this neat bash script. Though you can use this as a starting point to create any filters of your choosing, as being able to intelligently examine the entire e-mail before delivery (assuming its contents aren't encrypted) is a very powerful thing.

Hope my information helps, perhaps together we can create the perfect fraud-rejection tool :)

Solution 2:

I think I can finally answer my own question. I still wish I could capture both the envelope sender and message sender to reject the message in the SMTP transaction, and if anyone can suggest a better fix I'd appreciate it.

However, both envelope and message senders are available to sieve, so there's a way to drop the incoming spam:

require ["envelope", "fileinto"];

if address :domain "From" "example.org" {
   if not envelope :domain "From" "example.org" {
      fileinto "Trash";
      stop;
   }
}

So if email claims to be from my domain, but the envelope address is not my domain, it's dropped.

Documentation on envelope I used: https://support.tigertech.net/sieve