2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-09-02 07:05:27 +00:00

postfix-2.8-20100923

This commit is contained in:
Wietse Venema
2010-09-23 00:00:00 -05:00
committed by Viktor Dukhovni
parent 36a1c7272a
commit 038275e32e
11 changed files with 188 additions and 143 deletions

View File

@@ -16033,3 +16033,9 @@ Apologies for any names omitted.
Bugfix: cut-and-paste error. Postscreen used pregreet_ttl Bugfix: cut-and-paste error. Postscreen used pregreet_ttl
instead of dnsbnl_ttl. File: postscreen/postscreen_early.c. instead of dnsbnl_ttl. File: postscreen/postscreen_early.c.
20100920
Cleanup: minor cleanups and invisible fixes. Files:
postscreen/postscreen_misc.c, postscreen/postscreen.h,
postscreen/postscreen_tests.c.

View File

@@ -5,13 +5,13 @@ PPoossttffiixx PPoossttssccrreeeenn HHoowwttoo
IInnttrroodduuccttiioonn IInnttrroodduuccttiioonn
The Postfix postscreen(8) server performs triage on multiple inbound SMTP The Postfix postscreen(8) server performs triage on multiple inbound SMTP
connections in parallel. While a single postscreen(8) process keeps spambots connections in parallel. While a single postscreen(8) process keeps zombies
away from Postfix SMTP server processes, more Postfix SMTP server processes away from Postfix SMTP server processes, more Postfix SMTP server processes
remain available for legitimate clients. remain available for legitimate clients.
By doing these checks in a single postscreen(8) process, Postfix can avoid By doing these checks in a single postscreen(8) process, Postfix can avoid
wasting one SMTP server process per connection. A side benefit of postscreen wasting one SMTP server process per zombie. A side benefit of postscreen(8)'s
(8)'s DNSBL lookups is that DNS records are already cached before the Postfix DNSBL lookups is that DNS records will already be cached before the Postfix
SMTP server looks them up later. SMTP server looks them up later.
Topics in this document: Topics in this document:
@@ -29,26 +29,36 @@ Topics in this document:
TThhee bbaassiicc iiddeeaa bbeehhiinndd ppoossttssccrreeeenn((88)) TThhee bbaassiicc iiddeeaa bbeehhiinndd ppoossttssccrreeeenn((88))
Spambots have a limited amount of time to send out spam before they become Most email is spam, and most spam is sent out by zombies (malware on
blacklisted. For this reason, spambots make compromises in their SMTP protocol compromised end-user computers). Wietse expects that the zombie problem will
implementation to speed up spam deliveries. For example, they speak before get worse before things improve, if ever. Without a tool like postscreen(8)
their turn, or they ignore responses from SMTP servers. that keeps the zombies away, Postfix would be spending most of its resources
not receiving email.
Many spambots avoid spamming the same site repeatedly, in an attempt to fly The main challenge for postscreen(8) is to make an is-it-a-zombie decision
under the radar. Thus, postscreen(8) must make a long-term decision after a based on a single measurement. This is necessary because many zombies avoid
single measurement. For example, allow a good client to skip the "pregreet" spamming the same site repeatedly, in an attempt to fly under the radar. Once
test for 24 hours. postscreen(8) decides that a client is not-a-zombie, it whitelists the client
temporarily to avoid further delays for legitimate mail.
To recognize spambots, postscreen(8) measures properties of the client IP Zombies have challenges too: they have only a limited amount of time to deliver
address and of the client SMTP protocol implementation (the protocol spam before their IP address becomes blacklisted. To speed up spam deliveries,
compromises that were made to speed up delivery). These properties don't change zombies make compromises in their SMTP protocol implementation. For example,
with delivery attempts, and are therefore suitable for making a long-term they speak before their turn, or they ignore responses from SMTP servers and
decision after a single measurement. continue sending mail even when the server tells them to go away.
postscreen(8) does not inspect message content. The reason is that content can postscreen(8) uses a variety of measurements to recognize zombies. First,
change with each delivery attempt, especially with legitimate clients. Message postscreen(8) determines if the remote SMTP client IP address is blacklisted.
content is not good for making a long-term decision after a single measurement, Second, postscreen(8) looks for protocol compromises that are made to speed up
and that is the problem that postscreen(8) is focused on. delivery. The results of such measurements don't change with each delivery
attempt, and are therefore good for making an is-it-a-zombie decision based on
a single measurement.
postscreen(8) does not inspect message content. Message content can vary widely
with each delivery attempt, especially with clients that (also) send legitimate
email. Content is therefore not good for making an is-it-a-zombie decision
based on a single measurement, and that is the problem that postscreen(8) is
focused on.
GGeenneerraall ooppeerraattiioonn GGeenneerraall ooppeerraattiioonn
@@ -67,7 +77,7 @@ from clients that fail one or more tests, after logging the helo, sender and
recipient information. recipient information.
Note: postscreen(8) is not an SMTP proxy; this is intentional. The purpose is Note: postscreen(8) is not an SMTP proxy; this is intentional. The purpose is
to keep spambots away from Postfix, with minimal overhead for legitimate to keep zombies away from Postfix, with minimal overhead for legitimate
clients. clients.
QQuuiicckk tteessttss bbeeffoorree eevveerryytthhiinngg eellssee QQuuiicckk tteessttss bbeeffoorree eevveerryytthhiinngg eellssee
@@ -139,14 +149,14 @@ postscreen_greet_wait delay).
PPrreeggrreeeett tteesstt PPrreeggrreeeett tteesstt
The SMTP protocol is a classic example of a protocol where the server speaks The SMTP protocol is a classic example of a protocol where the server speaks
before the client. postscreen(8) detects spambots that are in a hurry and that before the client. postscreen(8) detects zombies that are in a hurry and that
speak before their turn. This test is enabled by default. speak before their turn. This test is enabled by default.
The postscreen_greet_banner parameter specifies the text portion of a "220- The postscreen_greet_banner parameter specifies the text portion of a "220-
text..." teaser banner (default: $smtpd_banner). Note that this becomes the text..." teaser banner (default: $smtpd_banner). Note that this becomes the
first part of a multi-line server greeting. The postscreen(8) daemon sends this first part of a multi-line server greeting. The postscreen(8) daemon sends this
before the postscreen_greet_wait timer is started. The purpose of the teaser before the postscreen_greet_wait timer is started. The purpose of the teaser
banner is to confuse spambots so that they speak before their turn. It has no banner is to confuse zombies so that they speak before their turn. It has no
effect on SMTP clients that correctly implement the protocol. effect on SMTP clients that correctly implement the protocol.
To avoid problems with poorly-implemented SMTP engines in network appliances or To avoid problems with poorly-implemented SMTP engines in network appliances or
@@ -189,7 +199,7 @@ When the postscreen_greet_wait time has elapsed, and the combined DNSBL score
is equal to or greater than the postscreen_dnsbl_threshold parameter value, is equal to or greater than the postscreen_dnsbl_threshold parameter value,
postscreen(8) logs this as: postscreen(8) logs this as:
DDNNSSBBLL rraannkk count ffoorr address DDNNSSBBLL rraannkk count ffoorr address
Translation: the SMTP client at address has a combined DNSBL score of count. Translation: the SMTP client at address has a combined DNSBL score of count.
@@ -259,7 +269,7 @@ command and one response at a time. Unlike the Postfix SMTP server, postscreen
are not allowed to send multiple commands. postscreen(8)'s deep protocol test are not allowed to send multiple commands. postscreen(8)'s deep protocol test
for this is disabled by default. for this is disabled by default.
With "postscreen_pipelining_enable = yes", postscreen(8) detects spambots that With "postscreen_pipelining_enable = yes", postscreen(8) detects zombies that
send multiple commands, instead of sending one command and waiting for the send multiple commands, instead of sending one command and waiting for the
server to reply. server to reply.
@@ -285,7 +295,7 @@ Postfix SMTP server's smtpd_forbidden_commands feature, postscreen(8) has an
equivalent postscreen_forbidden_commands feature to block these clients. equivalent postscreen_forbidden_commands feature to block these clients.
postscreen(8)'s deep protocol test for this is disabled by default. postscreen(8)'s deep protocol test for this is disabled by default.
With "postscreen_non_smtp_command_enable = yes", postscreen(8) detects spambots With "postscreen_non_smtp_command_enable = yes", postscreen(8) detects zombies
that send commands specified with the postscreen_forbidden_commands parameter. that send commands specified with the postscreen_forbidden_commands parameter.
This also detects commands with the syntax of a message header label. The This also detects commands with the syntax of a message header label. The
latter is a symptom that the client is sending message content after ignoring latter is a symptom that the client is sending message content after ignoring
@@ -501,7 +511,7 @@ more of:
* "postscreen_greet_action = enforce", to reject clients that talk before * "postscreen_greet_action = enforce", to reject clients that talk before
their turn, and to log the helo/sender/recipient information. This stops their turn, and to log the helo/sender/recipient information. This stops
over half of all known-to-be illegitimate connections to Wietse's mail over half of all known-to-be illegitimate connections to Wietse's mail
server. It is backup protection for spambots that haven't yet been server. It is backup protection for zombies that haven't yet been
blacklisted. blacklisted.
* You can also enable "deep protocol tests", but these are more intrusive * You can also enable "deep protocol tests", but these are more intrusive

View File

@@ -2,15 +2,17 @@ Wish list:
Remove this file from the stable release. Remove this file from the stable release.
how to prevent postscreen's cache sweeper from deleting
records that have failed ignored tests?
Update history in manpage/readme for SQLite driver.
header_checks(5): document synopsis and feature subsets.
Consistency: in postconf.proto make <dt>..</dt> tags bold. Consistency: in postconf.proto make <dt>..</dt> tags bold.
postscreen(8): listen on multiple IP addresses and enforce
that the client contacts the primary MX address first (i.e.
punish hosts that contact the secondary before the primary).
The downside with any approach that relies on temporary
punishment is that it does not scale to configurations
with multiple equal-preference MX hosts. Such hosts would
have to share the postscreen cache, causing an unacceptable
performance bottleneck and a single point of failure.
According to a paper by Ted Unangst at BSDCON09, kqueue According to a paper by Ted Unangst at BSDCON09, kqueue
reports state changes, i.e. kqueue indicates when the socket reports state changes, i.e. kqueue indicates when the socket
becomes readable. Specifically, he writes when kqueue reports becomes readable. Specifically, he writes when kqueue reports
@@ -24,12 +26,6 @@ Wish list:
repeats these tests with OpenBSD and NetBSD (and MacOS X repeats these tests with OpenBSD and NetBSD (and MacOS X
once they fix their kqueue implementation). once they fix their kqueue implementation).
postscreen(8): need some option to wait for DNSBL lookup
(etc.) completion. For example, postscreen_greet_wait would
become a lower bound, while postscreen_dnsbl_wait would
become an upper bound (or should all features use a shared
postscreen_max_wait upper bound?).
Would it help if there were different cleanup_service Would it help if there were different cleanup_service
parameter names for different message paths? smtpd(8) uses parameter names for different message paths? smtpd(8) uses
the same cleanup_service value for receiving remote mail the same cleanup_service value for receiving remote mail

View File

@@ -19,15 +19,14 @@
<p> The Postfix <a href="postscreen.8.html">postscreen(8)</a> server performs triage on multiple <p> The Postfix <a href="postscreen.8.html">postscreen(8)</a> server performs triage on multiple
inbound SMTP connections in parallel. While a single <a href="postscreen.8.html">postscreen(8)</a> inbound SMTP connections in parallel. While a single <a href="postscreen.8.html">postscreen(8)</a>
process keeps spambots away from Postfix SMTP server processes, process keeps zombies away from Postfix SMTP server processes,
more Postfix SMTP server processes remain available for legitimate more Postfix SMTP server processes remain available for legitimate
clients. </p> clients. </p>
<p> By doing these checks in a single <a href="postscreen.8.html">postscreen(8)</a> process, Postfix <p> By doing these checks in a single <a href="postscreen.8.html">postscreen(8)</a> process, Postfix
can avoid wasting one SMTP server process per connection. A side can avoid wasting one SMTP server process per zombie. A side benefit
benefit of <a href="postscreen.8.html">postscreen(8)</a>'s DNSBL lookups is that DNS records are of <a href="postscreen.8.html">postscreen(8)</a>'s DNSBL lookups is that DNS records will already be
already cached before the Postfix SMTP server looks them up later. cached before the Postfix SMTP server looks them up later. </p>
</p>
<p> Topics in this document: </p> <p> Topics in this document: </p>
@@ -57,30 +56,39 @@ already cached before the Postfix SMTP server looks them up later.
<h2> <a name="basic">The basic idea behind postscreen(8)</a> </h2> <h2> <a name="basic">The basic idea behind postscreen(8)</a> </h2>
<p> Spambots have a limited amount of time to send out spam before <p> Most email is spam, and most spam is sent out by zombies (malware
they become blacklisted. For this reason, spambots make compromises on compromised end-user computers). Wietse expects that the zombie
in their SMTP protocol implementation to speed up spam deliveries. problem will get worse before things improve, if ever. Without a
For example, they speak before their turn, or they ignore responses tool like <a href="postscreen.8.html">postscreen(8)</a> that keeps the zombies away, Postfix would be
from SMTP servers. </p> spending most of its resources not receiving email. </p>
<p> Many spambots avoid spamming the same site repeatedly, in an <p> The main challenge for <a href="postscreen.8.html">postscreen(8)</a> is to make an is-it-a-zombie
attempt to fly under the radar. Thus, <a href="postscreen.8.html">postscreen(8)</a> must make a decision based on a single measurement. This is necessary because
long-term decision after a single measurement. For example, allow many zombies avoid spamming the same site repeatedly, in an attempt
a good client to skip the "<a href="#pregreet">pregreet</a>" test to fly under the radar. Once <a href="postscreen.8.html">postscreen(8)</a> decides that a client
for 24 hours. </p> is not-a-zombie, it whitelists the client temporarily to avoid
further delays for legitimate mail. </p>
<p> To recognize spambots, <a href="postscreen.8.html">postscreen(8)</a> measures properties of the <p> Zombies have challenges too: they have only a limited amount
client IP address and of the client SMTP protocol implementation of time to deliver spam before their IP address becomes blacklisted.
(the protocol compromises that were made to speed up delivery). To speed up spam deliveries, zombies make compromises in their SMTP
These properties don't change with delivery attempts, and are protocol implementation. For example, they speak before their turn,
therefore suitable for making a long-term decision after a single or they ignore responses from SMTP servers and continue sending
measurement. </p> mail even when the server tells them to go away. </p>
<p> <a href="postscreen.8.html">postscreen(8)</a> does not inspect message content. The reason is <p> <a href="postscreen.8.html">postscreen(8)</a> uses a variety of measurements to recognize
that content can change with each delivery attempt, especially with zombies. First, <a href="postscreen.8.html">postscreen(8)</a> determines if the remote SMTP client
legitimate clients. Message content is not good for making a long-term IP address is blacklisted. Second, <a href="postscreen.8.html">postscreen(8)</a> looks for protocol
decision after a single measurement, and that is the problem that compromises that are made to speed up delivery. The results of
<a href="postscreen.8.html">postscreen(8)</a> is focused on. </p> such measurements don't change with each delivery attempt, and are
therefore good for making an is-it-a-zombie decision based on a
single measurement. </p>
<p> <a href="postscreen.8.html">postscreen(8)</a> does not inspect message content. Message content
can vary widely with each delivery attempt, especially with clients
that (also) send legitimate email. Content is therefore not good
for making an is-it-a-zombie decision based on a single measurement,
and that is the problem that <a href="postscreen.8.html">postscreen(8)</a> is focused on. </p>
<h2> <a name="general"> General operation </a> </h2> <h2> <a name="general"> General operation </a> </h2>
@@ -100,7 +108,7 @@ to reject mail from clients that fail one or more tests, after
logging the helo, sender and recipient information. </p> logging the helo, sender and recipient information. </p>
<p> Note: <a href="postscreen.8.html">postscreen(8)</a> is not an SMTP proxy; this is intentional. <p> Note: <a href="postscreen.8.html">postscreen(8)</a> is not an SMTP proxy; this is intentional.
The purpose is to keep spambots away from Postfix, with minimal The purpose is to keep zombies away from Postfix, with minimal
overhead for legitimate clients. </p> overhead for legitimate clients. </p>
<h2> <a name="quick">Quick tests before everything else</a> </h2> <h2> <a name="quick">Quick tests before everything else</a> </h2>
@@ -196,7 +204,7 @@ for the short <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_w
<h3> <a name="pregreet"> Pregreet test </a> </h3> <h3> <a name="pregreet"> Pregreet test </a> </h3>
<p> The SMTP protocol is a classic example of a protocol where the <p> The SMTP protocol is a classic example of a protocol where the
server speaks before the client. <a href="postscreen.8.html">postscreen(8)</a> detects spambots server speaks before the client. <a href="postscreen.8.html">postscreen(8)</a> detects zombies
that are in a hurry and that speak before their turn. This test is that are in a hurry and that speak before their turn. This test is
enabled by default. </p> enabled by default. </p>
@@ -205,7 +213,7 @@ portion of a "220-<i>text</i>..." teaser banner (default: $<a href="postconf.5.h
Note that this becomes the first part of a multi-line server greeting. Note that this becomes the first part of a multi-line server greeting.
The <a href="postscreen.8.html">postscreen(8)</a> daemon sends this before the <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a> The <a href="postscreen.8.html">postscreen(8)</a> daemon sends this before the <a href="postconf.5.html#postscreen_greet_wait">postscreen_greet_wait</a>
timer is started. The purpose of the teaser banner is to confuse timer is started. The purpose of the teaser banner is to confuse
spambots so that they speak before their turn. It has no effect on zombies so that they speak before their turn. It has no effect on
SMTP clients that correctly implement the protocol. </p> SMTP clients that correctly implement the protocol. </p>
<p> To avoid problems with poorly-implemented SMTP engines in network <p> To avoid problems with poorly-implemented SMTP engines in network
@@ -262,7 +270,9 @@ hide "password" information in DNSBL domain names.
DNSBL score is equal to or greater than the <a href="postconf.5.html#postscreen_dnsbl_threshold">postscreen_dnsbl_threshold</a> DNSBL score is equal to or greater than the <a href="postconf.5.html#postscreen_dnsbl_threshold">postscreen_dnsbl_threshold</a>
parameter value, <a href="postscreen.8.html">postscreen(8)</a> logs this as: </p> parameter value, <a href="postscreen.8.html">postscreen(8)</a> logs this as: </p>
<b>DNSBL rank</b> <i>count</i> <b>for</b> <i>address</i> <pre>
<b>DNSBL rank</b> <i>count</i> <b>for</b> <i>address</i>
</pre>
<p> Translation: the SMTP client at <i>address</i> has a combined <p> Translation: the SMTP client at <i>address</i> has a combined
DNSBL score of <i>count</i>. </p> DNSBL score of <i>count</i>. </p>
@@ -359,7 +369,7 @@ to send multiple commands. postscreen(8)'s <a href="#after_220">deep
protocol test</a> for this is disabled by default. </p> protocol test</a> for this is disabled by default. </p>
<p> With "<a href="postconf.5.html#postscreen_pipelining_enable">postscreen_pipelining_enable</a> = yes", <a href="postscreen.8.html">postscreen(8)</a> detects <p> With "<a href="postconf.5.html#postscreen_pipelining_enable">postscreen_pipelining_enable</a> = yes", <a href="postscreen.8.html">postscreen(8)</a> detects
spambots that send multiple commands, instead of sending one command zombies that send multiple commands, instead of sending one command
and waiting for the server to reply. </p> and waiting for the server to reply. </p>
<p> This test is opportunistically enabled when <a href="postscreen.8.html">postscreen(8)</a> has <p> This test is opportunistically enabled when <a href="postscreen.8.html">postscreen(8)</a> has
@@ -392,7 +402,7 @@ feature to block these clients. postscreen(8)'s <a href="#after_220">deep
protocol test</a> for this is disabled by default. </p> protocol test</a> for this is disabled by default. </p>
<p> With "<a href="postconf.5.html#postscreen_non_smtp_command_enable">postscreen_non_smtp_command_enable</a> = yes", <a href="postscreen.8.html">postscreen(8)</a> <p> With "<a href="postconf.5.html#postscreen_non_smtp_command_enable">postscreen_non_smtp_command_enable</a> = yes", <a href="postscreen.8.html">postscreen(8)</a>
detects spambots that send commands specified with the detects zombies that send commands specified with the
<a href="postconf.5.html#postscreen_forbidden_commands">postscreen_forbidden_commands</a> parameter. This also detects commands <a href="postconf.5.html#postscreen_forbidden_commands">postscreen_forbidden_commands</a> parameter. This also detects commands
with the syntax of a message header label. The latter is a symptom with the syntax of a message header label. The latter is a symptom
that the client is sending message content after ignoring all the that the client is sending message content after ignoring all the
@@ -695,7 +705,7 @@ Postfix SMTP servers dramatically. </p>
clients that talk before their turn, and to log the helo/sender/recipient clients that talk before their turn, and to log the helo/sender/recipient
information. This stops over half of all known-to-be illegitimate information. This stops over half of all known-to-be illegitimate
connections to Wietse's mail server. It is backup protection for connections to Wietse's mail server. It is backup protection for
spambots that haven't yet been blacklisted. </p> zombies that haven't yet been blacklisted. </p>
<li> <p> You can also enable "<a href="#after_220">deep protocol <li> <p> You can also enable "<a href="#after_220">deep protocol
tests</a>", but these are more intrusive than the pregreet or DNSBL tests</a>", but these are more intrusive than the pregreet or DNSBL

View File

@@ -19,15 +19,14 @@
<p> The Postfix postscreen(8) server performs triage on multiple <p> The Postfix postscreen(8) server performs triage on multiple
inbound SMTP connections in parallel. While a single postscreen(8) inbound SMTP connections in parallel. While a single postscreen(8)
process keeps spambots away from Postfix SMTP server processes, process keeps zombies away from Postfix SMTP server processes,
more Postfix SMTP server processes remain available for legitimate more Postfix SMTP server processes remain available for legitimate
clients. </p> clients. </p>
<p> By doing these checks in a single postscreen(8) process, Postfix <p> By doing these checks in a single postscreen(8) process, Postfix
can avoid wasting one SMTP server process per connection. A side can avoid wasting one SMTP server process per zombie. A side benefit
benefit of postscreen(8)'s DNSBL lookups is that DNS records are of postscreen(8)'s DNSBL lookups is that DNS records will already be
already cached before the Postfix SMTP server looks them up later. cached before the Postfix SMTP server looks them up later. </p>
</p>
<p> Topics in this document: </p> <p> Topics in this document: </p>
@@ -57,30 +56,39 @@ already cached before the Postfix SMTP server looks them up later.
<h2> <a name="basic">The basic idea behind postscreen(8)</a> </h2> <h2> <a name="basic">The basic idea behind postscreen(8)</a> </h2>
<p> Spambots have a limited amount of time to send out spam before <p> Most email is spam, and most spam is sent out by zombies (malware
they become blacklisted. For this reason, spambots make compromises on compromised end-user computers). Wietse expects that the zombie
in their SMTP protocol implementation to speed up spam deliveries. problem will get worse before things improve, if ever. Without a
For example, they speak before their turn, or they ignore responses tool like postscreen(8) that keeps the zombies away, Postfix would be
from SMTP servers. </p> spending most of its resources not receiving email. </p>
<p> Many spambots avoid spamming the same site repeatedly, in an <p> The main challenge for postscreen(8) is to make an is-it-a-zombie
attempt to fly under the radar. Thus, postscreen(8) must make a decision based on a single measurement. This is necessary because
long-term decision after a single measurement. For example, allow many zombies avoid spamming the same site repeatedly, in an attempt
a good client to skip the "<a href="#pregreet">pregreet</a>" test to fly under the radar. Once postscreen(8) decides that a client
for 24 hours. </p> is not-a-zombie, it whitelists the client temporarily to avoid
further delays for legitimate mail. </p>
<p> To recognize spambots, postscreen(8) measures properties of the <p> Zombies have challenges too: they have only a limited amount
client IP address and of the client SMTP protocol implementation of time to deliver spam before their IP address becomes blacklisted.
(the protocol compromises that were made to speed up delivery). To speed up spam deliveries, zombies make compromises in their SMTP
These properties don't change with delivery attempts, and are protocol implementation. For example, they speak before their turn,
therefore suitable for making a long-term decision after a single or they ignore responses from SMTP servers and continue sending
measurement. </p> mail even when the server tells them to go away. </p>
<p> postscreen(8) does not inspect message content. The reason is <p> postscreen(8) uses a variety of measurements to recognize
that content can change with each delivery attempt, especially with zombies. First, postscreen(8) determines if the remote SMTP client
legitimate clients. Message content is not good for making a long-term IP address is blacklisted. Second, postscreen(8) looks for protocol
decision after a single measurement, and that is the problem that compromises that are made to speed up delivery. The results of
postscreen(8) is focused on. </p> such measurements don't change with each delivery attempt, and are
therefore good for making an is-it-a-zombie decision based on a
single measurement. </p>
<p> postscreen(8) does not inspect message content. Message content
can vary widely with each delivery attempt, especially with clients
that (also) send legitimate email. Content is therefore not good
for making an is-it-a-zombie decision based on a single measurement,
and that is the problem that postscreen(8) is focused on. </p>
<h2> <a name="general"> General operation </a> </h2> <h2> <a name="general"> General operation </a> </h2>
@@ -100,7 +108,7 @@ to reject mail from clients that fail one or more tests, after
logging the helo, sender and recipient information. </p> logging the helo, sender and recipient information. </p>
<p> Note: postscreen(8) is not an SMTP proxy; this is intentional. <p> Note: postscreen(8) is not an SMTP proxy; this is intentional.
The purpose is to keep spambots away from Postfix, with minimal The purpose is to keep zombies away from Postfix, with minimal
overhead for legitimate clients. </p> overhead for legitimate clients. </p>
<h2> <a name="quick">Quick tests before everything else</a> </h2> <h2> <a name="quick">Quick tests before everything else</a> </h2>
@@ -196,7 +204,7 @@ for the short postscreen_greet_wait delay). </p>
<h3> <a name="pregreet"> Pregreet test </a> </h3> <h3> <a name="pregreet"> Pregreet test </a> </h3>
<p> The SMTP protocol is a classic example of a protocol where the <p> The SMTP protocol is a classic example of a protocol where the
server speaks before the client. postscreen(8) detects spambots server speaks before the client. postscreen(8) detects zombies
that are in a hurry and that speak before their turn. This test is that are in a hurry and that speak before their turn. This test is
enabled by default. </p> enabled by default. </p>
@@ -205,7 +213,7 @@ portion of a "220-<i>text</i>..." teaser banner (default: $smtpd_banner).
Note that this becomes the first part of a multi-line server greeting. Note that this becomes the first part of a multi-line server greeting.
The postscreen(8) daemon sends this before the postscreen_greet_wait The postscreen(8) daemon sends this before the postscreen_greet_wait
timer is started. The purpose of the teaser banner is to confuse timer is started. The purpose of the teaser banner is to confuse
spambots so that they speak before their turn. It has no effect on zombies so that they speak before their turn. It has no effect on
SMTP clients that correctly implement the protocol. </p> SMTP clients that correctly implement the protocol. </p>
<p> To avoid problems with poorly-implemented SMTP engines in network <p> To avoid problems with poorly-implemented SMTP engines in network
@@ -262,7 +270,9 @@ hide "password" information in DNSBL domain names.
DNSBL score is equal to or greater than the postscreen_dnsbl_threshold DNSBL score is equal to or greater than the postscreen_dnsbl_threshold
parameter value, postscreen(8) logs this as: </p> parameter value, postscreen(8) logs this as: </p>
<b>DNSBL rank</b> <i>count</i> <b>for</b> <i>address</i> <pre>
<b>DNSBL rank</b> <i>count</i> <b>for</b> <i>address</i>
</pre>
<p> Translation: the SMTP client at <i>address</i> has a combined <p> Translation: the SMTP client at <i>address</i> has a combined
DNSBL score of <i>count</i>. </p> DNSBL score of <i>count</i>. </p>
@@ -359,7 +369,7 @@ to send multiple commands. postscreen(8)'s <a href="#after_220">deep
protocol test</a> for this is disabled by default. </p> protocol test</a> for this is disabled by default. </p>
<p> With "postscreen_pipelining_enable = yes", postscreen(8) detects <p> With "postscreen_pipelining_enable = yes", postscreen(8) detects
spambots that send multiple commands, instead of sending one command zombies that send multiple commands, instead of sending one command
and waiting for the server to reply. </p> and waiting for the server to reply. </p>
<p> This test is opportunistically enabled when postscreen(8) has <p> This test is opportunistically enabled when postscreen(8) has
@@ -392,7 +402,7 @@ feature to block these clients. postscreen(8)'s <a href="#after_220">deep
protocol test</a> for this is disabled by default. </p> protocol test</a> for this is disabled by default. </p>
<p> With "postscreen_non_smtp_command_enable = yes", postscreen(8) <p> With "postscreen_non_smtp_command_enable = yes", postscreen(8)
detects spambots that send commands specified with the detects zombies that send commands specified with the
postscreen_forbidden_commands parameter. This also detects commands postscreen_forbidden_commands parameter. This also detects commands
with the syntax of a message header label. The latter is a symptom with the syntax of a message header label. The latter is a symptom
that the client is sending message content after ignoring all the that the client is sending message content after ignoring all the
@@ -695,7 +705,7 @@ Postfix SMTP servers dramatically. </p>
clients that talk before their turn, and to log the helo/sender/recipient clients that talk before their turn, and to log the helo/sender/recipient
information. This stops over half of all known-to-be illegitimate information. This stops over half of all known-to-be illegitimate
connections to Wietse's mail server. It is backup protection for connections to Wietse's mail server. It is backup protection for
spambots that haven't yet been blacklisted. </p> zombies that haven't yet been blacklisted. </p>
<li> <p> You can also enable "<a href="#after_220">deep protocol <li> <p> You can also enable "<a href="#after_220">deep protocol
tests</a>", but these are more intrusive than the pregreet or DNSBL tests</a>", but these are more intrusive than the pregreet or DNSBL

View File

@@ -20,7 +20,7 @@
* Patches change both the patchlevel and the release date. Snapshots have no * Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only. * patchlevel; they change the release date only.
*/ */
#define MAIL_RELEASE_DATE "20100918" #define MAIL_RELEASE_DATE "20100923"
#define MAIL_VERSION_NUMBER "2.8" #define MAIL_VERSION_NUMBER "2.8"
#ifdef SNAPSHOT #ifdef SNAPSHOT

View File

@@ -560,7 +560,7 @@ static void ps_service(VSTREAM *smtp_client_stream,
/* Not: PS_PASS_SESSION_STATE. Repeat this test the next time. */ /* Not: PS_PASS_SESSION_STATE. Repeat this test the next time. */
break; break;
default: default:
msg_panic("%s: unknown pregreet action value %d", msg_panic("%s: unknown blacklist action value %d",
myname, ps_blist_action); myname, ps_blist_action);
} }
} }
@@ -580,7 +580,7 @@ static void ps_service(VSTREAM *smtp_client_stream,
if (msg_verbose) if (msg_verbose)
msg_info("%s: cached + recent flags: %s", msg_info("%s: cached + recent flags: %s",
myname, ps_print_state_flags(state->flags, myname)); myname, ps_print_state_flags(state->flags, myname));
if ((state->flags & PS_STATE_FLAG_ANY_TODO) == 0) { if ((state->flags & PS_STATE_FLAG_ANY_TODO_FAIL) == 0) {
msg_info("PASS OLD %s", state->smtp_client_addr); msg_info("PASS OLD %s", state->smtp_client_addr);
ps_conclude(state); ps_conclude(state);
return; return;

View File

@@ -186,6 +186,12 @@ typedef struct {
#define PS_STATE_FLAG_ANY_TODO \ #define PS_STATE_FLAG_ANY_TODO \
(PS_STATE_FLAG_EARLY_TODO | PS_STATE_FLAG_SMTPD_TODO) (PS_STATE_FLAG_EARLY_TODO | PS_STATE_FLAG_SMTPD_TODO)
#define PS_STATE_FLAG_ANY_TODO_FAIL \
(PS_STATE_FLAG_ANY_TODO | PS_STATE_FLAG_ANY_FAIL)
#define PS_STATE_FLAG_ANY_UPDATE \
(PS_STATE_FLAG_ANY_PASS)
/* /*
* See log_adhoc.c for discussion. * See log_adhoc.c for discussion.
*/ */
@@ -383,6 +389,7 @@ extern void ps_dnsbl_request(const char *, void (*) (int, char *), char *);
(dst)->pregr_stamp = PS_TIME_STAMP_INVALID; \ (dst)->pregr_stamp = PS_TIME_STAMP_INVALID; \
(dst)->dnsbl_stamp = PS_TIME_STAMP_INVALID; \ (dst)->dnsbl_stamp = PS_TIME_STAMP_INVALID; \
(dst)->pipel_stamp = PS_TIME_STAMP_INVALID; \ (dst)->pipel_stamp = PS_TIME_STAMP_INVALID; \
(dst)->barlf_stamp = PS_TIME_STAMP_INVALID; \
} while (0) } while (0)
#define PS_BEGIN_TESTS(state, name) do { \ #define PS_BEGIN_TESTS(state, name) do { \
(state)->test_name = (name); \ (state)->test_name = (name); \
@@ -411,7 +418,7 @@ extern void ps_smtpd_init(void);
/* /*
* postscreen_misc.c * postscreen_misc.c
*/ */
extern char *ps_format_delta_time(VSTRING *, struct timeval, int *); extern char *ps_format_delta_time(VSTRING *, struct timeval, DELTA_TIME *);
extern void ps_conclude(PS_STATE *); extern void ps_conclude(PS_STATE *);
extern void ps_hangup_event(PS_STATE *); extern void ps_hangup_event(PS_STATE *);

View File

@@ -58,7 +58,7 @@ static void ps_early_event(int event, char *context)
char read_buf[PS_READ_BUF_SIZE]; char read_buf[PS_READ_BUF_SIZE];
int read_count; int read_count;
int dnsbl_score; int dnsbl_score;
int elapsed; DELTA_TIME elapsed;
const char *dnsbl_name; const char *dnsbl_name;
if (msg_verbose > 1) if (msg_verbose > 1)
@@ -206,13 +206,13 @@ static void ps_early_event(int event, char *context)
* EVENT_TIME, instead of calling ps_early_event recursively. * EVENT_TIME, instead of calling ps_early_event recursively.
*/ */
state->flags |= PS_STATE_FLAG_PREGR_DONE; state->flags |= PS_STATE_FLAG_PREGR_DONE;
if (elapsed >= PS_EFF_GREET_WAIT if (elapsed.dt_sec >= PS_EFF_GREET_WAIT
|| ((state->flags & PS_STATE_FLAG_EARLY_DONE) || ((state->flags & PS_STATE_FLAG_EARLY_DONE)
== PS_STATE_FLAGS_TODO_TO_DONE(state->flags & PS_STATE_FLAG_EARLY_TODO))) == PS_STATE_FLAGS_TODO_TO_DONE(state->flags & PS_STATE_FLAG_EARLY_TODO)))
ps_early_event(EVENT_TIME, context); ps_early_event(EVENT_TIME, context);
else else
event_request_timer(ps_early_event, context, event_request_timer(ps_early_event, context,
PS_EFF_GREET_WAIT - elapsed); PS_EFF_GREET_WAIT - elapsed.dt_sec);
return; return;
} }
} }

View File

@@ -9,7 +9,7 @@
/* char *ps_format_delta_time(buf, tv, delta) /* char *ps_format_delta_time(buf, tv, delta)
/* VSTRING *buf; /* VSTRING *buf;
/* struct timeval tv; /* struct timeval tv;
/* int *delta; /* DELTA_TIME *delta;
/* /*
/* void ps_conclude(state) /* void ps_conclude(state)
/* PS_STATE *state; /* PS_STATE *state;
@@ -66,7 +66,7 @@
/* ps_format_delta_time - pretty-formatted delta time */ /* ps_format_delta_time - pretty-formatted delta time */
char *ps_format_delta_time(VSTRING *buf, struct timeval tv, int *delta) char *ps_format_delta_time(VSTRING *buf, struct timeval tv, DELTA_TIME *delta)
{ {
DELTA_TIME pdelay; DELTA_TIME pdelay;
struct timeval now; struct timeval now;
@@ -75,7 +75,7 @@ char *ps_format_delta_time(VSTRING *buf, struct timeval tv, int *delta)
PS_CALC_DELTA(pdelay, now, tv); PS_CALC_DELTA(pdelay, now, tv);
VSTRING_RESET(buf); VSTRING_RESET(buf);
format_tv(buf, pdelay.dt_sec, pdelay.dt_usec, SIG_DIGS, var_delay_max_res); format_tv(buf, pdelay.dt_sec, pdelay.dt_usec, SIG_DIGS, var_delay_max_res);
*delta = pdelay.dt_sec; *delta = pdelay;
return (STR(buf)); return (STR(buf));
} }
@@ -95,8 +95,8 @@ void ps_conclude(PS_STATE *state)
* blacklisting. There may still be unfinished tests; those tests will * blacklisting. There may still be unfinished tests; those tests will
* need to be completed when the client returns in a later session. * need to be completed when the client returns in a later session.
*/ */
if ((state->flags & PS_STATE_FLAG_ANY_PASS) != 0 if (state->flags & PS_STATE_FLAG_ANY_FAIL)
&& (state->flags & PS_STATE_FLAG_ANY_FAIL) == 0) { state->flags &= ~PS_STATE_FLAG_ANY_PASS;
/* /*
* Log our final blessing when all unfinished tests were completed. * Log our final blessing when all unfinished tests were completed.
@@ -107,15 +107,15 @@ void ps_conclude(PS_STATE *state)
"OLD" : "NEW", state->smtp_client_addr); "OLD" : "NEW", state->smtp_client_addr);
/* /*
* Update the postscreen cache. This still supports a scenario where * Update the postscreen cache. This still supports a scenario where a
* a client gets whitelisted in the course of multiple sessions, as * client gets whitelisted in the course of multiple sessions, as long as
* long as that client does not "fail" any test. * that client does not "fail" any test.
*/ */
if (ps_cache_map != 0) { if ((state->flags & PS_STATE_FLAG_ANY_UPDATE) != 0
&& ps_cache_map != 0) {
ps_print_tests(ps_temp, state); ps_print_tests(ps_temp, state);
ps_cache_update(ps_cache_map, state->smtp_client_addr, STR(ps_temp)); ps_cache_update(ps_cache_map, state->smtp_client_addr, STR(ps_temp));
} }
}
/* /*
* Either hand off the socket to a real SMTP engine, or say bye-bye. * Either hand off the socket to a real SMTP engine, or say bye-bye.
@@ -136,7 +136,7 @@ void ps_conclude(PS_STATE *state)
void ps_hangup_event(PS_STATE *state) void ps_hangup_event(PS_STATE *state)
{ {
int elapsed; DELTA_TIME elapsed;
/* /*
* Sessions can break at any time, even after the client passes all tests * Sessions can break at any time, even after the client passes all tests

View File

@@ -191,11 +191,17 @@ void ps_parse_tests(PS_STATE *state,
default: default:
break; break;
} }
if ((state->pregr_stamp = pregr_stamp) == PS_TIME_STAMP_NEW state->pregr_stamp = pregr_stamp;
|| (state->dnsbl_stamp = dnsbl_stamp) == PS_TIME_STAMP_NEW state->dnsbl_stamp = dnsbl_stamp;
|| (state->pipel_stamp = pipel_stamp) == PS_TIME_STAMP_NEW state->pipel_stamp = pipel_stamp;
|| (state->nsmtp_stamp = nsmtp_stamp) == PS_TIME_STAMP_NEW state->nsmtp_stamp = nsmtp_stamp;
|| (state->barlf_stamp = barlf_stamp) == PS_TIME_STAMP_NEW) state->barlf_stamp = barlf_stamp;
if (pregr_stamp == PS_TIME_STAMP_NEW
|| dnsbl_stamp == PS_TIME_STAMP_NEW
|| pipel_stamp == PS_TIME_STAMP_NEW
|| nsmtp_stamp == PS_TIME_STAMP_NEW
|| barlf_stamp == PS_TIME_STAMP_NEW)
state->flags |= PS_STATE_FLAG_NEW; state->flags |= PS_STATE_FLAG_NEW;
/* /*
@@ -258,8 +264,8 @@ char *ps_print_tests(VSTRING *buf, PS_STATE *state)
/* /*
* Sanity check. * Sanity check.
*/ */
if ((state->flags & PS_STATE_FLAG_ANY_PASS) == 0) if ((state->flags & PS_STATE_FLAG_ANY_UPDATE) == 0)
msg_panic("%s: attempt to save a no-pass record", myname); msg_panic("%s: attempt to save a no-update record", myname);
/* /*
* Give disabled tests a dummy time stamp so that we don't log a client * Give disabled tests a dummy time stamp so that we don't log a client