dnl dnl Проверка соответствия HELO и PTR записи рилея dnl dnl соответствие HELO и PTR записей рилеев описано в файле confCONFDIR/access-helo-forged в виде: dnl : : : dnl dnl helo_regexp - регулярное выражение, применяемое к HELO dnl hostname_regexp - регулярное выражение, которому должна соответствовать PTR dnl запись рилея при соответствии HELO первому регуляному выражению dnl action - действие в случае несоответствия PTR записи рилея второму dnl регуляному выражению dnl возможные значения: dnl warn - выдать предупреждение в лог файл dnl deny - отвергнуть сообщение dnl reject - синоним deny dnl action_if_resolve_tempfail - действие в случае проблем с резолвингом PTR записи рилея dnl регулярное выражение обязательно указыватеся без \N в начале и в конце dnl возможные значения: dnl defer - вернуть клиенту 4xx dnl pass - принять сообщение dnl warn - выдать предупреждение в лог файл dnl dnl пример: dnl \N^(.+\.)*compuserve\.com$\N : deny : defer : ^(.+\.)*compuserve\.com$ dnl \N^(.+\.)*hotmail\.com$\N : deny : defer : ^(.+\.)*hotmail\.com$ dnl \N^(.+\.)*galaradio\.com$\N : warn : pass : ^(.+\.)*galaradio\.com$ dnl dnl исключения указываются в файле confCONFDIR/skip_helo_forged_check в виде: dnl <адрес_рилея> : dnl dnl в качестве адреса рилея может быть указана A запись хоста или сеть в виде CIDR dnl в качестве regexp указывается регулярное выражение, которому должно соответствовать HELO dnl сообщений данного рилея dnl регексп обязательно указыватеся без \N в начале и в конце dnl dnl пример: dnl 66.218.64.0/19 : ^(.+\.)*yahoo\.com$ dnl 213.180.200.0/24 : ^(.+\.)*yandex\.ru$ dnl # Проверка соответствия HELO и PTR записи рилея # HFO -- Forged HELO # ищем HELO в списке проверяемых warn set acl_m0 = ${lookup{$sender_helo_name}wildlsearch{CONFDIR/access-helo-forged}\ {${if eq{$value}{}{$sender_helo_name}{$value}}}{skip}} # если HELO найден в списке проверяемых, # при этом PTR запись рилея не отрезолвлена # именно из-за проблем резолвинга (не обязательно из-за отсутствия записи в реверсной зоне) # и в настройках указан pass для данного HELO warn condition = ${if eq{$acl_m0}{skip}{no}{yes}} condition = ${if eq{$sender_host_name}{}{yes}{no}} condition = ${if eq{$host_lookup_failed}{1}{no}{yes}} condition = ${if match{${extract{2}{:}{$acl_m0}}}\ {\N^(?i)\s*pass\s*$\N}{yes}{no}} set acl_m0 = skip # если HELO найден в списке проверяемых, # при этом PTR запись рилея не отрезолвлена # именно из-за проблем резолвинга (не обязательно из-за отсутствия записи в реверсной зоне) # проверяем, не указан ли IP адрес рилея или сеть в файле исключений; # пропускаем дальнейшие проверки, если HELO соответствует регулярному выражению, # указанному в файле исключений warn condition = ${if eq{$acl_m0}{skip}{no}{yes}} condition = ${if eq{$sender_host_name}{}{yes}{no}} condition = ${if eq{$host_lookup_failed}{1}{no}{yes}} set acl_m1 = ${lookup{$sender_host_address}\ iplsearch{CONFDIR/skip_helo_forged_check}} set acl_m0 = ${if and{\ {!eq{$acl_m1}{}}\ {match{$sender_helo_name}{$acl_m1}}\ }{skip}{$acl_m0}} # если HELO найден в списке проверяемых, # при этом PTR запись рилея не отрезолвлена # именно из-за проблем резолвинга (не обязательно из-за отсутствия записи в реверсной зоне) # и IP адрес рилея не находится в списке исключений для данного HELO # и в настройках указан defer для данного HELO defer condition = ${if eq{$acl_m0}{skip}{no}{yes}} condition = ${if eq{$sender_host_name}{}{yes}{no}} condition = ${if eq{$host_lookup_failed}{1}{no}{yes}} condition = ${if match{${extract{2}{:}{$acl_m0}}}\ {\N^(?i)\s*defer\s*$\N}{yes}{no}} message = Access temporarily denied. Cannot resolve PTR record for $sender_host_address # если HELO найден в списке проверяемых # при этом PTR запись рилея не отрезолвлена # именно из-за проблем резолвинга (не обязательно из-за отсутствия записи в реверсной зоне) # и IP адрес рилея не находится в списке исключений для данного HELO # и в настройках указан warn для данного HELO warn condition = ${if eq{$acl_m0}{skip}{no}{yes}} condition = ${if eq{$sender_host_name}{}{yes}{no}} condition = ${if eq{$host_lookup_failed}{1}{no}{yes}} condition = ${if match{${extract{2}{:}{$acl_m0}}}\ {\N^(?i)\s*warn\s*$\N}{yes}{no}} log_message = Cannot resolve PTR record for $sender_host_address for helo forged check add_header = X-Warn-HELO-Forged: Cannot resolve PTR record for $sender_host_address set acl_m0 = skip # если HELO находится в списке проверяемых # выделяем регулярное выражение для PTR записи рилея в отдельную переменную warn set acl_m1 = skip condition = ${if eq{$acl_m0}{skip}{no}{yes}} set acl_m1 = ${if match{$acl_m0}{\N^[^:]+:[^:]+:\s*(.+$)\N}{$1}{skip}} # если HELO находится в списке проверяемых # но PTR запись рилея не соответствует регулярному выражению # и в настройках указан deny для указанного helo deny condition = ${if eq{$acl_m1}{skip}{no}{yes}} condition = ${if match{${extract{1}{:}{$acl_m0}}}\ {\N^(?i)\s*(deny|reject)\s*$\N}{yes}{no}} condition = ${if match{$sender_host_name}{$acl_m1}{no}{yes}} message = Invalid greeting used log_message = Forged HELO used (HELO $sender_helo_name does not correspond to relay ${if eq{$sender_host_name}{}{[$sender_host_address]}{hostname $sender_host_name}}) # если HELO находится в списке проверяемых # но PTR запись рилея не соответствует регулярному выражению # и в настройках указан warn для указанного helo warn condition = ${if eq{$acl_m1}{skip}{no}{yes}} condition = ${if match{${extract{1}{:}{$acl_m0}}}\ {\N^(?i)\s*warn\s*$\N}{yes}{no}} condition = ${if match{$sender_host_name}{$acl_m1}{no}{yes}} add_header = X-Warn-HELO-Forged: Forged HELO used (HELO $sender_helo_name does not correspond to relay hostname $sender_host_name) log_message = Forged HELO used (HELO $sender_helo_name does not correspond to relay ${if eq{$sender_host_name}{}{[$sender_host_address]}{hostname $sender_host_name}})