2010年6月18日 星期五

SPF不過再檢查來源正反解

我架Postfix時,通常是在smtpd_client_restrictions時就用reject_unknown_client_hostname把正反解不合的來源擋掉,
而SPF的檢查也只能放在smtpd_recipient_restrictions。
但最近想想,要是sender domain都用SPF宣告某個ip是可信任的發信來源,
那他何必一定要設反解對應呢(spammer自己設SPF的狀況暫不考慮XD)?
...不過使用postfix-policyd-spf-perl-2.007下,單純只改postfix設定檔應該是不可能的,
還是很髒地得改部份程式~.~...在此記一下唄。

...結果本來五月中就要寫完,居然一堆事懶得寫到今天才補完...。


目的:當SPF不是pass, fail, *error時再檢查一次黑白名單,沒在名單的才檢查正反解。




main.cf 原本配置:

smtpd_client_restrictions =
        permit_mynetworks
        check_client_access hash:/usr/local/etc/postfix/access
        reject_unknown_client_hostname
        reject_rbl_client bl.spamcop.net
        reject_rbl_client smtp.dnsbl.sorbs.net
        reject_rbl_client sbl-xbl.spamhaus.org

smtpd_sender_restrictions =
        permit_mynetworks
        reject_unknown_sender_domain
        reject_unlisted_sender

smtpd_recipient_restrictions =
        permit_mynetworks
        reject_unauth_destination
        reject_unlisted_recipient
        reject_unverified_recipient
        check_policy_service inet:127.0.0.1:10023
        check_policy_service unix:private/spf-policy


將check_client_access及reject_unknown_client_hostname先移出smtpd_client_restrictions,
然後再新增兩行:
smtpd_restriction_classes = afterspf

afterspf = check_client_access pcre:/usr/local/etc/postfix/access, reject_unknown_client_hostname
也就是定義一個在postfix access格式中可使用的action,這action即表示要依序作那兩項檢查。需要另外定義是因為policy也只能回傳access可用的action。

接著就是改/usr/local/sbin/postfix-policyd-spf-perl,原本最後一段是:

    if ($mfrom_result->is_code('fail')) {
        return "550 $mfrom_authority_exp";
    }
    elsif ($mfrom_result->is_code('temperror')) {
        return "DEFER_IF_PERMIT SPF-Result=$mfrom_local_exp";
    }
    else {
        return "PREPEND $mfrom_spf_header"
            unless $cache->{added_spf_header}++;
    }


    return;
}

更改為:
    if ($mfrom_result->is_code('fail')) {
        return "550 $mfrom_authority_exp";
    }
    elsif ($mfrom_result->is_code('temperror')) {
        return "DEFER_IF_PERMIT SPF-Result=$mfrom_local_exp";
    }
    elsif ($mfrom_result->is_code('pass')) {
        return "PREPEND $mfrom_spf_header"
            unless $cache->{added_spf_header}++;
    }
    else {
        return "afterspf"
    }

    return;
}

這樣就OK啦,但因為沒有直接把變數透過自定action帶進postfix的方法(還是其實有我找不到?),
所以進入afterspf動作的信件即使最後成功通過也不會有SPF header...,
雖然說有個懶人作法是把原版未改過的postfix-policyd-spf-perl再另成一個policy,
afterspf後再進入該policy...不過就個人的個性來講覺得實再太髒了就算了...好一點的是第二次policy只專做加header的動作,但還是希望能有一次解決的方法啊...

參考文件:
http://www.postfix.org/SMTPD_POLICY_README.html
http://www.postfix.org/access.5.html
http://www.postfix.org/RESTRICTION_CLASS_README.html

沒有留言:

張貼留言