Bug#270735: exim4: Self-denial of mail service

Greg Kochanski Greg Kochanski <gpk@kochanski.org>, 270735@bugs.debian.org
Thu, 09 Sep 2004 00:35:09 +0100


Package: exim4
Version: 4.34-4
Severity: normal


Several of the settings in exim4 can easily lead to accidental
denial-of-service attacks on one's self.

Specifically, setting deliver_queue_load_max, queue_only_load, smtp_load_reserve
all will completely stop mail delivery if a user starts up some CPU-intensive
program.     And, this can happen easily -- in a scientific/university environment,
it's not unusual to start up a calculation that will take CPU-days to complete.

So, one user can accidentally block mail service to other users (and himself, of course).
To avoid this, you can't set these load limits much smaller than 3 or 4, and even then
it's still possible (though unlikely) for the limits to be exceeded for days at a time.

I suggest that what you really want is not for queueing and or delivery to be
completely stopped when the load limits are exceeded, but to be slowed down, instead:
deliver_queue_load_max pseudocode:
	if( load > 2*deliver_queue_load_max)
		abort_delivery()
	else if(load > deliver_queue_load_max && random() > RAND_MAX/10)
		abort_deliver()
	deliver()

On a system with light mail traffic, mail will then seep through, even if someone
has loaded up the system with some CPU-intensive process.   It's then possible
to set deliver_queue_load_max to a reasonable value like 1.5 or 2,
and have everything work in a sensible manner.

Similar logic applies to smtp_load_reserve.  In the current definition, it is essentially
useless on a system that is not a dedicated mail server without user shell access.
Again, one wants to accept a trickle of mail messages even if the computer is loaded up.
Here, though, random rejection is probably not the correct solution,
because other systems don't retry often and will retry only a limited number
of times.    There's a risk of completely losing mail, though it might be
acceptably small if you used ...random() > RAND_MAX/4) instead of .../10).

Instead, I think a good solution might be to maintain a file whose time-stamp
is updated each time a SMTP connection is accepted, and then to check if
it's been a while since the last connection.
Pseudocode:
	if(load > 2*smtp_load_reserve && !is_reserve_host())
		DO_NOT_ACCEPT
	else if(load > smtp_load_reserve && interval_since_last_smtp()<DELTA_T)
		DO_NOT_ACCEPT
	if(load > smtp_load_reserve)
		update_smtp_time_stamp()
	ACCEPT



The same could be applied to queue_only_load, but the case is not as strong.

-- Package-specific info:
Exim version 4.34 #1 built 27-Jul-2004 18:06:50
Copyright (c) University of Cambridge 2004
Berkeley DB: Sleepycat Software: Berkeley DB 3.2.9: (May 26, 2004)
Support for: iconv() IPv6 GnuTLS
Lookups: lsearch wildlsearch nwildlsearch iplsearch cdb dbm dbmnz dsearch nis nis0 passwd
Authenticators: cram_md5 plaintext
Routers: accept dnslookup ipliteral manualroute queryprogram redirect
Transports: appendfile/maildir/mailstore autoreply lmtp pipe smtp
Fixed never_users: 0
Configuration file is /var/lib/exim4/config.autogenerated
# /etc/exim4/update-exim4.conf.conf
#
# Edit this file and /etc/mailname by hand and execute update-exim4.conf
# yourself or use 'dpkg-reconfigure exim4-config'

dc_eximconfig_configtype='smarthost'
dc_other_hostnames='gpk.wftp.org : gpk.homeunix.net : kochanski.org : pribble.com : kochibble.com'
dc_local_interfaces=''
dc_readhost='kochanski.org'
dc_relay_domains=''
dc_minimaldns='false'
dc_relay_nets='192.168.1.0/25 : 192.168.1.128/25 : 127.0.0.1'
dc_smarthost='smtp.ntlworld.com'
CFILEMODE='644'
dc_use_split_config='true'
dc_hide_mailname='true'
mailname:kochanski.org

-- System Information:
Debian Release: 3.1
  APT prefers testing
  APT policy: (500, 'testing')
Architecture: i386 (i686)
Kernel: Linux 2.4.27-1-686
Locale: LANG=C, LC_CTYPE=C

Versions of packages exim4 depends on:
ii  exim4-base                    4.34-4     EXperimental Internal Mailer -- a 
ii  exim4-daemon-light            4.34-4     Lightweight version of the Exim (v

-- no debconf information