[exim] SPF/DKIM

Для работы потребуется, что бы Exim был собран с поддержкой SPF/DKIM. Для Debian это означает установку пакета exim4-daemon-heavy.

SPF

Добавляем в DNS такие записи (предпочтительнее):

mydomain.ru. IN TXT "v=spf1 a mx ~all"

а если позволяет DNS, то такую:

mydomain.ru. IN SPF "v=spf1 a mx ~all"

Для проверки того, что запись добавилась и работает, её нужно проверить через spfquery:

# dig -t spf mydomain.ru +short
"v=spf1 +a +mx ~all"
# apt-get install libspf2-2 libmail-spf-perl spf-tools-perl
# spfquery --ip 1.1.1.1 --mail-from a@mydomain.ru --helo mydomain.ru
softfail
mydomain.ru: Sender is not authorized by default to use 'mydomain.ru' in 'helo' identity, however domain is not currently prepared for false failures (mechanism '~all' matched)
mydomain.ru: Sender is not authorized by default to use 'mydomain.ru' in 'helo' identity, however domain is not currently prepared for false failures (mechanism '~all' matched)
Received-SPF: softfail (mydomain.ru: Sender is not authorized by default to use 'mydomain.ru' in 'helo' identity, however domain is not currently prepared for false failures (mechanism '~all' matched)) receiver=mydomain.ru; identity=helo; helo=mydomain.ru; client-ip=1.1.1.1
# spfquery --ip XX.XX.XX.XX --mail-from a@mydomain.ru --helo mydomain.ru
pass
mydomain.ru: XX.XX.XX.XX is authorized to use 'mydomain.ru' in 'helo' identity (mechanism 'a' matched)
mydomain.ru: XX.XX.XX.XX is authorized to use 'mydomain.ru' in 'helo' identity (mechanism 'a' matched)
Received-SPF: pass (mydomain.ru: XX.XX.XX.XX is authorized to use 'mydomain.ru' in 'helo' identity (mechanism 'a' matched)) receiver=mydomain.ru; identity=helo; helo=mydomain.ru; client-ip=XX.XX.XX.XX

Где XX.XX.XX.XX — это один был IN A в DNS для домена mydomain.ru

Примечание.

Некоторые почтовые сервера (например, gmail) в заголовки специально добавляют информацию об SPF:

spf=pass (google.com: domain of user@domain.ru designates XX.XX.XX.XX as permitted sender) smtp.mail=user@domain.ru

Настроим демон spfd.

Для запуска пишем такой init-скрипт:

#!/bin/sh

USER=Debian-exim
GROUP=mail

SOCK=/var/run/spfd/spfd.sock
PID=/var/run/spfd/spfd.pid

SPFD=/usr/sbin/spfd
DESC="SPF Daemon"

ARGS="-path=${SOCK} -setuser=${USER} -setgroup=${GROUP} -pathuser=${USER} -pathgroup=${GROUP}"

case "$1" in
    start)
        echo -n "Starting $DESC:"
            start-stop-daemon --start --quiet --background --make-pidfile \
                --pidfile ${PID} \
                --exec ${SPFD} -- ${ARGS}
        echo "."
        ;;

    stop)
        echo -n "Stopping $DESC:"
            start-stop-daemon --stop --quiet --oknodo --signal 9 --pidfile "${PID}"
            rm -f $SOCK $PID
        echo "."
        ;;

    restart|force-reload)
        /etc/init.d/spfd stop
        /etc/init.d/spfd start
        ;;

    *)
        N=/etc/init.d/$NAME
        echo "Usage: $N {start|stop|restart|force-reload}" >&2
        exit 1
        ;;
esac

exit 0

# update-rc.d spfd default

Для проверки exim’ом SPF-записей, добавляем такое:

begin acl

spf_rcpt_acl:

    # Check envelope sender
    warn     set acl_m8  = $sender_address
    deny     !acl        = spf_check     
    warn     message     = Received-SPF: $acl_m8 ($acl_m7)
    accept                                               

spf_from_acl:

    # Check header From:
    warn     set acl_m8  = ${address:$h_from:}
    deny     !acl        = spf_check         
    warn     message     = Received-SPF: $acl_m8 ($acl_m7)
    accept                                               

spf_check:

    warn     set acl_m9  = ${readsocket{/var/run/spfd/spfd.sock}\
                           {ip=$sender_host_address\n\
                           helo=${if def:sender_helo_name\
                           {$sender_helo_name}{NOHELO}}\ 
                           \nsender=$acl_m8\n\n}{20s}{\n}{socket failure}}

    # Defer on socket error
    defer    condition   = ${if eq{$acl_m9}{socket failure}{yes}{no}}
             message     = Cannot connect to spfd                   

    # Prepare answer and get results
    warn     set acl_m9  = ${sg{$acl_m9}{\N=(.*)\n\N}{=\"\$1\" }}
             set acl_m8  = ${extract{result}{$acl_m9}{$value}{unknown}}
             set acl_m7  = ${extract{header_comment}{$acl_m9}{$value}{}}

    # Check for fail
    deny     condition   = ${if eq{$acl_m8}{fail}{yes}{no}}
             message     = ${extract{smtp_comment}{$acl_m9}{$value}{}}
             log_message = Not authorized by SPF                      

    accept

acl_check_mail:
   
  accept authenticated = *
  deny    message       = $sender_host_address is not allowed to send mail from $sender_address_domain
          !acl          = spf_rcpt_acl
          hosts         = !+relay_from_hosts
  accept


acl_check_data:
  deny senders = :
       !acl = spf_from_acl
  accept

DKIM

Генерируем приватный ключ:

$ openssl genrsa -out /usr/local/etc/exim/dkim/mydomain.ru.key 1024
Generating RSA private key, 1024 bit long modulus
...++++++
.....................................................................++++++
e is 65537 (0x10001)

Теперь публичный:

$ openssl rsa -in /usr/local/etc/exim/dkim/mydomain.ru.key -pubout
writing RSA key
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYw9Ddhod6jZZkp0S0lf4I/j57
G8DnW5HDoKHDr0OwmbOhg0QOefHIpfrhBCrTK08dAvvvFnXs5/g1i9YU2ZDHE1uB
pSrtm33ZBAC9tUneqTM6J4PYAHKs1hOchoOZCYJBdZiNBFUtxT9Ma2Gldkgy5lhX
ZkS3pbIpEHYvI3PbewIDAQAB
-----END PUBLIC KEY-----

Копируем ключ и вставляем в ДНС зоне нашего домена mydomain.ru в поле:

dkim._domainkey TXT "k=rsa; p=MIGfMA0GCSqGSIb3D.........;"

Проверяем:

$ host -t txt dkim._domainkey.mydomain.ru.
;; Truncated, retrying in TCP mode.
dkim._domainkey.mydomain.ru. descriptive text "k=rsa\; p=MIGfMA0GCSqGS.....\;"

Теперь правим сам exim:

## DKIM:
DKIM_DOMAIN                     = ${lc:${domain:$h_from:}}
DKIM_FILE                       = /usr/local/etc/exim/dkim/${lc:${domain:$h_from:}}.key
DKIM_PRIVATE_KEY                = ${if exists{DKIM_FILE}{DKIM_FILE}{0}}
...
## чуть правим транспорт:
remote_smtp:
  driver                = smtp
  dkim_domain           = DKIM_DOMAIN
  dkim_selector         = dkim
  dkim_private_key      = DKIM_PRIVATE_KEY
...

Теперь, если отправить письмо, то в заголовках можно увидеть такое:

DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=domain.org; s=dkim;
h=Content-Transfer-Encoding:Content-Type:MIME-Version:Date:Subject:To:From:Message-ID; bh=47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=;
b=bfxwjczWz5OFi4LMTs4qpcOcl5p3RhKeC4iZp9KvOb6iI66ZxDSdYZSezJ5n3rdCHeQeTabF8NCTgUB65............YOlII=;

Что означает, что письма подписываются.

Примечание.

Для проверки работоспособности SPF/DKIM можно воспользоваться online сервисами:

http://www.mail-tester.com/
http://dkimvalidator.com/

[exim] SPF/DKIM: 2 комментария

  1. Сергей

    Добрый день. Пытаюсь настроить SPF по статье. SPF в DNS добавил, spfquery установил, проверку проходит, в конфиг эксима добавил правила из статьи. Пытаюсь проверить работу. При отправке письма с левого почтового сервера подделываю адрес отправителя. По идее письмо получать не должен, но получаю. В заголовках:
    0.9 SPF_FAIL SPF: sender does not match SPF record (fail)
    [SPF failed: Please see http://www.openspf.org/Why?s=mfrom;id=admin%40mydomain.com;ip=XXX.XXX.XXX.XXX;r=mail%5D
    Вроде все правильно. SPF отрабатывает, но почему письмо не отклоняется, а попадает во входящие? Не подскажете что не так? Спасибо.

    1. skeletor Автор записи

      Добрый.
      Скорее всего в exim’e не всё прописали, либо вместо deny поставили warn.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *