> my objective no one from outside world can connect to our mail server
> and sends bulk emails by using our domain email address. e.g.
> abc@??? in case if this account is compromised.
Separate port (or different hosts or usernames for POP3 and submission)
are useless because the Windows malware anyway needs to steal
hostname, username and password from settings of a mail program
(such as Outlook Express), port number is kept there too.
Two ways:
1. I suppose that spambots cannot authenticate over encrypted connection yet.
Therefore you can forbid relaying with authentication if connection is
not encrypted: in each of two authenticators PLAIN and LOGIN insert the line:
server_advertise_condition = ${if def:tls_cipher}
In the beginning of Exim config:
daemon_smtp_ports = 25 : 587 : 465
tls_on_connect_ports = 465
tls_advertise_hosts = *
tls_certificate = /etc/ssl/exim.crt
tls_privatekey = /etc/ssl/exim.pem
Of course, you need to generate a certificate if you didn't already:
http://www.exim.org/exim-html-current/doc/html/spec_html/ch41.html#SECID187
If some of your users prove to you that their mail programs can use
neither SSL nor TLS and they cannot use other software then:
2. Spammers send to huge lists of harvested email addresses.
Harvesters are robots which along with real email addresses collect
strings looking like email addresses but really nonexistent:
Message-IDs, obsolete addresses, corrupted strings in memory and files.
Spammers can check existence of a domain but they usually don't check
existence of each localpart on each domain: it's too labor-intensive,
cannot be automated because replies of recipients' mail servers
are not standartized; rejects can be caused by various reasons besides
real "user unknown". We can use this for automated detection of spamming
via compromised accounts: limit neither quantity of messages nor quantity
of recipients per hour (depending on exact limit that'll either
cause too much inconvenience for honest users or fail to catch spam),
but check rate (quantity per hour) of attempts to send to nonexistent
email addresses. In case of 100 attempts to send to nonexistent
email addresses the user is automatically blocked, you receive
email notification, all messages from that user are frozen in the queue.
When you receive notification, you look at content of frozen messages
using `exipick` command. If it's spam then you change the user's password
and exact a fine from the user according to contract
using frozen spam as evidence.
In unlikely case if it's not spam, you delete the line with the userid from
the blocked_authenticated_users file with a text editor
(or if the file contains only one line then you can just delete the file)
and unfreeze messages using `exipick`.
My implementation of such automatic detection, blocking and notification:
LIM = 100
PERIOD = 1h
WARNTO = abuse@???
EXIMBINARY = /usr/local/sbin/exim -f root
SHELL = /bin/sh
begin acl
acl_check_rcpt:
...
accept authenticated = *
set acl_m_user = $authenticated_id
# in case of mailboxes in /var/mail: ${sg{$authenticated_id}{\N\W.*$\N}{}}
condition = ${if exists{$spool_directory/blocked_authenticated_users}}
condition = ${lookup{$acl_m_user}lsearch\
{$spool_directory/blocked_authenticated_users}{1}{0}}
control = freeze/no_tell
control = submission/domain=
add_header = X-Authenticated-As: $acl_m_user
accept authenticated = *
!verify = recipient/defer_ok/callout=10s,defer_ok,use_sender
ratelimit = LIM / PERIOD / per_rcpt / user-$acl_m_user
continue = ${run{SHELL -c "echo $acl_m_user \
>>$spool_directory/blocked_authenticated_users; \
\N{\N echo Subject: user $acl_m_user blocked; echo; echo because \
has sent mail to LIM invalid recipients during PERIOD.; \
\N}\N | EXIMBINARY WARNTO"}}
control = freeze/no_tell
control = submission/domain=
add_header = X-Authenticated-As: $acl_m_user
accept authenticated = *
control = submission/domain=
Similarly for users on local network:
accept hosts = !@[] : +relay_from_hosts
set acl_m_user = $sender_host_address
# or an userid from RADIUS
condition = ${if exists{$spool_directory/blocked_relay_users}}
condition = ${lookup{$acl_m_user}lsearch\
{$spool_directory/blocked_relay_users}{1}{0}}
control = freeze/no_tell
control = submission/domain=
add_header = X-Relayed-From: $acl_m_user
accept hosts = !@[] : +relay_from_hosts
!verify = recipient/defer_ok/callout=10s,defer_ok,use_sender
ratelimit = LIM / PERIOD / per_rcpt / relayuser-$acl_m_user
continue = ${run{SHELL -c "echo $acl_m_user \
>>$spool_directory/blocked_relay_users; \
\N{\N echo Subject: relay user $acl_m_user blocked; echo; echo \
because has sent mail to LIM invalid recipients during PERIOD.; \
\N}\N | EXIMBINARY WARNTO"}}
control = freeze/no_tell
control = submission/domain=
add_header = X-Relayed-From: $acl_m_user
accept hosts = +relay_from_hosts
control = submission/domain=
Lena