Suggestion: Remove Paypal specific code, replace with dkim signature verification

interfasys

Verified User
Joined
Oct 31, 2003
Messages
2,100
Location
Switzerland
Paypal is not the only targeted organisation when it comes to online scams, so I think it's best to remove Paypal specific code and replace it with DKIM signature verification.
It's simple enough to do and can apply to a lot more domains.
 
Last edited:
dkim has been discussed several times in the past few days. I may very well be wrong but my understanding is that it requires special compile of exim to work. If so, then it's not something I can put into the standard exim.conf file until/unless DirectAdmin can figure out how to support it by default for every install of DirectAdmin.

Hopefully I'm wrong. If so, then will you (or someone) please send me a copy of my most recent release candidate, with no other changes except DKIM added in a way that it will work for everyone? If someone will do that quickly I can test it and hopefully add it to our latest exim.conf file.

This is what I'd expect you to use but I just don't have time right now to experiment with it.

Thanks!

Jeff

Thanks.

Jeff
 
Hello,

If you've got exim 4.70+, the DKIM should already be compiled in by default, as per:
http://www.exim.org/exim-html-current/doc/html/spec_html/ch54.html
Since version 4.70, DKIM support is compiled into Exim by default.
assuming of course you did't compile the binaries yourself and add the "DISABLE_DKIM=yes" option into the Local/Makefile.

On a side-note, if you are trying to compile exim 4.70+, it requires changes to the Makefile with regards to exim no longer including a packaged version of pcre.
Code:
PCRE_LIBS=-lpcre
INCLUDE=-I/usr/local/include
Our Makefile already has these changes. If you don't have pcre on your system, custombuild can install it for you (./build pcre), but if you have custombuild, you'll likely already have pcre anyway. If you have customapache, then you'd have to either upgrade to custombuild, or install pcre with other means (package system or manual compile).

The Makefile that custombuild 1.2 uses for exim 4.70+:
http://files.directadmin.com/services/custombuild/Makefile

Obviously, if you've got a version of exim older than 4.70, you won't have DKIM compiled in.

John
 
I'll see if I can extract something from my config tomorrow, but for a simple use case, it's as simple as adding this:
Code:
dkim_verify_signers = $sender_address_domain:$dkim_signers
acl_smtp_dkim = acl_check_dkim
acl_check_dkim:
# Warn when message apparently from GMail has no signature at all
warn log_message = GMail sender without DKIM signature
     sender_domains = gmail.com
     dkim_signers = gmail.com
     dkim_status = none

deny message = Message from Paypal with invalid or missing signature
     sender_domains = paypal.com:paypal.de
     dkim_signers = paypal.com:paypal.de
     dkim_status = none:invalid:fail

accept
In the right places.
 
Last edited:
Add it exactly where, relative to my new release candidate?

Why are you bothering to warn for gmail in the log files? The user doesn't read the logfiles.

And should we be blocking/warning for any other sender?

Opinions please.

Thanks.

Jeff
 
Those are just examples. As I said earlier, the possibilities are endless.
One thing that the default spamblocker could do is to add a DKIM-Status header that would help any antispam app deal with the message accordingly.
We check the signature for known signers and reject failed signatures.

Anyway, here is the modified RC.
Code:
# DirectAdmin SpamBlocker Version 3.2.5 RC exim.conf
# 13-Apr-2010  20:28 (-0700)
# Exim configuration file for DirectAdmin
# Requires exim.pl as distributed by DirectAdmin here:
# http://files.directadmin.com/services/exim.pl Dated 28-Mar-2008 or later
# SpamBlocker with Optional VirusBlocker
# Dovecot Only
# 
# WARNING! Be sure to back up your previous exim.conf file before
# attempting to use this exim.conf file.
#
# WARNING! This exim.conf file does not allow host literal addressing
# such as [email protected]
#
# If you need to allow host literals you're on your own.
# 
# Do NOT use this exim.conf Exim configuration file unless you
# make the required modifications to your Exim configuration
# following the instructions in the README file included in this
# distribution.
# 
# WARNING: The following files must exist and have the same ownership
# and permisssions as your /etc/virtual/domains file.
# 
# /etc/virtual/bad_sender_hosts
# /etc/virtual/bad_sender_hosts_ip
# /etc/virtual/blacklist_domains
# /etc/virtual/blacklist_senders
# /etc/virtual/whitelist_domains
# /etc/virtual/whitelist_hosts
# /etc/virtual/whitelist_hosts_ip
# /etc/virtual/whitelist_senders
# /etc/virtual/use_rbl_domains
# 
# Some of the above files may already exist and be populated.
# 
# If you have a prepopulated bad_sender_hosts file and if
# it's populated with listings which consist of IP#s, then those
# listings must be moved out of the bad_sender_hosts file and
# into the bad_sender_hosts_ip file.
# 
# If you have a prepopulated whitelist_hosts file and if it's
# populated with listings which consist of IP#s, then those
# listings must be moved out of the whitelist_hosts file and
# into the whitelist_hosts_ip file.
# 
# We recommend that your /etc/virtual/use_rbl_domains file not
# exist as a separate file, but rather be a link to your
# /etc/virtual/domains file in which case all domains on your
# server will use blocklisting, which will keep your email server
# load manageable. If you do so, we also recommend you also
# notify all your clients that you use spam-management protocols
# on your server and that to keep your server load to a reasonable
# level you do not allow opt-out from spam-management.
# 
# This is version "3.2.5-RC of the SpamBlocker exim.conf file as
# distributed by NoBaloney Internet Services for DirectAdmin based
# servers.
# 
# More information about NoBaloney Internet Services may be found at:
#  http://www.nobaloney.net/
# 
# More information about DirectAdmin may be found at:
#  http://www.directadmin.com/
# 
# More information about the SpamBlocker exim.conf file may be found on the
# DirectAdmin forums:
# http://www.directadmin.com/forum/forumdisplay.php?f=56
# and at the NoBaloney Internet Services site:
# http://www.nobaloney.net/downloads/spamblocker/DirectAdminSpamBlocker3/
# 
# This Exim configuration file has been modified from the original exim.conf
# file distributed with Exim 4.  The modifications have been made by:
# 
# NoBaloney Internet Services
# Post Office Box 52200
# Riverside, CA  92517-3200
# voice: +1 951 643-5345
# fax: +1 951 552-1182
# spamblocker -at- nobaloney.net
# 
# The original exim.conf file distributed with Exim 4, includes the
# following copyright notice:
# 
# Copyright (C) 2002 University of Cambridge, Cambridge, UK
# 
# Portions of the file are taken from the exim.conf file as
# distributed with DirectAdmin (http://www.directadmin.com/)
# 
# Copyright (C) 2003-2010 JBMC Software, St Albert, AB, Canada
# 
# Portions of this file are written by NoBaloney Internet Services
# and are copyright as follows:
# 
# Copyright (C) 2004-2010 NoBaloney Internet Services, Riverside, Calif., USA
# 
# The entire Exim 4 distribution, including the exim.conf file, is
# distributed under the GNU GENERAL PUBLIC LICENSE, Version 2,
# June 1991. If you do not have a copy of the GNU GENERAL PUBLIC LICENSE
# you may download it, in it's entirety, from the website at:
# 
# http://www.nobaloney.net/exim/gnu-gpl-v2.txt
# 
# With thanks to Martino Dell'Ambrogio <tillo -at- tillo.ch> for his
# much needed and appreciated help.
# 
# The most recent version of this file may always downloaded from the website
# at: http://www.nobaloney.net/downloads/spamblocker
# 
# IMPORTANT NOTICE:
# 
# Whenever you change Exim's configuration file, you *must* remember
# to HUP the Exim daemon, because it will not pick up the new
# configuration until you do. However, any other Exim processes that
# are started, for example, a process started by an MUA in order to
# send a message, will see the new configuration as soon as it is in
# place.
# 
# You do not need to HUP the daemon for changes in auxiliary files
# that are referenced from this file. They are read every time they
# are used.
# 
# It is usually a good idea to test a new configuration for
# syntactic correctness before installing it (for example, by
# running the command "exim -C /config/file.new -bV").
# 
# MODIFICATION INSTRUCTIONS
# 
# YOU MUST MAKE THE CHANGES TO THIS SpamBlocked exim.conf file as
# documented in the README file.
# 
# The README file for this version is named:
# ReadMe-SpamBlocker.3.2-RC.txt

# CONFIGURATION STARTS HERE

DKIM_VERIFY = no

# Specify your host's canonical name here. This should normally be the
# fully qualified "official" name of your host. If this option is not
# set, the uname() function is called to obtain the name. In many cases
# this does the right thing and you need not set anything explicitly.

# primary_hostname =

# EDIT FOR CLAMAV
# If you use ClamAv, then uncomment the line below and edit as
# necessary so it points to your ClamAV socket or port, depending
# on how you call ClamAV

# av_scanner = clamd:/var/run/clamav/clamd

# Specify the domain you want to be added to all unqualified addresses
# here. An unqualified address is one that does not contain an "@" character
# followed by a domain. For example, "[email protected]" is a fully qualified
# address, but the string "caesar" (i.e. just a login name) is an unqualified
# email address. Unqualified addresses are accepted only from local senders by
# default. See the receiver_unqualified_{hosts,nets} options if you want
# to permit unqualified addresses from remote sources. If this option is
# not set, the primary_hostname value is used for qualification.

# qualify_domain =

# the next line is required to start the smtp auth script included
# in DirectAdmin

perl_startup = do '/etc/exim.pl'

# the next line is required to start the system_filter included in
# DirectAdmin

system_filter = /etc/system_filter.exim

# the next line enabless the incoming email submission port 587
# as well as the standard email receipt port 25
# but see also check_recipient ACL port 587 ruleset

daemon_smtp_ports = 25 : 587

# SET SOME MEANINGFUL LIMITS
#  These defaults work for us; you may wish to modify them
#  for your environment

# EDIT AS REQUIRED TO FIT YOUR ENVIRONMENT
message_size_limit = 20M
smtp_receive_timeout = 5m
smtp_accept_max = 100
message_body_visible = 3000
print_topbitchars = true
smtp_accept_max_nonmail = 19
smtp_accept_max_per_host = 10
recipients_max = 150

# ALLOW UNDERSCORE IN EMAIL DOMAIN NAME
# domains shouldn't use the underscore character "_" but some
# may.  Because the late John Postel, one of the architects of
# the Internet, said "Be liberal in what you accept and conservative
# in what you transmit, we choose to allow underscore in email
# domain names so we can receive email from domains which use the
# underscore character in their domain name.

# EDIT AS REQUIRED TO FIT YOUR ENVIRONMENT
helo_allow_chars = _

# CHANGE LOGGING BEHAVIOR
# We weren't happy with the default Exim logging behavior through
# syslog; it didn't give us enough information.  So we turned off
# syslog behavior and changed the logging behavior to give us what we
# felt was more helpful information.  You may choose to delete or modify
# this section.

# EDIT AS REQUIRED TO FIT YOUR ENVIRONMENT
log_selector = \
  +delivery_size \
  +sender_on_delivery \
  +received_recipients \
  +received_sender \
  +smtp_confirmation \
  +subject \
  +smtp_incomplete_transaction \
  -dnslist_defer \
  -host_lookup_failed \
  -queue_run \
  -rejected_header \
  -retry_defer \
  -skip_delivery \
  +arguments
syslog_duplication = false

# define ACLs
# These options specify the Access Control Lists (ACLs) that
# are used for incoming SMTP messages - after the CONNECT, RCPT and DATA
# commands, respectively.
acl_smtp_connect = acl_connect
acl_smtp_helo = acl_check_helo
acl_smtp_rcpt = acl_check_recipient
.ifdef DKIM_VERIFY
acl_smtp_dkim = acl_check_dkim
.endif
acl_smtp_data = acl_check_message

# define local lists
# EDIT: NO EDIT TO THIS FILE NEEDED HERE BUT:
# MAKE SURE THE FOLLOWING FILES EXIST; IF THEY DON'T, CREATE THEM
# WITH THE SAME OWNERSHIP AND PERMISSIONS AS THE /etc/virtual/domains
# FILE.
# 
# EVERY FILE DEFINED BY AN addresslist, domainlist or hostlist MUST
# EXIST AT /etc/virtual OR ELSE EXIM WILL NOT RUN.
# 
# NOTE THAT SOME FILES ARE LISTED IN MULTIPLE LISTS BELOW; IF SO THE
# FILE SHOULD STILL ONLY EXIST ONCE.
# 
# IF YOU WANT TO RUN SPAMBLOCKER FOR ALL DOMAINS ON YOUR SERVER
# (RECOMMENDED ON TODAY'S INTERNET BUT YOU SHOULD NOTIFY YOUR CLIENTS)
# THEN YOU SHOULD CREATE /etc/virtual/use_rbl_domains AS A LINK TO
# THE FILE /etc/virtual/domains INSTEAD OF CREATING IT AS A NEW
# FILE.
#
# If you want to run SpamBlocker only for certain domains, then
# you should create /etc/virtual/use_rbl_domains as a file, and
# populate it with domain names from /etc/virtual/domains only
# for domains for which you DO want to run SpamBlocker
# 
# NOTE: No management tools are included in DirectAdmin to manage
# the whitelists, blacklists or list of domains using the RBLs,
# but commercial tools may be available; search the DirectAdmin
# Forums.

addresslist whitelist_senders = lsearch;/etc/virtual/whitelist_senders
addresslist blacklist_senders = lsearch;/etc/virtual/blacklist_senders
domainlist blacklist_domains = lsearch;/etc/virtual/blacklist_domains
domainlist whitelist_domains = lsearch;/etc/virtual/whitelist_domains
domainlist local_domains = lsearch;/etc/virtual/domains
domainlist relay_domains = lsearch;/etc/virtual/domains : localhost
domainlist use_rbl_domains = lsearch;/etc/virtual/use_rbl_domains

# EDIT AS REQUIRED TO FIT YOUR ENVIRONMENT
# If you run ClamAv then create an empty file /etc/virtual/skip_av_domains
# and uncomment the next line. Later you can copy domain names from
# the /etc/virtual/domains file for any domains that should NOT use
# ClamAv.
# NOTE: there's more to uncomment below for ClamAV to work.

# domainlist skip_av_domains = lsearch;/etc/virtual/skip_av_domains

hostlist auth_relay_hosts = *
hostlist bad_sender_hosts = lsearch;/etc/virtual/bad_sender_hosts
hostlist bad_sender_hosts_ip = /etc/virtual/bad_sender_hosts_ip
hostlist whitelist_hosts = lsearch;/etc/virtual/whitelist_hosts
hostlist whitelist_hosts_ip = /etc/virtual/whitelist_hosts_ip

# EDIT AS REQUIRED TO FIT YOUR ENVIRONMENT
# EITHER ALLOW OR DISALLOW 127.0.0.1 AS RELAY HOST;
# UNCOMMENT ONE OR THE OTHER.
# Some admins consider allowing 127.0.0.1 as a relay host to be
# spammer friendly, others choose to leave it because otherwise
# certain php and/or perl programs, including some webmail
# programs, may fail to work without it.

# hostlist relay_hosts = net-lsearch;/etc/virtual/pophosts : 127.0.0.1
# hostlist relay_hosts = net-lsearch;/etc/virtual/pophosts

# EDIT AS REQUIRED TO FIT YOUR ENVIRONMENT
# DISALLOW LOCAL DELIVERIES UNDER UIDs OF CERTAIN USERS
# No local deliveries will ever be run under the uids of these users
# (a colon-separated list). An attempt to do so gets changed so that
# it runs under the uid of "nobody" instead. This is a paranoic safety
# catch. Note the default setting means you cannot deliver mail
# addressed to root as if it were a normal user. This isn't usually a
# problem, as most sites have an alias for root that redirects such mail
# to a human administrator.  You may comment out the line below to
# allow user root to receive email, or you make add more usernames
# in a colon-separated list. Generally you should add the names of any
# other users who share the UID/GID 0:0, but you shouldn't need to add
# any other usernames to this list.  The default is generally perfect

never_users = root

# EDIT AS REQUIRED TO FIT YOUR ENVIRONMENT
# ALLOW HOST LOOKUPS ON INCOMING EMAIL
# The setting below causes Exim to do a reverse DNS lookup on all
# incoming IP email, in order to get the true host name. If you feel
# this is too time-consuming, you can comment out the next line.

host_lookup = *

# EDIT AS REQUIRED TO FIT YOUR ENVIRONMENT
# ENABLE IDENT CALLBACKS
# Exim may be set to make RFC 1413 (ident) callbacks for all incoming
# SMTP calls. You can limit the hosts to which these calls are made,
# and/or change the timeout that is used. If you set the timeout to zero,
# all RFC 1413 calls are disabled. RFC 1413 calls are cheap and can
# provide useful information for tracing problem messages, but some
# hosts and firewalls have problems with them. This can result in a
# timeout instead of an immediate refused connection, leading to delays
# on starting up an SMTP session.  By default we disable callbacks for
# incoming SMTP calls.  You may change rfc1413_query_timeout to 30s or
# some other positive number of seconds to enable callbacks for incoming
# SMTP calls.

rfc1413_hosts = *
rfc1413_query_timeout = 0s

# QUEUE RUNS
# The following settings modify when and how exim queue-runners run on your
# server.

# EDIT AS REQUIRED TO FIT YOUR ENVIRONMENT
# deliver_queue_load_max:
# If deliver_queue_load_max is set, then the value is used to determine
# whether to abandon a queue run, based on the system load average

deliver_queue_load_max = 5.0

# EDIT AS REQUIRED TO FIT YOUR ENVIRONMENT
# queue_only_load:
# If the queue_only_load_max is set, then all incoming messages are queued
# and no automatic deliveries are started, as long as the system load
# average is higher than this value. If this happens during local or remote
# smtp input, then all subsequent messages on the same connection are queued.
# Deliveries are subsequently performed by queue running processes, unless
# the load is higher than the setting for deliver_queue_load_max, above.

queue_only_load = 7.5

# EDIT AS REQUIRED TO FIT YOUR ENVIRONMENT
# queue_run_max
# queue_run_max determines the maximum number of queue-running processes
# exim will run simultaneously. This does not mean that it starts them all
# at once, but rather that if the maximum number are still running when the
# time comes to start another one, exim will not start it.  This can happen
# with very large queues and/or very sluggish deliveries. This option does
# not interlock with other processes: additional queue-running processes
# can be started by other means; i.e., from the command line, or by killing
# and restarting the exim daemon.

queue_run_max = 5

# MESSAGE BOUNCES
# When Exim can neither deliver a message nor return it to sender, it
# "freezes" the delivery error message (aka "bounce message"). There are
# also other circumstances in which messages get frozen. They will stay
# on the queue forever unless one or both of the following options is
# set.
#
# The default in this file is to freeze after two days, and then
# delete after three days; this results in shorter queues than you
# might otherwise have, but only gives you one day to study frozen
# messages. We've discovered that most of the time you don't ever
# actually study frozen messages, but just delete them, so this
# seems a workable compromise. You can change these if you wish. But
# remember that the timeout_frozen_after setting must be higher
# than the ignore_bounce_errors_after setting.

# EDIT AS REQUIRED TO FIT YOUR ENVIRONMENT
# This option unfreezes bounce messages after two days, tries
# once more to deliver them, and ignores any delivery failures.

ignore_bounce_errors_after = 2d
timeout_frozen_after = 3d

# EDIT AS REQUIRED TO FIT YOUR ENVIRONMENT
# TRUSTED USERS
#
# Exim uses the concept of trusted users, who are allowed certain
# liberties with changes to headers. For more information, see:
# http://www.exim.org/exim-html-4.00/doc/html/spec_5.html#SECT5.2
#
# if you must add additional trusted users, do so here; continue the
# colon-delimited list

trusted_users = mail:majordomo:apache:diradmin

# EDIT AS REQUIRED TO FIT YOUR ENVIRONMENT
# SSL/TLS cert and key
tls_certificate = /etc/exim.cert
tls_privatekey = /etc/exim.key
tls_advertise_hosts = *
#auth_over_tls_hosts = *
tls_require_ciphers = ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:-LOW:-SSLv2:-EXP

.ifdef DKIM_VERIFY
dkim_verify_signers = $sender_address_domain:$dkim_signers
.endif

# ACLs
######

# EDIT BOUNCE MESSAGES
# to allow for false positives on email checking against blocklists, you
# may want to set up a page somewhere on the Internet where you explain
# your whitelisting policy or precedure. This SpamBlocker exim.conf file
# does NOT define either that page, or your procedure; setting it up is
# your responsibility.

# In the following ACL sections you'll find many bounce messages; you
# should edit them as necessary.

begin acl

acl_connect:
  accept hosts = *
	 delay = 3s
  # above accepts hosts who are polite enough to wait rather than just
  #  send, as spammers do
  # EDIT DENY MESSAGE AS REQUIRED TO FIT YOUR ENVIRONMENT
  deny message = Too quick on the draw - to unblock wait for helo/ehlo

acl_check_helo:
  #accept email originating on this server unconditionally
  accept  hosts = @[] : @

  # deny if the HELO pretends to be this host
    deny message = You cannot be me
      condition = ${if or { \
                            {match{$sender_helo_name}{$smtp_active_hostname}} \
                            {eq{$sender_helo_name}{[$interface_address]}} \
                          } {true}{false} }

  # deny if the HELO is an IP address
    deny message = HELO is an IP address (See RFC2821 4.1.3)
         condition   = ${if isip{$sender_helo_name}}

  accept

# ACL that is used after the RCPT command
acl_check_recipient:

  # to block certain wellknown exploits, Deny for local domains if
  # local parts begin with a dot or contain @ % ! / |
  deny  domains       = +local_domains
        local_parts   = ^[.] : ^.*[@%!/|]

  # to restrict port 587 to authenticated users only
  # see also daemon_smtp_ports above
  accept  hosts = +auth_relay_hosts
	  condition = ${if eq {$interface_port}{587} {yes}{no}}
	  endpass
	  message = relay not permitted, authentication required
	  authenticated = *

  # RC 3,2,5 11-APR-2010
  # Mailer-Daemon messages must be for us
    accept senders = :
	   domains = +relay_domains

  # RC 3.2.5 11-APR-2010
  # deny if the recipient doesn't exist:
    deny message = No such recipient here
         domains = +local_domains
	 !verify = recipient

  # ACCEPTING AUTHENTICATED EMAIL FOR RELAY
  # EDIT IF REQUIRED:
  # COMMENT OUT ALL THREE DENY CHECKS BELOW TO ALLOW YOUR CLIENTS WITH
  # INCORRECT FQDN IN ehlo TO USE UNAUTHENTICATED SMTP TO RELAY EMAIL.
  # The three tests below will cause problems for some/most/many remote
  #  users not already using port 587 if their outlook or similar MUA
  # doesn't use a fully qualified domain name (FQDN) in their helo statement.
  # 
  # You may choose to comment out these three deny checks, but if you do
  # it's likely you'll see much more spam than if you don't.

  # Deny all unauthenticated if Helo is neither a FQDN nor address literal

  # 1st deny checks if it's a hostname or IPV4 address with dots or IPV6 address
    deny message = HELO should be a FQDN or address literal (See RFC 2821 4.1.1.1)
         !authenticated = *
         condition   = ${if match{$sender_helo_name}{\N^\[\N}{no}{yes}}
         condition   = ${if match{$sender_helo_name}{\N\.\N}{no}{yes}}

  # 2nd deny makes sure the hostname doesn't end with a dot (invalid)
    deny message = HELO should be a Fully Qualified Domain Name or an address literal (See RFC2821 4.1.1.1)
         !authenticated = *
         condition   = ${if match{$sender_helo_name}{\N\.$\N}}

  # 3rd deny makes sure the hostname has no double-dots (invalid)
    deny message = HELO should be a Fully Qualified Domain Name or an address literal (See RFC2821 4.1.1.1) 
         !authenticated = *
         condition   = ${if match{$sender_helo_name}{\N\.\.\N}}

  # EDIT AS REQUIRED TO FIT YOUR ENVIRONMENT
  # EDIT TO IMPLEMENT CLAMAV
  # if you use ClamAV uncomment the two lines below to set acl_m0 to
  # use later in the data acl to implement ClamAV for all domains not listed
  # in skip_av_domains

#  warn domains = +skip_av_domains
#  set acl_m0 = $tod_epoch

  # allow local users to send outgoing messages using slashes
  # and vertical bars in their local parts.
  # Block outgoing local parts that begin with a dot, slash, or vertical
  # bar but allows them within the local part.
  # The sequence \..\ is barred. The usage of @ % and ! is barred as
  # before. The motivation is to prevent your users (or their virii)
  # from mounting certain kinds of attacks on remote sites.
  deny  domains       = !+local_domains
        local_parts   = ^[./|] : ^.*[@%!] : ^.*/\\.\\./

  # local source whitelist
  # accept if the source is local SMTP (i.e. not over TCP/IP).
  # Test for this by testing for an empty sending host field.
  accept  hosts = :
          logwrite = Whitelisted as having local origination

  # sender domains whitelist
  # accept if sender domain is in whitelist
  accept  sender_domains = +whitelist_domains
         logwrite = $sender_host_address whitelisted in local whitelist

  # sender hosts whitelist
  # accept if sender host is in whitelist
  accept  hosts = +whitelist_hosts
  accept  hosts = +whitelist_hosts_ip
         logwrite = $sender_host_address whitelisted in local whitelist

  # envelope senders whitelist
  # accept if envelope sender is in whitelist
  accept  senders = +whitelist_senders
          logwrite = $sender_host_address whitelisted in local whitelist

  # deny email addresses in blacklist_senders
  # EDIT AS REQUIRED TO FIT YOUR ENVIRONMENT
  # EDIT edit message to fit your needs.
    deny message = Email blocked by local blacklist
    domains = +use_rbl_domains
    senders = +blacklist_senders

  # deny hostnames in bad_sender_hosts blacklist
  # even if sent to postmaster, hostmaster, or abuse
  # Note this breaks RFCs but we think you should be able to do this.
  # EDIT AS REQUIRED TO FIT YOUR ENVIRONMENT
  # EDIT Your deny message should be sent back to the original sender
  # you may want to change it to point to your policy or page on whitelisting
  # note this is placed before public whitelists because they're often
  #      wrong and you may need to block servers they whitelist.
  # EDIT edit message to fit your needs.
    deny message = Email blocked by server's local blacklist
       # only for domains that do want to be tested against RBLs
       domains = +use_rbl_domains
       hosts = +bad_sender_hosts

  # Deny IPs in your local bad_sender_hosts blacklist
  # even if sent to postmaster, hostmaster, or abuse
  # Note this breaks RFCs but we think you should be able to do this.
  # EDIT AS REQUIRED TO FIT YOUR ENVIRONMENT
  # EDIT Your deny message should be sent back to the original sender
  # you may want to change it to point to your policy or page on whitelisting
  # note this is placed before public whitelists because they're often
  #      wrong and you may need to block servers they whitelist..
  # EDIT edit message to fit your needs
  deny message = Email blocked by server's local blacklist
       hosts = +bad_sender_hosts_ip

  # dnswl.org whitelist (whitelist official ISP servers)
  # accept if IP# is listed at dnswl.org as whitelisted
  accept domains = +local_domains
         dnslists = list.dnswl.org
         logwrite = $sender_host_address whitelisted in list.dnswl.org

  # hostkarma.junkemailfilter.com used as whitelist
  # the hostkarma whitelist will help against some false negatives
  # but we find some additional false positives if we accept using this
  # whitelist; use it at your own risk.
  # 
  # to use it, uncommend the three lines below which begin with "accept"
  #
  # accept if IP# is listed at hostkarma.junkemailfilter.com as whitelisted
  # 127.0.0.1 means whitelisted
  # accept domains = +local_domains
  #        dnslists = hostkarma.junkemailfilter.com=127.0.0.1
  #        logwrite = $sender_host_address whitelisted in hostkarma.junkemailfilter.com

  # NOW ACCEPT EMAIL TO postmaster, hostmaster, or abuse
  # EDIT AS REQUIRED TO FIT YOUR ENVIRONMENT
  # accept mail to postmaster in any local domain, regardless of source
  accept  local_parts = postmaster
          domains     = +local_domains

  # accept mail to abuse in any local domain, regardless of source
  accept  local_parts = abuse
          domains     = +local_domains

  # accept mail to hostmaster in any local domain, regardless of source
  accept  local_parts = hostmaster
          domains     =+local_domains

  # OPTIONAL MODIFICATIONS:
  # If the page you're using to notify senders of blocked email of how
  # to get their address unblocked will use a web form to send you email so
  # you'll know to unblock those senders, then you may leave these lines
  # commented out.  However, for example, if you'll be telling your
  # senders of blocked email to send an email to [email protected],
  # then you should replace "errors" with the left side of the email
  # address you'll be using, and "example.com" with the right side of the
  # email address and then uncomment the two lines beginning with the line
  # which begins with the word accept
  #
  # Doing this will mean anyone can send email to this specific address,
  # even if they're at a blocked domain, and even if your domain is using
  # blocklists.

  # accept mail to [email protected], regardless of source
  # EDIT AS REQUIRED TO FIT YOUR ENVIRONMENT
  # EDIT be sure to change to use your own email address
  accept  local_parts = errors
          domains     = example.com

  # OPTIONAL MODIFICATIONS:
  # By default we do NOT require sender verification.
  # Sender verification denies email unless sender address can be
  # verified:
  # If you want to require sender verification, i.e., that the
  # sending address is routable and mail can be delivered to it, then
  # uncomment the line beginning with the word "require".

  # EDIT AS REQUIRED TO FIT YOUR ENVIRONMENT
  # Comment out the next line if you do not want sender verification
  require verify = sender
  
  # deny domains in local blacklist
  # EDIT AS REQUIRED TO FIT YOUR ENVIRONMENT
  # EDIT edit message to fit your needs.
    deny message = Email blocked by server's local blacklist
       # only for domains that do want to be tested against RBLs
       domains = +use_rbl_domains
       sender_domains = +blacklist_domains

  # deny email forging paypal sender
  # we find this a very safe block for use in the U.S. If this blocks real
  # PayPal email in your country, then you should disable it by
  # commenting out the three lines beginning with "deny".
    deny message = Forged Paypal Mail, not sent from PayPal.
         senders = *@paypal.com
         condition = ${if match {$sender_host_name}{\Npaypal.com$\N}{no}{yes}}

  # Next deny stuff from blacklists for hosts in use_rbl_domains

  # Deny using various RBLs
  # EDIT AS REQUIRED TO FIT YOUR ENVIRONMENT
  # EDIT edit message to fit your needs.
  deny message = Email blocked by $dnslist_domain
       hosts    = !+relay_hosts
       domains = +use_rbl_domains
       !authenticated = *
       dnslists = \
       zen.spamhaus.org : \
       dnsbl.njabl.org : \
       bl.spamcop.net : \
       dnsbl.ahbl.org : \
       cbl.abuseat.org : \
       combined.rbl.msrbl.net : \
       hostkarma.junkemailfilter.com=127.0.0.2

  ## LISTS NOT INCLUDED AT THIS TIME; PERHAPS WE'LL INCLUDE THEM LATER:
       # bogusmx.rfc-ignorant.org/$sender_address_domain

  ## WOULD BE NICE TO INCLUDE BUT REQUIRES DA-SANCTIONED ADDITION TO exim.pl
       # http://www.directadmin.com/forum/showthread.php?p=107371#post107371

  ## NAME BASED BLOCKLIST EMAIL CHECKS
  # EDIT AS REQUIRED TO FIT YOUR ENVIRONMENT
  # EDIT edit message to fit your needs.
  deny message = Email blocked by $dnslist_domain
       hosts    = !+relay_hosts
       domains = +use_rbl_domains
       !authenticated = *
       dnslists = \
       rhsbl.ahbl.org/$sender_address_domain : \
       block.rhs.mailpolice.com/$sender_address_domain

  # ACCEPT EMAIL BEGINNING HERE
  # accept if address is in a local domain as long as recipient can be verified
  accept  domains = +local_domains
          endpass
	  message = "Unknown User"
          verify = recipient

  # accept if address is in a domain for which we relay as long as recipient
  # can be verified
  accept  domains = +relay_domains
          endpass
          verify = recipient

  # accept if message comes for a host for which we are an outgoing relay
  # recipient verification is omitted because many MUA clients don't cope
  # well with SMTP error responses.
  # EDIT AS REQUIRED TO FIT YOUR ENVIRONMENT
  # EDIT If you are actually relaying from MTAs then you should probably
  #      add recipient verify here
  accept  hosts = +relay_hosts
  accept  hosts = +auth_relay_hosts
          endpass
          message = authentication required
          authenticated = *

  # FINAL DENY EMAIL BEFORE DATA BEGINS HERE
  # default at end of acl causes a "deny", but line below will give
  # an explicit error message:
  deny    message = relay not permitted

.ifdef DKIM_VERIFY
  # ACL that is used to check DKIM signatures
acl_check_dkim:
# Warn when message apparently from GMail has no signature at all
warn log_message = GMail sender without DKIM signature
     sender_domains = gmail.com
     dkim_signers = gmail.com
     dkim_status = none

deny message = Message from Paypal with invalid or missing signature
     sender_domains = paypal.com:paypal.de
     dkim_signers = paypal.com:paypal.de
     dkim_status = none:invalid:fail

  accept
.endif


# ACL that is used after the DATA command
acl_check_message:
  # EDIT AS REQUIRED TO FIT YOUR ENVIRONMENT
  # EDIT TO IMPLEMENT CLAMAV
  # Uncomment this entire section (except the comment lines beginning with "# #"
  # when implementing ClamAV

  # # accept without checking if in skip_av_domains
  #  accept condition =${if and {{def:acl_m0}{def:acl_m0}} {true}{false}}
  #
  #  deny message = This message contains malformed MIME ($demime_reason)
  #  demime = *
  #  condition = ${if >{$demime_errorlevel}{2}{1}{0}}
  #
  #  deny message = This message contains a virus or other harmful content ($malware_name)
  #  demime = *
  #  malware = *
  #
  #  deny message = This message contains an attachment of a type which we do not accept (.$found_extension)
  #  demime = bat:com:pif:prf:scr:vbs
  #
  # # Accept but put warning into headers if message over 1000k
  #  warn message = X-Antivirus-Scanner: Skipped scanning; size over 1000K. You should use an Antivirus Scanner
  #  condition = ${if >={$message_size}{1000k} {1}{0}}
  #
  #  warn message = X-Antivirus-Scanner: Seems clean.  You should still use an Antivirus Scanner

  # DO NOT COMMENT OUT accept line BELOW
  # default to accept (otherwise all would be denied)
  accept

# AUTHENTICATION CONFIGURATION
##############################
begin authenticators

plain:
    driver = plaintext
    public_name = PLAIN
    server_prompts = :
    server_condition = "${perl{smtpauth}}"
    server_set_id = $2

login:
    driver = plaintext
    public_name = LOGIN
    server_prompts = "Username:: : Password::"
    server_condition = "${perl{smtpauth}}"
    server_set_id = $1

# REWRITE CONFIGURATION
# There is no rewriting specification in this exim.conf file

# ROUTERS CONFIGURATION
# Specifies how remote addresses are handled.
#
# Remote addresses are those with a domain that does not match any item
# in the "local_domains" setting above.
#
# We specify two routers, but only one or the other may be used.
#
# If this server routes its own remote email, then the lookuphost
# router should be uncommented and the smarthost driver should be commented.
#
# If this router sends all remote email to a smarthost, then the lookuphost
# router should be commented and the smarthost driver should be uncommented.
#
# By default this exim.conf file presumes this server will rout its own
# remote email.

begin routers

# EDIT AS REQUIRED TO FIT YOUR ENVIRONMENT
# EDIT Only one of these routers may be uncommented; see notes above.
lookuphost:
  driver = dnslookup
  domains = ! +local_domains
  ignore_target_hosts = 127.0.0.0/8
  condition = "${perl{check_limits}}"
  transport = remote_smtp
  no_more

#smarthost:
#  driver = manualroute
#  route_list = !+local_domains da6.namelessnet.com
#  transport = remote_smtp

# DIRECTORS CONFIGURATION
# Specifies how local addresses are handled.
#
# Order does matter; a local address is passed to each in turn until
# it is accepted.

# Local addresses are those with a domain that matches some item in
# the local_domains setting above.

# Spam Assassin
# EDIT AS REQUIRED TO FIT YOUR ENVIRONMENT
# EDIT Uncomment the section below (including the "spamcheck_director"
#      line) if you've Installed Spam Assassin on your server. Note that
#      this section should NOT be uncommented unless Spam Assassin is
#      installed on your server.

# spamcheck_director:
#   driver = accept
#   condition = "${if and { \
# 			{!def:h_X-Spam-Flag:} \
#			{!eq {$received_protocol}{spam-scanned}} \
#			{!eq {$received_protocol}{local}} \
#			{exists{/home/${lookup{$domain}lsearch{/etc/virtual/domainowners}{$value}}/.spamassassin/user_prefs}} \
#			{<{$message_size}{100k}} \
#		} {1}{0}}"
#  retry_use_local_part
#  transport = spamcheck
#  no_verify

majordomo_aliases:
  driver = redirect
  allow_defer
  allow_fail
  data = ${if exists{/etc/virtual/${domain}/majordomo/list.aliases}{${lookup{$local_part}lsearch{/etc/virtual/${domain}/majordomo/list.aliases}}}}
  domains = lsearch;/etc/virtual/domainowners
  file_transport = address_file
  group = daemon
  pipe_transport = majordomo_pipe
  retry_use_local_part
  no_rewrite
  user = majordomo

majordomo_private:
  driver = redirect
  allow_defer
  allow_fail
  #condition = "${if eq {$received_protocol} {local} {true} {false} }"
  condition = "${if or { {eq {$received_protocol} {local}} \
                         {eq {$received_protocol} {spam-scanned}} } {true} {false} }"
  data = ${if exists{/etc/virtual/${domain}/majordomo/private.aliases}{${lookup{$local_part}lsearch{/etc/virtual/${domain}/majordomo/private.aliases}}}}
  domains = lsearch;/etc/virtual/domainowners
  file_transport = address_file
  group = daemon
  pipe_transport = majordomo_pipe
  retry_use_local_part
  user = majordomo

domain_filter:
  driver = redirect
  allow_filter
  no_check_local_user
  condition = "${if exists{/etc/virtual/${domain}/filter}{yes}{no}}"
  user = "${lookup{$domain}lsearch{/etc/virtual/domainowners}{$value}}"
  group = "mail"
  file = /etc/virtual/${domain}/filter
  directory_transport = address_file
  pipe_transport = virtual_address_pipe
  retry_use_local_part
  no_verify

uservacation:
  # uservacation reply to all except errors, bounces, lists
  driver = accept
  condition = ${lookup{$local_part} lsearch {/etc/virtual/${domain}/vacation.conf}{yes}{no}}
  require_files = /etc/virtual/${domain}/reply/${local_part}.msg
  # do not reply to errors and bounces or lists
  senders = " ! ^.*-request@.*:\
              ! ^owner-.*@.*:\
              ! ^postmaster@.*:\
              ! ^listmaster@.*:\
              ! ^mailer-daemon@.*\
              ! ^root@.*"
  transport = uservacation
  unseen

userautoreply:
  driver = accept
  condition = ${lookup{$local_part} lsearch {/etc/virtual/${domain}/autoresponder.conf}{yes}{no}}
  require_files = /etc/virtual/${domain}/reply/${local_part}.msg
  # do not reply to errors and bounces or lists
  senders = " ! ^.*-request@.*:\
              ! ^owner-.*@.*:\
              ! ^postmaster@.*:\
              ! ^listmaster@.*:\
              ! ^mailer-daemon@.*\
              ! ^root@.*"
  transport = userautoreply
  unseen

virtual_aliases_nostar:
  driver = redirect
  allow_defer
  allow_fail
  data = ${if exists{/etc/virtual/${domain}/aliases}{${lookup{$local_part}lsearch{/etc/virtual/${domain}/aliases}}}}
  file_transport = address_file
  group = mail
  pipe_transport = virtual_address_pipe
  retry_use_local_part
  unseen
  #include_domain = true

virtual_user:
  driver = accept
  condition = ${perl{save_virtual_user}}
  domains = lsearch;/etc/virtual/domainowners
  group = mail
  retry_use_local_part
  transport = virtual_localdelivery

# accept only if local_part is not in the aliases file
# (this implements catch-all)
virtual_aliases:
  driver = redirect
  allow_defer
  allow_fail
  condition = ${if eq {}{${if exists{/etc/virtual/${domain}/aliases}{${lookup{$local_part}lsearch{/etc/virtual/${domain}/aliases}}}}}{yes}{no}}
  data = ${if exists{/etc/virtual/$domain/aliases}{${lookup{$local_part}lsearch*{/etc/virtual/$domain/aliases}}}}
  file_transport = address_file
  group = mail
  pipe_transport = virtual_address_pipe
  retry_use_local_part
  #include_domain = true

# if we have an alias, but no passwd entry we have to drop the email because the
# first alias is unseen (so that you can forward as well as save it)
# The save part is "seen" (virtual_user), but the forward before it isn't.  This
# will be the spot where we "see" the email so that it doesn't send a bounce if
# we have an alias but no pop.
drop_solo_alias:
  driver = redirect
  allow_defer
  allow_fail
  data = ${if exists{/etc/virtual/$domain/aliases}{${lookup{$local_part}lsearch{/etc/virtual/$domain/aliases}}}}
  file_transport = devnull
  group = mail
  pipe_transport = devnull
  retry_use_local_part
  #include_domain = true

# This director handles forwarding using traditional .forward files.
# If you want it also to allow mail filtering when a forward file
# starts with the string "# Exim filter", uncomment the "filter" option.
# The check_ancestor option means that if the forward file generates an
# address that is an ancestor of the current one, the current one gets
# passed on instead. This covers the case where A is aliased to B and B
# has a .forward file pointing to A. The three transports specified at the
# end are those that are used when forwarding generates a direct delivery
# to a file, or to a pipe, or sets up an auto-reply, respectively.
userforward:
  driver = redirect
  allow_filter
  check_ancestor
  check_local_user
  no_expn
  file = $home/.forward
  file_transport = address_file
  pipe_transport = address_pipe
  reply_transport = address_reply
  no_verify

system_aliases:
  driver = redirect
  allow_defer
  allow_fail
  data = ${lookup{$local_part}lsearch{/etc/aliases}}
  file_transport = address_file
  pipe_transport = address_pipe
  retry_use_local_part
  # user = exim

# The director below matches local user mailboxes
localuser:
  driver = accept
  check_local_user
  condition = "${if eq {$domain} {$primary_hostname} {yes} {no}}"
  transport = local_delivery

# TRANSPORTS CONFIGURATION
# ORDER DOES NOT MATTER; ONLY ONE APPROPRIATE TRANSPORT
# IS CALLED FOR EACH DELIVERY

# A transport is used only when referenced from a director or a router that
# successfully handles an address.

begin transports

# The spamcheck router is used by SpamAssassin
# NOTE this transport need not be commented out if you don't use spamassassin
#      on your server; if that's the case it won't ever be called
spamcheck:
  driver = pipe
  batch_max = 100
  command = /usr/sbin/exim -oMr spam-scanned -bS
  current_directory = "/tmp"
  group = mail
  home_directory = "/tmp"
  log_output
  message_prefix = 
  message_suffix = 
  return_fail_output
  no_return_path_add
  transport_filter = /usr/bin/spamc -u ${lookup{$domain}lsearch*{/etc/virtual/domainowners}{$value}}
  use_bsmtp
  user = mail
  # must use a privileged user to set $received_protocol on the way back in!

#majordomo
majordomo_pipe:
  driver = pipe
  group = daemon
  return_fail_output
  user = majordomo

# The transport below is used for local delivery to user mailboxes
# in Maildir format, in the user's local Maildir Directory as defined
# by DirectAdmin
local_delivery:
  driver = appendfile
  delivery_date_add
  envelope_to_add
  directory = /home/$local_part/Maildir/
  directory_mode = 770
  create_directory = true
  maildir_format
  group = mail
  mode = 0660
  return_path_add
  user = ${local_part}

# The transport below is for delivering virtual domain users' email
# to their own mail spool
virtual_localdelivery:
  driver = appendfile
  create_directory
  delivery_date_add
  directory_mode = 770
  envelope_to_add
  directory = /home/${lookup{$domain}lsearch*{/etc/virtual/domainowners}{$value}}/imap/${domain}/${local_part}/Maildir
  maildir_format
  group = mail
  mode = 660
  return_path_add
  user = "${lookup{$domain}lsearch*{/etc/virtual/domainowners}{$value}}"
  quota = ${if exists{/etc/virtual/${domain}/quota}{${lookup{$local_part}lsearch*{/etc/virtual/${domain}/quota}{$value}{0}}}{0}}

# The vacation transport is below
uservacation:
  driver = autoreply
  file = /etc/virtual/${domain}/reply/${local_part}.msg
  from = "${local_part}@${domain}"
  log = /etc/virtual/${domain}/reply/${local_part}.log
  no_return_message
  subject = "${if def:h_Subject: {Autoreply: ${quote:${escape:$h_Subject:}}} {I am on vacation}}"
  text = "\
	------                                                           ------\n\n\
	This message was automatically generated by email software\n\
	The delivery of your message has not been affected.\n\n\
	------                                                           ------\n\n"
  to = "${sender_address}"
  user = mail
	#once = /etc/virtual/${domain}/reply/${local_part}.once

# The autoreply transport is below
userautoreply:
  driver = autoreply
  bcc = ${lookup{${local_part}} lsearch {/etc/virtual/${domain}/autoresponder.conf}{$value}}
  file = /etc/virtual/${domain}/reply/${local_part}.msg
  from = "${local_part}@${domain}"
  log = /etc/virtual/${domain}/reply/${local_part}.log
  no_return_message
  subject = "${if def:h_Subject: {Autoreply: ${quote:${escape:$h_Subject:}}} {Autoreply Message}}"
  to = "${sender_address}"
  user = mail
  #once = /etc/virtual/${domain}/reply/${local_part}.once

# The follow transport delivers email destined to /dev/null
devnull:
  driver = appendfile
  file = /dev/null

# This transport is used for delivering messages over SMTP connections.
remote_smtp:
  driver = smtp

# The transports below are used for handling pipe deliveries generated by alias
# or .forward files. If the pipe generates any standard output, it is returned
# to the sender of the message as a delivery error. Set return_fail_output
# instead of return_output if you want this to happen only when the pipe fails
# to complete normally. You can set different transports for aliases and
# forwards if you want to - see the references to address_pipe in the directors
# section below.
address_pipe:
  driver = pipe
  return_output

virtual_address_pipe:
  driver = pipe
  group = nobody
  return_output
  user = "${lookup{$domain}lsearch* {/etc/virtual/domainowners}{$value}}"

# The transport below is used for handling deliveries directly to files that are
# generated by aliasing or forwarding.
address_file:
  driver = appendfile
  delivery_date_add
  envelope_to_add
  return_path_add

# The transport below is used for handling autoreplies generated by the filtering
# option of the forwardfile director.
address_reply:
  driver = autoreply

# RETRY CONFIGURATION
# This single retry rule applies to all domains and all errors. It specifies
# retries every 15 minutes for 2 hours, then increasing retry intervals,
# starting at 1 hour and increasing each time by a factor of 1.5, up to 16
# hours, then retries every 8 hours until 4 days have passed since the first
# failed delivery.

# Domain               Error       Retries
# ------               -----       -------
begin retry
*                      *           F,2h,15m; G,16h,1h,1.5; F,4d,8h
# End of Exim 4 configuration


Edit: forgot the accept.
 
Last edited:
You're doing the work for me :). Either I'm going to use your changes or I'm going to wait until I have a week or so downstream, or I'm going to leave it out. If you assure me your work is working better than not having it, I'll put it on one of my systems and try it.

Why do you have: DKIM_VERIFY = no

???

Thanks.

Jeff
 
The conditions are straight from chapter 54. I suggest you test it first, just to make sure there aren't any unforseen issues.

I set the macro to no, so that people can choose to enable it or not.
 
One thing before I forget...
Since signature verification is costing CPU time, a good thing to do is to add "control = dkim_disable_verify" in the ACLs where you accept messages from authenticated users or relay hosts. No need to check the signature when sending messages.
 
How do we sign outgoing messages with DKIM? Did I miss that above? I know that is supposed to help with sending email to yahoo.
 
That's an entirely different matter...and it has to be implemented by DA, not the Spamblocker_Technology_for_Exim.conf (TM).
Would be great if DA could implement both DNSSEC and DKIM together since they both involve changing the way DNS is managed.
 
So exactly what is it that this code does?

I'm posting a new RC (6) tonight. The only way I'll consider this code is if you someone can create a diff file for me, comparing it with my new RC. Hopefully within a day or two.

Jeff
 
warn log_message = GMail sender without DKIM signature
deny message = Message from Paypal with invalid or missing signature
It warns you if a message from gmail wasn't signed.
It refuses messages from Paypal with an invalid or missing signature, which was the goal of that modification: to remove Paypal specific code and to replace it with something more flexible.

Keeping this in the exim.conf file will make it easier for people to add their own checks.
 
Last edited:
Keeping this in the exim.conf file will make it easier for people to add their own checks.
Where? I've agreed to put the code in, but only if I can get the diff file before the feature freeze. I just don't have time to do anymore myself right now.

Jeff
 
Back
Top