Sender Policy Framework
Введення перевірки SPF (Sender Policy Framework) до налаштувань поштового сервера, надає можливість достатньо ефективно боротися зі спамерами котрі відсилають пошту з недозволенних IP адрес для конкретного домену.  Так на сьогодні вже багато поштових доменів ввели запис типу TXT до DNS з описом дозволених адрес і дією щодо дозволу використання цих адрес. Наприклад:
example.com. IN TXT “v=spf1 a mx -all”
Для свого поштового сервера Postfix я використовував Python реалізацію “SPF Policy Server for Postfix (Python implementation)” на базі портації для FreeBSD “postfix-policyd-spf-python” тут є розширені можливості, чим наприклад у реалізації “postfix-policyd-spf-perl”.

Але за певних умов у мене перестала працювати реалізація “postfix-policyd-spf-python”, прийшлось тимчасово перемикатися на “postfix-policyd-spf-perl”, і надалі будуть описані деякі реалізації до дають можливість додати мінімально необхідного функціоналу.

Оновлення: виявлено проблему не функціювання “postfix-policyd-spf-python” - з оновленою версією компонента py27-dns-2.3.6. Виявленні проблеми з запитом DNS : DNS time out”. Для діагностики треба запустити python spf.py “209.85.214.49” “test@mail-bk0-f49.google.**com” “mail-bk0- f49.google.com” результат повинен бути (‘none’, 250, ‘’). Для виправлення - встановити попередню версію py27-dns-2.3.5.

Встановлення postfix-policyd-spf-python
Варіанти 

  • з портів FreeBSD, ports\postfix-policyd-spf-python, make install clean
  • з пакунків FreeBSD, pkg_add -r “py27-postfix-policyd-spf-python-*”
  • з дистрибутиву pypolicyd-spf , python setup.py build, python setup.py install

перевірити чи встановленні залежні модулі: python27, py27-spf, py27-dns
Знаходимо файл policyd-spf.conf, у мене це  /usr/local/etc/postfix-policyd-spf-python. Налаштовуємо згідно з описом  що знаходиться у policyd-spf.conf.commented.
Зробити зміни у Postfix, master.cf додавши:
policyd-spf  unix  -       n       n       -       0       spawn
    user=nobody argv=/usr/local/bin/python2.7 /usr/local/bin/policyd-spf /usr/local/etc/postfix-policyd-spf-python/policyd-spf.conf
Як і як мінімум зробити зміни у Postfix,main.cf:

smtpd_recipient_restrictions = …., check_policy_service unix:private/policyd-spf, ….

policyd-spf_time_limit = 3600

Встановлення postfix-policyd-spf-perl
Ви можете використовувати або python або perl версію.
Можете встановити з портів FreeBSD, ports\postfix-policyd-spf-perl, make install clean. Або іншим способом.
Зробити зміни у Postfix, master.cf додавши:
 spf-policy unix -       n       n       -       0       spawn
          user=nobody argv=/usr/local/sbin/postfix-policyd-spf-perl
Зробити зміни у Postfix,main.cf:
smtpd_recipient_restrictions = …., check_policy_service unix:private/spf-policy, ….
spf-policy_time_limit  = 3600

Як працює SPF.
У прикладі 1 ми бачимо авторизовано прийом листа з ip адреси за правилами що прописані у DNS TXT SPF:
host -t txt meta.ua
meta.ua descriptive text “v=spf1 +ip4:194.0.131.0/24 ~all”

Приклад 1.

Mar 21 11:34:42 postfix/policy-spf[19769]: : SPF pass (Mechanism ‘ip4:194.0.131.0/24’ matched): Envelope-from: nullsender@meta.ua* *Mar 21 11:34:42 postfix/policy-spf[19769]: : Policy action=PREPEND Received-SPF: pass (meta.ua: 194.0.131.41 is authorized to use ‘nullsender@meta.ua’ in ‘mfrom’ identity (mechanism ‘ip4:194.0.131.0/24’ matched)) receiver=mail.example.com.ua**; identity=mailfrom; envelope-from=”nullsender@meta.ua”; helo=smtp.meta.ua; client-ip=194.0.131.41

Приклад 2, демонструє як спрацьовує SPF реалізація на спробу прислати листа за IP адреси що не прописана як дозволена у spf правилах для домену meta.ua.

Приклад 2.

Mar 20 03:02:46 postfix/smtpd[53863]: connect from lovikupon.net.ru[95.167.71.117]
Mar 20 03:02:49 postfix/policy-spf[53868]: : SPF softfail (Mechanism ‘~all’ matched): Envelope-from: redkit@meta.ua
Mar 20 03:02:49 postfix/policy-spf[53868]: handler sender_policy_framework: is decisive.
Mar 20 03:02:49 postfix/policy-spf[53868]: : Policy action=PREPEND Received-SPF: softfail (meta.ua: Sender is not authorized by default to
use ‘redkit@meta.ua’ in ‘mfrom’ identity, however domain is not currently prepared for false failures (mechanism ‘~all’ matched)) receiver=mail.example.com.ua;
 identity=mailfrom; envelope-from=”redkit@meta.ua”; helo=mail6.vish.ru; client-ip=95.167.71.117

Перепризначення дії правил spf.
Але є велике запитання що робити з такими листами?
За spf правилом що надає домен meta.ua “v=spf1 +ip4:194.0.131.0/24 ~all
прописана дія ~all (SOFTFAIL), що означає примати листи але помічати як неблагонадійні.
Але для свого сервера я бажаю вжити більш жорсткі правила, і тому листи з SOFTFAIL повинні бути відкинуті на етапі перевірки заголовку листа.
Тому зробимо перевірку заголовка “Received-SPF” що є результатом роботи policy-spf.
Створюємо запис у файі header_checks.pcre
/^Received-SPF: softfail/i      REJECT SPF: softfail
У  файлі конфігурації postfix main.cf прописуємо:
header_checks = pcre:header_checks.pcre

Тепер ми бачимо у прикладі 3, як спрацьовує перепризначення дії правил: reject 5.7.1
За необхідністю таким чином можна додати перепризначення і на дію SPF neutral.

Приклад 3.
*Mar 20 03:02:50 postfix/cleanup[53879]: E297139DF7: reject: header Received-SPF: softfail (meta.ua: Sender is not authorized by default to
use ‘redkit@meta.ua’ in ‘mfrom’ identity, however domain is not currently prepared for false failures (mechanism ‘~all’ matched) from lovikupon.n
et.ru[95.167.71.117]; from=redkit@meta.ua to=user@example.com.ua proto=ESMTP helo=: 5.7.1 SPF: softfail*

Примітка: Таке перепризначення дії правил можна не робити якщо використовувати реалізацію “postfix-policyd-spf-python”. Достатньо описати це у файлі конфігурації postfix-policyd-spf-python/policyd-spf.conf, дивіться повний опис у файлі policyd-spf.conf.commented. Наприклад, HELO_reject = SPF_Not_Pass, Mail_From_reject =  SPF_Not_Pass.

У прикладі 4, Name сервер домену example.com взагалі видає помилку на запит DNS TXT. Тому додамо виключення для домену example.com.

Приклад 4.

Policy action=DEFER_IF_PERMIT SPF-Result=example.com: ‘SERVFAIL’ error on DNS ‘SPF’ lookup of ‘example.com’

*reject: RCPT from mail.example.com: 450 4.7.1 user@example.com: Sender address rejected: SPF-Result=example.com: ‘SERVFAIL’ error on DNS ‘SPF’ lookup of ‘example.com’; from=user@example.com to=some@example.com.ua proto=ESMTP helo=*

Білий список
У файлі конфігурації postfix main.cf прописуємо:

smtpd_restriction_classes = spf-sender, spf-policy

spf-sender = check_sender_access pcre:access_spf_sender.pcre

spf-policy = check_policy_service unix:private/spf-policy

Створюємо запис у файі access_spf_sender.pcre:

#CLASS that Allow checking FROM and apply whitelist for spf policy checking

#/whitelist.domain$/ DUNNO
/example.com$/ DUNNO

/.*/ spf-policy

Таким чином створені два класи spf-sender та spf-policy.
spf-sender перевіряє доменне ім’я адресата, якщо у ньому є ім’я на виключення, то спрацьовує правило DUNNO котре перериває перевірку поточних правил класу, і не виконує перевірку на SPF зовсім,  якщо немає такого то спрацьовує правило для усіх доменів з виконанням класу spf-policy.
Клас spf-policy описує дію для реалізації spf у postfix, він може відрізнятися в залежності від реалізації виконаної на базі python чи perl.

Якщо використовується  “postfix-policyd-spf-python” то білий список можемо налаштовувати у самому конфігураційному файлі postfix-policyd-spf-python/policyd-spf.conf.
Whitelist, Domain_Whitelist, Domain_Whitelist_PTR