A friend of mine is set up with a satellite Internet connection to his home in a not-all-that-rural part of Ireland. He’s been hosting his domain from there, with all email traffic and such going to his local server. Until recently, it was a perfectly workable solution, even with the normal supply of spam, virus, and other junk mail arriving.
But nearly two weeks ago, his domain came under attack from a bunch of spam botnets. Uncountable messages were forged to various places, all of which set up with the Sender:
header to be totally random addresses @domain.ie
. Unfortunately his ISP said they would not help block the traffic. (As opposed to could not.)
The workaround we came up with pushed his traffic through a virtual-hosted system I have set up over in the US with johncompanies.com (yes, a blatant plug, but I really like their service). There were a few steps I had to take in configuring Postfix before they added the MX record for his domain to reroute everything. (This is on a system running Debian GNU/Linux version 4.0, codenamed etch, using postfix 2.3.7.)
- In
main.cf
, add his domain to relay_domains
(which already existed for other domains I MX with).
- Since he uses a lot of different email addresses (to make it easy to catch re-use and selling of them), I didn’t set up a
relay_recipient_maps
hash table. That would have been even cooler with its ability to block every single address except for the few that are in fact valid. In this case, however, he had a number of variants of addresses he used so it wasn’t a practical choice.
- Add to
smtpd_recipient_restrictions
the line
check_recipient_access hash:/etc/postfix/maps/access_recipient
and created the file /etc/postfix/access_recipient
containing
postmaster@domain.ie REJECT
MAILER-DAEMON@domain.ie REJECT
and then ran postmap access_recipient
as root. I should note I did not put a line like domain.ie OK
which would have let all other mail for the domain go through—but usurped any other rules that smtpd_recipient_restrictions
may try to do after my access_recipients entry.
- I created a
/etc/postfix/access_sender
file with the lines below. The first was used because his server will never receive mail from someone in his domain.
domain.ie REJECT
MAILER-DAEMON@ REJECT
MailerDaemon@ REJECT
abuse@ REJECT
admin@ REJECT
Administrator@ REJECT
autoresponder@ REJECT
bounce@ REJECT
info@ REJECT
majordomo@ REJECT
Majordomo-Owner@ REJECT
nobody@ REJECT
postmaster@ REJECT
savrequest@ REJECT
senderchallenge@ REJECT
spam@ REJECT
vacation@ REJECT
Then I had to run postmap access_sender
as root. In main.cf
, for smtpd_sender_restrictions
I added
check_sender_access hash:/etc/postfix/access_sender
as well.
- I found I wanted to add some rules that used regular expressions. After installing the
postfix-pcre
Debian package, I created a new file /etc/postfix/access_sender.pcre
with the lines
/.*bounces\@/ REJECT
/confirm-return.*\@/ REJECT
and in main.cf
gave smtpd_sender_restrictions
yet another entry of
check_sender_access pcre:/etc/postfix/access_sender.pcre
- Following the hints from a post by Justin Mason, I created a new file
/etc/postfix/header_checks
and gave it the lines
/^Content-Type: multipart\/report; report-type=delivery-status\;/ REJECT no third-party DSNs
/^Content-Type: message\/delivery-status; / REJECT no third-party DSNs
A second file, /etc/postfix/null_sender
, had
<> 550 no third-party DSNs
In main.cf
I gave the smtpd_sender_restrictions
list the new entry of
hash:/etc/postfix/null_sender
and also added a new line defining header_checks
as
header_checks = regexp:/etc/postfix/header_checks
Finally I had to run postmap null_sender
as root.
- In
master.cf
I had to adjust the smtp unix
and relay unix
entries to only do 2 processes, not the default of 20, since having my machine try 20 simultaneous connections to his machine wouldn’t help. Under each, respectively, I had to add
-o smtp_destination_concurrency_limit=2
and
-o relay_destination_concurrency_limit=2
I’m still not positive if the maximum of 2 processes would make these options necessary. I should note that this particular system I was setting up did no other mail delivery, so this change was okay. If you’re doing this on a fully production-level host, you might find a different way to throttle the delivery connections going to a specific host, instead of this change which makes all outgoing mail connections happen only two-at-a-time.
- He’s closed port 25 on his router to try to at least stop the flood. Instead, he’s opening a random port number (like 1767) and having it listen there for new mail. I’ve made postfix deliver it by creating a
/etc/postfix/transport
file with the lines
# 20080327 help fight the flood, tunnel the mail to its real destination, e.g., his server is 1.2.3.4
domain.ie :[1.2.3.4]:1767
.domain.ie :[1.2.3.4]:1767
and ran postmap transport
as root. Into main.cf
I added
transport_maps = hash:/etc/postfix/transport
- After all of this was done, I had to do
postfix restart
The end result, with Justin’s rules in particular, has had thousands and thousands of attempts get blocked trying to get through the door. Some still trickle through, even after the amavis/clamav/spamassassin content filter has processed them.
This is the final accumulation (with a few I already had):
smtpd_sender_restrictions = check_sender_access hash:/etc/postfix/access_sender,
check_sender_access pcre:/etc/postfix/access_sender.pcre,
hash:/etc/postfix/null_sender
header_checks = regexp:/etc/postfix/header_checks
## Steps from http://www.akadia.com/services/postfix_spamassassin.html
smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks,
reject_unauth_destination,
reject_unauth_pipelining,
reject_invalid_hostname,
reject_non_fqdn_hostname,
reject_non_fqdn_sender,
reject_non_fqdn_recipient,
reject_unknown_sender_domain,
reject_unknown_recipient_domain,
check_recipient_access hash:/etc/postfix/access_recipient,
check_recipient_access pcre:/etc/postfix/access_recipient.pcre,
check_policy_service inet:127.0.0.1:60000,
permit
(The check_policy_service line is for my use of postgrey, another simple step which drastically reduced the amount of spam my own server was getting.)
Please let me know if any of the instructions above prove to not work out properly for you.
P.S. A command I found handy watching the logs to see what was getting through for attempted delivery, even after everything above:
sudo tail -f /var/log/mail.log | egrep -v '((RCPT|connect(ion)?).* from |smtpd_peer_init)'