mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-29 05:07:58 +00:00
postfix-2.8-20100830
This commit is contained in:
parent
4d9829bd37
commit
c78b3ad466
4
postfix/.indent.pro
vendored
4
postfix/.indent.pro
vendored
@ -191,8 +191,8 @@
|
||||
-TPOSTMAP_KEY_STATE
|
||||
-TPOST_MAIL_STATE
|
||||
-TPRIVATE_STR_TABLE
|
||||
-TPS_DNSBL_ENTRY
|
||||
-TPS_DNS_STREAM
|
||||
-TPS_DNSBL_SITE
|
||||
-TPS_DNSBL_SCORE
|
||||
-TPS_STATE
|
||||
-TQMGR_ENTRY
|
||||
-TQMGR_FEEDBACK
|
||||
|
@ -15908,3 +15908,30 @@ Apologies for any names omitted.
|
||||
"smtp_dns_resolver_options = res_defnames" to get the old
|
||||
behavior, which can produce unexpected results. Files:
|
||||
smtp/smtp.c, smtp/smtp_params.c, smtp/smtp_addr.c.
|
||||
|
||||
20100828
|
||||
|
||||
Refactoring: postscreen source code broken up into multiple
|
||||
files, and identifiers updated to match changes in their
|
||||
purpose. This will be the baseline for adding support for
|
||||
DNSBL weighting, then a dummy engine to collect forensic
|
||||
evidence with the option of future protocol checks. Files:
|
||||
postscreen/*.[hc], Makefile.in.
|
||||
|
||||
20100829
|
||||
|
||||
Postscreen DNSBL support for optional fixed-string filters
|
||||
and optional integral weight factors (use negative weights
|
||||
for whitelisting). See RELEASE_NOTES and postconf(5) for
|
||||
details. Files: postscreen/postscreen_dnsbl.c,
|
||||
proto/postconf.proto, mantools.postlink, global/mail_params.h.
|
||||
|
||||
Incompatibility: the postscreen-to-dnsblog protocol was
|
||||
changed to support DNSBL query result filters. Use "postfix
|
||||
reload" after installing the new version otherwise the
|
||||
dnsblog(8) server may complain.
|
||||
|
||||
20100830
|
||||
|
||||
Polished the postscreen documentation and comments to clarify
|
||||
the user interface and implementation. No code changes.
|
||||
|
@ -14,6 +14,46 @@ specifies the release date of a stable release or snapshot release.
|
||||
If you upgrade from Postfix 2.6 or earlier, read RELEASE_NOTES-2.7
|
||||
before proceeding.
|
||||
|
||||
Incompatibility with snapshot 20100830
|
||||
======================================
|
||||
|
||||
Use "postfix reload" after installing this code, otherwise the
|
||||
dnsblog(8) daemon may complain. The postscreen-to-dnsblog protocol
|
||||
had to be changed to support DNSBL query result filters.
|
||||
|
||||
Major changes with snapshot 20100830
|
||||
====================================
|
||||
|
||||
Postscreen DNSBL support is extended with optional fixed-string
|
||||
filters, with optional integral weight factors, and with an adjustable
|
||||
threshold to block SMTP clients with DNSBL score >= that threshold.
|
||||
Support for wild-card patterns will be added later.
|
||||
|
||||
The updated postscreen configuration syntax is:
|
||||
|
||||
postscreen_dnsbl_sites = domain[=ipaddr][*weight] ...
|
||||
postscreen_dnsbl_threshold = score
|
||||
|
||||
Elements inside [] are optional, ipaddr is an IPv4 address, and
|
||||
weight and score are integral numbers. The [] are not part of the
|
||||
postscreen_dnsbl_sites input. By default, weight and score are
|
||||
equal to 1, and entries without filter will match any non-error
|
||||
DNSBL reply. Use a negative weight value for whitelisting.
|
||||
|
||||
Examples:
|
||||
|
||||
To use example.com as a high-confidence blocklist, and to block
|
||||
mail with example.net and example.org only when both agree, use:
|
||||
|
||||
postscreen_dnsbl_threshold = 2
|
||||
postscreen_dnsbl_sites = example.com*2, example.net, example.org
|
||||
|
||||
To filter only DNSBL replies containing 127.0.0.4, use:
|
||||
|
||||
postscreen_dnsbl_sites = example.com=127.0.0.4
|
||||
|
||||
See also postconf(5) for the fine details.
|
||||
|
||||
Incompatibility with snapshot 20100827
|
||||
======================================
|
||||
|
||||
|
@ -6623,8 +6623,9 @@ parameter. Specify one of the following: </p>
|
||||
|
||||
<dd> Continue waiting until the <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> time has
|
||||
elapsed, and report whether the client triggers a PREGREET or HANGUP
|
||||
error, or whether the client is listed at the DNSBL sites specified
|
||||
with the <a href="postconf.5.html#postscreen_dnsbl_sites">postscreen_dnsbl_sites</a> parameter. Take the corresponding
|
||||
error, or whether the client's combined DNSBL score is equal to or
|
||||
greater than a threshold (as specified with the <a href="postconf.5.html#postscreen_dnsbl_sites">postscreen_dnsbl_sites</a>
|
||||
and <a href="postconf.5.html#postscreen_dnsbl_threshold">postscreen_dnsbl_threshold</a> parameters). Take the corresponding
|
||||
action, or forward the connection to a real SMTP server process.
|
||||
</dd>
|
||||
|
||||
@ -6678,7 +6679,7 @@ seconds. </p>
|
||||
</DD>
|
||||
|
||||
<DT><b><a name="postscreen_cache_map">postscreen_cache_map</a>
|
||||
(default: btree:$<a href="postconf.5.html#data_directory">data_directory</a>/ps_whitelist)</b></DT><DD>
|
||||
(default: btree:$<a href="postconf.5.html#data_directory">data_directory</a>/ps_cache)</b></DT><DD>
|
||||
|
||||
<p> Persistent storage for the <a href="postscreen.8.html">postscreen(8)</a> server decisions. </p>
|
||||
|
||||
@ -6724,9 +6725,10 @@ unit). </p>
|
||||
<DT><b><a name="postscreen_dnsbl_action">postscreen_dnsbl_action</a>
|
||||
(default: continue)</b></DT><DD>
|
||||
|
||||
<p>The action that <a href="postscreen.8.html">postscreen(8)</a> takes when an SMTP client is listed
|
||||
at the DNS blocklist domains specified with the <a href="postconf.5.html#postscreen_dnsbl_sites">postscreen_dnsbl_sites</a>
|
||||
parameter. Specify one of the following: </p>
|
||||
<p>The action that <a href="postscreen.8.html">postscreen(8)</a> takes when an SMTP client's combined
|
||||
DNSBL score is equal to or greater than a threshold (as defined
|
||||
with the <a href="postconf.5.html#postscreen_dnsbl_sites">postscreen_dnsbl_sites</a> and <a href="postconf.5.html#postscreen_dnsbl_threshold">postscreen_dnsbl_threshold</a>
|
||||
parameters). Specify one of the following: </p>
|
||||
|
||||
<dl>
|
||||
|
||||
@ -6748,14 +6750,70 @@ parameter. Specify one of the following: </p>
|
||||
<DT><b><a name="postscreen_dnsbl_sites">postscreen_dnsbl_sites</a>
|
||||
(default: empty)</b></DT><DD>
|
||||
|
||||
<p>Optional list of DNS blocklist domains. When the list is non-enpty,
|
||||
the <a href="dnsblog.8.html">dnsblog(8)</a> daemon will query these domains with the IP addresses
|
||||
of non-whitelisted <a href="postscreen.8.html">postscreen(8)</a> clients. Specify a list of domain
|
||||
names, separated by comma or whitespace. </p>
|
||||
<p>Optional list of DNS blocklist domains, filters and weight
|
||||
factors. When the list is non-empty, the <a href="dnsblog.8.html">dnsblog(8)</a> daemon will
|
||||
query these domains with the IP addresses of non-whitelisted remote
|
||||
SMTP clients, and <a href="postscreen.8.html">postscreen(8)</a> will update an SMTP client's DNSBL
|
||||
score with each non-error reply. </p>
|
||||
|
||||
<p> When a client's score is equal to or greater than the threshold
|
||||
specified with <a href="postconf.5.html#postscreen_dnsbl_threshold">postscreen_dnsbl_threshold</a>, <a href="postscreen.8.html">postscreen(8)</a> can drop
|
||||
the connection with the SMTP client. </p>
|
||||
|
||||
<p> Specify a list of domain=filter*weight entries, separated by
|
||||
comma or whitespace. </p>
|
||||
|
||||
<ul>
|
||||
|
||||
<li> <p> When no "=filter" is specified, <a href="postscreen.8.html">postscreen(8)</a> will use any
|
||||
non-error DNSBL reply. Otherwise, the filter must be an IPv4
|
||||
address, and <a href="postscreen.8.html">postscreen(8)</a> uses only DNSBL replies that match the
|
||||
filter. </p>
|
||||
|
||||
<li> <p> When no "*weight" is specified, <a href="postscreen.8.html">postscreen(8)</a> increments
|
||||
the SMTP client's DNSBL score by 1. Otherwise, the weight must be
|
||||
an integral number, and <a href="postscreen.8.html">postscreen(8)</a> adds the specified weight to
|
||||
the SMTP client's DNSBL score. Specify a negative number for
|
||||
whitelisting. </p>
|
||||
|
||||
<li> <p> When one <a href="postconf.5.html#postscreen_dnsbl_sites">postscreen_dnsbl_sites</a> entry produces multiple
|
||||
DNSBL responses, <a href="postscreen.8.html">postscreen(8)</a> applies the weight at most once.
|
||||
</p>
|
||||
|
||||
</ul>
|
||||
|
||||
<p> Examples: </p>
|
||||
|
||||
<p> To use example.com as a high-confidence blocklist, and to
|
||||
block mail with example.net and example.org only when both agree:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
<a href="postconf.5.html#postscreen_dnsbl_threshold">postscreen_dnsbl_threshold</a> = 2
|
||||
<a href="postconf.5.html#postscreen_dnsbl_sites">postscreen_dnsbl_sites</a> = example.com*2, example.net, example.org
|
||||
</pre>
|
||||
|
||||
<p> To filter only DNSBL replies containing 127.0.0.4: </p>
|
||||
|
||||
<pre>
|
||||
<a href="postconf.5.html#postscreen_dnsbl_sites">postscreen_dnsbl_sites</a> = example.com=127.0.0.4
|
||||
</pre>
|
||||
|
||||
<p> This feature is available in Postfix 2.8. </p>
|
||||
|
||||
|
||||
</DD>
|
||||
|
||||
<DT><b><a name="postscreen_dnsbl_threshold">postscreen_dnsbl_threshold</a>
|
||||
(default: 1)</b></DT><DD>
|
||||
|
||||
<p> The inclusive lower bound for blocking an SMTP client, based on
|
||||
its combined DNSBL score as defined with the <a href="postconf.5.html#postscreen_dnsbl_sites">postscreen_dnsbl_sites</a>
|
||||
parameter. </p>
|
||||
|
||||
<p> This feature is available in Postfix 2.8. </p>
|
||||
|
||||
|
||||
</DD>
|
||||
|
||||
<DT><b><a name="postscreen_greet_action">postscreen_greet_action</a>
|
||||
@ -6770,10 +6828,11 @@ parameter. Specify one of the following: </p>
|
||||
<dt> continue </dt>
|
||||
|
||||
<dd> Continue waiting until the <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> time has
|
||||
elapsed. If the client is listed at the DNS blocklist domains
|
||||
specified with the <a href="postconf.5.html#postscreen_dnsbl_sites">postscreen_dnsbl_sites</a> parameter, execute the
|
||||
action specified with the <a href="postconf.5.html#postscreen_dnsbl_action">postscreen_dnsbl_action</a> parameter, otherwise
|
||||
forward the connection to a real SMTP server process. </dd>
|
||||
elapsed. If the client's combined DNSBL score is equal to or greater
|
||||
than a threshold (as specified with the <a href="postconf.5.html#postscreen_dnsbl_sites">postscreen_dnsbl_sites</a> and
|
||||
<a href="postconf.5.html#postscreen_dnsbl_threshold">postscreen_dnsbl_threshold</a> parameters), execute the action specified
|
||||
with the <a href="postconf.5.html#postscreen_dnsbl_action">postscreen_dnsbl_action</a> parameter, otherwise forward the
|
||||
connection to a real SMTP server process. </dd>
|
||||
|
||||
<dt> drop </dt>
|
||||
|
||||
@ -6836,9 +6895,11 @@ without sending data, within the time specified with the
|
||||
<dt> continue </dt>
|
||||
|
||||
<dd> Continue waiting until the <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> time has
|
||||
elapsed, and report whether the client is listed at the DNSBL sites
|
||||
specified with the <a href="postconf.5.html#postscreen_dnsbl_sites">postscreen_dnsbl_sites</a> parameter. Do not
|
||||
forward the broken connection to a real SMTP server process. </dd>
|
||||
elapsed, and report whether the client's combined DNSBL score is
|
||||
equal to or greater than a threshold (as defined with the
|
||||
<a href="postconf.5.html#postscreen_dnsbl_sites">postscreen_dnsbl_sites</a> and <a href="postconf.5.html#postscreen_dnsbl_threshold">postscreen_dnsbl_threshold</a> parameters).
|
||||
Do not forward the broken connection to a real SMTP server process.
|
||||
</dd>
|
||||
|
||||
<dt> drop </dt>
|
||||
|
||||
@ -8617,17 +8678,17 @@ discard EHLO keywords selectively. </p>
|
||||
(default: empty)</b></DT><DD>
|
||||
|
||||
<p> DNS Resolver options for the Postfix SMTP client. Specify zero
|
||||
or more of the following, separated by comma or whitespace. Option
|
||||
names are case-sensitive. Some options refer to domain names that
|
||||
are specified in /etc/resolv.conf or equivalent. </p>
|
||||
or more of the following options, separated by comma or whitespace.
|
||||
Option names are case-sensitive. Some options refer to domain names
|
||||
that are specified in the file /etc/resolv.conf or equivalent. </p>
|
||||
|
||||
<dl>
|
||||
|
||||
<dt><b>res_defnames</b></dt>
|
||||
|
||||
<dd> Append the <a href="ADDRESS_CLASS_README.html#default_domain_class">default domain</a> name to single-component names (those
|
||||
that do not contain a dot). This can produce incorrect results,
|
||||
and was the behavior prior to Postfix 2.8. </dd>
|
||||
<dd> Append the current domain name to single-component names (those
|
||||
that do not contain a "." character). This can produce incorrect
|
||||
results, and is the hard-coded behavior prior to Postfix 2.8. </dd>
|
||||
|
||||
<dt><b>res_dnsrch</b></dt>
|
||||
|
||||
|
@ -182,30 +182,31 @@ POSTSCREEN(8) POSTSCREEN(8)
|
||||
are made in parallel.
|
||||
|
||||
When the <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> time has elapsed, and the
|
||||
SMTP client address is listed with at least one of these
|
||||
blocklists, this is logged as:
|
||||
combined DNSBL score is equal to or greater than the
|
||||
<a href="postconf.5.html#postscreen_dnsbl_threshold">postscreen_dnsbl_threshold</a> parameter value, this is logged
|
||||
as:
|
||||
|
||||
<b>DNSBL rank</b> <i>count</i> <b>for</b> <i>address</i>
|
||||
|
||||
Translation: the client at <i>address</i> is listed with <i>count</i>
|
||||
DNSBL servers. The <i>count</i> does not depend on the number of
|
||||
DNS records that an individual DNSBL server returns.
|
||||
Translation: the SMTP client at <i>address</i> has a combined
|
||||
DNSBL score of <i>count</i>.
|
||||
|
||||
The <a href="postconf.5.html#postscreen_dnsbl_action">postscreen_dnsbl_action</a> parameter specifies the action
|
||||
that is taken next:
|
||||
that is taken when the combined DNSBL score is equal to or
|
||||
greater than the threshold:
|
||||
|
||||
<b>continue</b> (default)
|
||||
Forward the connection to a real SMTP server
|
||||
process.
|
||||
|
||||
<b>drop</b> Drop the connection immediately with a 521 SMTP
|
||||
reply. In a future implementation, the connection
|
||||
may instead be passed to a dummy SMTP protocol
|
||||
engine that logs sender and recipient information.
|
||||
<b>drop</b> Drop the connection immediately with a 521 SMTP
|
||||
reply. In a future implementation, the connection
|
||||
may instead be passed to a dummy SMTP protocol
|
||||
engine that logs sender and recipient information.
|
||||
|
||||
<b>SECURITY</b>
|
||||
The <a href="postscreen.8.html"><b>postscreen</b>(8)</a> server is moderately security-sensitive.
|
||||
It talks to untrusted clients on the network. The process
|
||||
It talks to untrusted clients on the network. The process
|
||||
can be run chrooted at fixed low privilege.
|
||||
|
||||
<b>STANDARDS</b>
|
||||
@ -216,34 +217,42 @@ POSTSCREEN(8) POSTSCREEN(8)
|
||||
Problems and transactions are logged to <b>syslogd</b>(8).
|
||||
|
||||
<b>CONFIGURATION PARAMETERS</b>
|
||||
Changes to <a href="postconf.5.html">main.cf</a> are not picked up automatically, as
|
||||
<a href="postscreen.8.html"><b>postscreen</b>(8)</a> processes may run for several hours. Use
|
||||
Changes to <a href="postconf.5.html">main.cf</a> are not picked up automatically, as
|
||||
<a href="postscreen.8.html"><b>postscreen</b>(8)</a> processes may run for several hours. Use
|
||||
the command "postfix reload" after a configuration change.
|
||||
|
||||
The text below provides only a parameter summary. See
|
||||
The text below provides only a parameter summary. See
|
||||
<a href="postconf.5.html"><b>postconf</b>(5)</a> for more details including examples.
|
||||
|
||||
<b>TRIAGE PARAMETERS</b>
|
||||
<b><a href="postconf.5.html#postscreen_blacklist_action">postscreen_blacklist_action</a> (continue)</b>
|
||||
The action that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> takes when an SMTP
|
||||
client is permanently blacklisted with the
|
||||
The action that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> takes when an SMTP
|
||||
client is permanently blacklisted with the
|
||||
<a href="postconf.5.html#postscreen_blacklist_networks">postscreen_blacklist_networks</a> parameter.
|
||||
|
||||
<b><a href="postconf.5.html#postscreen_blacklist_networks">postscreen_blacklist_networks</a> (empty)</b>
|
||||
Network addresses that are permanently blacklisted;
|
||||
see the <a href="postconf.5.html#postscreen_blacklist_action">postscreen_blacklist_action</a> parameter for
|
||||
see the <a href="postconf.5.html#postscreen_blacklist_action">postscreen_blacklist_action</a> parameter for
|
||||
possible actions.
|
||||
|
||||
<b><a href="postconf.5.html#postscreen_dnsbl_action">postscreen_dnsbl_action</a> (continue)</b>
|
||||
The action that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> takes when an SMTP
|
||||
client is listed at the DNS blocklist domains spec-
|
||||
ified with the <a href="postconf.5.html#postscreen_dnsbl_sites">postscreen_dnsbl_sites</a> parameter.
|
||||
The action that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> takes when an SMTP
|
||||
client's combined DNSBL score is equal to or
|
||||
greater than a threshold (as defined with the
|
||||
<a href="postconf.5.html#postscreen_dnsbl_sites">postscreen_dnsbl_sites</a> and postscreen_dnsbl_thresh-
|
||||
old parameters).
|
||||
|
||||
<b><a href="postconf.5.html#postscreen_dnsbl_sites">postscreen_dnsbl_sites</a> (empty)</b>
|
||||
Optional list of DNS blocklist domains.
|
||||
Optional list of DNS blocklist domains, filters and
|
||||
weight factors.
|
||||
|
||||
<b><a href="postconf.5.html#postscreen_dnsbl_threshold">postscreen_dnsbl_threshold</a> (1)</b>
|
||||
The inclusive lower bound for blocking an SMTP
|
||||
client, based on its combined DNSBL score as
|
||||
defined with the <a href="postconf.5.html#postscreen_dnsbl_sites">postscreen_dnsbl_sites</a> parameter.
|
||||
|
||||
<b><a href="postconf.5.html#postscreen_greet_action">postscreen_greet_action</a> (continue)</b>
|
||||
The action that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> takes when an SMTP
|
||||
The action that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> takes when an SMTP
|
||||
client speaks before its turn within the time spec-
|
||||
ified with the <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> parameter.
|
||||
|
||||
@ -251,72 +260,72 @@ POSTSCREEN(8) POSTSCREEN(8)
|
||||
The <i>text</i> in the optional "220-<i>text</i>..." server
|
||||
response that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> sends ahead of the real
|
||||
Postfix SMTP server's "220 text..." response, in an
|
||||
attempt to confuse bad SMTP clients so that they
|
||||
attempt to confuse bad SMTP clients so that they
|
||||
speak before their turn (pre-greet).
|
||||
|
||||
<b><a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> (4s)</b>
|
||||
The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will wait for
|
||||
an SMTP client to send a command before its turn,
|
||||
an SMTP client to send a command before its turn,
|
||||
and for DNS blocklist lookup results to arrive.
|
||||
|
||||
<b><a href="postconf.5.html#postscreen_hangup_action">postscreen_hangup_action</a> (continue)</b>
|
||||
The action that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> takes when an SMTP
|
||||
The action that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> takes when an SMTP
|
||||
client disconnects without sending data, within the
|
||||
time specified with the <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a>
|
||||
time specified with the <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a>
|
||||
parameter.
|
||||
|
||||
<b><a href="postconf.5.html#postscreen_post_queue_limit">postscreen_post_queue_limit</a> ($<a href="postconf.5.html#default_process_limit">default_process_limit</a>)</b>
|
||||
The number of clients that can be waiting for ser-
|
||||
The number of clients that can be waiting for ser-
|
||||
vice from a real SMTP server process.
|
||||
|
||||
<b><a href="postconf.5.html#postscreen_pre_queue_limit">postscreen_pre_queue_limit</a> ($<a href="postconf.5.html#default_process_limit">default_process_limit</a>)</b>
|
||||
The number of non-whitelisted clients that can be
|
||||
waiting for a decision whether they will receive
|
||||
The number of non-whitelisted clients that can be
|
||||
waiting for a decision whether they will receive
|
||||
service from a real SMTP server process.
|
||||
|
||||
<b><a href="postconf.5.html#postscreen_whitelist_networks">postscreen_whitelist_networks</a> ($<a href="postconf.5.html#mynetworks">mynetworks</a>)</b>
|
||||
Network addresses that are permanently whitelisted,
|
||||
and that will not be subjected to <a href="postscreen.8.html"><b>postscreen</b>(8)</a>
|
||||
and that will not be subjected to <a href="postscreen.8.html"><b>postscreen</b>(8)</a>
|
||||
checks.
|
||||
|
||||
<b><a href="postconf.5.html#smtpd_service">smtpd_service</a> (smtpd)</b>
|
||||
The internal service that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> forwards
|
||||
The internal service that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> forwards
|
||||
allowed connections to.
|
||||
|
||||
<b>CACHE CONTROLS</b>
|
||||
<b><a href="postconf.5.html#postscreen_cache_cleanup_interval">postscreen_cache_cleanup_interval</a> (12h)</b>
|
||||
The amount of time between <a href="postscreen.8.html"><b>postscreen</b>(8)</a> cache
|
||||
The amount of time between <a href="postscreen.8.html"><b>postscreen</b>(8)</a> cache
|
||||
cleanup runs.
|
||||
|
||||
<b><a href="postconf.5.html#postscreen_cache_map">postscreen_cache_map</a> (btree:$<a href="postconf.5.html#data_directory">data_directory</a>/ps_whitelist)</b>
|
||||
Persistent storage for the <a href="postscreen.8.html"><b>postscreen</b>(8)</a> server
|
||||
<b><a href="postconf.5.html#postscreen_cache_map">postscreen_cache_map</a> (btree:$<a href="postconf.5.html#data_directory">data_directory</a>/ps_cache)</b>
|
||||
Persistent storage for the <a href="postscreen.8.html"><b>postscreen</b>(8)</a> server
|
||||
decisions.
|
||||
|
||||
<b><a href="postconf.5.html#postscreen_cache_retention_time">postscreen_cache_retention_time</a> (1d)</b>
|
||||
The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will cache an
|
||||
expired temporary whitelist entry before it is
|
||||
expired temporary whitelist entry before it is
|
||||
removed.
|
||||
|
||||
<b><a href="postconf.5.html#postscreen_cache_ttl">postscreen_cache_ttl</a> (1d)</b>
|
||||
The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will cache a
|
||||
The amount of time that <a href="postscreen.8.html"><b>postscreen</b>(8)</a> will cache a
|
||||
decision for a specific SMTP client IP address.
|
||||
|
||||
<b>MISCELLANEOUS CONTROLS</b>
|
||||
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
|
||||
The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
|
||||
The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
|
||||
<a href="master.5.html">master.cf</a> configuration files.
|
||||
|
||||
<b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
|
||||
How much time a Postfix daemon process may take to
|
||||
handle a request before it is terminated by a
|
||||
How much time a Postfix daemon process may take to
|
||||
handle a request before it is terminated by a
|
||||
built-in watchdog timer.
|
||||
|
||||
<b><a href="postconf.5.html#delay_logging_resolution_limit">delay_logging_resolution_limit</a> (2)</b>
|
||||
The maximal number of digits after the decimal
|
||||
The maximal number of digits after the decimal
|
||||
point when logging sub-second delay values.
|
||||
|
||||
<b><a href="postconf.5.html#command_directory">command_directory</a> (see 'postconf -d' output)</b>
|
||||
The location of all postfix administrative com-
|
||||
The location of all postfix administrative com-
|
||||
mands.
|
||||
|
||||
<b><a href="postconf.5.html#ipc_timeout">ipc_timeout</a> (3600s)</b>
|
||||
@ -324,24 +333,24 @@ POSTSCREEN(8) POSTSCREEN(8)
|
||||
over an internal communication channel.
|
||||
|
||||
<b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b>
|
||||
The maximum amount of time that an idle Postfix
|
||||
daemon process waits for an incoming connection
|
||||
The maximum amount of time that an idle Postfix
|
||||
daemon process waits for an incoming connection
|
||||
before terminating voluntarily.
|
||||
|
||||
<b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
|
||||
The process ID of a Postfix command or daemon
|
||||
The process ID of a Postfix command or daemon
|
||||
process.
|
||||
|
||||
<b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b>
|
||||
The process name of a Postfix command or daemon
|
||||
The process name of a Postfix command or daemon
|
||||
process.
|
||||
|
||||
<b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
|
||||
The syslog facility of Postfix logging.
|
||||
|
||||
<b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
|
||||
The mail system name that is prepended to the
|
||||
process name in syslog records, so that "smtpd"
|
||||
The mail system name that is prepended to the
|
||||
process name in syslog records, so that "smtpd"
|
||||
becomes, for example, "postfix/smtpd".
|
||||
|
||||
<b>SEE ALSO</b>
|
||||
@ -350,7 +359,7 @@ POSTSCREEN(8) POSTSCREEN(8)
|
||||
syslogd(8), system logging
|
||||
|
||||
<b>LICENSE</b>
|
||||
The Secure Mailer license must be distributed with this
|
||||
The Secure Mailer license must be distributed with this
|
||||
software.
|
||||
|
||||
<b>AUTHOR(S)</b>
|
||||
|
@ -3726,8 +3726,9 @@ parameter. Specify one of the following:
|
||||
.IP "continue"
|
||||
Continue waiting until the postscreen_greet_wait time has
|
||||
elapsed, and report whether the client triggers a PREGREET or HANGUP
|
||||
error, or whether the client is listed at the DNSBL sites specified
|
||||
with the postscreen_dnsbl_sites parameter. Take the corresponding
|
||||
error, or whether the client's combined DNSBL score is equal to or
|
||||
greater than a threshold (as specified with the postscreen_dnsbl_sites
|
||||
and postscreen_dnsbl_threshold parameters). Take the corresponding
|
||||
action, or forward the connection to a real SMTP server process.
|
||||
.IP "drop"
|
||||
Drop the connection immediately with a 521 SMTP reply, without
|
||||
@ -3759,7 +3760,7 @@ Time units: s (seconds), m (minutes), h (hours), d (days), w
|
||||
(weeks).
|
||||
.PP
|
||||
This feature is available in Postfix 2.8.
|
||||
.SH postscreen_cache_map (default: btree:$data_directory/ps_whitelist)
|
||||
.SH postscreen_cache_map (default: btree:$data_directory/ps_cache)
|
||||
Persistent storage for the \fBpostscreen\fR(8) server decisions.
|
||||
.PP
|
||||
This feature is available in Postfix 2.8.
|
||||
@ -3786,9 +3787,10 @@ Time units: s (seconds), m (minutes), h (hours), d (days), w
|
||||
.PP
|
||||
This feature is available in Postfix 2.8.
|
||||
.SH postscreen_dnsbl_action (default: continue)
|
||||
The action that \fBpostscreen\fR(8) takes when an SMTP client is listed
|
||||
at the DNS blocklist domains specified with the postscreen_dnsbl_sites
|
||||
parameter. Specify one of the following:
|
||||
The action that \fBpostscreen\fR(8) takes when an SMTP client's combined
|
||||
DNSBL score is equal to or greater than a threshold (as defined
|
||||
with the postscreen_dnsbl_sites and postscreen_dnsbl_threshold
|
||||
parameters). Specify one of the following:
|
||||
.IP "continue"
|
||||
Forward the connection to a real SMTP server process.
|
||||
.IP "drop"
|
||||
@ -3796,10 +3798,62 @@ Drop the connection with a 521 SMTP reply.
|
||||
.PP
|
||||
This feature is available in Postfix 2.8.
|
||||
.SH postscreen_dnsbl_sites (default: empty)
|
||||
Optional list of DNS blocklist domains. When the list is non-enpty,
|
||||
the \fBdnsblog\fR(8) daemon will query these domains with the IP addresses
|
||||
of non-whitelisted \fBpostscreen\fR(8) clients. Specify a list of domain
|
||||
names, separated by comma or whitespace.
|
||||
Optional list of DNS blocklist domains, filters and weight
|
||||
factors. When the list is non-empty, the \fBdnsblog\fR(8) daemon will
|
||||
query these domains with the IP addresses of non-whitelisted remote
|
||||
SMTP clients, and \fBpostscreen\fR(8) will update an SMTP client's DNSBL
|
||||
score with each non-error reply.
|
||||
.PP
|
||||
When a client's score is equal to or greater than the threshold
|
||||
specified with postscreen_dnsbl_threshold, \fBpostscreen\fR(8) can drop
|
||||
the connection with the SMTP client.
|
||||
.PP
|
||||
Specify a list of domain=filter*weight entries, separated by
|
||||
comma or whitespace.
|
||||
.IP \(bu
|
||||
When no "=filter" is specified, \fBpostscreen\fR(8) will use any
|
||||
non-error DNSBL reply. Otherwise, the filter must be an IPv4
|
||||
address, and \fBpostscreen\fR(8) uses only DNSBL replies that match the
|
||||
filter.
|
||||
.IP \(bu
|
||||
When no "*weight" is specified, \fBpostscreen\fR(8) increments
|
||||
the SMTP client's DNSBL score by 1. Otherwise, the weight must be
|
||||
an integral number, and \fBpostscreen\fR(8) adds the specified weight to
|
||||
the SMTP client's DNSBL score. Specify a negative number for
|
||||
whitelisting.
|
||||
.IP \(bu
|
||||
When one postscreen_dnsbl_sites entry produces multiple
|
||||
DNSBL responses, \fBpostscreen\fR(8) applies the weight at most once.
|
||||
.PP
|
||||
Examples:
|
||||
.PP
|
||||
To use example.com as a high-confidence blocklist, and to
|
||||
block mail with example.net and example.org only when both agree:
|
||||
.PP
|
||||
.nf
|
||||
.na
|
||||
.ft C
|
||||
postscreen_dnsbl_threshold = 2
|
||||
postscreen_dnsbl_sites = example.com*2, example.net, example.org
|
||||
.fi
|
||||
.ad
|
||||
.ft R
|
||||
.PP
|
||||
To filter only DNSBL replies containing 127.0.0.4:
|
||||
.PP
|
||||
.nf
|
||||
.na
|
||||
.ft C
|
||||
postscreen_dnsbl_sites = example.com=127.0.0.4
|
||||
.fi
|
||||
.ad
|
||||
.ft R
|
||||
.PP
|
||||
This feature is available in Postfix 2.8.
|
||||
.SH postscreen_dnsbl_threshold (default: 1)
|
||||
The inclusive lower bound for blocking an SMTP client, based on
|
||||
its combined DNSBL score as defined with the postscreen_dnsbl_sites
|
||||
parameter.
|
||||
.PP
|
||||
This feature is available in Postfix 2.8.
|
||||
.SH postscreen_greet_action (default: continue)
|
||||
@ -3808,10 +3862,11 @@ before its turn within the time specified with the postscreen_greet_wait
|
||||
parameter. Specify one of the following:
|
||||
.IP "continue"
|
||||
Continue waiting until the postscreen_greet_wait time has
|
||||
elapsed. If the client is listed at the DNS blocklist domains
|
||||
specified with the postscreen_dnsbl_sites parameter, execute the
|
||||
action specified with the postscreen_dnsbl_action parameter, otherwise
|
||||
forward the connection to a real SMTP server process.
|
||||
elapsed. If the client's combined DNSBL score is equal to or greater
|
||||
than a threshold (as specified with the postscreen_dnsbl_sites and
|
||||
postscreen_dnsbl_threshold parameters), execute the action specified
|
||||
with the postscreen_dnsbl_action parameter, otherwise forward the
|
||||
connection to a real SMTP server process.
|
||||
.IP "drop"
|
||||
Drop the connection immediately with a 521 SMTP reply, without
|
||||
examining DNSBL lookup results.
|
||||
@ -3847,9 +3902,10 @@ without sending data, within the time specified with the
|
||||
postscreen_greet_wait parameter. Specify one of the following:
|
||||
.IP "continue"
|
||||
Continue waiting until the postscreen_greet_wait time has
|
||||
elapsed, and report whether the client is listed at the DNSBL sites
|
||||
specified with the postscreen_dnsbl_sites parameter. Do not
|
||||
forward the broken connection to a real SMTP server process.
|
||||
elapsed, and report whether the client's combined DNSBL score is
|
||||
equal to or greater than a threshold (as defined with the
|
||||
postscreen_dnsbl_sites and postscreen_dnsbl_threshold parameters).
|
||||
Do not forward the broken connection to a real SMTP server process.
|
||||
.IP "drop"
|
||||
Drop the connection immediately, without reporting DNSBL lookup
|
||||
results.
|
||||
@ -4903,13 +4959,13 @@ Use the smtp_discard_ehlo_keyword_address_maps feature to
|
||||
discard EHLO keywords selectively.
|
||||
.SH smtp_dns_resolver_options (default: empty)
|
||||
DNS Resolver options for the Postfix SMTP client. Specify zero
|
||||
or more of the following, separated by comma or whitespace. Option
|
||||
names are case-sensitive. Some options refer to domain names that
|
||||
are specified in /etc/resolv.conf or equivalent.
|
||||
or more of the following options, separated by comma or whitespace.
|
||||
Option names are case-sensitive. Some options refer to domain names
|
||||
that are specified in the file /etc/resolv.conf or equivalent.
|
||||
.IP "\fBres_defnames\fR"
|
||||
Append the default domain name to single-component names (those
|
||||
that do not contain a dot). This can produce incorrect results,
|
||||
and was the behavior prior to Postfix 2.8.
|
||||
Append the current domain name to single-component names (those
|
||||
that do not contain a "." character). This can produce incorrect
|
||||
results, and is the hard-coded behavior prior to Postfix 2.8.
|
||||
.IP "\fBres_dnsrch\fR"
|
||||
Search for host names in the current domain and in parent
|
||||
domains. This can produce incorrect results and is therefore not
|
||||
|
@ -199,20 +199,20 @@ specifies a list of DNS blocklist servers. These lookups
|
||||
are made in parallel.
|
||||
|
||||
When the postscreen_greet_wait time has elapsed, and the
|
||||
SMTP client address is listed with at least one of these
|
||||
blocklists, this is logged as:
|
||||
combined DNSBL score is equal to or greater than the
|
||||
postscreen_dnsbl_threshold parameter value, this is logged
|
||||
as:
|
||||
.sp
|
||||
.nf
|
||||
\fBDNSBL rank \fIcount \fBfor \fIaddress\fR
|
||||
.fi
|
||||
.sp
|
||||
Translation: the client at \fIaddress\fR is listed with
|
||||
\fIcount\fR DNSBL servers. The \fIcount\fR does not
|
||||
depend on the number of DNS records that an individual DNSBL
|
||||
server returns.
|
||||
Translation: the SMTP client at \fIaddress\fR has a combined
|
||||
DNSBL score of \fIcount\fR.
|
||||
|
||||
The postscreen_dnsbl_action parameter specifies the action
|
||||
that is taken next:
|
||||
that is taken when the combined DNSBL score is equal to or
|
||||
greater than the threshold:
|
||||
.IP "\fBcontinue\fR (default)"
|
||||
Forward the connection to a real SMTP server process.
|
||||
.IP \fBdrop\fR
|
||||
@ -262,11 +262,17 @@ parameter.
|
||||
Network addresses that are permanently blacklisted; see the
|
||||
postscreen_blacklist_action parameter for possible actions.
|
||||
.IP "\fBpostscreen_dnsbl_action (continue)\fR"
|
||||
The action that \fBpostscreen\fR(8) takes when an SMTP client is listed
|
||||
at the DNS blocklist domains specified with the postscreen_dnsbl_sites
|
||||
parameter.
|
||||
The action that \fBpostscreen\fR(8) takes when an SMTP client's combined
|
||||
DNSBL score is equal to or greater than a threshold (as defined
|
||||
with the postscreen_dnsbl_sites and postscreen_dnsbl_threshold
|
||||
parameters).
|
||||
.IP "\fBpostscreen_dnsbl_sites (empty)\fR"
|
||||
Optional list of DNS blocklist domains.
|
||||
Optional list of DNS blocklist domains, filters and weight
|
||||
factors.
|
||||
.IP "\fBpostscreen_dnsbl_threshold (1)\fR"
|
||||
The inclusive lower bound for blocking an SMTP client, based on
|
||||
its combined DNSBL score as defined with the postscreen_dnsbl_sites
|
||||
parameter.
|
||||
.IP "\fBpostscreen_greet_action (continue)\fR"
|
||||
The action that \fBpostscreen\fR(8) takes when an SMTP client speaks
|
||||
before its turn within the time specified with the postscreen_greet_wait
|
||||
@ -305,7 +311,7 @@ connections to.
|
||||
.fi
|
||||
.IP "\fBpostscreen_cache_cleanup_interval (12h)\fR"
|
||||
The amount of time between \fBpostscreen\fR(8) cache cleanup runs.
|
||||
.IP "\fBpostscreen_cache_map (btree:$data_directory/ps_whitelist)\fR"
|
||||
.IP "\fBpostscreen_cache_map (btree:$data_directory/ps_cache)\fR"
|
||||
Persistent storage for the \fBpostscreen\fR(8) server decisions.
|
||||
.IP "\fBpostscreen_cache_retention_time (1d)\fR"
|
||||
The amount of time that \fBpostscreen\fR(8) will cache an expired
|
||||
|
@ -916,6 +916,7 @@ while (<>) {
|
||||
s;\bpostscreen_greet_wait\b;<a href="postconf.5.html#postscreen_greet_wait">$&</a>;g;
|
||||
s;\bpostscreen_greet_action\b;<a href="postconf.5.html#postscreen_greet_action">$&</a>;g;
|
||||
s;\bpostscreen_dnsbl_sites\b;<a href="postconf.5.html#postscreen_dnsbl_sites">$&</a>;g;
|
||||
s;\bpostscreen_dnsbl_threshold\b;<a href="postconf.5.html#postscreen_dnsbl_threshold">$&</a>;g;
|
||||
s;\bpostscreen_dnsbl_action\b;<a href="postconf.5.html#postscreen_dnsbl_action">$&</a>;g;
|
||||
s;\bpostscreen_hangup_action\b;<a href="postconf.5.html#postscreen_hangup_action">$&</a>;g;
|
||||
s;\bpostscreen_whitelist_networks\b;<a href="postconf.5.html#postscreen_whitelist_networks">$&</a>;g;
|
||||
|
@ -12512,7 +12512,7 @@ inspection for DKIM-signed mail from known friendly domains. </p>
|
||||
<p> This feature is available in Postfix 2.7, and as an optional
|
||||
patch for Postfix 2.6. </p>
|
||||
|
||||
%PARAM postscreen_cache_map btree:$data_directory/ps_whitelist
|
||||
%PARAM postscreen_cache_map btree:$data_directory/ps_cache
|
||||
|
||||
<p> Persistent storage for the postscreen(8) server decisions. </p>
|
||||
|
||||
@ -12604,18 +12604,63 @@ an optional one-letter suffix that specifies the time unit). </p>
|
||||
|
||||
%PARAM postscreen_dnsbl_sites
|
||||
|
||||
<p>Optional list of DNS blocklist domains. When the list is non-enpty,
|
||||
the dnsblog(8) daemon will query these domains with the IP addresses
|
||||
of non-whitelisted postscreen(8) clients. Specify a list of domain
|
||||
names, separated by comma or whitespace. </p>
|
||||
<p>Optional list of DNS blocklist domains, filters and weight
|
||||
factors. When the list is non-empty, the dnsblog(8) daemon will
|
||||
query these domains with the IP addresses of non-whitelisted remote
|
||||
SMTP clients, and postscreen(8) will update an SMTP client's DNSBL
|
||||
score with each non-error reply. </p>
|
||||
|
||||
<p> When a client's score is equal to or greater than the threshold
|
||||
specified with postscreen_dnsbl_threshold, postscreen(8) can drop
|
||||
the connection with the SMTP client. </p>
|
||||
|
||||
<p> Specify a list of domain=filter*weight entries, separated by
|
||||
comma or whitespace. </p>
|
||||
|
||||
<ul>
|
||||
|
||||
<li> <p> When no "=filter" is specified, postscreen(8) will use any
|
||||
non-error DNSBL reply. Otherwise, the filter must be an IPv4
|
||||
address, and postscreen(8) uses only DNSBL replies that match the
|
||||
filter. </p>
|
||||
|
||||
<li> <p> When no "*weight" is specified, postscreen(8) increments
|
||||
the SMTP client's DNSBL score by 1. Otherwise, the weight must be
|
||||
an integral number, and postscreen(8) adds the specified weight to
|
||||
the SMTP client's DNSBL score. Specify a negative number for
|
||||
whitelisting. </p>
|
||||
|
||||
<li> <p> When one postscreen_dnsbl_sites entry produces multiple
|
||||
DNSBL responses, postscreen(8) applies the weight at most once.
|
||||
</p>
|
||||
|
||||
</ul>
|
||||
|
||||
<p> Examples: </p>
|
||||
|
||||
<p> To use example.com as a high-confidence blocklist, and to
|
||||
block mail with example.net and example.org only when both agree:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
postscreen_dnsbl_threshold = 2
|
||||
postscreen_dnsbl_sites = example.com*2, example.net, example.org
|
||||
</pre>
|
||||
|
||||
<p> To filter only DNSBL replies containing 127.0.0.4: </p>
|
||||
|
||||
<pre>
|
||||
postscreen_dnsbl_sites = example.com=127.0.0.4
|
||||
</pre>
|
||||
|
||||
<p> This feature is available in Postfix 2.8. </p>
|
||||
|
||||
%PARAM postscreen_dnsbl_action continue
|
||||
|
||||
<p>The action that postscreen(8) takes when an SMTP client is listed
|
||||
at the DNS blocklist domains specified with the postscreen_dnsbl_sites
|
||||
parameter. Specify one of the following: </p>
|
||||
<p>The action that postscreen(8) takes when an SMTP client's combined
|
||||
DNSBL score is equal to or greater than a threshold (as defined
|
||||
with the postscreen_dnsbl_sites and postscreen_dnsbl_threshold
|
||||
parameters). Specify one of the following: </p>
|
||||
|
||||
<dl>
|
||||
|
||||
@ -12642,10 +12687,11 @@ parameter. Specify one of the following: </p>
|
||||
<dt> continue </dt>
|
||||
|
||||
<dd> Continue waiting until the postscreen_greet_wait time has
|
||||
elapsed. If the client is listed at the DNS blocklist domains
|
||||
specified with the postscreen_dnsbl_sites parameter, execute the
|
||||
action specified with the postscreen_dnsbl_action parameter, otherwise
|
||||
forward the connection to a real SMTP server process. </dd>
|
||||
elapsed. If the client's combined DNSBL score is equal to or greater
|
||||
than a threshold (as specified with the postscreen_dnsbl_sites and
|
||||
postscreen_dnsbl_threshold parameters), execute the action specified
|
||||
with the postscreen_dnsbl_action parameter, otherwise forward the
|
||||
connection to a real SMTP server process. </dd>
|
||||
|
||||
<dt> drop </dt>
|
||||
|
||||
@ -12671,9 +12717,11 @@ postscreen_greet_wait parameter. Specify one of the following:
|
||||
<dt> continue </dt>
|
||||
|
||||
<dd> Continue waiting until the postscreen_greet_wait time has
|
||||
elapsed, and report whether the client is listed at the DNSBL sites
|
||||
specified with the postscreen_dnsbl_sites parameter. Do not
|
||||
forward the broken connection to a real SMTP server process. </dd>
|
||||
elapsed, and report whether the client's combined DNSBL score is
|
||||
equal to or greater than a threshold (as defined with the
|
||||
postscreen_dnsbl_sites and postscreen_dnsbl_threshold parameters).
|
||||
Do not forward the broken connection to a real SMTP server process.
|
||||
</dd>
|
||||
|
||||
<dt> drop </dt>
|
||||
|
||||
@ -12726,8 +12774,9 @@ parameter. Specify one of the following: </p>
|
||||
|
||||
<dd> Continue waiting until the postscreen_greet_wait time has
|
||||
elapsed, and report whether the client triggers a PREGREET or HANGUP
|
||||
error, or whether the client is listed at the DNSBL sites specified
|
||||
with the postscreen_dnsbl_sites parameter. Take the corresponding
|
||||
error, or whether the client's combined DNSBL score is equal to or
|
||||
greater than a threshold (as specified with the postscreen_dnsbl_sites
|
||||
and postscreen_dnsbl_threshold parameters). Take the corresponding
|
||||
action, or forward the connection to a real SMTP server process.
|
||||
</dd>
|
||||
|
||||
@ -12942,17 +12991,17 @@ configuration parameter. See there for details. </p>
|
||||
%PARAM smtp_dns_resolver_options
|
||||
|
||||
<p> DNS Resolver options for the Postfix SMTP client. Specify zero
|
||||
or more of the following, separated by comma or whitespace. Option
|
||||
names are case-sensitive. Some options refer to domain names that
|
||||
are specified in /etc/resolv.conf or equivalent. </p>
|
||||
or more of the following options, separated by comma or whitespace.
|
||||
Option names are case-sensitive. Some options refer to domain names
|
||||
that are specified in the file /etc/resolv.conf or equivalent. </p>
|
||||
|
||||
<dl>
|
||||
|
||||
<dt><b>res_defnames</b></dt>
|
||||
|
||||
<dd> Append the default domain name to single-component names (those
|
||||
that do not contain a dot). This can produce incorrect results,
|
||||
and was the behavior prior to Postfix 2.8. </dd>
|
||||
<dd> Append the current domain name to single-component names (those
|
||||
that do not contain a "." character). This can produce incorrect
|
||||
results, and is the hard-coded behavior prior to Postfix 2.8. </dd>
|
||||
|
||||
<dt><b>res_dnsrch</b></dt>
|
||||
|
||||
@ -12971,3 +13020,10 @@ configuration parameter. See there for details. </p>
|
||||
|
||||
<p> This feature is available in Postfix 2.8 and later. </p>
|
||||
|
||||
%PARAM postscreen_dnsbl_threshold 1
|
||||
|
||||
<p> The inclusive lower bound for blocking an SMTP client, based on
|
||||
its combined DNSBL score as defined with the postscreen_dnsbl_sites
|
||||
parameter. </p>
|
||||
|
||||
<p> This feature is available in Postfix 2.8. </p>
|
||||
|
@ -99,7 +99,7 @@ int main(int argc, char **argv)
|
||||
argv_free(types_argv);
|
||||
name = argv[2];
|
||||
msg_verbose = 1;
|
||||
switch (dns_lookup_v(name, RES_DEFNAMES | RES_DEBUG, &rr, fqdn, why,
|
||||
switch (dns_lookup_v(name, RES_DEBUG, &rr, fqdn, why,
|
||||
DNS_REQ_FLAG_NONE, types)) {
|
||||
default:
|
||||
msg_fatal("%s", vstring_str(why));
|
||||
|
@ -108,15 +108,18 @@ static VSTRING *rbl_domain;
|
||||
static VSTRING *addr;
|
||||
static VSTRING *query;
|
||||
static VSTRING *why;
|
||||
static VSTRING *result;
|
||||
|
||||
/*
|
||||
* Silly little macros.
|
||||
*/
|
||||
#define STR(x) vstring_str(x)
|
||||
#define LEN(x) VSTRING_LEN(x)
|
||||
|
||||
/* static void dnsblog_query - query DNSBL for client address */
|
||||
|
||||
static int dnsblog_query(const char *dnsbl_domain, const char *addr)
|
||||
static VSTRING *dnsblog_query(VSTRING *result, const char *dnsbl_domain,
|
||||
const char *addr)
|
||||
{
|
||||
const char *myname = "dnsblog_query";
|
||||
ARGV *octets;
|
||||
@ -127,7 +130,6 @@ static int dnsblog_query(const char *dnsbl_domain, const char *addr)
|
||||
DNS_RR *addr_list;
|
||||
DNS_RR *rr;
|
||||
MAI_HOSTADDR_STR hostaddr;
|
||||
int found = 0;
|
||||
|
||||
if (msg_verbose)
|
||||
msg_info("%s: addr %s dnsbl_domain %s",
|
||||
@ -168,11 +170,11 @@ static int dnsblog_query(const char *dnsbl_domain, const char *addr)
|
||||
}
|
||||
|
||||
/*
|
||||
* Tack on the RBL domain name and query the DNS for an A record. Don't
|
||||
* do this for AAAA records. Yet.
|
||||
* Tack on the RBL domain name and query the DNS for an A record.
|
||||
*/
|
||||
vstring_strcat(query, dnsbl_domain);
|
||||
dns_status = dns_lookup(STR(query), T_A, 0, &addr_list, (VSTRING *) 0, why);
|
||||
VSTRING_RESET(result);
|
||||
if (dns_status == DNS_OK) {
|
||||
for (rr = addr_list; rr != 0; rr = rr->next) {
|
||||
if (dns_rr_to_pa(rr, &hostaddr) == 0) {
|
||||
@ -181,7 +183,9 @@ static int dnsblog_query(const char *dnsbl_domain, const char *addr)
|
||||
} else {
|
||||
msg_info("addr %s blocked by domain %s as %s",
|
||||
addr, dnsbl_domain, hostaddr.buf);
|
||||
found = 1;
|
||||
if (LEN(result) > 0)
|
||||
vstring_strcat(result, " ");
|
||||
vstring_strcat(result, hostaddr.buf);
|
||||
}
|
||||
}
|
||||
dns_rr_free(addr_list);
|
||||
@ -193,7 +197,8 @@ static int dnsblog_query(const char *dnsbl_domain, const char *addr)
|
||||
msg_warn("%s: lookup error for DNS query %s: %s",
|
||||
myname, STR(query), STR(why));
|
||||
}
|
||||
return (found);
|
||||
VSTRING_TERMINATE(result);
|
||||
return (result);
|
||||
}
|
||||
|
||||
/* dnsblog_service - perform service for client */
|
||||
@ -201,7 +206,6 @@ static int dnsblog_query(const char *dnsbl_domain, const char *addr)
|
||||
static void dnsblog_service(VSTREAM *client_stream, char *unused_service,
|
||||
char **argv)
|
||||
{
|
||||
int found;
|
||||
|
||||
/*
|
||||
* Sanity check. This service takes no command-line arguments.
|
||||
@ -217,13 +221,13 @@ static void dnsblog_service(VSTREAM *client_stream, char *unused_service,
|
||||
if (attr_scan(client_stream,
|
||||
ATTR_FLAG_MORE | ATTR_FLAG_STRICT,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_RBL_DOMAIN, rbl_domain,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_ADDR, addr,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_ACT_CLIENT_ADDR, addr,
|
||||
ATTR_TYPE_END) == 2) {
|
||||
found = dnsblog_query(STR(rbl_domain), STR(addr));
|
||||
(void) dnsblog_query(result, STR(rbl_domain), STR(addr));
|
||||
attr_print(client_stream, ATTR_FLAG_NONE,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_RBL_DOMAIN, STR(rbl_domain),
|
||||
ATTR_TYPE_STR, MAIL_ATTR_ADDR, STR(addr),
|
||||
ATTR_TYPE_INT, MAIL_ATTR_STATUS, found,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_ACT_CLIENT_ADDR, STR(addr),
|
||||
ATTR_TYPE_STR, MAIL_ATTR_RBL_ADDR, STR(result),
|
||||
ATTR_TYPE_END);
|
||||
vstream_fflush(client_stream);
|
||||
}
|
||||
@ -237,6 +241,7 @@ static void post_jail_init(char *unused_name, char **unused_argv)
|
||||
addr = vstring_alloc(100);
|
||||
query = vstring_alloc(100);
|
||||
why = vstring_alloc(100);
|
||||
result = vstring_alloc(100);
|
||||
}
|
||||
|
||||
MAIL_VERSION_STAMP_DECLARE;
|
||||
|
@ -3251,6 +3251,10 @@ extern char *var_ps_greet_action;
|
||||
#define DEF_PS_DNSBL_SITES ""
|
||||
extern char *var_ps_dnsbl_sites;
|
||||
|
||||
#define VAR_PS_DNSBL_THRESH "postscreen_dnsbl_threshold"
|
||||
#define DEF_PS_DNSBL_THRESH 1
|
||||
extern int var_ps_dnsbl_thresh;
|
||||
|
||||
#define VAR_PS_DNSBL_ACTION "postscreen_dnsbl_action"
|
||||
#define DEF_PS_DNSBL_ACTION "continue"
|
||||
extern char *var_ps_dnsbl_action;
|
||||
|
@ -160,6 +160,7 @@ extern char *mail_pathname(const char *, const char *);
|
||||
#define MAIL_ATTR_RBL_TXT "rbl_txt" /* LaMont compatibility */
|
||||
#define MAIL_ATTR_RBL_CLASS "rbl_class"
|
||||
#define MAIL_ATTR_RBL_CODE "rbl_code"
|
||||
#define MAIL_ATTR_RBL_ADDR "rbl_addr"
|
||||
|
||||
/*
|
||||
* The following attribute names are stored in queue files. Changing this
|
||||
|
@ -20,7 +20,7 @@
|
||||
* Patches change both the patchlevel and the release date. Snapshots have no
|
||||
* patchlevel; they change the release date only.
|
||||
*/
|
||||
#define MAIL_RELEASE_DATE "20100827"
|
||||
#define MAIL_RELEASE_DATE "20100829"
|
||||
#define MAIL_VERSION_NUMBER "2.8"
|
||||
|
||||
#ifdef SNAPSHOT
|
||||
|
@ -1,6 +1,6 @@
|
||||
SHELL = /bin/sh
|
||||
SRCS = postscreen.c
|
||||
OBJS = postscreen.o
|
||||
SRCS = postscreen.c postscreen_dict.c postscreen_dnsbl.c
|
||||
OBJS = postscreen.o postscreen_dict.o postscreen_dnsbl.o
|
||||
HDRS =
|
||||
TESTSRC =
|
||||
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
@ -87,3 +87,40 @@ postscreen.o: ../../include/vbuf.h
|
||||
postscreen.o: ../../include/vstream.h
|
||||
postscreen.o: ../../include/vstring.h
|
||||
postscreen.o: postscreen.c
|
||||
postscreen.o: postscreen.h
|
||||
postscreen_dict.o: ../../include/addr_match_list.h
|
||||
postscreen_dict.o: ../../include/argv.h
|
||||
postscreen_dict.o: ../../include/dict.h
|
||||
postscreen_dict.o: ../../include/dict_cache.h
|
||||
postscreen_dict.o: ../../include/match_list.h
|
||||
postscreen_dict.o: ../../include/match_ops.h
|
||||
postscreen_dict.o: ../../include/msg.h
|
||||
postscreen_dict.o: ../../include/sys_defs.h
|
||||
postscreen_dict.o: ../../include/vbuf.h
|
||||
postscreen_dict.o: ../../include/vstream.h
|
||||
postscreen_dict.o: ../../include/vstring.h
|
||||
postscreen_dict.o: postscreen.h
|
||||
postscreen_dict.o: postscreen_dict.c
|
||||
postscreen_dnsbl.o: ../../include/addr_match_list.h
|
||||
postscreen_dnsbl.o: ../../include/argv.h
|
||||
postscreen_dnsbl.o: ../../include/attr.h
|
||||
postscreen_dnsbl.o: ../../include/connect.h
|
||||
postscreen_dnsbl.o: ../../include/dict.h
|
||||
postscreen_dnsbl.o: ../../include/dict_cache.h
|
||||
postscreen_dnsbl.o: ../../include/events.h
|
||||
postscreen_dnsbl.o: ../../include/htable.h
|
||||
postscreen_dnsbl.o: ../../include/iostuff.h
|
||||
postscreen_dnsbl.o: ../../include/mail_params.h
|
||||
postscreen_dnsbl.o: ../../include/mail_proto.h
|
||||
postscreen_dnsbl.o: ../../include/match_list.h
|
||||
postscreen_dnsbl.o: ../../include/match_ops.h
|
||||
postscreen_dnsbl.o: ../../include/msg.h
|
||||
postscreen_dnsbl.o: ../../include/mymalloc.h
|
||||
postscreen_dnsbl.o: ../../include/split_at.h
|
||||
postscreen_dnsbl.o: ../../include/sys_defs.h
|
||||
postscreen_dnsbl.o: ../../include/valid_hostname.h
|
||||
postscreen_dnsbl.o: ../../include/vbuf.h
|
||||
postscreen_dnsbl.o: ../../include/vstream.h
|
||||
postscreen_dnsbl.o: ../../include/vstring.h
|
||||
postscreen_dnsbl.o: postscreen.h
|
||||
postscreen_dnsbl.o: postscreen_dnsbl.c
|
||||
|
@ -191,20 +191,20 @@
|
||||
/* are made in parallel.
|
||||
/*
|
||||
/* When the postscreen_greet_wait time has elapsed, and the
|
||||
/* SMTP client address is listed with at least one of these
|
||||
/* blocklists, this is logged as:
|
||||
/* combined DNSBL score is equal to or greater than the
|
||||
/* postscreen_dnsbl_threshold parameter value, this is logged
|
||||
/* as:
|
||||
/* .sp
|
||||
/* .nf
|
||||
/* \fBDNSBL rank \fIcount \fBfor \fIaddress\fR
|
||||
/* .fi
|
||||
/* .sp
|
||||
/* Translation: the client at \fIaddress\fR is listed with
|
||||
/* \fIcount\fR DNSBL servers. The \fIcount\fR does not
|
||||
/* depend on the number of DNS records that an individual DNSBL
|
||||
/* server returns.
|
||||
/* Translation: the SMTP client at \fIaddress\fR has a combined
|
||||
/* DNSBL score of \fIcount\fR.
|
||||
/*
|
||||
/* The postscreen_dnsbl_action parameter specifies the action
|
||||
/* that is taken next:
|
||||
/* that is taken when the combined DNSBL score is equal to or
|
||||
/* greater than the threshold:
|
||||
/* .IP "\fBcontinue\fR (default)"
|
||||
/* Forward the connection to a real SMTP server process.
|
||||
/* .IP \fBdrop\fR
|
||||
@ -244,11 +244,17 @@
|
||||
/* Network addresses that are permanently blacklisted; see the
|
||||
/* postscreen_blacklist_action parameter for possible actions.
|
||||
/* .IP "\fBpostscreen_dnsbl_action (continue)\fR"
|
||||
/* The action that \fBpostscreen\fR(8) takes when an SMTP client is listed
|
||||
/* at the DNS blocklist domains specified with the postscreen_dnsbl_sites
|
||||
/* parameter.
|
||||
/* The action that \fBpostscreen\fR(8) takes when an SMTP client's combined
|
||||
/* DNSBL score is equal to or greater than a threshold (as defined
|
||||
/* with the postscreen_dnsbl_sites and postscreen_dnsbl_threshold
|
||||
/* parameters).
|
||||
/* .IP "\fBpostscreen_dnsbl_sites (empty)\fR"
|
||||
/* Optional list of DNS blocklist domains.
|
||||
/* Optional list of DNS blocklist domains, filters and weight
|
||||
/* factors.
|
||||
/* .IP "\fBpostscreen_dnsbl_threshold (1)\fR"
|
||||
/* The inclusive lower bound for blocking an SMTP client, based on
|
||||
/* its combined DNSBL score as defined with the postscreen_dnsbl_sites
|
||||
/* parameter.
|
||||
/* .IP "\fBpostscreen_greet_action (continue)\fR"
|
||||
/* The action that \fBpostscreen\fR(8) takes when an SMTP client speaks
|
||||
/* before its turn within the time specified with the postscreen_greet_wait
|
||||
@ -285,7 +291,7 @@
|
||||
/* .fi
|
||||
/* .IP "\fBpostscreen_cache_cleanup_interval (12h)\fR"
|
||||
/* The amount of time between \fBpostscreen\fR(8) cache cleanup runs.
|
||||
/* .IP "\fBpostscreen_cache_map (btree:$data_directory/ps_whitelist)\fR"
|
||||
/* .IP "\fBpostscreen_cache_map (btree:$data_directory/ps_cache)\fR"
|
||||
/* Persistent storage for the \fBpostscreen\fR(8) server decisions.
|
||||
/* .IP "\fBpostscreen_cache_retention_time (1d)\fR"
|
||||
/* The amount of time that \fBpostscreen\fR(8) will cache an expired
|
||||
@ -381,6 +387,10 @@
|
||||
|
||||
#include <mail_server.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
#include <postscreen.h>
|
||||
|
||||
/*
|
||||
* Configuration parameters.
|
||||
*/
|
||||
@ -402,6 +412,7 @@ char *var_ps_wlist_nets;
|
||||
char *var_ps_blist_nets;
|
||||
char *var_ps_greet_banner;
|
||||
char *var_ps_blist_action;
|
||||
int var_ps_dnsbl_thresh;
|
||||
|
||||
/*
|
||||
* Per-session state. See also: new_session_state() and free_event_state()
|
||||
@ -442,10 +453,6 @@ static DICT_CACHE *cache_map; /* cache table handle */
|
||||
static VSTRING *temp; /* scratchpad */
|
||||
static char *smtp_service_name; /* path to real SMTPD */
|
||||
static char *teaser_greeting; /* spamware teaser banner */
|
||||
static ARGV *dnsbl_sites; /* dns blocklist domains */
|
||||
static VSTRING *reply_addr; /* address in DNSBL reply */
|
||||
static VSTRING *reply_domain; /* domain in DNSBL reply */
|
||||
static HTABLE *dnsbl_cache; /* entries being queried */
|
||||
static int dnsbl_action; /* PS_ACT_DROP or PS_ACT_CONT */
|
||||
static int greet_action; /* PS_ACT_DROP or PS_ACT_CONT */
|
||||
static int hangup_action; /* PS_ACT_DROP or PS_ACT_CONT */
|
||||
@ -453,239 +460,6 @@ static ADDR_MATCH_LIST *wlist_nets; /* permanently whitelisted networks */
|
||||
static ADDR_MATCH_LIST *blist_nets; /* permanently blacklisted networks */
|
||||
static int blist_action; /* PS_ACT_DROP or PS_ACT_CONT */
|
||||
|
||||
/*
|
||||
* See log_adhoc.c for discussion.
|
||||
*/
|
||||
typedef struct {
|
||||
int dt_sec; /* make sure it's signed */
|
||||
int dt_usec; /* make sure it's signed */
|
||||
} DELTA_TIME;
|
||||
|
||||
#define PS_CALC_DELTA(x, y, z) \
|
||||
do { \
|
||||
(x).dt_sec = (y).tv_sec - (z).tv_sec; \
|
||||
(x).dt_usec = (y).tv_usec - (z).tv_usec; \
|
||||
while ((x).dt_usec < 0) { \
|
||||
(x).dt_usec += 1000000; \
|
||||
(x).dt_sec -= 1; \
|
||||
} \
|
||||
while ((x).dt_usec >= 1000000) { \
|
||||
(x).dt_usec -= 1000000; \
|
||||
(x).dt_sec += 1; \
|
||||
} \
|
||||
if ((x).dt_sec < 0) \
|
||||
(x).dt_sec = (x).dt_usec = 0; \
|
||||
} while (0)
|
||||
|
||||
#define SIG_DIGS 2
|
||||
|
||||
/* READ_EVENT_REQUEST - prepare for transition to next state */
|
||||
|
||||
#define READ_EVENT_REQUEST(fd, action, context, timeout) do { \
|
||||
if (msg_verbose) msg_info("%s: read-request fd=%d", myname, (fd)); \
|
||||
event_enable_read((fd), (action), (context)); \
|
||||
event_request_timer((action), (context), (timeout)); \
|
||||
} while (0)
|
||||
|
||||
/* CLEAR_EVENT_REQUEST - complete state transition */
|
||||
|
||||
#define CLEAR_EVENT_REQUEST(fd, action, context) do { \
|
||||
if (msg_verbose) msg_info("%s: clear-request fd=%d", myname, (fd)); \
|
||||
event_disable_readwrite(fd); \
|
||||
event_cancel_timer((action), (context)); \
|
||||
} while (0)
|
||||
|
||||
/* SLMs. */
|
||||
|
||||
#define STR(x) vstring_str(x)
|
||||
#define LEN(x) VSTRING_LEN(x)
|
||||
|
||||
/*
|
||||
* Monitor time-critical operations.
|
||||
*/
|
||||
#define PS_GET_TIME_BEFORE_LOOKUP \
|
||||
struct timeval _before, _after; \
|
||||
DELTA_TIME _delta; \
|
||||
GETTIMEOFDAY(&_before);
|
||||
|
||||
#define PS_DELTA_MS(d) ((d).dt_sec * 1000 + (d).dt_usec / 1000)
|
||||
|
||||
#define PS_CHECK_TIME_AFTER_LOOKUP(table, action) \
|
||||
GETTIMEOFDAY(&_after); \
|
||||
PS_CALC_DELTA(_delta, _after, _before); \
|
||||
if (_delta.dt_sec > 1 || _delta.dt_usec > 100000) \
|
||||
msg_warn("%s: %s %s took %d ms", \
|
||||
myname, (table), (action), PS_DELTA_MS(_delta));
|
||||
|
||||
/* ps_addr_match_list_match - time-critical address list lookup */
|
||||
|
||||
static int ps_addr_match_list_match(ADDR_MATCH_LIST *addr_list,
|
||||
const char *addr_str)
|
||||
{
|
||||
const char *myname = "ps_addr_match_list_match";
|
||||
int result;
|
||||
|
||||
PS_GET_TIME_BEFORE_LOOKUP;
|
||||
result = addr_match_list_match(addr_list, addr_str);
|
||||
PS_CHECK_TIME_AFTER_LOOKUP("address list", "lookup");
|
||||
return (result);
|
||||
}
|
||||
|
||||
/* ps_dict_get - time-critical table lookup */
|
||||
|
||||
static const char *ps_dict_get(DICT_CACHE *cache, const char *key)
|
||||
{
|
||||
const char *myname = "ps_dict_get";
|
||||
const char *result;
|
||||
|
||||
PS_GET_TIME_BEFORE_LOOKUP;
|
||||
result = dict_cache_lookup(cache, key);
|
||||
PS_CHECK_TIME_AFTER_LOOKUP(dict_cache_name(cache), "lookup");
|
||||
return (result);
|
||||
}
|
||||
|
||||
/* ps_dict_put - table dictionary update */
|
||||
|
||||
static void ps_dict_put(DICT_CACHE *cache, const char *key, const char *value)
|
||||
{
|
||||
const char *myname = "ps_dict_put";
|
||||
|
||||
PS_GET_TIME_BEFORE_LOOKUP;
|
||||
dict_cache_update(cache, key, value);
|
||||
PS_CHECK_TIME_AFTER_LOOKUP(dict_cache_name(cache), "update");
|
||||
}
|
||||
|
||||
/*
|
||||
* DNSBL lookup status per client IP address.
|
||||
*/
|
||||
typedef struct {
|
||||
int dnsbl_count; /* is this address listed */
|
||||
int refcount; /* query reference count */
|
||||
} PS_DNSBL_ENTRY;
|
||||
|
||||
/* postscreen_dnsbl_entry_create - create blocklist cache entry */
|
||||
|
||||
static PS_DNSBL_ENTRY *postscreen_dnsbl_entry_create(void)
|
||||
{
|
||||
PS_DNSBL_ENTRY *entry;
|
||||
|
||||
entry = (PS_DNSBL_ENTRY *) mymalloc(sizeof(*entry));
|
||||
entry->dnsbl_count = 0;
|
||||
entry->refcount = 0;
|
||||
return (entry);
|
||||
}
|
||||
|
||||
/* postscreen_dnsbl_done - get blocklist cache entry, decrement refcount */
|
||||
|
||||
static int postscreen_dnsbl_done(const char *addr)
|
||||
{
|
||||
const char *myname = "postscreen_dnsbl_done";
|
||||
PS_DNSBL_ENTRY *entry;
|
||||
int dnsbl_count;
|
||||
|
||||
/*
|
||||
* Sanity check.
|
||||
*/
|
||||
if ((entry = (PS_DNSBL_ENTRY *) htable_find(dnsbl_cache, addr)) == 0)
|
||||
msg_panic("%s: no blocklist cache entry for %s", myname, addr);
|
||||
|
||||
/*
|
||||
* Yes, cache reads are destructive.
|
||||
*/
|
||||
dnsbl_count = entry->dnsbl_count;
|
||||
entry->refcount -= 1;
|
||||
if (entry->refcount < 1) {
|
||||
if (msg_verbose)
|
||||
msg_info("%s: delete cache entry for %s", myname, addr);
|
||||
htable_delete(dnsbl_cache, addr, myfree);
|
||||
}
|
||||
return (dnsbl_count);
|
||||
}
|
||||
|
||||
/* postscreen_dnsbl_reply - receive dnsbl reply, update blocklist cache entry */
|
||||
|
||||
static void postscreen_dnsbl_reply(int event, char *context)
|
||||
{
|
||||
const char *myname = "postscreen_dnsbl_reply";
|
||||
VSTREAM *stream = (VSTREAM *) context;
|
||||
PS_DNSBL_ENTRY *entry;
|
||||
int dnsbl_count;
|
||||
|
||||
CLEAR_EVENT_REQUEST(vstream_fileno(stream), postscreen_dnsbl_reply, context);
|
||||
|
||||
/*
|
||||
* Later, this will become an UDP-based DNS client that is built directly
|
||||
* into the postscreen daemon.
|
||||
*
|
||||
* Don't panic when no blocklist cache entry exists. It may be gone when the
|
||||
* client triggered a "drop" action after pregreet, DNSBL lookup, or
|
||||
* hangup.
|
||||
*/
|
||||
if (event == EVENT_READ
|
||||
&& attr_scan(stream,
|
||||
ATTR_FLAG_MORE | ATTR_FLAG_STRICT,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_RBL_DOMAIN, reply_domain,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_ADDR, reply_addr,
|
||||
ATTR_TYPE_INT, MAIL_ATTR_STATUS, &dnsbl_count,
|
||||
ATTR_TYPE_END) == 3) {
|
||||
if ((entry = (PS_DNSBL_ENTRY *)
|
||||
htable_find(dnsbl_cache, STR(reply_addr))) != 0)
|
||||
entry->dnsbl_count += dnsbl_count;
|
||||
}
|
||||
vstream_fclose(stream);
|
||||
}
|
||||
|
||||
/* postscreen_dnsbl_query - send dnsbl query */
|
||||
|
||||
static void postscreen_dnsbl_query(const char *addr)
|
||||
{
|
||||
const char *myname = "postscreen_dnsbl_query";
|
||||
int fd;
|
||||
VSTREAM *stream;
|
||||
char **cpp;
|
||||
PS_DNSBL_ENTRY *entry;
|
||||
|
||||
/*
|
||||
* Avoid duplicate effort when this lookup is already in progress. Now,
|
||||
* we destroy the entry when the client replies. Later, we increment
|
||||
* refcounts with queries sent, and decrement refcounts with replies
|
||||
* received, so we can maintain state even after a client talks early,
|
||||
* and update the external cache asynchronously.
|
||||
*/
|
||||
if ((entry = (PS_DNSBL_ENTRY *) htable_find(dnsbl_cache, addr)) != 0) {
|
||||
entry->refcount += 1;
|
||||
return;
|
||||
}
|
||||
if (msg_verbose)
|
||||
msg_info("%s: create cache entry for %s", myname, addr);
|
||||
entry = postscreen_dnsbl_entry_create();
|
||||
(void) htable_enter(dnsbl_cache, addr, (char *) entry);
|
||||
entry->refcount = 1;
|
||||
|
||||
/*
|
||||
* Later, this will become an UDP-based DNS client that is built directly
|
||||
* into the postscreen daemon.
|
||||
*/
|
||||
for (cpp = dnsbl_sites->argv; *cpp; cpp++) {
|
||||
if ((fd = LOCAL_CONNECT("private/" DNSBL_SERVICE, NON_BLOCKING, 1)) < 0) {
|
||||
msg_warn("%s: connect to " DNSBL_SERVICE " service: %m", myname);
|
||||
return;
|
||||
}
|
||||
stream = vstream_fdopen(fd, O_RDWR);
|
||||
attr_print(stream, ATTR_FLAG_NONE,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_RBL_DOMAIN, *cpp,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_ADDR, addr,
|
||||
ATTR_TYPE_END);
|
||||
if (vstream_fflush(stream) != 0) {
|
||||
msg_warn("%s: error sending to " DNSBL_SERVICE " service: %m", myname);
|
||||
vstream_fclose(stream);
|
||||
return;
|
||||
}
|
||||
READ_EVENT_REQUEST(vstream_fileno(stream), postscreen_dnsbl_reply,
|
||||
(char *) stream, DNSBLOG_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
/* new_session_state - fill in connection state for event processing */
|
||||
|
||||
static PS_STATE *new_session_state(VSTREAM *stream, const char *addr,
|
||||
@ -842,7 +616,7 @@ static void send_socket(PS_STATE *state)
|
||||
vstream_fileno(state->smtp_client_stream)) < 0) {
|
||||
msg_warn("cannot pass connection to service %s: %m", smtp_service_name);
|
||||
smtp_reply(vstream_fileno(state->smtp_client_stream), state->smtp_client_addr,
|
||||
state->smtp_client_port, "421 4.3.2 No system resources\r\n");
|
||||
state->smtp_client_port, "421 4.3.2 No system resources\r\n");
|
||||
free_session_state(state);
|
||||
return;
|
||||
} else {
|
||||
@ -863,15 +637,15 @@ static void send_socket(PS_STATE *state)
|
||||
}
|
||||
}
|
||||
|
||||
/* smtp_read_event - handle pre-greet, EOF or timeout. */
|
||||
/* smtp_early_event - handle pre-greet, EOF or timeout. */
|
||||
|
||||
static void smtp_read_event(int event, char *context)
|
||||
static void smtp_early_event(int event, char *context)
|
||||
{
|
||||
const char *myname = "smtp_read_event";
|
||||
const char *myname = "smtp_early_event";
|
||||
PS_STATE *state = (PS_STATE *) context;
|
||||
char read_buf[PS_READ_BUF_SIZE];
|
||||
int read_count;
|
||||
int dnsbl_count;
|
||||
int dnsbl_score;
|
||||
int elapsed;
|
||||
int action;
|
||||
|
||||
@ -886,7 +660,7 @@ static void smtp_read_event(int event, char *context)
|
||||
* was closed, or we reached the limit of our patience.
|
||||
*/
|
||||
CLEAR_EVENT_REQUEST(vstream_fileno(state->smtp_client_stream),
|
||||
smtp_read_event, context);
|
||||
smtp_early_event, context);
|
||||
|
||||
/*
|
||||
* If this session ends here, we MUST read the blocklist cache otherwise
|
||||
@ -905,12 +679,12 @@ static void smtp_read_event(int event, char *context)
|
||||
*/
|
||||
case EVENT_TIME:
|
||||
if (*var_ps_dnsbl_sites)
|
||||
dnsbl_count = postscreen_dnsbl_done(state->smtp_client_addr);
|
||||
dnsbl_score = ps_dnsbl_retrieve(state->smtp_client_addr);
|
||||
else
|
||||
dnsbl_count = 0;
|
||||
if (dnsbl_count > 0) {
|
||||
dnsbl_score = 0;
|
||||
if (dnsbl_score >= var_ps_dnsbl_thresh) {
|
||||
msg_info("DNSBL rank %d for %s",
|
||||
dnsbl_count, state->smtp_client_addr);
|
||||
dnsbl_score, state->smtp_client_addr);
|
||||
if (dnsbl_action == PS_ACT_DROP) {
|
||||
smtp_reply(vstream_fileno(state->smtp_client_stream),
|
||||
state->smtp_client_addr, state->smtp_client_port,
|
||||
@ -927,7 +701,7 @@ static void smtp_read_event(int event, char *context)
|
||||
"OLD" : "NEW", state->smtp_client_addr);
|
||||
if (cache_map != 0) {
|
||||
vstring_sprintf(temp, "%ld", (long) event_time());
|
||||
ps_dict_put(cache_map, state->smtp_client_addr, STR(temp));
|
||||
ps_cache_update(cache_map, state->smtp_client_addr, STR(temp));
|
||||
}
|
||||
}
|
||||
send_socket(state);
|
||||
@ -964,14 +738,14 @@ static void smtp_read_event(int event, char *context)
|
||||
}
|
||||
if (action == PS_ACT_DROP) {
|
||||
if (*var_ps_dnsbl_sites)
|
||||
(void) postscreen_dnsbl_done(state->smtp_client_addr);
|
||||
(void) ps_dnsbl_retrieve(state->smtp_client_addr);
|
||||
free_session_state(state);
|
||||
} else {
|
||||
state->flags |= PS_FLAG_NOCACHE;
|
||||
/* not: postscreen_dnsbl_done */
|
||||
/* not: ps_dnsbl_retrieve */
|
||||
if (elapsed > var_ps_greet_wait)
|
||||
elapsed = var_ps_greet_wait;
|
||||
event_request_timer(smtp_read_event, context,
|
||||
event_request_timer(smtp_early_event, context,
|
||||
var_ps_greet_wait - elapsed);
|
||||
}
|
||||
break;
|
||||
@ -1145,7 +919,7 @@ static void postscreen_service(VSTREAM *smtp_client_stream,
|
||||
* lowest precedence.
|
||||
*/
|
||||
else if (cache_map != 0
|
||||
&& (stamp_str = ps_dict_get(cache_map, smtp_client_addr.buf)) != 0) {
|
||||
&& (stamp_str = ps_cache_lookup(cache_map, smtp_client_addr.buf)) != 0) {
|
||||
stamp_time = strtoul(stamp_str, 0, 10);
|
||||
if (stamp_time > event_time() - var_ps_cache_ttl) {
|
||||
msg_info("PASS OLD %s", smtp_client_addr.buf);
|
||||
@ -1202,13 +976,13 @@ static void postscreen_service(VSTREAM *smtp_client_stream,
|
||||
smtp_client_port.buf);
|
||||
state->flags |= state_flags;
|
||||
READ_EVENT_REQUEST(vstream_fileno(state->smtp_client_stream),
|
||||
smtp_read_event, (char *) state, var_ps_greet_wait);
|
||||
smtp_early_event, (char *) state, var_ps_greet_wait);
|
||||
|
||||
/*
|
||||
* Run a DNS blocklist query while we wait for the client to respond.
|
||||
*/
|
||||
if (*var_ps_dnsbl_sites)
|
||||
postscreen_dnsbl_query(smtp_client_addr.buf);
|
||||
ps_dnsbl_request(smtp_client_addr.buf);
|
||||
}
|
||||
|
||||
/* postscreen_cache_validator - validate one cache entry */
|
||||
@ -1315,10 +1089,7 @@ static void post_jail_init(char *unused_name, char **unused_argv)
|
||||
vstring_sprintf(temp, "220-%s\r\n", var_ps_greet_banner);
|
||||
teaser_greeting = mystrdup(STR(temp));
|
||||
}
|
||||
dnsbl_sites = argv_split(var_ps_dnsbl_sites, ", \t\r\n");
|
||||
dnsbl_cache = htable_create(13);
|
||||
reply_addr = vstring_alloc(100);
|
||||
reply_domain = vstring_alloc(100);
|
||||
ps_dnsbl_init();
|
||||
if ((blist_action = name_code(actions, NAME_CODE_FLAG_NONE,
|
||||
var_ps_blist_action)) < 0)
|
||||
msg_fatal("bad %s value: %s", VAR_PS_BLIST_ACTION, var_ps_blist_action);
|
||||
@ -1371,6 +1142,7 @@ int main(int argc, char **argv)
|
||||
};
|
||||
static const CONFIG_INT_TABLE int_table[] = {
|
||||
VAR_PROC_LIMIT, DEF_PROC_LIMIT, &var_proc_limit, 1, 0,
|
||||
VAR_PS_DNSBL_THRESH, DEF_PS_DNSBL_THRESH, &var_ps_dnsbl_thresh, 0, 0,
|
||||
0,
|
||||
};
|
||||
static const CONFIG_NINT_TABLE nint_table[] = {
|
||||
|
92
postfix/src/postscreen/postscreen.h
Normal file
92
postfix/src/postscreen/postscreen.h
Normal file
@ -0,0 +1,92 @@
|
||||
/*++
|
||||
/* NAME
|
||||
/* postscreen 3h
|
||||
/* SUMMARY
|
||||
/* postscreen internal interfaces
|
||||
/* SYNOPSIS
|
||||
/* #include <postscreen.h>
|
||||
/* DESCRIPTION
|
||||
/* .nf
|
||||
|
||||
/*
|
||||
* Utility library.
|
||||
*/
|
||||
#include <dict_cache.h>
|
||||
|
||||
/*
|
||||
* Global library.
|
||||
*/
|
||||
#include <addr_match_list.h>
|
||||
|
||||
/*
|
||||
* See log_adhoc.c for discussion.
|
||||
*/
|
||||
typedef struct {
|
||||
int dt_sec; /* make sure it's signed */
|
||||
int dt_usec; /* make sure it's signed */
|
||||
} DELTA_TIME;
|
||||
|
||||
#define PS_CALC_DELTA(x, y, z) \
|
||||
do { \
|
||||
(x).dt_sec = (y).tv_sec - (z).tv_sec; \
|
||||
(x).dt_usec = (y).tv_usec - (z).tv_usec; \
|
||||
while ((x).dt_usec < 0) { \
|
||||
(x).dt_usec += 1000000; \
|
||||
(x).dt_sec -= 1; \
|
||||
} \
|
||||
while ((x).dt_usec >= 1000000) { \
|
||||
(x).dt_usec -= 1000000; \
|
||||
(x).dt_sec += 1; \
|
||||
} \
|
||||
if ((x).dt_sec < 0) \
|
||||
(x).dt_sec = (x).dt_usec = 0; \
|
||||
} while (0)
|
||||
|
||||
#define SIG_DIGS 2
|
||||
|
||||
/* READ_EVENT_REQUEST - prepare for transition to next state */
|
||||
|
||||
#define READ_EVENT_REQUEST(fd, action, context, timeout) do { \
|
||||
if (msg_verbose) msg_info("%s: read-request fd=%d", myname, (fd)); \
|
||||
event_enable_read((fd), (action), (context)); \
|
||||
event_request_timer((action), (context), (timeout)); \
|
||||
} while (0)
|
||||
|
||||
/* CLEAR_EVENT_REQUEST - complete state transition */
|
||||
|
||||
#define CLEAR_EVENT_REQUEST(fd, action, context) do { \
|
||||
if (msg_verbose) msg_info("%s: clear-request fd=%d", myname, (fd)); \
|
||||
event_disable_readwrite(fd); \
|
||||
event_cancel_timer((action), (context)); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* SLMs.
|
||||
*/
|
||||
#define STR(x) vstring_str(x)
|
||||
#define LEN(x) VSTRING_LEN(x)
|
||||
|
||||
/*
|
||||
* postscreen_dict.c
|
||||
*/
|
||||
extern int ps_addr_match_list_match(ADDR_MATCH_LIST *, const char *);
|
||||
extern const char *ps_cache_lookup(DICT_CACHE *, const char *);
|
||||
extern void ps_cache_update(DICT_CACHE *, const char *, const char *);
|
||||
|
||||
/*
|
||||
* postscreen_dnsbl.c
|
||||
*/
|
||||
extern void ps_dnsbl_init(void);
|
||||
extern int ps_dnsbl_retrieve(const char *);
|
||||
extern void ps_dnsbl_request(const char *);
|
||||
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* The Secure Mailer license must be distributed with this software.
|
||||
/* AUTHOR(S)
|
||||
/* Wietse Venema
|
||||
/* IBM T.J. Watson Research
|
||||
/* P.O. Box 704
|
||||
/* Yorktown Heights, NY 10598, USA
|
||||
/*--*/
|
107
postfix/src/postscreen/postscreen_dict.c
Normal file
107
postfix/src/postscreen/postscreen_dict.c
Normal file
@ -0,0 +1,107 @@
|
||||
/*++
|
||||
/* NAME
|
||||
/* postscreen_dict 3
|
||||
/* SUMMARY
|
||||
/* postscreen table access wrappers
|
||||
/* SYNOPSIS
|
||||
/* #include <postscreen.h>
|
||||
/*
|
||||
/* int ps_addr_match_list_match(match_list, client_addr)
|
||||
/* ADDR_MATCH_LIST *match_list;
|
||||
/* const char *client_addr;
|
||||
/*
|
||||
/* const char *ps_cache_lookup(DICT_CACHE *cache, const char *key)
|
||||
/* DICT_CACHE *cache;
|
||||
/* const char *key;
|
||||
/*
|
||||
/* void ps_cache_update(cache, key, value)
|
||||
/* DICT_CACHE *cache;
|
||||
/* const char *key;
|
||||
/* const char *value;
|
||||
/* DESCRIPTION
|
||||
/* This module implements wrappers around time-critical table
|
||||
/* access functions. The functions log a warning when table
|
||||
/* access takes a non-trivial amount of time.
|
||||
/*
|
||||
/* ps_addr_match_list_match() is a wrapper around
|
||||
/* addr_match_list_match().
|
||||
/*
|
||||
/* ps_cache_lookup() and ps_cache_update() are wrappers around
|
||||
/* the corresponding dict_cache() methods.
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* The Secure Mailer license must be distributed with this software.
|
||||
/* AUTHOR(S)
|
||||
/* Wietse Venema
|
||||
/* IBM T.J. Watson Research
|
||||
/* P.O. Box 704
|
||||
/* Yorktown Heights, NY 10598, USA
|
||||
/*--*/
|
||||
|
||||
/* System library. */
|
||||
|
||||
#include <sys_defs.h>
|
||||
|
||||
/* Utility library. */
|
||||
|
||||
#include <msg.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
#include <postscreen.h>
|
||||
|
||||
/*
|
||||
* Monitor time-critical operations.
|
||||
*/
|
||||
#define PS_GET_TIME_BEFORE_LOOKUP \
|
||||
struct timeval _before, _after; \
|
||||
DELTA_TIME _delta; \
|
||||
GETTIMEOFDAY(&_before);
|
||||
|
||||
#define PS_DELTA_MS(d) ((d).dt_sec * 1000 + (d).dt_usec / 1000)
|
||||
|
||||
#define PS_CHECK_TIME_AFTER_LOOKUP(table, action) \
|
||||
GETTIMEOFDAY(&_after); \
|
||||
PS_CALC_DELTA(_delta, _after, _before); \
|
||||
if (_delta.dt_sec > 1 || _delta.dt_usec > 100000) \
|
||||
msg_warn("%s: %s %s took %d ms", \
|
||||
myname, (table), (action), PS_DELTA_MS(_delta));
|
||||
|
||||
/* ps_addr_match_list_match - time-critical address list lookup */
|
||||
|
||||
int ps_addr_match_list_match(ADDR_MATCH_LIST *addr_list,
|
||||
const char *addr_str)
|
||||
{
|
||||
const char *myname = "ps_addr_match_list_match";
|
||||
int result;
|
||||
|
||||
PS_GET_TIME_BEFORE_LOOKUP;
|
||||
result = addr_match_list_match(addr_list, addr_str);
|
||||
PS_CHECK_TIME_AFTER_LOOKUP("address list", "lookup");
|
||||
return (result);
|
||||
}
|
||||
|
||||
/* ps_cache_lookup - time-critical cache lookup */
|
||||
|
||||
const char *ps_cache_lookup(DICT_CACHE *cache, const char *key)
|
||||
{
|
||||
const char *myname = "ps_cache_lookup";
|
||||
const char *result;
|
||||
|
||||
PS_GET_TIME_BEFORE_LOOKUP;
|
||||
result = dict_cache_lookup(cache, key);
|
||||
PS_CHECK_TIME_AFTER_LOOKUP(dict_cache_name(cache), "lookup");
|
||||
return (result);
|
||||
}
|
||||
|
||||
/* ps_cache_update - time-critical cache update */
|
||||
|
||||
void ps_cache_update(DICT_CACHE *cache, const char *key, const char *value)
|
||||
{
|
||||
const char *myname = "ps_cache_update";
|
||||
|
||||
PS_GET_TIME_BEFORE_LOOKUP;
|
||||
dict_cache_update(cache, key, value);
|
||||
PS_CHECK_TIME_AFTER_LOOKUP(dict_cache_name(cache), "update");
|
||||
}
|
382
postfix/src/postscreen/postscreen_dnsbl.c
Normal file
382
postfix/src/postscreen/postscreen_dnsbl.c
Normal file
@ -0,0 +1,382 @@
|
||||
/*++
|
||||
/* NAME
|
||||
/* postscreen_dnsbl 3
|
||||
/* SUMMARY
|
||||
/* postscreen DNSBL support
|
||||
/* SYNOPSIS
|
||||
/* #include <postscreen.h>
|
||||
/*
|
||||
/* void ps_dnsbl_init(void)
|
||||
/*
|
||||
/* void ps_dnsbl_request(client_addr)
|
||||
/* char *client_addr;
|
||||
/*
|
||||
/* int ps_dnsbl_retrieve(client_addr)
|
||||
/* char *client_addr;
|
||||
/* DESCRIPTION
|
||||
/* This module implements preliminary support for DNSBL lookups
|
||||
/* that complete in the background. Multiple requests for the
|
||||
/* same information are handled with reference counts.
|
||||
/*
|
||||
/* ps_dnsbl_init() initializes this module, and must be called
|
||||
/* once before any of the other functions in this module.
|
||||
/*
|
||||
/* ps_dnsbl_request() requests a blocklist score for the specified
|
||||
/* client IP address and increments the reference count. The
|
||||
/* client IP address must be in inet_ntop(3) output format.
|
||||
/*
|
||||
/* ps_dnsbl_retrieve() retrieves the result score requested with
|
||||
/* ps_dnsbl_request() and decrements the reference count. It
|
||||
/* is an error to retrieve a score without requesting it first.
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* The Secure Mailer license must be distributed with this software.
|
||||
/* AUTHOR(S)
|
||||
/* Wietse Venema
|
||||
/* IBM T.J. Watson Research
|
||||
/* P.O. Box 704
|
||||
/* Yorktown Heights, NY 10598, USA
|
||||
/*--*/
|
||||
|
||||
/* System library. */
|
||||
|
||||
#include <sys_defs.h>
|
||||
#include <stdio.h> /* sscanf */
|
||||
|
||||
/* Utility library. */
|
||||
|
||||
#include <msg.h>
|
||||
#include <mymalloc.h>
|
||||
#include <argv.h>
|
||||
#include <htable.h>
|
||||
#include <events.h>
|
||||
#include <vstream.h>
|
||||
#include <connect.h>
|
||||
#include <split_at.h>
|
||||
#include <valid_hostname.h>
|
||||
|
||||
/* Global library. */
|
||||
|
||||
#include <mail_params.h>
|
||||
#include <mail_proto.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
#include <postscreen.h>
|
||||
|
||||
#define DNSBL_SERVICE "dnsblog"
|
||||
#define DNSBLOG_TIMEOUT 10
|
||||
|
||||
/*
|
||||
* Per-DNSBL filters and weights.
|
||||
*
|
||||
* The postscreen_dnsbl_sites parameter specifies zero or more DNSBL domains.
|
||||
* We provide multiple access methods, one for quick iteration when sending
|
||||
* queries to all DNSBL servers, and one for quick location when receiving a
|
||||
* reply from one DNSBL server.
|
||||
*
|
||||
* Each DNSBL domain can be specified more than once, each time with a
|
||||
* different (filter, weight) pair. We group (filter, weight) pairs in a
|
||||
* linked list under their DNSBL domain name.
|
||||
*/
|
||||
static HTABLE *dnsbl_site_cache; /* indexed by DNSBNL domain */
|
||||
static HTABLE_INFO **dnsbl_site_list; /* flattened cache */
|
||||
|
||||
typedef struct PS_DNSBL_SITE {
|
||||
char *filter; /* reply filter (default: null) */
|
||||
int weight; /* reply weight (default: 1) */
|
||||
struct PS_DNSBL_SITE *next; /* linked list */
|
||||
} PS_DNSBL_SITE;
|
||||
|
||||
/*
|
||||
* Per-client DNSBL scores.
|
||||
*
|
||||
* One remote SMTP client may make parallel connections and thereby trigger
|
||||
* parallel blocklist score requests. We combine identical requests under
|
||||
* the client IP address in a single reference-counted entry. The reference
|
||||
* count goes up with each score request, and it goes down with each score
|
||||
* retrieval.
|
||||
*/
|
||||
static HTABLE *dnsbl_score_cache; /* indexed by client address */
|
||||
|
||||
typedef struct {
|
||||
int total; /* combined blocklist score */
|
||||
int refcount; /* score reference count */
|
||||
} PS_DNSBL_SCORE;
|
||||
|
||||
/*
|
||||
* Per-request state.
|
||||
*
|
||||
* This implementation stores the client IP address and DNSBL domain in the
|
||||
* DNSBLOG query/reply stream. This simplifies code, and allows the DNSBLOG
|
||||
* server to produce more informative logging.
|
||||
*/
|
||||
static VSTRING *reply_client; /* client address in DNSBLOG reply */
|
||||
static VSTRING *reply_dnsbl; /* domain in DNSBLOG reply */
|
||||
static VSTRING *reply_addr; /* adress list in DNSBLOG reply */
|
||||
|
||||
/* ps_dnsbl_add_site - add DNSBL site information */
|
||||
|
||||
static void ps_dnsbl_add_site(const char *site)
|
||||
{
|
||||
const char *myname = "ps_dnsbl_add_site";
|
||||
char *saved_site = mystrdup(site);
|
||||
PS_DNSBL_SITE *old_site;
|
||||
PS_DNSBL_SITE *new_site;
|
||||
char junk;
|
||||
const char *weight_text;
|
||||
const char *pattern_text;
|
||||
int weight;
|
||||
|
||||
/*
|
||||
* Parse the required DNSBL domain name, the optional reply filter and
|
||||
* the optional reply weight factor.
|
||||
*/
|
||||
#define DO_GRIPE 1
|
||||
|
||||
/* Negative weight means whitelist. */
|
||||
if ((weight_text = split_at(saved_site, '*')) != 0) {
|
||||
if (sscanf(weight_text, "%d%c", &weight, &junk) != 1)
|
||||
msg_fatal("bad DNSBL weight factor \"%s\" in \"%s\"",
|
||||
weight_text, site);
|
||||
} else {
|
||||
weight = 1;
|
||||
}
|
||||
/* Preliminary fixed-string filter. */
|
||||
if ((pattern_text = split_at(saved_site, '=')) != 0) {
|
||||
if (valid_ipv4_hostaddr(pattern_text, DO_GRIPE) == 0)
|
||||
msg_fatal("bad DNSBL filter syntax \"%s\" in \"%s\"",
|
||||
pattern_text, site);
|
||||
}
|
||||
if (valid_hostname(saved_site, DO_GRIPE) == 0)
|
||||
msg_fatal("bad DNSBL domain name \"%s\" in \"%s\"",
|
||||
saved_site, site);
|
||||
|
||||
if (msg_verbose)
|
||||
msg_info("%s: \"%s\" -> domain=\"%s\" pattern=\"%s\" weight=%d",
|
||||
myname, site, saved_site, pattern_text ? pattern_text :
|
||||
"null", weight);
|
||||
|
||||
/*
|
||||
* Add a new node for this DNSBL domain name. One DNSBL domain name can
|
||||
* be specified multiple times with different filters and weights. These
|
||||
* are stored as a linked list under the DNSBL domain name.
|
||||
*/
|
||||
new_site = (PS_DNSBL_SITE *) mymalloc(sizeof(*new_site));
|
||||
new_site->filter = (pattern_text ? mystrdup(pattern_text) : 0);
|
||||
new_site->weight = weight;
|
||||
|
||||
if ((old_site = (PS_DNSBL_SITE *)
|
||||
htable_find(dnsbl_site_cache, saved_site)) != 0) {
|
||||
new_site->next = old_site->next;
|
||||
old_site->next = new_site;
|
||||
} else {
|
||||
(void) htable_enter(dnsbl_site_cache, saved_site, (char *) new_site);
|
||||
new_site->next = 0;
|
||||
}
|
||||
myfree(saved_site);
|
||||
}
|
||||
|
||||
/* ps_dnsbl_match - match DNSBL reply filter */
|
||||
|
||||
static int ps_dnsbl_match(const char *filter, ARGV *reply)
|
||||
{
|
||||
char **cpp;
|
||||
|
||||
/*
|
||||
* Preliminary fixed-string implementation.
|
||||
*/
|
||||
for (cpp = reply->argv; *cpp != 0; cpp++)
|
||||
if (strcmp(filter, *cpp) == 0)
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* ps_dnsbl_retrieve - retrieve blocklist score, decrement reference count */
|
||||
|
||||
int ps_dnsbl_retrieve(const char *client_addr)
|
||||
{
|
||||
const char *myname = "ps_dnsbl_retrieve";
|
||||
PS_DNSBL_SCORE *score;
|
||||
int result_score;
|
||||
|
||||
/*
|
||||
* Sanity check.
|
||||
*/
|
||||
if ((score = (PS_DNSBL_SCORE *)
|
||||
htable_find(dnsbl_score_cache, client_addr)) == 0)
|
||||
msg_panic("%s: no blocklist score for %s", myname, client_addr);
|
||||
|
||||
/*
|
||||
* Reads are destructive.
|
||||
*/
|
||||
result_score = score->total;
|
||||
score->refcount -= 1;
|
||||
if (score->refcount < 1) {
|
||||
if (msg_verbose)
|
||||
msg_info("%s: delete blocklist score for %s", myname, client_addr);
|
||||
htable_delete(dnsbl_score_cache, client_addr, myfree);
|
||||
}
|
||||
return (result_score);
|
||||
}
|
||||
|
||||
/* ps_dnsbl_receive - receive DNSBL reply, update blocklist score */
|
||||
|
||||
static void ps_dnsbl_receive(int event, char *context)
|
||||
{
|
||||
const char *myname = "ps_dnsbl_receive";
|
||||
VSTREAM *stream = (VSTREAM *) context;
|
||||
PS_DNSBL_SCORE *score;
|
||||
PS_DNSBL_SITE *site;
|
||||
ARGV *reply_argv;
|
||||
|
||||
CLEAR_EVENT_REQUEST(vstream_fileno(stream), ps_dnsbl_receive, context);
|
||||
|
||||
/*
|
||||
* Receive the DNSBL lookup result.
|
||||
*
|
||||
* This is preliminary code to explore the field. Later, DNSBL lookup will
|
||||
* be handled by an UDP-based DNS client that is built directly into some
|
||||
* Postfix daemon.
|
||||
*
|
||||
* Don't bother looking up the blocklist score when the client IP address is
|
||||
* not listed at the DNSBL.
|
||||
*
|
||||
* Don't panic when the blocklist score no longer exists. It may be deleted
|
||||
* when the client triggers a "drop" action after pregreet, when the
|
||||
* client does not pregreet and the DNSBL reply arrives late, or when the
|
||||
* client triggers a "drop" action after hanging up.
|
||||
*/
|
||||
if (event == EVENT_READ
|
||||
&& attr_scan(stream,
|
||||
ATTR_FLAG_MORE | ATTR_FLAG_STRICT,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_RBL_DOMAIN, reply_dnsbl,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_ACT_CLIENT_ADDR, reply_client,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_RBL_ADDR, reply_addr,
|
||||
ATTR_TYPE_END) == 3
|
||||
&& *STR(reply_addr) != 0
|
||||
&& (score = (PS_DNSBL_SCORE *)
|
||||
htable_find(dnsbl_score_cache, STR(reply_client))) != 0) {
|
||||
|
||||
/*
|
||||
* Run this response past all applicable DNSBL filters and update the
|
||||
* blocklist score for this client IP address.
|
||||
*
|
||||
* Don't panic when the DNSBL domain name is not found. The DNSBLOG
|
||||
* server may be messed up.
|
||||
*/
|
||||
if (msg_verbose)
|
||||
msg_info("%s: client=\"%s\" score=%d domain=\"%s\" reply=\"%s\"",
|
||||
myname, STR(reply_client), score->total,
|
||||
STR(reply_dnsbl), STR(reply_addr));
|
||||
for (reply_argv = 0, site = (PS_DNSBL_SITE *)
|
||||
htable_find(dnsbl_site_cache, STR(reply_dnsbl));
|
||||
site != 0; site = site->next) {
|
||||
if (site->filter == 0
|
||||
|| ps_dnsbl_match(site->filter, reply_argv ? reply_argv :
|
||||
(reply_argv = argv_split(STR(reply_addr), " ")))) {
|
||||
score->total += site->weight;
|
||||
if (msg_verbose)
|
||||
msg_info("%s: filter=\"%s\" weight=%d score=%d",
|
||||
myname, site->filter ? site->filter : "null",
|
||||
site->weight, score->total);
|
||||
}
|
||||
}
|
||||
if (reply_argv != 0)
|
||||
argv_free(reply_argv);
|
||||
}
|
||||
vstream_fclose(stream);
|
||||
}
|
||||
|
||||
/* ps_dnsbl_request - send dnsbl query, increment reference count */
|
||||
|
||||
void ps_dnsbl_request(const char *client_addr)
|
||||
{
|
||||
const char *myname = "ps_dnsbl_request";
|
||||
int fd;
|
||||
VSTREAM *stream;
|
||||
HTABLE_INFO **ht;
|
||||
PS_DNSBL_SCORE *score;
|
||||
|
||||
/*
|
||||
* Avoid duplicate effort when this lookup is already in progress. We
|
||||
* store a reference-counted DNSBL score under its client IP address. We
|
||||
* increment the reference count with each request, and decrement the
|
||||
* reference count with each retrieval.
|
||||
*/
|
||||
if ((score = (PS_DNSBL_SCORE *)
|
||||
htable_find(dnsbl_score_cache, client_addr)) != 0) {
|
||||
score->refcount += 1;
|
||||
return;
|
||||
}
|
||||
if (msg_verbose)
|
||||
msg_info("%s: create blocklist score for %s", myname, client_addr);
|
||||
score = (PS_DNSBL_SCORE *) mymalloc(sizeof(*score));
|
||||
score->total = 0;
|
||||
score->refcount = 1;
|
||||
(void) htable_enter(dnsbl_score_cache, client_addr, (char *) score);
|
||||
|
||||
/*
|
||||
* Send a query to all DNSBL servers. Later, DNSBL lookup will be done
|
||||
* with an UDP-based DNS client that is built directly into Postfix code.
|
||||
* We therefore do not optimize the maximum out of this temporary
|
||||
* implementation.
|
||||
*/
|
||||
for (ht = dnsbl_site_list; *ht; ht++) {
|
||||
if ((fd = LOCAL_CONNECT("private/" DNSBL_SERVICE, NON_BLOCKING, 1)) < 0) {
|
||||
msg_warn("%s: connect to " DNSBL_SERVICE " service: %m", myname);
|
||||
return;
|
||||
}
|
||||
stream = vstream_fdopen(fd, O_RDWR);
|
||||
attr_print(stream, ATTR_FLAG_NONE,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_RBL_DOMAIN, ht[0]->key,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_ACT_CLIENT_ADDR, client_addr,
|
||||
ATTR_TYPE_END);
|
||||
if (vstream_fflush(stream) != 0) {
|
||||
msg_warn("%s: error sending to " DNSBL_SERVICE " service: %m", myname);
|
||||
vstream_fclose(stream);
|
||||
return;
|
||||
}
|
||||
READ_EVENT_REQUEST(vstream_fileno(stream), ps_dnsbl_receive,
|
||||
(char *) stream, DNSBLOG_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
/* ps_dnsbl_init - initialize */
|
||||
|
||||
void ps_dnsbl_init(void)
|
||||
{
|
||||
const char *myname = "ps_dnsbl_init";
|
||||
ARGV *dnsbl_site = argv_split(var_ps_dnsbl_sites, ", \t\r\n");
|
||||
char **cpp;
|
||||
|
||||
/*
|
||||
* Sanity check.
|
||||
*/
|
||||
if (dnsbl_site_cache != 0)
|
||||
msg_panic("%s: called more than once", myname);
|
||||
|
||||
/*
|
||||
* Prepare for quick iteration when sending out queries to all DNSBL
|
||||
* servers, and for quick lookup when a reply arrives from a specific
|
||||
* DNSBL server.
|
||||
*/
|
||||
dnsbl_site_cache = htable_create(13);
|
||||
for (cpp = dnsbl_site->argv; *cpp; cpp++)
|
||||
ps_dnsbl_add_site(*cpp);
|
||||
argv_free(dnsbl_site);
|
||||
dnsbl_site_list = htable_list(dnsbl_site_cache);
|
||||
|
||||
/*
|
||||
* The per-client blocklist score.
|
||||
*/
|
||||
dnsbl_score_cache = htable_create(13);
|
||||
|
||||
/*
|
||||
* Space for ad-hoc DNSBLOG server request/reply parameters.
|
||||
*/
|
||||
reply_client = vstring_alloc(100);
|
||||
reply_dnsbl = vstring_alloc(100);
|
||||
reply_addr = vstring_alloc(100);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user