Calling a SMTP Milter before local_recipient_maps

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

Calling a SMTP Milter before local_recipient_maps

Fred Morris
By default, local_recipient_maps looks something like this, and to be
(locally) delivered something must have an envelope recipient in here.
In fact, SMTP milters are not called until after this check is made:

    local_recipient_maps = proxy:unix:passwd.byname $alias_maps

I want to call a milter as a "bump in the wire" before this check to
potentially alter local recipients prior to them ricocheting off of all
of that shininess. I've read through
http://www.postfix.org/SMTPD_PROXY_README.html and it talks about
milters but the topology shown doesn't look right:

**SHOWN**

net -> Postfix -> filter -> Postfix

**DESIRED**

net -> Postfix -> Postfix
          ^          ^
          |          |
          v          v
       milter     local_recip_maps

If it can't be done with Postfix, is there a milter I could chain to
which does the equivalent of the built in local_recipient_maps?

The objective is to preserve the ability to reject recipients during the
SMTP conversation.

Thanks in advance...

--

Fred Morris

Reply | Threaded
Open this post in threaded view
|

Re: Calling a SMTP Milter before local_recipient_maps

Wietse Venema
Fred Morris:
> By default, local_recipient_maps looks something like this, and to be
> (locally) delivered something must have an envelope recipient in here.
> In fact, SMTP milters are not called until after this check is made:
>
>     local_recipient_maps = proxy:unix:passwd.byname $alias_maps
>
> I want to call a milter as a "bump in the wire" before this check to
> potentially alter local recipients prior to them ricocheting off of all
> of that shininess.

Why use a milter? Why not tweak local_recipient_maps lookups?

You should be able to use a milter before the proxy filter to BLOCK
a recipient that Postfix would have accepted (the opposite, using
a milter to ACCEPT a recipient that Postfix would reject makes no
sense).

net - postfix smtpd - proxy filter - postfix smtpd - cleanup  - queue
        milter

But this milter won't be able to process header, body, or end-of-body
events. Only the events associated with SMTP commands.

        Wietse
Reply | Threaded
Open this post in threaded view
|

Re: Calling a SMTP Milter before local_recipient_maps

Viktor Dukhovni
In reply to this post by Fred Morris
On Fri, Jan 24, 2020 at 10:04:26AM -0800, Fred Morris wrote:

> I want to call a milter as a "bump in the wire" before this check to
> potentially alter local recipients prior to them ricocheting off of all
> of that shininess.
>
> net -> Postfix -> Postfix
>           ^          ^
>           |          |
>           v          v
>        milter     local_recip_maps

Milters get to process each SMTP command as it comes in, however
smtpd_recipient_restrictions are processed before handing off "RCPT TO"
to the milter.  So the milter cannot modify the recipient address before
local_recipient_maps checks happen.

You can use socketmap tables in local_recipient_maps if for some reason
you want to apply some non-trivial computation to the address in order
to determine whether it is valid.

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

Fast forwarding Milters Re: Calling a SMTP Milter before local_recipient_maps

Fred Morris
I apologize for my boundless optimism. I think the "it can't be done"
mantra is really "it's always been this way".

I understand that there is an impedance mismatch between the SMTP and
milter protocols in that a milter is allowed to inspect and even reject
an address supplied via SMTP RECV, but it is not allowed to edit it
until the entire body has been processed (EOB/EOM).

I see flags (SMFIP_NO*, SMFIP_NR_*) expressly intended to suppress large
parts of the protocol exchange. Seems to me that for SMTP MAIL and RECV
events at least, it is possible to use these flags to skip basically all
of the intervening protocol goop between e.g. RECV and EOB/EOM (this
works, PCAP of POC on request).

I see no reason that a milter executor cannot fast forward to EOB/EOM
based on these flags (seems to occur in milters when they're deciding
what to ack or not); and that therefore milter edits to e.g. recipients
in EOB/EOM can take place in the context of the SMTP RECV; and that a
milter not desiring of this behavior can request intervening data /
handshakes to disable this behavior, at least until an
"allow_fast_forward" flag is decided upon (if ever).

On 1/24/20 10:49 AM, Viktor Dukhovni wrote:

> On Fri, Jan 24, 2020 at 10:04:26AM -0800, Fred Morris wrote:
>
>> I want to call a milter as a "bump in the wire" before this check to
>> potentially alter local recipients prior to them ricocheting off of all
>> of that shininess.
>>
>> net -> Postfix -> Postfix
>>           ^          ^
>>           |          |
>>           v          v
>>        milter     local_recip_maps
> Milters get to process each SMTP command as it comes in, however
> smtpd_recipient_restrictions are processed before handing off "RCPT TO"
> to the milter.  So the milter cannot modify the recipient address before
> local_recipient_maps checks happen.
>
> You can use socketmap tables in local_recipient_maps if for some reason
> you want to apply some non-trivial computation to the address in order
> to determine whether it is valid.

At least privately, the milter camp has provided aid and comfort.
Whereas, nothing around domain socket support has risen above the usual
background noise of people stating opinions about open source software
they do not write or use; zero, nothing.

Hence, milter! (At the moment I have no plans to write a milter executor
and nobody has offered money, although I'd be happy to provide aid and
comfort for anyone wanting to implement fast forwarding). Personally I'd
rather disable the security checks preventing TCP tables in local(8) and
recompile, but that's just my opinion. (I'll save my quibbles with
Postfix's implementation of VRFY for another day.)

--

Fred Morris


Reply | Threaded
Open this post in threaded view
|

Re: Fast forwarding Milters Re: Calling a SMTP Milter before local_recipient_maps

Wietse Venema
Fred Morris:
> I apologize for my boundless optimism. I think the "it can't be done"
> mantra is really "it's always been this way".
>
> I understand that there is an impedance mismatch between the SMTP and
> milter protocols in that a milter is allowed to inspect and even reject
> an address supplied via SMTP RECV, but it is not allowed to edit it
> until the entire body has been processed (EOB/EOM).

You are describing something that is controlled by entities outside
of Postfix.

> I see flags (SMFIP_NO*, SMFIP_NR_*) expressly intended to suppress large
> parts of the protocol exchange. Seems to me that for SMTP MAIL and RECV
> events at least, it is possible to use these flags to skip basically all
> of the intervening protocol goop between e.g. RECV and EOB/EOM (this
> works, PCAP of POC on request).

Always good to know this (still) works as promised.

> I see no reason that a milter executor cannot fast forward to EOB/EOM
> based on these flags (seems to occur in milters when they're deciding
> what to ack or not); and that therefore milter edits to e.g. recipients
> in EOB/EOM can take place in the context of the SMTP RECV; and that a

The Milter protocol as defined supports envelope and content
modifications after SMTP END-OF-DATA. In the case of Postfix, this
means that the cleanup daemon makes the changes AFTER the entire
envelope and message are stored in a queue file.

> milter not desiring of this behavior can request intervening data /
> handshakes to disable this behavior, at least until an
> "allow_fast_forward" flag is decided upon (if ever).

It requires a completely different Postfix implementation where the
smtpd daemon receives the sender or recipient change request and
makes the change in-memory, instead of the cleanup daemon receiving
the change request and making the change in-file. Although technically
possible, such a parallel implementation would be a very costly
optimization for a really rare use case.

Asking is cheap. Even explaining why it is a bad idea costs time.

        Wietse