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?


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:

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

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

    localhost      local_only      local_only
    /* check bash#postconf mynetworks for full list of your networks */

    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.


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,

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 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).
  • Hi, I think this is exactly what I was looking for. I tried to understand it from the postfix documentation. Can you please explain me how the mail flow is going through this setting. Is it also possible to combine it with my mysql:/etc/postfix/mysql-virtual_recipient.cf database? – Bene Apr 26 '16 at 17:50
  • Your mysql:/etc/postfix/mysql-virtual_recipient.cf is there. Nothing changed. I'll edit my post to explain mail flow. – Darigaaz Apr 26 '16 at 18:11
  • Great explanation thank you. One last question, can I just do something like this: local_only = check_recipient_access mysql:/etc/postfix/mysql-virtual_recipient.cf, reject... should work right? – Bene Apr 26 '16 at 18:49
  • You didnt show us /etc/postfix/mysql-virtual_recipient.cf file (query part), but i guess its just simple check like query = SELECT access FROM virtual_recipient WHERE source='%s'. Are you interested in "reject" part? Like "if client is localhost and the recipient is NOT in database - reject". Yeah, it will do. But as i said, your spam filter may not play nice with it. – Darigaaz Apr 26 '16 at 19:51
  • I just tried the permit_auth_destination, however I removed the permit_mynetworks first in order to test what exactly was going wrong with antispam last time. I just realized that it has no effect when I remove permit_mynetworks from smtpd_receipient_restrictions... I can still send emails unauthenticated from localhost... Is there anything else to be checked? – Bene Apr 26 '16 at 20:36

One option would be to use iptables to prevent those users from being able to connect to localhost on port 25. For example:

iptables -A OUTPUT -p tcp -d --dport 25 -m owner --uid-owner user1 -j REJECT
iptables -A OUTPUT -p tcp -d --dport 25 -m owner --uid-owner user2 -j REJECT

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.