How we implemented DKIM in Mail.Ru for Business



    Recently on Habré there was already an article about how “Mail.Ru for business” is getting better thanks to your comments: we told how we implemented your wishes. Today I want to focus on one of the embodied Wishlist - the ability to configure your own DKIM signature. For us, it was one of the priorities: the DKIM setup allows domain owners to verify the sender of a letter. In this post, I’ll talk about how we implemented this feature and how to set up a DKIM signature for my domain.

    A little bit about why DKIM technology is needed

    Wikipedia reminds us that “DomainKeys Identified Mail (DKIM) technology combines several existing anti-phishing and anti-spam methods to improve the classification and identification of legitimate email. Instead of the traditional IP address for determining the sender of the message, DKIM adds a digital signature to it, associated with the organization's domain name. The signature is automatically verified by the recipient. ”

    That is, whenever a user sends an email, our server adds a special header with a digital DKIM signature to it. When generating a signature, a secret key is used (each domain has its own) and excerpts from the letter. This header allows the recipient server to verify that the email is indeed sent by the owner of this domain.

    DKIM signatures are one of the factors that allow our, as well as other anti-spam systems to separate letters from trusted senders from fakes. For example, DKIM provides DMARC technology, which we already wrote about earlier . DMARC allows you to recognize and filter out spam and phishing emails disguised as messages from well-known services.

    In addition, a DKIM signature is needed for the FBL technology to work (thanks to FBL, mailing senders can collect feedback about the status of the customer base and their loyalty, as well as check how subscribers react to mailings and modify the content of letters).

    In general, setting up DKIM signatures is certainly a useful and necessary thing, so the question is “To do it or not?” did not arise. We got to work. Further we will talk in detail about how we implemented this functionality in Mail.Ru for Business. If you don’t want the details, we recommend that you immediately go to the “How do I configure DKIM?” .

    How to set up DKIM signatures appeared in Mail.Ru for Business

    To send letters, we use a very common exim4 Mail Transfer Agent (MTA). It already has built-in tools for placing DKIM signatures in outgoing messages. Until recently, we signed all our letters in exactly this way. However, the problem is that the number of connected business domains is constantly growing, and each domain has its own secret key. If earlier it was enough to spread the keys once across all servers and tell Exim the path to these keys, now this solution is no good. The problem could be solved if Exim was "taught" to apply for a key in a centralized database. So we decided to do so.

    No sooner said than done. Many experts appreciate Exim for its rich customization options. Using the built-in configuration language, you can easily teach Exim to apply for data in “flat” files, Berkeley databases, and even execute SQL queries in relational databases such as MySQL. For the needs of the mail server of an average company, the configuration capabilities are enough for the eyes. If something more is required, then in Exim there are opportunities for writing your own lookup-module, which can be used in configurations along with built-in capabilities.

    To request a key from the database, a small auxiliary lookup-module is created. He is engaged in establishing a connection to the database, authorization, searching for the desired shard, replica, decrypting the received data, etc., providing outward a simple dictionary interface. The process of creating the module is briefly described below.

    First, add the src / lookups / dkim.c file to the source tree (do not forget to add it to the build system by analogy with existing modules). It contains the source code of our module.

    Next, we describe the structure of the new lookup requests in the file:

    /* Какой приватный ключ использовать для подписи */
    static lookup_info _lookup_info1 = {
      US"dkim_privkey",      /* lookup name */
      lookup_querystyle,
      _open_connection,      /* open function */
      NULL,                          /* no check function */
      _get_priv_key,             /* find function */
      _close_connection,      /* close function */
      _tidy_cache,                /* tidy function */
      NULL,                          /* no quoting function */
      NULL                           /* no version function */
    };
    /* Какой селектор указывать в подписи */
    static lookup_info _lookup_info2 = {
      US"dkim_selector",        /* lookup name */
      …
    }; 
    /* Какой домен указывать в подписи */
    static lookup_info _lookup_info3 = {
      US"dkim_domain",        /* lookup name */
      …
    };
    static lookup_info *_lookup_list[] = { &_lookup_info1, &_lookup_info2, &_lookup_info3 };
    lookup_module_info dkim_lookup_module_info = { LOOKUP_MODULE_INFO_MAGIC, _lookup_list, 3 };


    Callback functions in structures have a clear interface and purpose. Details of the implementation of these functions are beyond the scope of the article. I only note that the documentation and examples are enough for the eyes to understand all this.

    After implementing the insides of the module, it remains to register it. We go into the src / drtables.c file and add the module description (where exactly to insert the lines, it is clear from the context - by analogy with the standard code):

    extern lookup_module_info dkim_lookup_module_i
    void init_lookup_list(void)
    {
    …
      addlookupmodule(NULL, &dkim_lookup_module_info);
    ...
    }


    Here's what the use of the module looks like in Exim's configuration:

    begin transports
    remote_smtp:
      driver = smtp
      dkim_domain = ${lookup dkim_domain{$sender_address_domain}{$value}{DKIM_DEFAULT_DOMAIN}}
      dkim_selector = ${lookup dkim_selector{$sender_address_domain}{$value}{DKIM_DEFAULT_SELECTOR}}
      dkim_private_key = ${lookup dkim_privkey{$sender_address_domain}{$value}{DKIM_DEFAULT_KEY}}


    You probably already noticed that three lookups are made to fill in all the parameters in the config. We decided to simply use caching: the first request immediately receives all the necessary information and stores it in the module’s internal variable, subsequent requests check whether the necessary information is cached, and if so, they don’t contact the database anymore - they give it ready.

    The scheme of work is as follows: the domain administrator, through the admin panel, adds an existing one or generates a new secret and public DKIM key. The admin panel saves them in the keystore. Each time a message is sent on behalf of a business domain, Exim requests its secret key from the database. If there is no key, then the default key is used for signing.

    To communicate with the database, we use our standard Kapron component, which we already described earlier inanother article .

    How do I configure DKIM?

    If you already use Mail.Ru for Business, setting up your own DKIM signature is very simple:



    1. Go to biz.mail.ru with authorization of the domain administrator's box.
    2. Select the connected domain for which you want to configure a DKIM signature.
    3. Go to the Server Status section and verify that the MX record is configured correctly. There, after successfully checking the MX record, the value of the TXT record appears, which must be set in the DNS editor.
    4. Copy the value of the TXT record and set it in the DNS editor of your domain.
    5. Wait a few hours after the record is set so that the information is distributed across all DNS servers.
    6. If the record is configured correctly and has passed all our checks, we will send you an email with the successful setup and begin to sign all your letters with the correct DKIM signature.

    If you still have questions about setting up and using a DKIM signature, leave them in the comments.

    Also popular now: