Score:0

postfix: send mail through milter only if authenticated?

np flag

Is there a way with Postfix to send mail through a milter only if you are authenticated?

For instance, if you are not authenticated, I'm hoping to have the effect of

smtpd_milters = inet:localhost:8891
non_smtpd_milters = inet:localhost:8891

and if you are authenticated, I'm hoping to have the effect of

smtpd_milters = inet:localhost:8891,inet:localhost:7357
non_smtpd_milters = inet:localhost:8891,inet:localhost:7357

Thanks!

Nikita Kipriyanov avatar
za flag
No. What do you want to achieve with this? Anyway, the segregation must be intergrated into milter itself. Postfix sends to milter authentication information, so the second milter should itself check if the request was for the authenticated user and enable itself.
etnguyen03 avatar
np flag
Essentially, I need to be able to receive mail that ClamAV thinks is infected (and am aware of the risks of doing this), but block mail from being sent that is infected.
Score:3
fr flag
anx

Not precisely what you ask for, but usually sufficient for common use cases: Configure separate ports, one where authentication is never allowed, and one where it is required. This likely already matches your usage: MUAs submitting mail to port 465, always authenticating - other servers submitting mail to port 25, never authenticating.

Then you can configure different milter lists for each port. Then, your extra milter will only be processing authenticated submissions - because only those are accepted at the port the milter is attached to.

In postfix, you can easily do so by attaching -o options to the relevant service definitions in the master.cf file.

My example defines the lists of milters in main.cf, and then references those from master.cf:

# in main.cf:
my_auth_milters = inet:localhost:8891,inet:localhost:7357
my_unauth_milters = inet:localhost:8891

# in master.cf
smtp inet [..] smtpd
 -o smtpd_sasl_auth_enable=no
 -o smtpd_milters=$my_unauth_milters
 -o non_smtpd_milters=$my_unauth_milters

smtps inet [..] smtpd
[..]
 -o smtpd_sasl_auth_enable=yes
 -o smtpd_[..]_restrictions=permit_sasl_authenticated,reject
 -o smtpd_milters=$my_auth_milters
 -o non_smtpd_milters=$my_auth_milters
[..]

I added smtpd_[..]_restrictions as a reminder to modify (replacing without checking might override intentional restrictions!) some restriction set for those ports to require authentication, if not already configured that way.

Score:2
za flag

It is impossible to do directly as you presented it in the question. The only conditional milter invocation that is preset in Postfix is checking the source IP address.

However, by splitting the pipelines for the "reception" path and the "submission" path you can make this possible. I'd recommend to do this regardless of milter settings, because such setup is much easier to manage. Effectively you do this in the following way:

The smtpd service on the port tcp/25 should be the inter-server only service which should not support authentication. It is only for remote servers to deliver mail to you. It should not have the second milter.

The smtpd service on the port tcp/587 should be the dedicated submission service. It must enable authentication and only should relay mail for authenticated users. It should include both milters. The default variant of master.cf includes the definition of this service, it is just commented out, you need to uncomment it and add your milters configuration override:

submission inet n       -       y       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_tls_auth_only=yes
  -o smtpd_reject_unlisted_recipient=no
  -o smtpd_client_restrictions=$mua_client_restrictions
  -o smtpd_helo_restrictions=$mua_helo_restrictions
  -o smtpd_sender_restrictions=$mua_sender_restrictions
  -o smtpd_recipient_restrictions=
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING
  -o smtpd_milters=$mua_milters

(the last line is the override added for your case. Notice there must be no spaces around "="!).

In main.cf you need to define those four variables; the most interesting is the last one:

smtpd_milters = inet:localhost:8891
mua_milters = inet:localhost:8891,inet:localhost:7357
non_smtpd_milters = $mua_milters

Now, the default smtpd service will use the first setting, while submission service will use the second variant.

There is no reason to override the setting for non-smtpd milters in submission service, because it is smtpd service which doesn't use that setting. Non-smtpd milters are only invoked for mail injected without using SMTP, e.g. sent locally using the sendmail local command, so in general they should be regarded just like authenticated clients. This is why I set it to the same value as for MUAs.

Finally, have all MUAs (Thunderbird, RoundCube and so on) to use ESMTP on port 587 for mail submission. The configuration as it is defined above requires the use of STARTTLS encryption, so you probably also want to use a globally trusted certificate from e.g. Let's Encrypt with Postfix.

I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.