Make postfix reject incoming email spoofed as from my own domain
I have a postfix server correctly configured to allow incoming mail to my domain, and to require authentication in order to send mail to any other network.
A lot of spam that I get has a forged "from" address of non-existent users at my own domain. SPF could stop this, and I have SPF configured in my DNS, but I'm not sure I want to go the route of fully blocking all SPF fails at the SMTP level.
Is there a quick postfix configuration item I can add that would reject incoming email which is FROM mydomain and wasn't authenticated?
To be very specific, this is my postfix conf:
smtpd_relay_restrictions = permit_sasl_authenticated, reject_unauth_destination
smtpd_recipient_restrictions =
permit_sasl_authenticated,
reject_invalid_hostname,
reject_non_fqdn_hostname,
reject_non_fqdn_sender,
reject_non_fqdn_recipient,
reject_unknown_sender_domain,
reject_unknown_recipient_domain,
reject_rhsbl_sender dbl.spamhaus.org,
permit
smtpd_sender_restrictions = reject_unknown_sender_domain
smtpd_helo_restrictions = reject_unknown_helo_hostname, reject_invalid_helo_hostname
yet it is still possible to connect to port 25 and
MAIL FROM: [email protected]
RCPT TO: [email protected]
without authenticating.
If you enable Postfix's message submission service (on port 587), you can separate "message submission from message relay, allowing each service to operate according to its own rules (for security, policy, etc.)" (RFC 4409).
Under this configuration, since legitimate users must authenticate to use port 587 for message submission, you can safely reject spoofed, unauthenticated mail submitted via port 25.
To enable (SASL-authenticated) message submission on port 587, add a section like the following to Postfix's master.cf:
submission inet n - n - - smtpd
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_sasl_type=dovecot
-o smtpd_sasl_path=private/auth
-o smtpd_sasl_security_options=noanonymous
-o smtpd_sasl_local_domain=$myhostname
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
-o smtpd_sender_login_maps=hash:/etc/postfix/virtual
-o smtpd_sender_restrictions=reject_sender_login_mismatch
-o smtpd_recipient_restrictions=reject_non_fqdn_recipient,reject_unknown_recipient_domain,permit_sasl_authenticated,reject
(Source)
Then, create a Postfix access table (at /etc/postfix/access) specifying how Postfix should respond to certain senders:
[email protected] OK
[email protected] HOLD
mydomain.com REJECT
See the access
man page for details.
Run postmap
on the access file (to create an indexed lookup table):
postmap /etc/postfix/access
Add appropriate sender restrictions to main.cf:
smtpd_sender_restrictions = permit_sasl_authenticated,
check_sender_access hash:/etc/postfix/access
Finally, reload the new configuration. On Debian-based systems, this is done using:
sudo service postfix reload
Is there a quick postfix configuration item I can add that would reject incoming email which is FROM mydomain and wasn't authenticated?
Not so quick, but you could implement a simple SMTPd Policy and pick the sender
and sasl_username
and check whether the first one comes from your domain and the second one exists and also comes from your domain, if so, return DUNNO
, otherwise, REJECT
. This way you ensure that for any incoming mail, if it is from your users, it must be SASL authenticated.
To be very specific, this is my postfix conf:
There are some additional items you can add to your smtpd_recipient_restrictions
policy to try to stop the spam and at the same time improve your security:
smtpd_sender_restrictions =
permit_mynetworks
reject_unknown_sender_domain
reject_sender_login_mismatch
reject_unauth_pipelining
reject_non_fqdn_sender
permit
What means each might be found in the Postfix Configuration Parameters page.
There are some additional items you might want to include to stop the spam:
SPF
is one of them, but I agree that blocking any non-matching test is quite heavy bearing in mind that some poorly implemented mail lists send e-mails with the original sender address from their servers so they fail.DKIM
is very powerful as well (checkOpenDKIM
).SpamAssassin
might be very helpful in this case. It won't block mail, but it will be added a Spam header and consequently be classified so.You didn't provide a Postfix message of one of those spoofed attempts, but you could check if they are originated from the same IP address or at least a concrete CIDR address and put them into a blacklist with the
smtpd_client_restrictions
parameter.Same may be applied to the
HELO/EHLO
message and might be placed intosmtpd_helo_restrictions
.
As you can see, there are a lot of ways, maybe you are able to find a combination of them that suits your case and stop all the spoofed attempts.
I found one way to solve it, though I'm curious if anyone has a more direct/simple answer.
I used the reject_sender_login_mismatch
setting so that if postfix can find a mapping from "FROM" address to a username, it requires that that user name be authenticated.
Then, the task is to build a map which handles all addresses @mydomain but which correctly lets local users send mail for their address.
On my particular configuration, I use
virtual_alias_maps = sqlite:/etc/postfix/db-public-alias.cf pcre:/etc/postfix/db-public-alias-regex.cf
to map addresses to actual users.
I added another address database pcre:/etc/postfix/db-sender-logins-fallback.cf
which has a regex from all my domains to my main user. So now when combined:
smtpd_sender_login_maps = sqlite:/etc/postfix/db-public-alias.cf pcre:/etc/postfix/db-public-alias-regex.cf pcre:/etc/postfix/db-sender-logins-fallback.cf
smtpd_sender_restrictions = reject_unknown_sender_domain, reject_sender_login_mismatch
every alias can only be sent from the user it is routed to, and every other address at my domains can only be sent from my main user account, and so any spammer trying to send FROM: my domain will fail because they aren't logged in as me.
While this is a nice improvement to my mail setup (local users can no longer impersonate eachother) it could be too complicated for people with very advanced user account configurations. I'm still curious if there is a way to just say "for these domains in FROM:, user must be logged in".