Postfix allow localhost only local users

localhostpostfixsmtpsmtpd

I have a little problem. I am offering some clients access to my server in order to execute own scripts (of course in their own chroot environment, etc…). The problem which occured today: Some people gain telnet access to localhost on port 25 and are sending emails out in the world which is nearly an open relay 🙁

I am using postfix and it also requires authentication:

smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, check_recipient_access mysql:/etc/postfix/mysql-virtual_recipient.cf, reject_unauth_destination

But local scripts obviously do not need to be sasl authenticated. If a remove localhost from permit_mynetworks, some antispam routines are not working anymore…

So how to configure postfix in order to allow localhost delivering mails locally but not externally without authentication?

Any suggestions?

Best Answer

So your antispam routines are using localhost, and bad people are using localhost and postfix cant tell the difference.

Ban bad people or remove localhost from trusted network (permit_mynetworks) and configure your antispam to use something else. Or allow your antispam with smtpd_client_restrictions check_ccert_access.

Back to your question. You are asking for something like this:

/etc/postfix/main.cf:
    smtpd_recipient_restrictions =
        /* replace permit_mynetworks with the next line */ 
        check_client_access hash:/etc/postfix/client_access,
        /* your other stuff */
        permit_sasl_authenticated,
        check_recipient_access mysql:/etc/postfix/mysql-virtual_recipient.cf,
        reject_unauth_destination

    smtpd_restriction_classes = local_only
    local_only = 
        check_recipient_access hash:/etc/postfix/local_domains, reject

/etc/postfix/client_access:
    localhost      local_only
    127.0.0.1      local_only
    /* check bash#postconf mynetworks for full list of your networks */

/etc/postfix/local_domains:
    this.domain     OK      matches this.domain and subdomains
    that.domain     OK      matches that.domain and subdomains

But propably it wont work, because your antispam reinjects mail with external recipients. But it depends.

Give us more info about your antispam tools and may be we will able to help.

UDP:

Can you please explain me how the mail flow is going through this setting.

Cant explain restriction classes better then official docs.

Postfix restriction classes

The Postfix SMTP server supports access restrictions such as reject_rbl_client or reject_unknown_client_hostname on the right-hand side of SMTP server access(5) tables. This allows you to implement different junk mail restrictions for different clients or users.

Having to specify lists of access restrictions for every recipient becomes tedious quickly. Postfix restriction classes allow you to give easy-to-remember names to groups of UCE restrictions (such as "permissive", "restrictive", and so on).

The real reason for the existence of Postfix restriction classes is more mundane: you can't specify a lookup table on the right-hand side of a Postfix access table. This is because Postfix needs to open lookup tables ahead of time, but the reader probably does not care about these low-level details.

We define our restriction class local_only with smtpd_restriction_classes = local_only. And

local_only = 
        check_recipient_access hash:/etc/postfix/local_domains,
        reject

says "whenever this class is checked check check_recipient_access (Search the specified access(5) database for the resolved RCPT TO address, domain, parent domains, or localpart@, and execute the corresponding action.) first and reject mail otherwise. And local_domains file says "if its this.domain pass the check, if its that.domain pass the check".

But we do not want to apply this restriction class to ALL emails. We want to apply it when sending host is localhost and remove permit_mynetworks rule. To do so we add check_client_access hash:/etc/postfix/client_access ( Search the specified access database for the client hostname, parent domains, client IP address, or networks obtained by stripping least significant octets. See the access(5) manual page for details.) to smtpd_recipient_restrictions. It says to check /etc/postfix/client_access file and if its localhost apply local_only restriction. It is exactly what we want to do.

Hope it helps.

The mail flow is:

  • Mail arrives
  • loop through smtpd_recipient_restrictions
    • check_client_access (if sending host is localhost apply local_only restriction class)
      • now check_recipient_access (if recipient RCPT TO address, domain, parent domains, or localpart@ is "this.domain" or "that.domain" then accept this mail) (skip futher checks)
      • otherwise reject
    • otherwise continue with permit_sasl_authenticated, check_recipient_access mysql:/etc/postfix/mysql-virtual_recipient.cf, etc

UPD2 I just found another option for smtpd_recipient_restrictions (and other self defined classes) you may be interested in

permit_auth_destination

Permit the request when one of the following is true:

  • Postfix is mail forwarder: the resolved RCPT TO domain matches $relay_domains or a subdomain thereof, and the address contains no sender-specified routing (user@elsewhere@domain),
  • Postfix is the final destination: the resolved RCPT TO domain matches $mydestination, $inet_interfaces, $proxy_interfaces, $virtual_alias_domains, or $virtual_mailbox_domains, and the address contains no sender-specified routing (user@elsewhere@domain).