dnl dnl проверка FQDN хоста отправителя в HELO по следующему алгоритму: dnl dnl 1. поизводится получение A записи аргумента команды HELO dnl 2. полученная A запись сравнивается с A записью рилея dnl 3. если A записи равны, проверка оканчивается успешно dnl 4. если A записи не равны, сравниваются доменные части HELO и PTR записи рилея dnl 5. если они не равны, сообщение считается не прошедшим проверку dnl 6. если доменные части HELO и PTR записи рилея равны, то сравниваются номера dnl сетей класса C полученной ранее A записи HELO и A записи рилея dnl 7. если номера сетей равны (A запись HELO и A запись рилея находятся в одной dnl сети класса C), то проверка оканчивается успешно dnl 8. в противном случае сообщение считается не прошедшим проверку dnl NO - не проводить проверку dnl REJECT - возврата клиенту кода 5xx dnl DROP - возврат клиенту кода 5xx и обрыв соединения dnl DEFER - возврата клиенту кода 451 dnl WARN - вывода в лог файл предупреждения dnl PAUSE:XX - пауза XX секунд dnl GREYLIST:XX - добавить XX баллов к счетчику опционального greylisting'а dnl REJECT:XX - добавить XX баллов к счетчику опционального reject'а dnl define(`confCHECK_HELO_FQDN_FORGED', `NO')dnl dnl define(`confCHECK_HELO_FQDN_DEFER', `NO')dnl dnl define(`confCHECK_HELO_FQDN_NOT_RESOLVE', `NO')dnl dnl в confCHECK_HELO_FQDN_FORGED, confCHECK_HELO_FQDN_DEFER и dnl confCHECK_HELO_FQDN_NOT_RESOLVE могут быть указаны несколько значений, dnl разделеные пробелом dnl dnl исключеня из проверки FQDN в HELO (список) dnl AUTH - не проводить проверку аутентифицированных отправителей dnl RELAY_FROM - не проводить проверку исходящих сообщений dnl HOST_LIST - не проводить проверку сообщений, получаемых с определенного списка хостов dnl (список хостов/сетей находится в файле skip_helo_fqdn_check) dnl define(`confCHECK_HELO_FQDN_SKIP', `AUTH RELAY_FROM')dnl dnl ifelse(SECTION, `MAIN', `dnl ifelse_strstr(confCHECK_HELO_FQDN_SKIP, `HOST_LIST', `dnl hostlist skip_helo_fqdn_check = CONFDIR/skip_helo_fqdn_check ')') ifelse(SECTION, `ACL_CHECK_RCPT', `dnl define(`_CHECK_HELO_FQDN_TMP1', `NORMALIZE_ACTION(confCHECK_HELO_FQDN_FORGED)')dnl define(`confCHECK_HELO_FQDN_FORGED', _CHECK_HELO_FQDN_TMP1` ')dnl define(`_CHECK_HELO_FQDN_TMP2', `NORMALIZE_ACTION(confCHECK_HELO_FQDN_DEFER)')dnl define(`confCHECK_HELO_FQDN_DEFER', _CHECK_HELO_FQDN_TMP2` ')dnl define(`_CHECK_HELO_FQDN_TMP3', `NORMALIZE_ACTION(confCHECK_HELO_FQDN_NOT_RESOLVE)')dnl define(`confCHECK_HELO_FQDN_NOT_RESOLVE', _CHECK_HELO_FQDN_TMP3` ')dnl # проверка соответствия HELO и FQDN хоста отправителя warn set acl_m0 = set acl_m3 = ifelse_strstr(confCHECK_HELO_FQDN_SKIP, `AUTH', `dnl warn condition = ${if eq{$acl_m3}{}{yes}{no}} authenticated = * set acl_m3 = skip ')dnl ifelse_strstr(confCHECK_HELO_FQDN_SKIP, `RELAY_FROM', `dnl warn condition = ${if eq{$acl_m3}{}{yes}{no}} hosts = +relay_from_hosts set acl_m3 = skip ')dnl ifelse_strstr(confCHECK_HELO_FQDN_SKIP, `HOST_LIST', `dnl warn condition = ${if eq{$acl_m3}{}{yes}{no}} hosts = +skip_helo_fqdn_check set acl_m3 = skip ')dnl warn condition = ${if eq{$acl_m3}{}{yes}{no}} condition = ${if match{$sender_helo_name}{\N^\d+\.\d+\.\d+\.\d+$\N}{yes}{no}} set acl_m3 = skip warn condition = ${if eq{$acl_m3}{}{yes}{no}} set acl_m3 = defer set acl_m1 = ${if match{$sender_helo_name}{\N^\[?(\d+\.\d+\.\d+\.\d+)\]?$\N}{$1}{${sg{${lookup dnsdb{a=$sender_helo_name}}}{\n}{:}}}} set acl_m3 = condition = ${if eq{$acl_m1}{}{no}{yes}} # condition = ${if match_ip{$sender_host_address}{$acl_m1}{yes}{no}} condition = ${if forany{$acl_m1}{eq{$item}{$sender_host_address}}{yes}{no}} set acl_m3 = ok warn condition = ${if eq{$acl_m3}{}{yes}{no}} condition = ${if eq{$acl_m1}{}{yes}{no}} set acl_m3 = not_resolve warn condition = ${if eq{$acl_m3}{}{yes}{no}} condition = ${if match{$acl_m1}{\N^(\d{1,3}\.\d{1,3}\.\d{1,3})\.\d{1,3}\N}{no}{yes}} set acl_m3 = not_resolve warn condition = ${if eq{$acl_m3}{}{yes}{no}} condition = ${if eq{$acl_m_sender_helo_domain}{}{yes}{no}} set acl_m_sender_helo_domain = ${sg{$sender_helo_name}{\N^([^\.]*)(?:\.(.+))*$\N}{\$2}} warn condition = ${if eq{$acl_m3}{}{yes}{no}} condition = ${if eq{$acl_m_sender_host_name_list}{}{yes}{no}} set acl_m_sender_host_name_list = ${sg{${lookup dnsdb{ptr=$sender_host_address}}}{\n}{:}} warn condition = ${if eq{$acl_m3}{}{yes}{no}} condition = ${if eq{$acl_m_sender_host_name_list}{}{yes}{no}} set acl_m_sender_host_name_list = $sender_host_name # warn condition = ${if eq{$acl_m3}{}{yes}{no}} # condition = ${if or{\ # {eq{$acl_m_sender_helo_domain}{}}\ # {eq{$acl_m_sender_host_name_list}{}}\ # }{yes}{no}} # set acl_m3 = defer warn condition = ${if eq{$acl_m3}{}{yes}{no}} condition = ${if eq{$acl_m_sender_helo_domain}{}{yes}{no}} set acl_m3 = defer warn condition = ${if eq{$acl_m3}{}{yes}{no}} condition = ${if eq{$acl_m_sender_host_name_list}{}{yes}{no}} set acl_m3 = not_resolve sender_host_address warn condition = ${if eq{$acl_m3}{}{yes}{no}} set acl_m3 = ${if and{\ {\ forany{$acl_m1}{eq{\ ${sg{$item}{\N^(\d{1,3}\.\d{1,3}\.\d{1,3})\.\d{1,3}\N}{\$1}}\ }{\ ${sg{$sender_host_address}{\N^(\d{1,3}\.\d{1,3}\.\d{1,3})\.\d{1,3}\N}{\$1}}\ }}\ }{\ forany{$acl_m_sender_host_name_list}{\ match{$item}{\N^(.+\.)?\N${expand:$acl_m_sender_helo_domain}\N$\N}\ }\ }\ }{ok}{forged}} warn condition = ${if eq{$acl_m3}{forged}{yes}{no}} set acl_m2 = Forged HELO used set acl_m0 = Forged HELO used (A record of HELO $sender_helo_name does not correspond to relay address $sender_host_address) warn condition = ${if eq{$acl_m3}{defer}{yes}{no}} set acl_m2 = Forged HELO used set acl_m0 = Forged HELO used (Resolve of HELO $sender_helo_name gave DEFER) warn condition = ${if eq{$acl_m3}{not_resolve}{yes}{no}} set acl_m2 = Forged HELO used set acl_m0 = Forged HELO used (HELO $sender_helo_name does not resolve) set acl_m3 = defer warn condition = ${if eq{$acl_m3}{not_resolve sender_host_address}{yes}{no}} set acl_m2 = Forged HELO used set acl_m0 = Forged HELO used (sender host address $sender_host_address does not resolve) set acl_m3 = defer ifelse_strstr(confCHECK_HELO_FQDN_FORGED, `warn', `dnl # Warning в случае указания в качестве HELO не FQDN хоста-отправителя warn condition = ${if eq{$acl_m3}{forged}{yes}{no}} add_header = X-Warn-HELO-Forged: $acl_m0 log_message = $acl_m0 ')dnl ifelse_strstr(confCHECK_HELO_FQDN_FORGED, `warn', `') ifelse_strstr(confCHECK_HELO_FQDN_DEFER, `warn', `dnl # Warning в случае defer-а при резолвинге HELO warn condition = ${if eq{$acl_m3}{defer}{yes}{no}} add_header = X-Warn-HELO-Forged: $acl_m0 log_message = $acl_m0 ')dnl ifelse_strstr(confCHECK_HELO_FQDN_DEFER, `warn', `') ifelse_strstr(confCHECK_HELO_FQDN_NOT_RESOLVE, `warn', `dnl # Warning в случае нерезолвящегося HELO warn condition = ${if eq{$acl_m3}{not_resolve}{yes}{no}} add_header = X-Warn-HELO-Forged: $acl_m0 log_message = $acl_m0 ')dnl ifelse_strstr(confCHECK_HELO_FQDN_NOT_RESOLVE, `warn', `') ifelse_strstr(confCHECK_HELO_FQDN_FORGED, `pause', ` # пауза в случае указания в качестве HELO не FQDN хоста-отправителя warn condition = ${if eq{$acl_m3}{forged}{yes}{no}} delay = EXTRACT_NAMED(`pause', confCHECK_HELO_FQDN_FORGED)s set acl_m15 = ${acl_m15}\t\ delay=EXTRACT_NAMED(`pause', confCHECK_HELO_FQDN_FORGED)s\t\t\ $acl_m0\n ')dnl ifelse_strstr(confCHECK_HELO_FQDN_FORGED, `pause', `') ifelse_strstr(confCHECK_HELO_FQDN_DEFER, `pause', ` # пауза в случае defer-а при резолвинге HELO warn condition = ${if eq{$acl_m3}{defer}{yes}{no}} delay = EXTRACT_NAMED(`pause', confCHECK_HELO_FQDN_DEFER)s set acl_m15 = ${acl_m15}\t\ delay=EXTRACT_NAMED(`pause', confCHECK_HELO_FQDN_DEFER)s\t\t\ $acl_m0\n ')dnl ifelse_strstr(confCHECK_HELO_FQDN_DEFER, `pause', `') ifelse_strstr(confCHECK_HELO_FQDN_NOT_RESOLVE, `pause', ` # пауза в случае нерезолвящегося HELO warn condition = ${if eq{$acl_m3}{not_resolve}{yes}{no}} delay = EXTRACT_NAMED(`pause', confCHECK_HELO_FQDN_NOT_RESOLVE)s set acl_m15 = ${acl_m15}\t\ delay=EXTRACT_NAMED(`pause', confCHECK_HELO_FQDN_NOT_RESOLVE)s\t\t\ $acl_m0\n ')dnl ifelse_strstr(confCHECK_HELO_FQDN_NOT_RESOLVE, `pause', `') ifelse_strstr(confCHECK_HELO_FQDN_FORGED, `reject ', `dnl # отказ в примете письма в случае указания в качестве HELO не FQDN хоста-отправителя deny condition = ${if eq{$acl_m3}{forged}{yes}{no}} message = $acl_m2 log_message = $acl_m0 ')dnl ifelse_strstr(confCHECK_HELO_FQDN_FORGED, `reject ', `') ifelse_strstr(confCHECK_HELO_FQDN_DEFER, `reject ', `dnl # отказ в примете письма в случае defer-а при резолвинге HELO deny condition = ${if eq{$acl_m3}{defer}{yes}{no}} message = $acl_m2 log_message = $acl_m0 ')dnl ifelse_strstr(confCHECK_HELO_FQDN_DEFER, `reject ', `') ifelse_strstr(confCHECK_HELO_FQDN_NOT_RESOLVE, `reject ', `dnl # отказ в примете письма в случае нерезолвящегося HELO deny condition = ${if eq{$acl_m3}{not_resolve}{yes}{no}} message = $acl_m2 log_message = $acl_m0 ')dnl ifelse_strstr(confCHECK_HELO_FQDN_NOT_RESOLVE, `reject ', `') ifelse_strstr(confCHECK_HELO_FQDN_FORGED, `defer', `dnl # возврат временной ошибки в случае указания в качестве HELO не FQDN хоста-отправителя defer condition = ${if eq{$acl_m3}{forged}{yes}{no}} message = $acl_m2 log_message = $acl_m0 ')dnl ifelse_strstr(confCHECK_HELO_FQDN_FORGED, `defer', `') ifelse_strstr(confCHECK_HELO_FQDN_DEFER, `defer', `dnl # возврат временной ошибки в случае defer-а при резолвинге HELO defer condition = ${if eq{$acl_m3}{defer}{yes}{no}} message = $acl_m2 log_message = $acl_m0 ')dnl ifelse_strstr(confCHECK_HELO_FQDN_DEFER, `defer', `') ifelse_strstr(confCHECK_HELO_FQDN_NOT_RESOLVE, `defer', `dnl # возврат временной ошибки в случае нерезолвящегося HELO defer condition = ${if eq{$acl_m3}{not_resolve}{yes}{no}} message = $acl_m2 log_message = $acl_m0 ')dnl ifelse_strstr(confCHECK_HELO_FQDN_NOT_RESOLVE, `defer', `') ifelse_strstr(confCHECK_HELO_FQDN_FORGED, `drop', ` # сброс соединения в случае указания в качестве HELO не FQDN хоста-отправителя drop condition = ${if eq{$acl_m3}{forged}{yes}{no}} message = $acl_m2 log_message = $acl_m0 ')dnl ifelse_strstr(confCHECK_HELO_FQDN_FORGED, `drop', `') ifelse_strstr(confCHECK_HELO_FQDN_DEFER, `drop', ` # сброс соединения в случае defer-а при резолвинге HELO drop condition = ${if eq{$acl_m3}{defer}{yes}{no}} message = $acl_m2 log_message = $acl_m0 ')dnl ifelse_strstr(confCHECK_HELO_FQDN_DEFER, `drop', `') ifelse_strstr(confCHECK_HELO_FQDN_NOT_RESOLVE, `drop', ` # сброс соединения в случае нерезолвящегося HELO drop condition = ${if eq{$acl_m3}{not_resolve}{yes}{no}} message = $acl_m2 log_message = $acl_m0 ')dnl ifelse_strstr(confCHECK_HELO_FQDN_NOT_RESOLVE, `drop', `') ifelse(confGREYLIST, `OPTIONAL', ` ifelse_strstr(confCHECK_HELO_FQDN_FORGED, `greylist', ` # применение опционального грейлистинга в случае указания в качестве HELO не FQDN хоста-отправителя warn condition = ${if eq{$acl_m3}{forged}{yes}{no}} set acl_m_optional_greylist = \ scores=${eval:${extract{scores}{$acl_m_optional_greylist}}+EXTRACT_NAMED(`greylist', confCHECK_HELO_FQDN_FORGED)} \ log_message="${extract{log_message}{$acl_m_optional_greylist}} $acl_m0;" set acl_m15 = ${acl_m15}\t\ greylist scores=EXTRACT_NAMED(`greylist', confCHECK_HELO_FQDN_FORGED)\t\ $acl_m0\n ')dnl ifelse_strstr(confCHECK_HELO_FQDN_FORGED, `greylist', `') ifelse_strstr(confCHECK_HELO_FQDN_DEFER, `greylist', ` # применение опционального грейлистинга в случае defer-а при резолвинге HELO warn condition = ${if eq{$acl_m3}{defer}{yes}{no}} set acl_m_optional_greylist = \ scores=${eval:${extract{scores}{$acl_m_optional_greylist}}+EXTRACT_NAMED(`greylist', confCHECK_HELO_FQDN_DEFER)} \ log_message="${extract{log_message}{$acl_m_optional_greylist}} $acl_m0;" set acl_m15 = ${acl_m15}\t\ greylist scores=EXTRACT_NAMED(`greylist', confCHECK_HELO_FQDN_DEFER)\t\ $acl_m0\n ')dnl ifelse_strstr(confCHECK_HELO_FQDN_DEFER, `greylist', `') ifelse_strstr(confCHECK_HELO_FQDN_NOT_RESOLVE, `greylist', ` # применение опционального грейлистинга в случае нерезолвящегося HELO warn condition = ${if eq{$acl_m3}{not_resolve}{yes}{no}} set acl_m_optional_greylist = \ scores=${eval:${extract{scores}{$acl_m_optional_greylist}}+EXTRACT_NAMED(`greylist', confCHECK_HELO_FQDN_NOT_RESOLVE)} \ log_message="${extract{log_message}{$acl_m_optional_greylist}} $acl_m0;" set acl_m15 = ${acl_m15}\t\ greylist scores=EXTRACT_NAMED(`greylist', confCHECK_HELO_FQDN_NOT_RESOLVE)\t\ $acl_m0\n ')dnl ifelse_strstr(confCHECK_HELO_FQDN_NOT_RESOLVE, `greylist', `') ')dnl ifelse(confGREYLIST, `OPTIONAL', `') ifdef(`confOPTIONAL_REJECT', `ifelse(confOPTIONAL_REJECT, `NO', `dnl', `dnl ifelse_strstr(confCHECK_HELO_FQDN_FORGED, `reject=', ` # применение опционального отказа в приеме письма в случае указания в качестве HELO не FQDN хоста-отправителя warn condition = ${if eq{$acl_m3}{forged}{yes}{no}} set acl_m_optional_reject = \ scores=${eval:${extract{scores}{$acl_m_optional_reject}}+EXTRACT_NAMED(`reject', confCHECK_HELO_FQDN_FORGED)} \ log_message="${extract{log_message}{$acl_m_optional_reject}} $acl_m0;" set acl_m15 = ${acl_m15}\t\ reject scores=EXTRACT_NAMED(`reject', confCHECK_HELO_FQDN_FORGED)\t\t\ $acl_m0\n ')dnl ifelse_strstr(confCHECK_HELO_FQDN_FORGED, `reject=', `') ifelse_strstr(confCHECK_HELO_FQDN_DEFER, `reject=', ` # применение опционального отказа в приеме письма в случае defer-а при резолвинге HELO warn condition = ${if eq{$acl_m3}{defer}{yes}{no}} set acl_m_optional_reject = \ scores=${eval:${extract{scores}{$acl_m_optional_reject}}+EXTRACT_NAMED(`reject', confCHECK_HELO_FQDN_DEFER)} \ log_message="${extract{log_message}{$acl_m_optional_reject}} $acl_m0;" set acl_m15 = ${acl_m15}\t\ reject scores=EXTRACT_NAMED(`reject', confCHECK_HELO_FQDN_DEFER)\t\t\ $acl_m0\n ')dnl ifelse_strstr(confCHECK_HELO_FQDN_DEFER, `reject=', `') ifelse_strstr(confCHECK_HELO_FQDN_NOT_RESOLVE, `reject=', ` # применение опционального отказа в приеме письма в случае нерезолвящегося HELO warn condition = ${if eq{$acl_m3}{not_resolve}{yes}{no}} set acl_m_optional_reject = \ scores=${eval:${extract{scores}{$acl_m_optional_reject}}+EXTRACT_NAMED(`reject', confCHECK_HELO_FQDN_NOT_RESOLVE)} \ log_message="${extract{log_message}{$acl_m_optional_reject}} $acl_m0;" set acl_m15 = ${acl_m15}\t\ reject scores=EXTRACT_NAMED(`reject', confCHECK_HELO_FQDN_NOT_RESOLVE)\t\t\ $acl_m0\n ')dnl ifelse_strstr(confCHECK_HELO_FQDN_NOT_RESOLVE, `reject=', `') ')') dnl ifdef(`confOPTIONAL_REJECT', `ifelse(confOPTIONAL_REJECT, `NO', `', `')') ')dnl ifelse(SECTION, `ACL_CHECK_RCPT', `')