I run a Postfix + Dovecot email server for my personal email. A common Postfix setup includes
reject_unknown_reverse_client_hostname for SMTP clients to reduce invalid connections attempts, such as botnet spammers attempting to find open mail servers. Typical residential ISP connections have PTR entries for their IPs, whereas many botnet devices may not. It’s not foolproof nor even necessarily particularly effective, but it helps cut down on invalid SMTP connection attempts.
This became a problem for me when my new metro wireless ISP assigned me an IP that has no PTR record, and has been slow addressing the issue. Thus, my mail server rejects my own local email client’s SMTP connections!
A typical Postfix configuration file1 has SMTP restrictions like this:
smtpd_sender_restrictions = reject_unknown_sender_domain, reject_unknown_reverse_client_hostname smtpd_client_restrictions = warn_if_reject, reject_unknown_reverse_client_hostname
The simplest way to allow a real client to send regardless of their PTR record is by adding
permit_sasl_authenticated to the top of the restrictions, assuming
smtpd_delay_reject is the default ‘yes’2. The new configuration is simply:
smtpd_sender_restrictions = permit_sasl_authenticated, reject_unknown_sender_domain, reject_unknown_reverse_client_hostname smtpd_client_restrictions = permit_sasl_authenticated, warn_if_reject, reject_unknown_reverse_client_hostname
This permits any authenticated clients to send email, regardless. Don’t forget to
sudo service postfix restart after making changes to the configuration file.
A more complex solution, also necessary if
smtpd_delay_reject = no, is to use a client whitelist lookup. I use a MariaDB3 database for all of my email configuration4, so this whitelist will involve reading allowed clients from a database. It uses
check_client_access in lieu of the above
permit_sasl_authenticated to whitelist a client’s IP.
First, create a SQL table for listing allowed clients – actions are restricted to a few of Postfix’s
access ‘action’ codes:
CREATE TABLE `client_whitelist` ( `UID` int(10) UNSIGNED NOT NULL, `Client` varchar(120) NOT NULL COMMENT 'Single IP', `Action` enum('OK','REJECT','DUNNO','WARN') NOT NULL DEFAULT 'REJECT' ) ENGINE=InnoDB DEFAULT COMMENT='SMTP clients that match here bypass sender restrictions';
Then create a configuration file to use with Postfix’s MySQL interface; I used
hosts = <DB host> user = <DB user> password = <DB password> dbname = <DB name> query = SELECT action FROM client_whitelist WHERE '%s' = client
This simply returns one of the enumerated actions from the table if the client matches. Unfortunately the
Client field can only contain IPs, not hostnames: Postfix is only expecting a simple action to be returned, only knows the client IP at this point, and MySQL doesn’t have a built-in hostname resolution function.
The Postfix configuration to execute this query against SMTP clients is simply:
proxymap to maintain a persistent database connection to the
mysql handler that is used for
proxy is not required, but reduces database traffic. However, if you do use
proxy, you must also add
$smtpd_sender_restrictions $smtd_client_restrictions to
proxy_read_maps to allow it access!
To test the database configuration file and table contents, try:
sudo postmap -q <your IP> mysql:/etc/postfix/mysql-smtp_whitelist.cf
If this returns
OK, then it’s ready to be placed into the Postfix master configuration file:
smtpd_sender_restrictions = check_client_access proxy:mysql:/etc/postfix/mysql-smtp_whitelist.cf, reject_unknown_sender_domain, reject_unknown_reverse_client_hostname smtpd_client_restrictions = check_client_access proxy:mysql:/etc/postfix/mysql-smtp_whitelist.cf, warn_if_reject, reject_unknown_reverse_client_hostname ... proxy_read_maps = ... $smtpd_sender_restrictions $smtd_client_restrictions
Restart Postfix via
sudo service postfix restart and check the status – clients listed in the
client_whitelist table should now be able to send via SMTP regardless of other restrictions.