divert(-1) # # Copyright (c) 2003, 2004 Victor Ustugov # This hack is under BSD License # Redistributions of source code must retain the above copyright notice # # hacks disscussion's maillist - http://www.mta.org.ua/mailman/listinfo/sendmail-conf # # # Relay based on MX # Рилеинг входящей почты доменов на основании MX записей # dnl # разрешение рилеинга почты домена, если: dnl # best MX указан в $R в виде: dnl # имени хоста dnl # IP адреса A.B.C.D dnl # сети A.B.C dnl # сети A.B dnl # сети A dnl # best MX указан в access_db в виде: dnl # имени хоста dnl # IP адреса A.B.C.D dnl # сети A.B.C dnl # сети A.B dnl # сети A dnl # dnl # возможные значения управляющей переменной confRELAY_BASED_ON_MX: dnl # CHECK_BACKUP_MX - перед проверкой best MX проверять, является ли наш хост backup MX'ом домена получателя dnl # RELAY_DOMAINS - проверять наличие best MX в trusted сетях в классе $R dnl # ACCESS_DB - проверять наличие best MX в trusted сетях в access_db dnl # CHECK_SUBDOMAINS - хост some-host.subdomain.foo.bar считать trusted при наличии в списке trusted сетей foo.bar dnl # dnl # несколько значений можно указывать через пробел dnl # dnl # пример включения в sendmail.mc проверки backup MX и проверки наличия best MX в классе $R: dnl # define(`confRELAY_BASED_ON_MX', `CHECK_BACKUP_MX RELAY_DOMAINS')dnl dnl # HACK(`relay_based_on_MX')snl dnl # dnl divert(0) VERSIONID(`$Id: relay_based_on_MX.m4,v 8.12-0.10 2004/11/14 00:54:09 corvax Exp $')dnl divert(-1) dnl ifdef(confRELAY_BASED_ON_MX, `ACCESS_DB', ` ifdef(`_ACCESS_TABLE_', `', ` errprint(`*** ERROR: HACK(relay_based_on_MX) requires FEATURE(access_db) ')')') dnl dnl LOCAL_CONFIG dnl dnl dnl HACK(`cfhead')dnl dnl dnl LOCAL_RULESETS dnl dnl SRcpt_ok R $* $: $>Check_relay_based_on_MX $1 ###################################################################### ### Check_relay_based_on_MX -- check if need to relay mail ### for recipient's domain ### ### Parameter: ### mailbox < @ domain > ### ###################################################################### SCheck_relay_based_on_MX dnl # убираем точку R $+ < @ $+ . > $: $1 < @ $2 > dnl ifelse_strstr(confRELAY_BASED_ON_MX, `CHECK_BACKUP_MX', `dnl dnl # применять relay_based_on_MX только для доменов, для которых мы являемся backup MX R$+ < @ $+ > $: < : $(mxserved $2 $) : > $1 < @ $2 > # получаем MX записи домена получателя R < : $* : > $* $#TEMP $@ 4.7.1 $: "450 Can not check MX records for recipient host " $1 R < : $+ : $* > $* $: $>is_mx_in_w <$1> < : $2 > $3 # проверяем наличие хотя бы одного из MX в классе $w dnl ',` dnl # не проверять принадлежность нашего хоста к backup MX записям домена получателя, # будем лишь проверять принадлежность best MX к нашим trusted networks R$+ < @ $+ > $: $1 < @ $2 > dnl ') dnl # получаем PTR запись best MX записи R$+ < @ $+ > $: < : $(mxserved_best $2 $) : ? : > $1 < @ $2 > # получаем best MX запись R < : $* : $* > $* $#TEMP $@ 4.7.1 $: "450 Can not check best MX record(s) for recipient host " $1 dnl ifelse_strstr(confRELAY_BASED_ON_MX, `RELAY_DOMAINS', `dnl ifelse_strstr(confRELAY_BASED_ON_MX, `CHECK_SUBDOMAINS', `dnl # проверяем $R на наличие в нем best MX домена в виде имени хоста R < : $+ . : $* > $* $: $>LookUpDomainR <$1> << : $1. : $2 > $3> R $* $@ RELAY R<$*> <$*> $: <$1> $2 ',` # проверяем $R на наличие в нем best MX домена в виде имени хоста R < : $=R . : $* > $* $@ RELAY ') ') dnl ifelse_strstr(confRELAY_BASED_ON_MX, `ACCESS_DB', `dnl ifelse_strstr(confRELAY_BASED_ON_MX, `CHECK_SUBDOMAINS', `dnl # проверяем наличие best MX или домена, в котором он находится, в access_db # в виде имени хоста с квалификатором Connect или без квалификатора R < : $+ . : $-.$-.$-.$- : > $* $: $>D <$1> <+Connect> < : $1 . : $2.$3.$4.$5 : > $6 ',` # проверяем наличие best MX в access_db в виде имени хоста с квалификатором Connect R < : $+ . : $-.$-.$-.$- : > $* $: < $(access Connect:$1 $: MX0 $) > < : $1 . : $2.$3.$4.$5 : > $6 # проверяем наличие best MX в access_db в виде имени хоста без квалификатора R < : $+ . : $-.$-.$-.$- : > $* $: < $(access $1 $: MX0 $) > < : $1 . : $2.$3.$4.$5 : > $6 ') R $* $@ RELAY ') dnl # получаем A запись хоста best MX записи R < : $+ : $* > $* $: < : $1 : $(dns_a $1 $) : > $3 R < : $+ : $* : > $* $#TEMP $@ 4.7.1 $: "450 Can not resolve A record of host " $2 R < : $+ : $+ . : > $* $: < : $1 : $2 : > $3 dnl ifelse_strstr(confRELAY_BASED_ON_MX, `RELAY_DOMAINS', `dnl # проверяем $R на наличие в нем best MX домена в виде IP адреса R < : $+ : $=R : > $* $@ RELAY R < : $+ : $=R .$- : > $* $@ RELAY R < : $+ : $=R .$-.$- : > $* $@ RELAY R < : $+ : $=R .$-.$-.$- : > $* $@ RELAY dnl ') dnl ifelse_strstr(confRELAY_BASED_ON_MX, `ACCESS_DB', `dnl # проверяем наличие best MX в access_db в виде IP адреса с квалификатором Connect или без квалификатора R < : $+ . : $-.$-.$-.$- : > $* $: $>A <$2.$3.$4.$5> <+Connect> < : $1 . : $2.$3.$4.$5 : > $6 # если best MX прописан в trusted сетях в access_db R $* $@ RELAY dnl ') dnl R<$*> < : $* : $* : > $* $: $4 # приводим адрес получателя к виду mailbox < @ domain >, пригодному для дальнейших проверок R $+ < @ $+ > $: $1 < @ $2 > dnl ###################################################################### ### is_mx_in_w -- check if hostname is in $w ### ### Parameters: ### <$1> -- key (hostname) ### <$2> -- what to return if found in $w ### <$3> -- what to return if not found in $w ### <$4> -- MX records list ### $5 -- passthru (additional data passed through) ###################################################################### Sis_mx_in_w R <$=w> <$+> <$+> <$+> $* $@ <$2> $5 R <$=w.> <$+> <$+> <$+> $* $@ <$2> $5 R <$+> <$+> <$+> <$+> $* $: <$(dns_a $1 $)> <$2> <$3> <$4> $5 R <$* > $* $#TEMP $@ 4.7.1 $: "450 Can not resolve A record of host " $1 R <$=w> <$+> <$+> <$+> $* $@ <$2> $5 R <$+> <$+> <$+> <$+> $* $: <[$1]> <$2> <$3> <$4> $5 R <$=w> <$+> <$+> <$+> $* $@ <$2> $5 R <$+> <$+> <$+> <:$+:$*> $* $: $>is_mx_in_w <$4> <$2> <$3> < : $5 > $6 R <$+> <$+> <$+> <$*> $* $: <$3> $5 ###################################################################### ### LookUpDomainR -- recursion search for domain in $R ### ### Parameters: ### <$1> -- key (domain name) ### <$2> -- default (what to return if not found in $R) ### $3 -- passthru (additional data passed unchanged through) ###################################################################### SLookUpDomainR R < $=R > < $+ > < $* > $@ < RELAY > <$3> R < $-.$+ > < $+ > < $* > $: $>LookUpDomainR <$2> <$3> <$4> R $* $@ < RELAY > $1 R < $* > < $+ > < $* > $@ <$2> <$3>