Combining header/body checks into a single action?

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Combining header/body checks into a single action?

Bryan K. Walton-2
Is it possible to combine header/body checks in such a way:

If /^(From|Return-Path):.*\b(user@testdomain\.org)\b/
! /^Message-ID:.*@(testdomain\.org)/
        Reject ...

Essentially, I want to only reject a message if the From/Return-Path
matches a specific email address AND the Message-ID doesn't match the
same domain.  

I've read the backscatter howto.  But in our case, we are receiving
backscatter spam NDRs, where the recipient is a real recipient and the
email server appears to not be forged.  All I know is that the email
server was not OUR email server.

I can't reject on just the email address, because that would block
legitimate NDRs that should come back to the original sender.  And I
obviously cannot block all Message-IDs that don't match our domain, as
that would block almost all incoming mail.  So, I believe I need to
combine the two, if possible.

Thanks,
Bryan
Reply | Threaded
Open this post in threaded view
|

Re: Combining header/body checks into a single action?

Wietse Venema
Bryan K. Walton:
> Is it possible to combine header/body checks in such a way:
>
> If /^(From|Return-Path):.*\b(user@testdomain\.org)\b/
> ! /^Message-ID:.*@(testdomain\.org)/
>       Reject ...

That is documented as NOT POSSIBLE.

   if /pattern/flags

   endif  If the input string matches /pattern/, then match that input
          string against the patterns between if and endif. The if..endif
          can nest.

> Essentially, I want to only reject a message if the From/Return-Path
> matches a specific email address AND the Message-ID doesn't match the
> same domain.  

For complex content filtering strategies you would need to use an
external filter. See http://www.postfix.org/CONTENT_INSPECTION_README.html

> I've read the backscatter howto.  But in our case, we are receiving
> backscatter spam NDRs, where the recipient is a real recipient and the
> email server appears to not be forged.  All I know is that the email
> server was not OUR email server.

If it really is backscatter to a testdomain address, consider
temporarily rejecting NDRs for that address (or the testdomain).

/etc/postfix/main.cf:
    restriction_classes = reject-bounces
    reject-bounces = check_sender_access inline:{{<> = reject}}

    smtpd_recipient_restrictions =
        ...
        reject_unauth_destination
        check_recipient_access inline:{
                { [hidden email] = reject-bounces }
        }

http://www.postfix.orgpostconf.5.html#restriction_classes
http://www.postfix.org/DATABASE_README.html#types

Untested example, requires Postfix 3.0 or later. With earlier Postfix
versions, replace the inline:{a=b} with hash:/etc/postfix/whatever,
with /etc/postfix/whatever containing "a b".

> I can't reject on just the email address, because that would block
> legitimate NDRs that should come back to the original sender.  And I
> obviously cannot block all Message-IDs that don't match our domain, as
> that would block almost all incoming mail.  So, I believe I need to
> combine the two, if possible.
>
> Thanks,
> Bryan
>
Reply | Threaded
Open this post in threaded view
|

Re: Combining header/body checks into a single action?

Bryan K. Walton-2
On Mon, Dec 24, 2018 at 09:02:53AM -0500, Wietse Venema wrote:

> > Is it possible to combine header/body checks in such a way:
> >
> > If /^(From|Return-Path):.*\b(user@testdomain\.org)\b/
> > ! /^Message-ID:.*@(testdomain\.org)/
> >       Reject ...
>
> That is documented as NOT POSSIBLE.
>
>    if /pattern/flags
>
>    endif  If the input string matches /pattern/, then match that input
>           string against the patterns between if and endif. The if..endif
>           can nest.

Thank you for your reply, Wietse, about this not being possible.

However, I am slightly confused about the documentation saying that
if..endif is allowed to nest.  Does this mean that I could write
something like the following:

if /pattern/flags
        if !/pattern/flags
        endif
endif

If so, I would think I could write a nested if..endif that did what I
wanted.  The first if..endif could check to see if the From/Return Path
matched our domain. If it did, wouldn't it then step into the internal
if..endif, where I could check to see if the message ID was ours?  If
not, I could tell Postfix to then reject the message.

Or am I misunderstanding what is meant by "the if..endif can nest"?

Thanks,
Bryan
Reply | Threaded
Open this post in threaded view
|

Re: Combining header/body checks into a single action?

Viktor Dukhovni
On Thu, Dec 27, 2018 at 08:58:46AM -0600, Bryan K. Walton wrote:

> However, I am slightly confused about the documentation saying that
> if..endif is allowed to nest.  Does this mean that I could write
> something like the following:
>
> if /pattern/flags
> if !/pattern/flags
> endif
> endif

The checks are applied to *ONE LOGICAL HEADER AT A TIME*.
So while the patterns can nest, they are matching the
content of a *single* logical header line, not the entire
message header.

    For each header line "x":
        For each rule "r":
                if ("x" ~ "r"):
                        perform rule action

When "r" is a sequence of nested "if" statments "r1" .. "rN", the
meanining of "x" ~ "r" is:

        if  "x" ~ "r1"
        and "x" ~ "r2"
        ...
        and "x" ~ "rN"
                perform rule action

but, note that all the rules see the same input "x", which is still
just a single logical header line.

--
        Viktor.
Reply | Threaded
Open this post in threaded view
|

Re: Combining header/body checks into a single action?

Wietse Venema
In reply to this post by Bryan K. Walton-2
Bryan K. Walton:

> On Mon, Dec 24, 2018 at 09:02:53AM -0500, Wietse Venema wrote:
> > > Is it possible to combine header/body checks in such a way:
> > >
> > > If /^(From|Return-Path):.*\b(user@testdomain\.org)\b/
> > > ! /^Message-ID:.*@(testdomain\.org)/
> > >       Reject ...
> >
> > That is documented as NOT POSSIBLE.
> >
> >    if /pattern/flags
> >
> >    endif  If the input string matches /pattern/, then match that input
> >           string against the patterns between if and endif. The if..endif
> >           can nest.
>
> Thank you for your reply, Wietse, about this not being possible.
>
> However, I am slightly confused about the documentation saying that
> if..endif is allowed to nest.  Does this mean that I could write
> something like the following:
>
> if1 /pattern1/flags
> if2 !/pattern2/flags
> endif2
> endif1

If the input string matches /pattern1/, then match THAT INPUT STRING
against the patterns between the if1 and endif1.

Therefore, match THAT INPUT STRING against if2..endif2.

        Wietse
Reply | Threaded
Open this post in threaded view
|

Re: Combining header/body checks into a single action?

Bryan K. Walton-2
In reply to this post by Viktor Dukhovni
On Thu, Dec 27, 2018 at 10:07:46AM -0500, Viktor Dukhovni wrote:
> The checks are applied to *ONE LOGICAL HEADER AT A TIME*.
> So while the patterns can nest, they are matching the
> content of a *single* logical header line, not the entire
> message header.

Thanks, Viktor and Wietse.

I understand this now.

-Bryan