Если настройка OpenDKIM производится для сервера servername.example.com который отвечает за почту домена example.com, то последовательность действий будет следующая.

Перед выполнением инструкций убедитесь что:

  • команда hostname -f возвращает FQDN вида servername.example.com
  • hostname без аргументов возвращает servername
  • hostname -d возвращает example.com

    $ hostname -f; hostname; hostname -d
    servername.example.com
    servername
    example.com
    

Если у вас это не так, смотрите подсказку после инструкций.

Только при выполнении этих условий указанные ниже команды сработают корректно.

Делаем по шагам

Инструкции должны работать как минимум в Debian "stretch" и "jessie", а также в родственных дистрибутивах включая Ubuntu. В других дистрибутивах могут быть существенные или несущественные отличия.

apt install opendkim opendkim-tools
  1. Создадим набор ключей для сервера исходя из его имени.

    mkdir /etc/opendkim/
    opendkim-genkey -D /etc/opendkim/ -d $(hostname -d) -s $(hostname)
    
  2. Зададим корректные права на доступ к ключам и защитим их от случайной перезаписи.

    chgrp opendkim /etc/opendkim/*
    chmod g+r /etc/opendkim/*
    chown opendkim /etc/opendkim/*.private
    chmod go-rwx,a-w /etc/opendkim/*.private
    chmod a+r /etc/opendkim/*.txt
    chattr +i /etc/opendkim/*.txt /etc/opendkim/*.private
    
  3. Пропишем ключи в конфигурационных файлах.

    echo $(hostname -f | sed s/\\./._domainkey./) $(hostname -d):$(hostname):$(ls /etc/opendkim/*.private) | 
        tee -a /etc/opendkim/keytable
    echo $(hostname -d) $(hostname -f | sed s/\\./._domainkey./) | 
        tee -a /etc/opendkim/signingtable
    
  4. Запишем базовую конфигурацию для OpenDKIM включающую только добавление подписей.

    tee -a /etc/opendkim.conf  <<EOF
    Canonicalization relaxed/relaxed
    Mode s
    KeyTable file:/etc/opendkim/keytable
    SigningTable file:/etc/opendkim/signingtable
    SoftwareHeader yes
    Socket /var/spool/postfix/var/run/opendkim/opendkim.sock
    PidFile /var/run/opendkim/opendkim.pid
    UserID opendkim
    EOF
    
  5. Дадим Postfix доступ к сокету OpenDKIM.

    gpasswd -a postfix opendkim
    
  6. Настроим Postfix на использование OpenDKIM с учетом работы того в chroot.

    postconf -e milter_default_action=accept
    postconf -e milter_protocol=2
    postconf -e smtpd_milters=unix:/var/run/opendkim/opendkim.sock
    postconf -e non_smtpd_milters=unix:/var/run/opendkim/opendkim.sock
    echo SOCKET="local:/var/spool/postfix/var/run/opendkim/opendkim.sock" | 
       tee -a /etc/default/opendkim
    echo RUNDIR=/var/spool/postfix/var/run/opendkim |
       tee -a /etc/default/opendkim
    mkdir -p /var/spool/postfix/var/run/opendkim
    chown opendkim:opendkim /var/spool/postfix/var/run/opendkim
    
  7. Postfix должен использовать TLS для общения с другими серверами, если возможно.

    postconf -e smtp_tls_security_level=may
    
  8. Перезапустим все задействованные службы.

    service opendkim restart
    service postfix reload
    
  9. Посмотрим публичный ключ и добавим его в DNS.

    cat /etc/opendkim/*.txt
    
  10. Наконец, проверим что публичный ключ виден миру.

    dig +short TXT $(hostname -f | sed s/\\./._domainkey./)
    

Для желающих разобраться есть и более подробное описание настройки связки Postfix + OpenDKIM с разбором каждого шага и детальными объяснениями.

Что дальше?

Можно попросить весь интернет не принимать письма без DKIM-подписи с вашего домена.

_adsp._domainkey IN TXT "dkim=all"
_dmarc IN TXT "v=DMARC1; p=reject"

Что если hostname у меня работает не так?

Имя хоста в Debian и родственных дистрибутивах задаётся в двух местах:

  1. В /etc/hostname указывается имя сервера без домена. В нашем случае в /etc/hostname должна быть только одна строка:

    servername
    
  2. FQDN задаётся в /etc/hosts в следующем формате:

    172.31.64.88    servername.example.com  servername
    

    Где 172.31.64.88 - публичный IP сервера.

При успешной настройке вы должны получить аналогичный вывод:

$ hostname -f; hostname; hostname -d
servername.example.com
servername
example.com

Добавить ещё один домен

Нужно подписывать письма для ещё одного домена? Легче лёгкого!

read -p "Enter domain name: " domainname

Затем:

echo $(date -I)._domainkey.$domainname $domainname:$(date -I):$(ls /etc/opendkim/*.private) |
    tee -a /etc/opendkim/keytable
echo $domainname $(date -I)._domainkey.$domainname |
    tee -a /etc/opendkim/signingtable

Перезапускаем OpenDKIM, добавляем TXT запись для этого домена с текущей датой:

service opendkim restart
cat /etc/opendkim/*.txt | sed s/$(hostname)/$(date -I)/ | sed s/$(hostname -d)/$domainname/g

Готово!

Решение проблем

Подписи перестали добавляться к письмам, а письма - попадают в спам. Обычно в заголовках таких писем пишется что именно пошло не так. Например:

Authentication-Results: i=1; mx.example.com;
    arc=none (no signatures found);
    dkim=none (no signatures found);
    dmarc=fail (p=reject) header.from=my.test.ru;

Какие-то почтовики (например, Gmail и Яндекс) при ошибках могут конкретно отказаться получать письмо, а отправителю придёт сообщение с ошибкой вида:

host mx.yandex.ru[213.180.204.89] said:
    550 5.7.1 Email rejected per DMARC policy for test.ru (in reply to end of DATA command)

host aspmx.l.google.com[2404:6800:4008:c04::1a] said:
    550-5.7.1 Unauthenticated email from test.ru is not accepted due to
    domain's DMARC policy. Please contact the administrator of
    test.ru domain if this was a legitimate mail.

В таких случаях обычно в логе вы увидите следующую ошибку:

$ grep warning /var/log/mail.log
postfix/cleanup: warning: connect to Milter service unix:/var/run/opendkim/opendkim.sock: Permission denied

Проверьте, что у пользователей из группы opendkim в самом деле есть доступ к этому файлу. Например, с такими правами на файл у них доступа нет:

# ls -l /var/spool/postfix/var/run/opendkim/opendkim.sock
srwxrwx--- 1 root root 0 Sep 30 21:37 /var/spool/postfix/var/run/opendkim/opendkim.sock

Если у вас такая ситуация, убедитесь что в конфиге OpenDKIM есть директива, указывающая с какой группой ему следует работать:

$ grep UserID /etc/opendkim.conf
UserID opendkim

Если директивы нет, то её следует добавить, затем удалить файл сокета и перезапустить OpenDKIM:

tee -a /etc/opendkim.conf <<EOF
UserID opendkim
EOF
rm /var/spool/postfix/var/run/opendkim/opendkim.sock
service opendkim restart

После перезапуска файл будет иметь правильную группу и владельца:

# ls -l /var/spool/postfix/var/run/opendkim/opendkim.sock
srwxrwx--- 1 opendkim opendkim 0 Sep 30 21:39 /var/spool/postfix/var/run/opendkim/opendkim.sock

После обновления с переходом на systemd перестал запускаться OpenDKIM?

Если с правами на доступ к файлу всё в порядке, или же файла просто нет, то дело может быть в том, что с переходом на systemd перестали использоваться настройки из /etc/default/opendkim для запуска демона OpenDKIM. Теперь всё-всё нужно указывать в самом конфигурационном файле. Конкретно, нужно добавить три директивы для сокета, который нужен Postfix, для файла с PID, который ожидает найти systemd, и для пользователя, с которым должен работать OpenDKIM:

tee -a /etc/opendkim.conf <<EOF
UserID opendkim
Socket /var/spool/postfix/var/run/opendkim/opendkim.sock
PidFile /var/run/opendkim/opendkim.pid
EOF
systemctl restart opendkim

При любых сомнениях корректность конфигурации можно проверить так:

/usr/sbin/opendkim -n -x /etc/opendkim.conf && echo OK

Должно вывести OK.

Всё ещё что-то не так

Если у вас правильно настроен обратный адрес (можно ответить на письмо и вы получите ответ), воспользуйтесь тестером писем от IETF отправив простое письмо:

echo test | mail -s test tester@email-test.had.dnsops.gov

Вы получите письмо с описанием ошибок, или с отчётом об успешном прохождении всех тестов. Аналогичные отчёты можно получить отправив письмо на адреса autoreply@dmarctest.org и check-auth@verifier.port25.com. Более полный список способов проверить настройку почтового сервера на сайте DMARC.