spamassassin-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From j.@jmason.org (Justin Mason)
Subject Re: Setting up DKIM and DomainKeys mail signing and verification
Date Tue, 12 Sep 2006 15:32:47 GMT

Good article -- and thanks for posting it!

For what it's worth, I think it's likely that DomainKeys will be around
for quite a while yet, with plenty of inertia regarding switching to DKIM;
but currently the text makes it sound like DK is already obsolete.  It
might be worth de-emphasising that.

Someday I'll have the tuits to set up signing on our server ;)

--j.

Mark Martinec writes:
> I'm finishing up writing what I have learned in the last
> couple of weeks on setting up a DKIM/DK signing/verifying
> mail system using Postfix, milters, amavisd-new and
> SpamAssassin. The following text will be part of the
> documentation for amavisd-new (text is also available
> at http://www.ijs.si/software/amavisd/amavisd-new-docs.html ),
> but may be general enough so I hope it can be of interest
> to the SpamAssassin community.
> 
> Comments, experience, suggestions and further discussion
> on the topic is most welcome. If considered off-topic,
> off-list mail would be welcome too.
> 
>   Mark
> 
> 
> Setting up DKIM and DomainKeys mail signing and verification
> ============================================================
> 
> The goals of DKIM and DomainKeys are:
>   * assurance of sender identities
>   * protection against message tampering.
> 
> A DKIM draft states the following, which applies to its predecessor
> DomainKeys as well:
> 
>   DomainKeys Identified Mail (DKIM) defines a mechanism by which email
>   messages can be cryptographically signed, permitting a signing domain
>   to claim responsibility for the introduction of a message into the mail
>   stream. Message recipients can verify the signature by querying the
>   signer's domain directly to retrieve the appropriate public key, and
>   thereby confirm that the message was attested to by a party in
>   possession of the private key for the signing domain.
> 
> A gentle introduction and deployment guide is available at:
> http://antispam.yahoo.com/domainkeys. Except for some minor details, it
> applies to DKIM system as well.
> 
> With added support in Postfix 2.3 for a milter protocol, it became
> possible to use with Postfix many of existing milters (mail filters) that
> were originally developed with sendmail in mind. It was hoped that a
> widespread use of milters with sendmail offered a fertile ground for
> software development, producing software of sufficient quality to be able
> to use it with Postfix. It remains to be seen whether quality of freely
> available milters comes anywhere close to high standards we are accustomed
> to with Postfix, but with a bit of luck and reasonable expectations, some
> of it can be put to good use.
> 
> Two of such milters are dkim-milter offering support for DomainKeys
> Identified Mail (DKIM) Signatures, and dk-milter, offering support for
> Domain-based Email Authentication (DomainKeys). The DomainKeys (DK) is a
> predecessor of DKIM, as recognized by draft-delany-domainkeys-base-06:
> 
>   The DomainKeys specification was a primary source from which the
>   DomainKeys Identified Mail [DKIM] specification has been derived. The
>   purpose in submitting this document is as an historical reference for
>   deployed implementations written prior to the DKIM specification.
> 
> At the time of this writing it appears the dkim-milter is more reliable
> and better maintained than dk-milter, which is slowly fading into
> oblivion. Similar holds true in the world of Perl modules: there are
> modules Mail::DomainKeys and Mail::DKIM, both of which can be used by
> SpamAssassin. Again the Mail::DKIM seems to be of higher quality than an
> older Mail::DomainKeys. SpamAssassin makes it very easy to use each or
> both of them (for verification only), just by enabling the already
> provided plugins.
> 
> Despite DomainsKeys slowly giving grounds to DKIM, the DomainsKeys is
> currently still in use by several large players in the Internet world, so
> this section will describe how to integrate both of them with Postfix and
> amavisd-new (an after-queue content filter) into a mail system.
> 
> Mail signing and verification is a two-part job: signing of originating
> mail (or mail being redistributed) from our domain, and verifying
> signatures of incoming mail. Both tasks can be done by the same program,
> or they can be performed by separate entities. Traditionally with
> sendmail, both tasks are performed by the same milter, which may be easier
> to maintain, but has certain disadvantages.
> 
> Verifying signatures should be performed early, before any local mail
> transformations get a chance of invalidating signature, e.g. by performing
> MIME conversions to quote-printable, by fixing syntactically invalid mail
> header, by editing/inserting/removing certain header fields, or by a local
> mailing list modifying mail text, e.g. by appending footnotes.
> 
> Signing outgoing mail should be performed late, after mail sanitation,
> after conversion to 7-bit characters (to avoid later uncontrollable
> changes by a relaying or receiving MTA), and after adding header fields by
> a content filter. Similar applies to local mailing lists, which may be
> rewriting messages, requiring them to be re-signed by the domain hosting a
> mailing list, just before being sent out.
> 
> Since SpamAssassin only provides signature verification but not signing,
> one obvious choice for signing is to use dkim-milter and dk-milter in
> signing-only mode, invoked by a Postfix smtpd service which is receiving
> content-checked mail from a content filter such as amavisd-new. As this
> second-stage smtpd service does not reliably know how a given message came
> into a mail system and whether it is supposed to be signed or not, a clean
> solution is to provide two parallel paths through a content filter, one
> used for mail to be signed (originating mail), the other for all the rest:
> 
>               +------+
>               |verify|            (verify)
>               +--+---+          SpamAssassin
>                  ^                   ^v
> incoming:        |              +----++-----+
>   MX ---->  25 smtpd ---> 10024 >           >--> 10025 smtpd -->
> submission:                     |           |
>   SASL -->  25 smtpd \          |  amavisd  |
>                       +->       |           |
>   mynets->  25 smtpd ---> 10026 >ORIGINATING>--> 10027 smtpd -->
>        --> 587 smtpd --->       +-----------+            |
>                (convert to 7-bit)                        v
>                                                        +----+
>                                                        |sign|
>                                                        +----+
> 
> There are other benefits to providing two parallal paths: a content filter
> may be configured to apply different rules and settings to mail that is
> known to be originating from our users, compared to the rest. Some
> suggestions: apply less strict banning rules, enable spam administrator
> notifications for internally originating spam and viruses, letting
> SpamAssassin rules be conditionalized based on amavisd-new policy banks
> loaded, etc.
> 
> For verification there are two choices: either a SpamAssassin plugin can
> do it by calling Perl modules, or a milter in verification-only mode can
> be invoked by the incoming Postfix smtpd service. In the setup described,
> SpamAssassin sees almost the same message as a milter on the incoming
> smtpd would (just few header fields including a Received are prepended),
> so there is no concern that a signature would become invalid.
> 
> Invoking signature verification by SpamAssassin has an advantage that
> DKIM-based or DomainKeys-based whitelisting or scoring can be used, but
> has a disadvantage that possibly not all mail is checked (e.g. large mail
> may be exempt from spam checks).
> 
> On the other hand, invoking signature verification by calling a milter
> from incoming smtpd service can insert a header field reporting a result
> of verification, which may be used by MUA or by SpamAssassin rules,
> although currently no such rules are provided ready-made.
> 
> For the purpose of gathering experience, both methods for signature
> verification are described. It turns out that one or the other
> implementation (in C or in Perl) may be buggy, and being able to compare
> both results of signature verification can help with troubleshooting.
> 
> Let's begin by starting both milters, each in two instances, one dedicated
> for signing, the other for verification. For security purposes all milters
> should be run under a dedicated username, certainly not as root, not as
> user amavis and not as user postfix:
> 
> dk, verifying:
>   dk-filter   -u dkfilter -b v -m MTA -H \
>     -l -p inet:4442@127.0.0.1 -P /var/run/dk-filter-v.pid
> 
> dkim, verifying:
>   dkim-filter -u dkfilter -b v -m MTA \
>     -l -p inet:4443@127.0.0.1 -P /var/run/dkim-filter-v.pid
> 
> dk, signing:
>   dk-filter   -u dkfilter -b s -m ORIGINATING \
>     -H -c nofws \
>     -d example.com -S myselector -s /var/db/dkim/mykey.pem \
>     -l -p inet:4444@127.0.0.1 -P /var/run/dk-filter-s.pid
> 
> dkim, signing:
>   dkim-filter -u dkfilter -b s -m ORIGINATING \
>     -c relaxed/simple -S rsa-sha1 \
>     -d example.com -s myselector -k /var/db/dkim/mykey.pem \
>     -l -p inet:4445@127.0.0.1 -P /var/run/dkim-filter-s.pid
> 
> Note that both signing milters may (but need not) use the same signing key
> and the same selector. Generating a pair of public and private key and
> publishing a public key and a policy in DNS is described in the
> documentation of each milter.
> 
> Now we can tie both verifying milters to a Postfix smtpd service listening
> for incoming mail:
> 
> master.cf:
>   smtp inet n - n - 300 smtpd
>     -o milter_default_action=accept
>     -o milter_macro_daemon_name=MTA
>     -o smtpd_milters=inet:127.0.0.1:4442,inet:127.0.0.1:4443
> 
> and tie both signing milters to a Postfix smtpd service that is receiving
> checked mail from amavisd, intended to be signed:
> 
> master.cf:
>   # mail return from a content filter (non-signing)
>   10025 inet n - n - - smtpd
>     -o content_filter=
>     ... (other options, mail not to be signed) ...
> 
>   # mail from our users returning from a content filter (DKIM or DK signing)
>   10027 inet n - n - - smtpd
>     -o content_filter=
>     ... (other options, mail to be signed) ...
>     -o milter_default_action=accept
>     -o milter_macro_daemon_name=ORIGINATING
>     -o smtpd_milters=inet:127.0.0.1:4444,inet:127.0.0.1:4445
> 
> Note the order for signing milters: dk-milter is invoked first, and
> dkim-milter second, so that DK signature will be protected by a later DKIM
> signature. The reason is that DomainKeys specification does not protect
> its own signature in its signed data, but the newer DKIM fixes this
> omission and does protect its own signature.
> 
> Default content filter is to be amavisd, listening on port 10026 (intended
> for signing). Locally submited or SASL-authenticated mail will go to a
> content filter on this default port 10026 and will be signed on its way
> out. All other mail (incoming) will be diverted to port 10024 for content
> filtering by a final catchall FILTER, and will never hit the signing
> milter:
> 
> main.cf:
>   content_filter = smtp-amavis:[127.0.0.1]:10026
> 
>   smtpd_recipient_restrictions =
>     ...
>     permit_mynetworks
>     permit_sasl_authenticated
>     reject_unauth_destination
>     ...
>     check_sender_access regexp:/etc/postfix/filter_10024_catchall
>     permit
> 
> /etc/postfix/filter_10024_catchall:
>   /^/  FILTER smtp-amavis:[127.0.0.1]:10024
> 
> In SpamAssassin all that is necessary is to add (or uncomment) lines in
> any of the .pre files (e.g. in local.pre, or in init.pre and v312.pre):
>   loadplugin Mail::SpamAssassin::Plugin::DomainKeys
>   loadplugin Mail::SpamAssassin::Plugin::DKIM
> 
> Perl modules Mail::DomainKeys (version 0.86 or better) and Mail::DKIM
> (0.19 or better) need to be installed.
> 
> The following SpamAssassin rules (in local.cf) work fairly well, giving
> verified mail a little bit of advantage and slightly favourize mail from
> some popular domains, and encourage people to start signing their mail.
> Possible signed spam can be counterbalanced by other measures (see below).
>   score DK_VERIFIED -1.5
>   score DK_POLICY_SIGNSOME 0
>   score DK_POLICY_TESTING  0
> 
>   score DKIM_VERIFIED -1.5
> 
>   # DKIM and DK-based whitelisting may be used reliably:
>   score USER_IN_DKIM_WHITELIST -3.0
>   whitelist_from_dkim *@friends.example.com
>   whitelist_from_dk   *@friends.example.com
> 
> In amavisd.conf two parallel paths need to be provided, one receiving on
> port 10024 and forwarding to 10025, the other receiving on port 10026 and
> forwarding to 10027.
>   $inet_socket_port = [10024,10026];  # listen on two ports
> 
> The 10024/10025 will use a default policy bank, the other, dedicated to
> mail needing to be signed, will use a policy bank ORIGINATING:
>   $forward_method = 'smtp:[127.0.0.1]:10025';  # MTA with non-signing service
>   $notify_method  = 'smtp:[127.0.0.1]:10027';  # MTA with DKIM signing service
> 
>   # switch policy bank to 'ORIGINATING' for mail received on port 10026:
>   $interface_policy{'10026'} = 'ORIGINATING';
> 
>   $policy_bank{'ORIGINATING'} = {  # mail originating from our users
>     # force MTA to convert mail to 7-bit before DKIM signing
>     # to avoid later conversions which could destroy signature:
>     smtpd_discard_ehlo_keywords => ['8BITMIME'],
>     #
>     # forward to a smtpd service providing DKIM/DomainKeys signing service:
>     forward_method => 'smtp:[127.0.0.1]:10027',
>     #
>     # other special treatment of locally originating mail, e.g.:
>     spam_admin_maps => ["virusalert\@$mydomain"],  # warn of spam from us
>     banned_filename_maps => ['ALT-RULES'],  # more relaxed rules...
>   };
> 
> The smtpd_discard_ehlo_keywords=>['8BITMIME'] serves to persuade Postfix
> to convert mail to 7-bit quoted-printable before submitting it to content
> filtering and signing (this configuration variable was introduced with
> version 2.4.3 of amavisd-new). Avoiding 8-bit characters in mail body
> makes signatures less susceptible to breaking by some relaying or
> receiving MTA over which we have no control. Note that the same effect
> (making Postfix convert outgoing mail to 7-bits before DKIM signing) could
> be achieved by a Postfix setting smtp_discard_ehlo_keywords=8bitmime on a
> smtp service feeding mail to be signed to amavisd, but this would require
> setting up two such services, one with the option and one without.
> 
> While testing how the configured system plays with some mailing lists
> (such as postfix-users or SpamAssassin users list), one has to keep in
> mind that amavisd-new caches spam checking results of recently seen
> message bodies, so a mail going out to a mailing list is not yet signed as
> it reaches a content filter, but the SpamAssassin verdict is remembered as
> that point (claiming the message is not signed). When this message with
> unchanged body comes back from a mailing list, this time signed in the
> header by our domain, the signature should prove correct, yet the cached
> result from a minute ago still claims the message is not signed. If this
> is a problem, one can turn off caching of spam checking results for ham by
> setting: $spam_check_negative_ttl = 0;
> 
> ome experience with DKIM and DomainKeys
> 
> Recent versions of software components must be used to avoid bugs and
> interoperability problems with earlier versions:
>   * use Postfix 2.3.3 or later (fixing minor 2.3 problems with milter);
>   * amavisd-new 2.4.3 polished some corner issues on modifying mail header
>     on releasing from a quarantine and defanging, and added some goodies
>     affecting DKIM and DomainKeys to facilitate integration;
>   * Mail::DomainKeys 0.86 or later must be used, the last couple of
>     versions squashed several bugs, one at a time. Version 0.84 dropped
>     the use of unreliable Email::Address (which could cause deep recursion
>     in evaluating regular expressions, bringing processing to a halt).
>     Nevertheless, one patch is still needed (
>     http://www.ijs.si/software/amavisd/Mail-DomainKeys-mark.patch ),
>     hopefully to be included with the next version;
>   * Mail::DKIM 0.19 is very solid, it is the only component where no bugs
>     or design flaws were found during experimenting; in fact, this module
>     helped to discover bugs in other components;
>   * SpamAssassin 3.1.5 added whitelisting based on verified DomainKeys
>     signatures, similar to what was already available for DKIM
>     whitelisting in earlier versions of SA;
>   * both the dkim-milter 0.5.1 and the dk-milter 0.4.1 need a patch as
>     described in the Postfix documentation file MILTER_README. The
>     dkim-milter already supplies a required patch in its bug tracking
>     system under "[1537905] delayed queue ID"; which will be included in
>     the next release;
>   * the dk-milter 0.4.1 seems to be neglected lately and is rather buggy
>     compared to dkim-milter. Nevertheless, with command options as given
>     in the above example, it does its job sufficiently well in a described
>     Postfix + amavisd-new setup, so that it may be deployed for a
>     production use; see its bug tracking system for details;
>   * the dkim-milter 0.4.1 works well with simple/simple or relaxed/simple
>     canononicalization algorithms, while the relaxed/relaxed is to be
>     avoided (and may even be dropped when the specification reaches a RFC
>     stage);
> 
> Instead of signing mail with dkim-milter, the same can be achieved by
> using Jason Long's DKIM Proxy, which is a Perl program calling a Perl
> module Mail::DKIM, i.e. the same modules as used by a SpamAssassin DKIM
> plugin. As the Mail::DKIM turned out to be a reliable and quite efficient
> module, this may be a good alternative to dkim-milter (which is also quite
> good).
> 
> On the other hand there exist a dkfilter SMTP-proxy by the same author,
> which calls a Perl module Mail::DomainKays, which in turn is not
> recommended for processing of entire messages because of its design
> limitation which requires loading the whole message into memory. The use
> of Mail::DomainKays from within SpamAssassin does not represent such a
> problem, as messages checked by SpamAssassin are already limited in size.
> 
> Mail transformations as performed by some mailing lists are the most
> challenging problem facing DKIM and DomainKeys deployment (and to other
> schemes as well). Nevertheless, mailing lists can be configured to either
> avoid transformations which invalidate mail signatures, or can re-sign
> fan-out mail. Examples of mailing lists which work very well with DKIM and
> DomainKeys, preserving existing signatures provided by posters, are the
> postfix-users ( postfix-users@postfix.org ) and the SpamAssassin users
> list ( users@spamassassin.apache.org ). Example of re-signing mailing
> lists are Yahoo groups. A representative of another type of mailing lists
> is currently Mailman, which modifies mail body, but at least it is
> stripping original signatures and adding a Sender header, so that original
> signatures do not appear to be broken, they are just missing, and mail may
> be re-signed.
> 
> Several big players are already signing mail from their users or
> employees: Yahoo! (worldwide), gmail.com and google.com, eBay, Earthlink,
> Cisco, (not to mention porcupine.org :)
> 
> When signatures are missing on mail from domains which are known to be
> signing all their mail (yahoo.com, gmail.com), the most common reason is
> that a sender submitted his mail through some other provider, but supplied
> his Yahoo or gmail e-mail address in the From header field. Similar to
> other schemes designed to prevent faking of sending address, the DKIM (and
> the DomainKeys) encourage mail submission only through a domain which is
> used in the From address - although there are other possibilities for
> roving users, especially in the DKIM system. People will need to become
> aware that their best choice is to submit mail through their home domain
> to prevent their messages being treated as second-class or appear
> suspicious.
> 
> Note that some spam is also being signed by DomainKeys or DKIM lately,
> which is a good thing -- it indicates the sender owns (or ownz) a domain
> they are sending mail from. This either shows sender's sincere interest of
> not hiding behind a faked sender mail address (in which case such mail can
> be easily filtered if desired), or they are using short-lived temporary
> domain (perhaps through domain kiting), which can be counteracted by black
> lists of few-days old freshly registered domains. Adding a small negative
> spam score to successfully verified mail will encourage people to start
> signing their mail, benefiting legitimate senders and recipients, while
> signed spam can be counterbalanced by other measures.
> 
> Signing and verifying mail is a good mechanism for companies to reliably
> whitelist mail from their partner companies or frequent clients.
> 
> 
>   Mark

Mime
View raw message