How to detect and prevent postfix from dishing out spam email from compromised mail account

We host email and websites for numerous customers on a dedicated server running CentOS and configured through Virtualmin.

Email is handled through Postfix.

Over the weekend we noticed that a clients email account had been compromised and the server had been used to basically pump out spam. As a result our server was blacklisted, affecting every other account on the server. We believe that a desktop machine was infected with malware which allowed the spammers access to the SMTP login credentials to the account in question. From that point on it was open season.

My question is: is there anyway to put anything in place to automatically detect spam like activity of this nature?

Thanks


If you use SASL/TLS to authenticate your users, you can set up different "paths" through your server. One path could be the classical port 25 incoming mail, which will run through amavisd-new, to be scanned for spam and viruses, and you could set up another path which has more permissive patterns, possibly with a higher spam threshold. You could also allow or disallow different types of email attachments.

You could even limit the sort of email, or more specifically, with what addresses your users can send as.

How you go about it depends on what sort of software you have in place at the moment.


As I posted above as a comment, I also had the same problem. After doing some research, I came up with this quick solution (still under testing -use it at your own risk-):

at your postfix main.cf file:

smtpd_relay_restrictions =
    ...
    permit_mynetworks,
    reject_unknown_reverse_client_hostname,
    permit_sasl_authenticated,
    ...

Be aware the "smtpd_relay_restrictions" are available from postfix 2.10, but you can apply them as well before 2.10, please check the Documentation.

In my case, I needed to perform 2 changes:

  1. move "permit_sasl_authenticated" down in my rules. Before, I was trusting to much in my authenticated users.
  2. add the rule: "reject_unknown_reverse_client_hostname", as most of the "authorized-spammers" where reporting "unknown" host (unfortunately, some of them contained hostname information). I also added a white list (using: check_client_access rule) from some of my customer's servers that are known to not being resolving their IP -> hostname.

So far, so good. Even better, as it is showing as "rejected" in the mail log, now I can ban those clients using my current fail2ban configuration.

As side note, you could perform an extensive checking (like perhaps rbl checking, before permitting your auth users to send mails). I haven't tried that though.

It would be nice to add spamassassin into the game and be able to flag and block those SPAM mails before delivering them. However as spamassassin was not playing really nice with Japanese messages (all my customers are Japanese), I don't feel like giving it so much power for now.

I hope it can help you.


My question is: is there anyway to put anything in place to automatically detect spam like activity of this nature?

For your use-case I would recommend to use postfwd. It has a flexible system of rules which can do smart filtering.

Features

  • Complex combinations of smtp parameters in a single rule
  • Macros/ACLs/Groups for frequently used statements
  • Combined asynchronous dnsbl lookups with arbitrary actions depending on the results (e.g. allows dns whitelists or selective greylisting based on rbl lookup results)
  • Automatic deactivation of non-responding dnsbls
  • Rate limits for message count and size for any available item (user, client, sender, recipient, ...)
  • Scoring system for fine granular access control Date/time based rules
  • Conditional jumps to certain rules (like iptables -j)
  • Internal caching for requests and dns lookups
  • Runs as network daemon (no need to spawn processes)
  • Built in statistics for rule efficiency analysis

For e.g.

Do not allow more than 20MB or 1000 recipients per day for users alice and bob:

id=RULE003
    sasl_username=~/^(alice|bob)$/
    action=size(sasl_username/20971520/86400/REJECT only 20mb per day for $$recipient)
id=RULE004
    sasl_username=~/^(alice|bob)$/
    action=rcpt(sasl_username/100/86400/REJECT only 100 recipients per day for $$sasl_username)

Or you can configure different policies for different clients

# Class 1: high volume clients
# - per mail: max 30MB, max 200 concurrent recipients
id=CLASS100; client_address=table:/etc/postfwd/class1.cf; action=jump(CLASS101)

# Class 2: medium limited access
# - per mail: max 10MB, max 50 concurrent recipients
# - rate limit: 1000 recipients or 100MB per day
id=CLASS200; client_address=table:/etc/postfwd/class2.cf; action=jump(CLASS201)

# Class 3: very tight limits
# - per mail: max 4MB, max 10 concurrent recipients
# - rate limit: 100 recipients or 20MB per day
id=CLASS300; client_address=table:/etc/postfwd/class3.cf; action=jump(CLASS301)

# Does not fit anywhere? REJECT
id=DEFAULT; action=REJECT please contact [email protected]

And so on. The only restriction - is your fantasy :)