As I see it, there are two complementary paths we can take
with DNS whitelists, each with a slightly different purpose.
While these are both useful, neither depends on the other, so
postfix can implement either or both.
My proposals:
A) scoring in postscreen
A dns whitelist/blacklist scoring system in postscreen,
whereby a dnswl hit can overrule dnsbl hits and other
postscreen tests.
Since this is in postscreen, the only data available would be
the client IP and hopefully the hostname. This would be
automatically safe from open-relay abuse since the client gets
no more rights than other "screened" clients. The transaction
could still be rejected by other tests done in the real SMTP
server. The user interface would consist of
- postscreen_dnsl_client_sites (default empty); a list of
dnsbl and dnswl domains for client IP lookup.
Specify a list of dns blacklist and whitelist sites with an
optional A result: dnsl_site=d.d.d.d, dnsl_site=d.d.d.d, ...
Count one hit when the A record =d.d.d.d is listed. If no
=d.d.d.d is specified, count one hit if one or more A records
is listed.
- postscreen_dnsl_hostname_sites (default empty); a list of
dnsbl and dnswl sites for hostname lookup using the verified
client hostname. This is recommended for domain-based whitelists.
Specify a list of dns blacklist and whitelist sites with an
optional A result, dnsl_site=d.d.d.d, dnsl_site=d.d.d.d, ...
Count one hit when the A record =d.d.d.d is listed. If no
=d.d.d.d is specified, count one hit if one or more A records
is listed.
- postscreen_dnsl_reverse_hostname_sites (default empty); a
list of dnsbl and dnswl sites for hostname lookup using the
unverified client hostname. This is recommended for
domain-based blacklists.
Specify a list of dns blacklist and whitelist sites with an
optional A result, dnsl_site=d.d.d.d, dnsl_site=d.d.d.d, ...
Count one hit when the A record =d.d.d.d is listed. If no
=d.d.d.d is specified, count one hit if one or more A records
is listed.
- postscreen_dnsl_site_score_default (default 1); default
score for any dns list result. I suppose this could be a
non-user-visible default, since it doesn't seem to make much
sense to adjust this; any adjustments would be made in the
score map.
- postscreen_dnsl_site_score_maps (no default); an optional
table that overrides postscreen_dnsl_site_score_default,
indexed by the list name. The key is the exact dnsl site
name as specified in the dnsl sites maps, including any
optional =d.d.d.d result filter. The result is a positive
number for blacklists, negative number for whitelist.
This table is required when using dns whitelists.
- postscreen_dnsl_whitelist_score (default=-1); a "pass"
threshold score. clients scoring at or BELOW this value
trigger the postscreen_dnsl_whitelist_action.
- postscreen_dnsl_blacklist_score (default=1) a "drop"
threshold score. Clients scoring at or ABOVE this value
trigger the postscreen_dnsl_blacklist_action.
- postscreen_dnsl_whitelist_action (default continue); the
action postscreen takes when a client matches the
postscreen_dnsl_whitelist_score. Specify one of:
continue; perform additional postscreen tests to determine
disposition.
pass; exempt the client from further postscreen tests and pass
it to a real SMTP server process
- postscreen_dnsl_blacklist_action (default continue); the
action postscreen takes when a client exceeds the
postscreen_dnsl_blacklist_score. Specify one of:
continue; perform additional postscreen tests to determine
disposition.
drop; drop the connection with a 521 SMTP reply
There are a lot of parameters, but sane defaults would allow a
simple "drop everything using this one blacklist" config,
while still allowing much more complex multi-list scoring. A
minimal config would be simply:
postscreen_dnsl_client_sites = zen.spamhaus.org
postscreen_dnsl_blacklist_action = drop
The downside of this method is it will require a lot of new code.
B) a "permit" based system, a mirror of reject_rbl_client.
This would have a user interface similar to the existing
reject_rbl_client with expected usage similar to access(5)
based whitelists.
Seems to me that checks using sender-supplied info such as
{helo, sender domain, recipient domain} are unsafe -- give
whitelist control to unverified information -- and probably
shouldn't be implemented.
To prevent open-relay accidents, this would need to return
permit_auth_destination rather than a blanket permit. Maybe
the result action will need to be configurable? Nah.
The user interface would be familiar to anyone using rbl
checks. Sample documentation under the appropriate
smtpd_mumble_restrictions section:
- permit_dnswl_client dnswl_domain=d.d.d.d
Accept the request when the reversed client IP network
address is listed with an A record of d.d.d.d under
dnswl_domain. If no =d.d.d.d is given, accept the request
with any A record under dnswl_domain. For safety, only
authorized destinations are accepted, see permit_auth_destination.
- permit_rhswl_client rhswl_domain=d.d.d.d
Accept the request when the client hostname is listed with
an A record of d.d.d.d under rhswl_domain. If no =d.d.d.d is
given, accept the request with any A record under
rhswl_domain. For safety, only authorized destinations are
accepted, see permit_auth_destination.
Seems like this one would be very easy to use, and fairly easy
to implement.
-- Noel Jones