Recommended postfix tuning for Plesk 10+

If you’re building Plesk 10+ servers for shared hosting, here are some useful changes you can make, and some useful parameters you can set, specific to Postfix, and an explanation of why they’re useful.  The characteristic that is most likely to cause you grief on a shared hosting server is if it has a lot of IP-based domains rather than name-based domains sharing an IP; so these parameters are much more important if you are running an ecommerce server, since sites that have their own SSL cert are going to have their own IP and that means you could end up with a server having hundreds of IP addresses.  When you have that type of setup, you’re going to be bombarded endlessly by script kiddies attacking port 587 for smtp authentication because they’re going to scan one IP after another, or perhaps even several IP’s simultaneously, not realizing it’s all the same server.

  • smtpd_client_connection_count_limit – This value controls how many concurrent incoming connections one specific remote IP can make to services handled by the ‘smtpd’ command; i.e. things defined in the /etc/postfix/master.cf file that have smtpd listed as the 8th paramter, which typically on a Plesk server would be smtp (port 25), smtps (port 465) and submission (port 587).

    The default for this is 50, which is half the default process count limit of 100.  I feel like this is way too high for a typical Plesk web hosting server.  You most likely won’t have more than 300 or so domains on a server since Plesk seems to grind to a halt and cause outages from rebuilding configs, etc. when domains are added and removed if you go past that point.  Since we’re not talking about thousands of domains per server, the chance of a legit big mail provider needing to deliver 50 emails to your server simultaneously is going to be pretty low.  Additionally, the chances of a spammer or script kiddie making 50+ simultaneous connections is high, and if you allow just one IP to do that, you’ve allowed one spammer/script kiddie to consume half your process limit and are that much closer to letting them deny service to your legit customers.

    So, with that being the case, I like to set the default for this value down to 20:
    echo 'smtpd_client_connection_count_limit = 20' >> /etc/postfix/main.cf
    

    Keep in mind that this limit does NOT apply to networks listed in the postfix ‘mynetworks’ variable, so setting this down to 20 does not affect your customers’ websites from being able to connect to ‘localhost’ or 127.0.0.1 with a high rate of concurrency, such as for sending email blasts from web-based software.  To confirm Plesk has set this up correctly, just type “postconf -n | grep mynetworks”; the postconf -n command prints all non-default variables.

    Additionally, since this value applies to any service calling the ‘smtpd’ program, your legit users connecting to port 587 for outbound authenticated email also must abide by this limit.  That being the case, I like to limit that even more in most cases because the submission port is often targeted by script kiddies trying to brute force your customers’ email address passwords via smtp authentication testing.  It is not uncommon to find your submission port being beat up by these connections; just grep your /usr/local/psa/var/log/maillog for ‘concurrency limit’ and you’ll probably see things like this:

    Jul 20 06:28:40 server1 postfix/smtpd[1767]: warning: Connection concurrency limit exceeded: 51 from unknown[142.0.41.169] for service submission

    I prefer to set the value down to 10 just for the submission port.  Before I tell you how to do that, there are a few reasons you would not want to do this.  If you allow your customers to do email blasts through your server using software on their computer, that could result in high concurrency legit connections.  In fact, you may even want to implement the above 20 connection limit on smtp and then intentionally raise the submission limit back to 50.  A second reason would be if your server is serving a customer who has a large office; chances are in that case they’ll be doing NAT so all the employees in the office will appear to be coming from the same IP and if there’s a chance more than 10 could be sending at the same time, they may hit the concurrency limit.  If neither of those are factors, here’s the change you need to make; find this line in the /etc/postfix/master.cf file:

    submission inet n - n - - smtpd -o smtpd_enforce_tls=yes -o smtpd_tls_security_level=encrypt -o smtpd_sasl_auth_enable=yes -o smtpd_client_restrictions=permit_sasl_authenticated,reject -o smtpd_sender_restrictions=

    Change it to:

    submission inet n - n - - smtpd -o smtpd_client_connection_count_limit=10 -o smtpd_enforce_tls=yes -o smtpd_tls_security_level=encrypt -o smtpd_sasl_auth_enable=yes -o smtpd_client_restrictions=permit_sasl_authenticated,reject -o smtpd_sender_restrictions=

    Now you’ve successfully dropped your SMTP concurrency to 20 and customer concurrency to 10.

  • smtpd_sasl_authenticated_header – This value does just one thing; adds a string to the first received header of the message that logs which user sent it if it was sent via smtp/submission with smtp authentication.  If you view headers on a message that was sent, it will look like this:
    Received: from OfficePC (static-102-0-2-1.lsanca.fios.verizon.net [192.0.2.1])
            (Authenticated sender: sales@sender-domain.com)
            by server1.hosting-company.com (Postfix) with ESMTPA id C91E51A6B42
            for <recipient@receiving-domain.com>; Fri, 19 Jul 2013 13:10:05 -0400 (EDT)
    

    To implement, just run:

    echo 'smtpd_sasl_authenticated_header = yes' >> /etc/postfix/main.cf
  • maximal_queue_lifetime – This defines how long Postfix will keep attempting to deliver a particular message before bouncing it back to the recipient.  The default is a waaaaaay too long value of five days.  This means if your customer sends a message to someone whose domain is down, hosting broken in a refusing connections kind of way, has a spam filter issuing temporary deferrals, etc., they won’t know for five days that their message never made it.  I think one day is a good value for a web hosting server.  To implement, run:
    echo 'maximal_queue_lifetime = 1d' >> /etc/postfix/main.cf
  • default_process_limit – This defines how many postfix processes can be active at any given point.  The default is 100.  On a shared hosting server with lots of IP addresses, I’ve found 100 to be far too low.  If you have a lot of IP’s, you’re going to get bombarded by script kiddies and spammers chewing up 20, or even 50 (the default) SMTP and submission connections at a time, and those consume that number of processes.  So even if you’ve scaled it down to 20, you’re still only going to handle five spammers before hitting the limit and denying legit customers service.  I bump this up to 200 or 250 on big servers:
    echo 'default_process_limit = 200' >> /etc/postfix/main.cf

    You can check to see if this is an issue on your servers by: “grep STRESS /usr/local/psa/var/log/maillog” If you’re hitting the limit, you’ll see log entries that look like:

    Jul 20 06:28:32 server1 postfix/master[31340]: warning: see http://www.postfix.org/STRESS_README.html for examples of stress-adapting configuration settings

  • smtpd_enforce_tls and smtpd_tls_security_level – By default, Plesk puts the following in the /etc/postfix/matser.cf file for implementing submission (port 587) smtp service:
    submission inet n - n - - smtpd -o smtpd_enforce_tls=yes -o smtpd_tls_security_level=encrypt -o smtpd_sasl_auth_enable=yes -o smtpd_client_restrictions=permit_sasl_authenticated,reject -o smtpd_sender_restrictions=

    In a web hosting operation, that will often cause problems.  Yes it is nice to force good security practices upon people, but in reality, the support burden of walking each of your end users through configuring their email software to use TLS can be quite large.  I prefer to make extensive documentation available to customers on how to enable TLS, offer support for enabling it is requested, make it abundantly clear in their setup documents that come with their hosting account that they should do this and list all the reasons why, but then on the server make TLS optional on port 587.  To make it optional, change that above line to smtpd_enforce_tls=no and smtpd_tls_security_level=may

  • smtpd_client_restrictions – This configuration option defines restrictions on who can connect to your smtp ports; the Postfix default value is none, meaning anyone can connect.  Parallels chose to make use of this setting in two ways with Plesk.  The first; in your /etc/postfix/master.cf file you’ll find:
    submission inet n - n - - smtpd -o smtpd_enforce_tls=yes -o smtpd_tls_security_level=encrypt -o smtpd_sasl_auth_enable=yes -o smtpd_client_restrictions=permit_sasl_authenticated,reject -o smtpd_sender_restrictions=

    This one is fine; it basically just means that on the submission port, only authenticated emails will be accepted, anything else will be rejected.  Where we run into a problem is in the /etc/postfix/main.cf file.  In that file they have:

    smtpd_client_restrictions = permit_mynetworks

    That by itself is fine.  It means anyone can connect, and the IP addresses and ranges listed in the variable ‘mynetworks’ (shown by postconf -n | grep mynetworks) can relay mail; i.e. just the local server can relay typically.  Where you run into a problem is if you choose to configure Realtime Blackhole List’s (RBL’s) on your server as an anti-spam measure.  If you do that, you’ll end up with a line that looks something like this:

    smtpd_client_restrictions = permit_mynetworks, reject_rbl_client bl.spamcop.net, reject_rbl_client zen.spamhaus.org

    On the surface you’d think that is fine.  You’re still letting your server relay through itself and you’re rejecting service to blacklisted servers.  Well what makes the above stupid is the fact that even authenticated users’ connections are rejected in the above, so if one of your own customers has an issue and gets blacklisted, now they’re not going to be able to even send you a support request about it via email, and people get blacklisted all the time for real issues and non-real issues.  For example, perhaps a customer simply gets an IP address from their ISP that a spammer was on four hours earlier; now they’re blocked from sending email through their account with you.  To fix this, change the line to the following:

    smtpd_client_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_rbl_client bl.spamcop.net, reject_rbl_client zen.spamhaus.org

    Since the permit_sasl_authenticated comes before the rejections, and Postfix stops looking at the rules once an explicit permit is hit, this prevents the RBL check from being done if the user successfully authenticated.

  • Two final non-config tips:
    • I haven’t done this because I don’t know if it will break anything in Plesk, but at http://www.lamoree.com/machblog/index.cfm?event=showEntry&entryId=DE299549-D2CF-4061-9DB317384673FE78 the author notes that if you make a symbolic link in /usr/libexec/postfix/ from ‘submission’ to ‘smtpd’, you can then adjust your /etc/postfix/master.cf submission entry to use ‘submission’ as the service name, i.e. the 8th parameter on the submission line, instead of ‘smtpd’, and the beneficial result is now your syslogs will have postfix/submission as the logged service instead of postfix/smtpd for both port 25 and 587 connections; makes it easy to differentiate between the two.  I *think* this would be completely safe to do since I’m already altering the submission line myself for the TLS stuff and Plesk hasn’t broken over that, but I haven’t tried this personally.
    • Definitely look into using Fail2Ban on your hosting servers to block script kiddies and spammers; I have an article on that.

One Reply to “Recommended postfix tuning for Plesk 10+”

Leave a Reply

Your email address will not be published. Required fields are marked *