1215 lines
44 KiB
HTML
1215 lines
44 KiB
HTML
<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"
|
|
"https://www.w3.org/TR/html4/loose.dtd">
|
|
|
|
<head>
|
|
|
|
<title>Postfix Postscreen Howto</title>
|
|
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
|
<link rel='stylesheet' type='text/css' href='postfix-doc.css'>
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<h1><img src="postfix-logo.jpg" width="203" height="98" ALT="">Postfix Postscreen Howto</h1>
|
|
|
|
<hr>
|
|
|
|
<h2> <a name="intro">Introduction</a> </h2>
|
|
|
|
<p> This document describes features that are available in Postfix
|
|
3.6 and later. See <a href="POSTSCREEN_3_5_README.html">
|
|
POSTSCREEN_3_5_README.html</a> for Postfix versions 2.8 - 3.5. </p>
|
|
|
|
<p> The Postfix postscreen(8) daemon provides additional protection
|
|
against mail server overload. One postscreen(8) process handles
|
|
multiple inbound SMTP connections, and decides which clients may
|
|
talk to a Postfix SMTP server process. By keeping spambots away,
|
|
postscreen(8) leaves more SMTP server processes available for
|
|
legitimate clients, and delays the onset of <a
|
|
href="STRESS_README.html">server overload</a> conditions. </p>
|
|
|
|
<p> postscreen(8) should not be used on SMTP ports that receive
|
|
mail from end-user clients (MUAs). In a typical deployment,
|
|
postscreen(8) handles the MX service on TCP port 25, while MUA
|
|
clients submit mail via the submission service on TCP port 587 which
|
|
requires client authentication. Alternatively, a site could set up
|
|
a dedicated, non-postscreen, "port 25" server that provides submission
|
|
service and client authentication, but no MX service. </p>
|
|
|
|
<p> postscreen(8) maintains a temporary allowlist for clients that
|
|
pass its tests; by allowing allowlisted clients to skip tests,
|
|
postscreen(8) minimizes its impact on legitimate email traffic.
|
|
</p>
|
|
|
|
<p> postscreen(8) is part of a multi-layer defense. <p>
|
|
|
|
<ul>
|
|
|
|
<li> <p> As the first layer, postscreen(8) blocks connections from
|
|
zombies and other spambots that are responsible for about 90% of
|
|
all spam. It is implemented as a single process to make this defense
|
|
as inexpensive as possible. </p>
|
|
|
|
<li> <p> The second layer implements more complex SMTP-level access
|
|
checks with <a href="SMTPD_ACCESS_README.html">Postfix SMTP servers</a>,
|
|
<a href="SMTPD_POLICY_README.html">policy daemons</a>, and
|
|
<a href="MILTER_README.html">Milter applications</a>. </p>
|
|
|
|
<li> <p> The third layer performs light-weight content inspection
|
|
with the Postfix built-in header_checks and body_checks. This can
|
|
block unacceptable attachments such as executable programs, and
|
|
worms or viruses with easy-to-recognize signatures. </p>
|
|
|
|
<li> <p> The fourth layer provides heavy-weight content inspection
|
|
with external content filters. Typical examples are <a
|
|
href="https://www.ijs.si/software/amavisd/">Amavisd-new</a>, <a
|
|
href="https://spamassassin.apache.org/">SpamAssassin</a>, and <a
|
|
href="MILTER_README.html">Milter applications</a>. </p>
|
|
|
|
</ul>
|
|
|
|
<p> Each layer reduces the spam volume. The general strategy is to
|
|
use the less expensive defenses first, and to use the more expensive
|
|
defenses only for the spam that remains. </p>
|
|
|
|
<p> Topics in this document: </p>
|
|
|
|
<ul>
|
|
|
|
<li> <a href="#intro">Introduction</a>
|
|
|
|
<li> <a href="#basic">The basic idea behind postscreen(8)</a>
|
|
|
|
<li> <a href="#general"> General operation </a>
|
|
|
|
<li> <a href="#quick">Quick tests before everything else</a>
|
|
|
|
<li> <a href="#before_220"> Tests before the 220 SMTP server greeting </a>
|
|
|
|
<li> <a href="#after_220">Tests after the 220 SMTP server greeting</a>
|
|
|
|
<li> <a href="#other_error">Other errors</a>
|
|
|
|
<li> <a href="#victory">When all tests succeed</a>
|
|
|
|
<li> <a href="#config"> Configuring the postscreen(8) service</a>
|
|
|
|
<li> <a href="#historical"> Historical notes and credits </a>
|
|
|
|
</ul>
|
|
|
|
<h2> <a name="basic">The basic idea behind postscreen(8)</a> </h2>
|
|
|
|
<p> Most email is spam, and most spam is sent out by zombies (malware
|
|
on compromised end-user computers). Wietse expects that the zombie
|
|
problem will get worse before things improve, if ever. Without a
|
|
tool like postscreen(8) that keeps the zombies away, Postfix would be
|
|
spending most of its resources not receiving email. </p>
|
|
|
|
<p> The main challenge for postscreen(8) is to make an is-a-zombie
|
|
decision based on a single measurement. This is necessary because
|
|
many zombies try to fly under the radar and avoid spamming the same
|
|
site repeatedly. Once postscreen(8) decides that a client is
|
|
not-a-zombie, it allowlists the client temporarily to avoid further
|
|
delays for legitimate mail. </p>
|
|
|
|
<p> Zombies have challenges too: they have only a limited amount
|
|
of time to deliver spam before their IP address becomes denylisted.
|
|
To speed up spam deliveries, zombies make compromises in their SMTP
|
|
protocol implementation. For example, they speak before their turn,
|
|
or they ignore responses from SMTP servers and continue sending
|
|
commands even when the server tells them to go away. </p>
|
|
|
|
<p> postscreen(8) uses a variety of measurements to recognize
|
|
zombies. First, postscreen(8) determines if the remote SMTP client
|
|
IP address is denylisted. Second, postscreen(8) looks for protocol
|
|
compromises that are made to speed up delivery. These are good
|
|
indicators for making is-a-zombie decisions based on single
|
|
measurements. </p>
|
|
|
|
<p> postscreen(8) does not inspect message content. Message content
|
|
can vary from one delivery to the next, especially with clients
|
|
that (also) send legitimate email. Content is not a good indicator
|
|
for making is-a-zombie decisions based on single measurements,
|
|
and that is the problem that postscreen(8) is focused on. </p>
|
|
|
|
<h2> <a name="general"> General operation </a> </h2>
|
|
|
|
<p> For each connection from an SMTP client, postscreen(8) performs
|
|
a number of tests
|
|
in the order as described below. Some tests introduce a delay of
|
|
a few seconds. postscreen(8) maintains a temporary allowlist for
|
|
clients that pass its tests; by allowing allowlisted clients to
|
|
skip tests, postscreen(8) minimizes its impact on legitimate email
|
|
traffic. </p>
|
|
|
|
<p> By default, postscreen(8) hands off all connections to a Postfix
|
|
SMTP server process after logging its findings. This mode is useful
|
|
for non-destructive testing. </p>
|
|
|
|
<p> In a typical production setting, postscreen(8) is configured
|
|
to reject mail from clients that fail one or more tests, after
|
|
logging the helo, sender and recipient information. </p>
|
|
|
|
<p> Note: postscreen(8) is not an SMTP proxy; this is intentional.
|
|
The purpose is to keep zombies away from Postfix, with minimal
|
|
overhead for legitimate clients. </p>
|
|
|
|
<h2> <a name="quick">Quick tests before everything else</a> </h2>
|
|
|
|
<p> Before engaging in SMTP-level tests, postscreen(8) queries a
|
|
number of local deny and allowlists. These tests speed up the
|
|
handling of known clients. </p>
|
|
|
|
<ul>
|
|
|
|
<li> <a href="#perm_allow_deny"> Permanent allow/denylist test </a>
|
|
|
|
<li> <a href="#temp_allow"> Temporary allowlist test </a>
|
|
|
|
<li> <a href="#allow_veto"> MX Policy test </a>
|
|
|
|
</ul>
|
|
|
|
<h3> <a name="perm_allow_deny"> Permanent allow/denylist test </a> </h3>
|
|
|
|
<p> The postscreen_access_list parameter (default: permit_mynetworks)
|
|
specifies a permanent access list for SMTP client IP addresses. Typically
|
|
one would specify something that allowlists local networks, followed
|
|
by a CIDR table for selective allow- and denylisting. </p>
|
|
|
|
<p> Example: </p>
|
|
|
|
<pre>
|
|
/etc/postfix/main.cf:
|
|
postscreen_access_list = permit_mynetworks,
|
|
cidr:/etc/postfix/postscreen_access.cidr
|
|
|
|
/etc/postfix/postscreen_access.cidr:
|
|
# Rules are evaluated in the order as specified.
|
|
# Denylist 192.168.* except 192.168.0.1.
|
|
192.168.0.1 permit
|
|
192.168.0.0/16 reject
|
|
</pre>
|
|
|
|
<p> See the postscreen_access_list manpage documentation for more
|
|
details. </p>
|
|
|
|
<p> When the SMTP client address matches a "permit" action,
|
|
postscreen(8) logs this with the client address and port number as:
|
|
</p>
|
|
|
|
<blockquote>
|
|
<pre>
|
|
<b>ALLOWLISTED</b> <i>[address]:port</i>
|
|
</pre>
|
|
</blockquote>
|
|
|
|
<blockquote> <p> Use the respectful_logging configuration parameter to
|
|
select a deprecated form of this logging. </p> </blockquote>
|
|
|
|
<p> The allowlist action is not configurable: immediately hand off the
|
|
connection to a Postfix SMTP server process. </p>
|
|
|
|
<p> When the SMTP client address matches a "reject" action,
|
|
postscreen(8) logs this with the client address and port number as:
|
|
</p>
|
|
|
|
<blockquote>
|
|
<pre>
|
|
<b>DENYLISTED</b> <i>[address]:port</i>
|
|
</pre>
|
|
</blockquote>
|
|
|
|
<blockquote> <p> Use the respectful_logging configuration parameter to
|
|
select a deprecated form of this logging. </p> </blockquote>
|
|
|
|
<p> The postscreen_denylist_action parameter specifies the action
|
|
that is taken next. See "<a href="#fail_before_220">When tests
|
|
fail before the 220 SMTP server greeting</a>" below. </p>
|
|
|
|
<h3> <a name="temp_allow"> Temporary allowlist test </a> </h3>
|
|
|
|
<p> The postscreen(8) daemon maintains a <i>temporary</i>
|
|
allowlist for SMTP client IP addresses that have passed all
|
|
the tests described below. The postscreen_cache_map parameter
|
|
specifies the location of the temporary allowlist. The
|
|
temporary allowlist is not used for SMTP client addresses
|
|
that appear on the <i>permanent</i> access list. </p>
|
|
|
|
<p> By default the temporary allowlist is not shared with other
|
|
postscreen(8) daemons. See
|
|
<a href="#temp_allow_sharing"> Sharing
|
|
the temporary allowlist </a> below for alternatives. </p>
|
|
|
|
<p> When the SMTP client address appears on the temporary
|
|
allowlist, postscreen(8) logs this with the client address and port
|
|
number as: </p>
|
|
|
|
<pre>
|
|
<b>PASS OLD</b> <i>[address]:port</i>
|
|
</pre>
|
|
|
|
<p> The action is not configurable: immediately hand off the
|
|
connection to a Postfix SMTP server process. The client is
|
|
excluded from further tests until its temporary allowlist
|
|
entry expires, as controlled with the postscreen_*_ttl
|
|
parameters. Expired entries are silently renewed if possible. </p>
|
|
|
|
<h3> <a name="allow_veto"> MX Policy test </a> </h3>
|
|
|
|
<p> When the remote SMTP client is not on the static access list
|
|
or temporary allowlist, postscreen(8) can implement a number of
|
|
allowlist tests, before it grants the client a temporary allowlist
|
|
status that allows it to talk to a Postfix SMTP server process. </p>
|
|
|
|
<p> When postscreen(8) is configured to monitor all primary and
|
|
backup MX addresses, it can refuse to allowlist clients that connect
|
|
to a backup MX address only (an old spammer trick to take advantage
|
|
of backup MX hosts with weaker anti-spam policies than primary MX
|
|
hosts). </p>
|
|
|
|
<blockquote> <p> NOTE: The following solution is for small sites.
|
|
Larger sites would have to share the postscreen(8) cache between
|
|
primary and backup MTAs, which would introduce a common point of
|
|
failure. </p> </blockquote>
|
|
|
|
<ul>
|
|
|
|
<li> <p> First, configure the host to listen on both primary and
|
|
backup MX addresses. Use the appropriate <tt>ifconfig</tt> or <tt>ip</tt>
|
|
command for the local operating system, or update the appropriate
|
|
configuration files and "refresh" the network protocol stack. </p>
|
|
|
|
<p> <p> Second, configure Postfix to listen on the new IP address
|
|
(this step is needed when you have specified inet_interfaces in
|
|
main.cf). </p>
|
|
|
|
<li> <p> Then, configure postscreen(8) to deny the temporary allowlist
|
|
status on the backup MX address(es). An example for Wietse's
|
|
server is: </p>
|
|
|
|
<pre>
|
|
/etc/postfix/main.cf:
|
|
postscreen_allowlist_interfaces = !168.100.189.8 static:all
|
|
</pre>
|
|
|
|
<p> Translation: allow clients to obtain the temporary allowlist
|
|
status on all server IP addresses except 168.100.189.8, which is a
|
|
backup MX address. </p>
|
|
|
|
</ul>
|
|
|
|
<p> When a non-allowlisted client connects the backup MX address,
|
|
postscreen(8) logs this with the client address and port number as:
|
|
</p>
|
|
|
|
<blockquote> <pre>
|
|
<b>CONNECT from</b> <i>[address]:port</i> <b>to [168.100.189.8]:25</b>
|
|
<b>ALLOWLIST VETO</b> <i>[address]:port</i>
|
|
</pre> </blockquote>
|
|
|
|
<blockquote> <p> Use the respectful_logging configuration parameter to
|
|
select a deprecated form of this logging. </p> </blockquote>
|
|
|
|
<p> Translation: the client at <i>[address]:port</i> connected to
|
|
the backup MX address 168.100.189.8 while it was not allowlisted.
|
|
The client will not be granted the temporary allowlist status, even
|
|
if passes all the allowlist tests described below. </p>
|
|
|
|
<h2> <a name="before_220"> Tests before the 220 SMTP server greeting </a> </h2>
|
|
|
|
<p> The postscreen_greet_wait parameter specifies a short time
|
|
interval before the "220 <i>text</i>..." server greeting, where
|
|
postscreen(8) can run a number of tests in parallel. </p>
|
|
|
|
<p> When a good client passes these tests, and no "<a
|
|
href="#after_220">deep protocol tests</a>"
|
|
are configured, postscreen(8)
|
|
adds the client to the temporary allowlist and hands off the "live"
|
|
connection to a Postfix SMTP server process. The client can then
|
|
continue as if postscreen(8) never even existed (except of course
|
|
for the short postscreen_greet_wait delay). </p>
|
|
|
|
<ul>
|
|
|
|
<li> <a href="#pregreet"> Pregreet test </a>
|
|
|
|
<li> <a href="#dnsbl"> DNS Allow/denylist test </a>
|
|
|
|
<li> <a href="#fail_before_220">When tests fail before the 220 SMTP server greeting</a>
|
|
|
|
</ul>
|
|
|
|
<h3> <a name="pregreet"> Pregreet test </a> </h3>
|
|
|
|
<p> The SMTP protocol is a classic example of a protocol where the
|
|
server speaks before the client. postscreen(8) detects zombies
|
|
that are in a hurry and that speak before their turn. This test is
|
|
enabled by default. </p>
|
|
|
|
<p> The postscreen_greet_banner parameter specifies the <i>text</i>
|
|
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.
|
|
The postscreen(8) daemon sends this before the postscreen_greet_wait
|
|
timer is started. The purpose of the teaser banner is to confuse
|
|
zombies so that they speak before their turn. It has no effect on
|
|
SMTP clients that correctly implement the protocol. </p>
|
|
|
|
<p> To avoid problems with poorly-implemented SMTP engines in network
|
|
appliances or network testing tools, either exclude them from all
|
|
tests with the postscreen_access_list feature or else specify
|
|
an empty teaser banner: </p>
|
|
|
|
<pre>
|
|
/etc/postfix/main.cf:
|
|
# Exclude broken clients by allowlisting. Clients in mynetworks
|
|
# should always be allowlisted.
|
|
postscreen_access_list = permit_mynetworks,
|
|
cidr:/etc/postfix/postscreen_access.cidr
|
|
|
|
/etc/postfix/postscreen_access.cidr:
|
|
192.168.254.0/24 permit
|
|
</pre>
|
|
|
|
<pre>
|
|
/etc/postfix/main.cf:
|
|
# Disable the teaser banner (try allowlisting first if you can).
|
|
postscreen_greet_banner =
|
|
</pre>
|
|
|
|
<p> When an SMTP client sends a command before the
|
|
postscreen_greet_wait time has elapsed, postscreen(8) logs this as:
|
|
</p>
|
|
|
|
<pre>
|
|
<b>PREGREET</b> <i>count</i> <b>after</b> <i>time</i> <b>from</b> <i>[address]:port text...</i>
|
|
</pre>
|
|
|
|
<p> Translation: the client at <i>[address]:port</i> sent <i>count</i>
|
|
bytes before its turn to speak. This happened <i>time</i> seconds
|
|
after the postscreen_greet_wait timer was started. The <i>text</i>
|
|
is what the client sent (truncated to 100 bytes, and with non-printable
|
|
characters replaced with C-style escapes such as \r for carriage-return
|
|
and \n for newline). </p>
|
|
|
|
<p> The postscreen_greet_action parameter specifies the action that
|
|
is taken next. See "<a href="#fail_before_220">When tests fail
|
|
before the 220 SMTP server greeting</a>" below. </p>
|
|
|
|
<h3> <a name="dnsbl"> DNS Allow/denylist test </a> </h3>
|
|
|
|
<p> The postscreen_dnsbl_sites parameter (default: empty) specifies
|
|
a list of DNS blocklist servers with optional filters and weight
|
|
factors (positive weights for denylisting, negative for allowlisting).
|
|
These servers will be queried in parallel with the reverse client
|
|
IP address. This test is disabled by default. </p>
|
|
|
|
<blockquote>
|
|
<p>
|
|
CAUTION: when postscreen rejects mail, its SMTP reply contains the
|
|
DNSBL domain name. Use the postscreen_dnsbl_reply_map feature to
|
|
hide "password" information in DNSBL domain names.
|
|
</p>
|
|
</blockquote>
|
|
|
|
<p> 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, postscreen(8) logs this as: </p>
|
|
|
|
<pre>
|
|
<b>DNSBL rank</b> <i>count</i> <b>for</b> <i>[address]:port</i>
|
|
</pre>
|
|
|
|
<p> Translation: the SMTP client at <i>[address]:port</i> has a combined
|
|
DNSBL score of <i>count</i>. </p>
|
|
|
|
<p> The postscreen_dnsbl_action parameter specifies the action that
|
|
is taken when the combined DNSBL score is equal to or greater than
|
|
the threshold. See "<a href="#fail_before_220">When tests fail
|
|
before the 220 SMTP server greeting</a>" below. </p>
|
|
|
|
<h3> <a name="fail_before_220">When tests fail before the 220 SMTP server greeting</a> </h3>
|
|
|
|
<p> When the client address matches the permanent denylist, or
|
|
when the client fails the pregreet or DNSBL tests, the action is
|
|
specified with postscreen_denylist_action, postscreen_greet_action,
|
|
or postscreen_dnsbl_action, respectively. </p>
|
|
|
|
<dl>
|
|
|
|
<dt> <b>ignore</b> (default) </dt>
|
|
|
|
<dd> Ignore the failure of this test. Allow other tests to complete.
|
|
Repeat this test the next time the client connects. This option
|
|
is useful for testing and collecting statistics without blocking
|
|
mail. </dd>
|
|
|
|
<dt> <b>enforce</b> </dt>
|
|
|
|
<dd> Allow other tests to complete. Reject attempts to deliver mail
|
|
with a 550 SMTP reply, and log the helo/sender/recipient information.
|
|
Repeat this test the next time the client connects. </dd>
|
|
|
|
<dt> <b>drop</b> </dt>
|
|
|
|
<dd> Drop the connection immediately with a 521 SMTP reply. Repeat
|
|
this test the next time the client connects. </dd>
|
|
|
|
</dl>
|
|
|
|
<h2> <a name="after_220">Tests after the 220 SMTP server greeting</a> </h2>
|
|
|
|
<p> In this phase of the protocol, postscreen(8) implements a
|
|
number of "deep protocol" tests. These tests use an SMTP protocol
|
|
engine that is built into the postscreen(8) server. </p>
|
|
|
|
<p> Important note: these protocol tests are disabled by default.
|
|
They are more intrusive than the pregreet and DNSBL tests, and they
|
|
have limitations as discussed next. </p>
|
|
|
|
<ul>
|
|
|
|
<li> <p> The main limitation of "after 220 greeting" tests is that
|
|
a new client must disconnect after passing these tests (reason:
|
|
postscreen is not a proxy). Then the client must reconnect from
|
|
the same IP address before it can deliver mail. The following
|
|
measures may help to avoid email delays: </p>
|
|
|
|
<ul>
|
|
|
|
<li> <p> Allow "good" clients to skip tests with the
|
|
postscreen_dnsbl_allowlist_threshold feature. This is especially effective
|
|
for large providers that usually don't retry from the same IP
|
|
address. </p>
|
|
|
|
<li> <p> Small sites: Configure postscreen(8) to listen on multiple
|
|
IP addresses, published in DNS as different IP addresses for the
|
|
same MX hostname or for different MX hostnames. This avoids mail
|
|
delivery delays with clients that reconnect immediately from the
|
|
same IP address. </p>
|
|
|
|
<li> <p> Large sites: Share the postscreen(8) cache between different
|
|
Postfix MTAs with a large-enough memcache_table(5). Again, this
|
|
avoids mail delivery delays with clients that reconnect immediately
|
|
from the same IP address. </p>
|
|
|
|
</ul>
|
|
|
|
<li> <p> postscreen(8)'s built-in SMTP engine does not implement the
|
|
AUTH, XCLIENT, and XFORWARD features. If you need to make these
|
|
services available on port 25, then do not enable the tests after
|
|
the 220 server greeting. </p>
|
|
|
|
<li> <p> End-user clients should connect directly to the submission
|
|
service, so that they never have to deal with postscreen(8)'s tests.
|
|
</p>
|
|
|
|
</ul>
|
|
|
|
<p> The following "after 220 greeting" tests are available: </p>
|
|
|
|
<ul>
|
|
|
|
<li> <a href="#pipelining">Command pipelining test</a>
|
|
|
|
<li> <a href="#non_smtp">Non-SMTP command test</a>
|
|
|
|
<li> <a href="#barelf">Bare newline test</a>
|
|
|
|
<li> <a href="#fail_after_220">When tests fail after the 220 SMTP server greeting</a>
|
|
|
|
</ul>
|
|
|
|
<h3> <a name="pipelining">Command pipelining test</a> </h3>
|
|
|
|
<p> By default, SMTP is a half-duplex protocol: the sender and
|
|
receiver send one command and one response at a time. Unlike the
|
|
Postfix SMTP server, postscreen(8) does not announce support
|
|
for ESMTP command pipelining. Therefore, clients are not allowed
|
|
to send multiple commands. postscreen(8)'s
|
|
<a href="#after_220">deep
|
|
protocol test</a> for this is disabled by default. </p>
|
|
|
|
<p> With "postscreen_pipelining_enable = yes", postscreen(8) detects
|
|
zombies that send multiple commands, instead of sending one command
|
|
and waiting for the server to reply. </p>
|
|
|
|
<p> This test is opportunistically enabled when postscreen(8) has
|
|
to use the built-in SMTP engine anyway. This is to make postscreen(8)
|
|
logging more informative. </p>
|
|
|
|
<p> When a client sends multiple commands, postscreen(8) logs this
|
|
as: </p>
|
|
|
|
<pre>
|
|
<b>COMMAND PIPELINING from</b> <i>[address]:port</i> <b>after</b> <i>command</i>: <i>text</i>
|
|
</pre>
|
|
|
|
<p> Translation: the SMTP client at <i>[address]:port</i> sent
|
|
multiple SMTP commands, instead of sending one command and then
|
|
waiting for the server to reply. This happened after the client
|
|
sent <i>command</i>. The <i>text</i> shows part of the input that
|
|
was sent too early; it is not logged with Postfix 2.8. </p>
|
|
|
|
<p> The postscreen_pipelining_action parameter specifies the action
|
|
that is taken next. See "<a href="#fail_after_220">When tests fail
|
|
after the 220 SMTP server greeting</a>" below. </p>
|
|
|
|
<h3> <a name="non_smtp">Non-SMTP command test</a> </h3>
|
|
|
|
<p> Some spambots send their mail through open proxies. A symptom
|
|
of this is the usage of commands such as CONNECT and other non-SMTP
|
|
commands. Just like the Postfix SMTP server's smtpd_forbidden_commands
|
|
feature, postscreen(8) has an equivalent postscreen_forbidden_commands
|
|
feature to block these clients. postscreen(8)'s
|
|
<a href="#after_220">deep
|
|
protocol test</a> for this is disabled by default. </p>
|
|
|
|
<p> With "postscreen_non_smtp_command_enable = yes", postscreen(8)
|
|
detects zombies that send commands specified with the
|
|
postscreen_forbidden_commands parameter. 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 all the
|
|
responses from postscreen(8) that reject mail. </p>
|
|
|
|
<p> This test is opportunistically enabled when postscreen(8) has
|
|
to use the built-in SMTP engine anyway. This is to make postscreen(8)
|
|
logging more informative. </p>
|
|
|
|
<p> When a client sends non-SMTP commands, postscreen(8) logs this
|
|
as: </p>
|
|
|
|
<pre>
|
|
<b>NON-SMTP COMMAND from</b> <i>[address]:port</i> <b>after</b> <i>command: text</i>
|
|
</pre>
|
|
|
|
<p> Translation: the SMTP client at <i>[address]:port</i> sent a
|
|
command that matches the postscreen_forbidden_commands
|
|
parameter, or that has the syntax of a message header label (text
|
|
followed by optional space and ":").
|
|
The "<tt><b>after</b> <i>command</i></tt>" portion is logged with
|
|
Postfix 2.10 and later. </p>
|
|
|
|
<p> The postscreen_non_smtp_command_action parameter specifies
|
|
the action that is taken next. See "<a href="#fail_after_220">When
|
|
tests fail after the 220 SMTP server greeting</a>" below. </p>
|
|
|
|
<h3> <a name="barelf">Bare newline test</a> </h3>
|
|
|
|
<p> SMTP is a line-oriented protocol: lines have a limited length,
|
|
and are terminated with <CR><LF>. Lines ending in a
|
|
"bare" <LF>, that is newline not preceded by carriage return,
|
|
are not allowed in SMTP. postscreen(8)'s
|
|
<a href="#after_220">deep
|
|
protocol test</a> for this is disabled by default. </p>
|
|
|
|
<p> With "postscreen_bare_newline_enable = yes", postscreen(8)
|
|
detects clients that send lines ending in bare newline characters.
|
|
</p>
|
|
|
|
<p> This test is opportunistically enabled when postscreen(8) has
|
|
to use the built-in SMTP engine anyway. This is to make postscreen(8)
|
|
logging more informative. </p>
|
|
|
|
<p> When a client sends bare newline characters, postscreen(8) logs
|
|
this as:
|
|
</p>
|
|
|
|
<pre>
|
|
<b>BARE NEWLINE from</b> <i>[address]:port</i> <b>after</b> <i>command</i>
|
|
</pre>
|
|
|
|
<p> Translation: the SMTP client at <i>[address]:port</i> sent a bare
|
|
newline character, that is newline not preceded by carriage
|
|
return.
|
|
The "<tt><b>after</b> <i>command</i></tt>" portion is logged with
|
|
Postfix 2.10 and later. </p>
|
|
|
|
<p> The postscreen_bare_newline_action parameter specifies the
|
|
action that is taken next. See "<a href="#fail_after_220">When
|
|
tests fail after the 220 SMTP server greeting</a>" below. </p>
|
|
|
|
<h3> <a name="fail_after_220">When tests fail after the 220 SMTP server greeting</a> </h3>
|
|
|
|
<p> When the client fails the pipelining, non-SMTP command or bare
|
|
newline tests, the action is specified with postscreen_pipelining_action,
|
|
postscreen_non_smtp_command_action or postscreen_bare_newline_action,
|
|
respectively. </p>
|
|
|
|
<dl>
|
|
|
|
<dt> <b>ignore</b> (default for bare newline) </dt>
|
|
|
|
<dd> Ignore the failure of this test. Allow other tests to complete.
|
|
Do NOT repeat this test before the result from some other test
|
|
expires.
|
|
|
|
This option is useful for testing and collecting statistics without
|
|
blocking mail permanently. </dd>
|
|
|
|
<dt> <b>enforce</b> (default for pipelining) </dt>
|
|
|
|
<dd> Allow other tests to complete. Reject attempts to deliver
|
|
mail with a 550 SMTP reply, and log the helo/sender/recipient
|
|
information. Repeat this test the next time the client connects.
|
|
</dd>
|
|
|
|
<dt> <b>drop</b> (default for non-SMTP commands) </dt>
|
|
|
|
<dd> Drop the connection immediately with a 521 SMTP reply. Repeat
|
|
this test the next time the client connects. This action is
|
|
compatible with the Postfix SMTP server's smtpd_forbidden_commands
|
|
feature. </dd>
|
|
|
|
</dl>
|
|
|
|
<h2> <a name="other_error">Other errors</a> </h2>
|
|
|
|
<p> When an SMTP client hangs up unexpectedly, postscreen(8) logs
|
|
this as: </p>
|
|
|
|
<pre>
|
|
<b>HANGUP after</b> <i>time</i> <b>from</b> <i>[address]:port</i> <b>in</b> <i>test name</i>
|
|
</pre>
|
|
|
|
<p> Translation: the SMTP client at <i>[address]:port</i> disconnected
|
|
unexpectedly, <i>time</i> seconds after the start of the
|
|
test named <i>test name</i>. </p>
|
|
|
|
<p> There is no punishment for hanging up. A client that hangs up
|
|
without sending the QUIT command can still pass all postscreen(8)
|
|
tests. </p>
|
|
|
|
<!--
|
|
|
|
<p> While an unexpired penalty is in effect, an SMTP client is not
|
|
allowed to pass any tests, and postscreen(8) logs each connection
|
|
with the remaining amount of penalty time as: </p>
|
|
|
|
<pre>
|
|
<b>PENALTY</b> <i>time</i> <b>for</b> <i>[address]:port</i>
|
|
</pre>
|
|
|
|
<p> During this time, all attempts by the client to deliver mail
|
|
will be deferred with a 450 SMTP status. </p>
|
|
|
|
-->
|
|
|
|
<p> The following errors are reported by the built-in SMTP engine.
|
|
This engine never accepts mail, therefore it has per-session limits
|
|
on the number of commands and on the session length. </p>
|
|
|
|
<pre>
|
|
<b>COMMAND TIME LIMIT</b> <b>from</b> <i>[address]:port</i> <b>after</b> <i>command</i>
|
|
</pre>
|
|
|
|
<p> Translation: the SMTP client at <i>[address]:port</i> reached the
|
|
per-command time limit as specified with the postscreen_command_time_limit
|
|
parameter. The session is terminated immediately.
|
|
The "<tt><b>after</b> <i>command</i></tt>" portion is logged with
|
|
Postfix 2.10 and later. </p>
|
|
|
|
<pre>
|
|
<b>COMMAND COUNT LIMIT from</b> <i>[address]:port</i> <b>after</b> <i>command</i>
|
|
</pre>
|
|
|
|
<p> Translation: the SMTP client at <i>[address]:port</i> reached the
|
|
per-session command count limit as specified with the
|
|
postscreen_command_count_limit parameter. The session is terminated
|
|
immediately.
|
|
The "<tt><b>after</b> <i>command</i></tt>" portion is logged with
|
|
Postfix 2.10 and later. </p>
|
|
|
|
<pre>
|
|
<b>COMMAND LENGTH LIMIT from</b> <i>[address]:port</i> <b>after</b> <i>command</i>
|
|
</pre>
|
|
|
|
<p> Translation: the SMTP client at <i>[address]:port</i> reached the
|
|
per-command length limit, as specified with the line_length_limit
|
|
parameter. The session is terminated immediately.
|
|
The "<tt><b>after</b> <i>command</i></tt>" portion is logged with
|
|
Postfix 2.10 and later. </p>
|
|
|
|
<p> When an SMTP client makes too many connections at the same time,
|
|
postscreen(8) rejects the connection with a 421 status code and logs: </p>
|
|
|
|
<pre>
|
|
<b>NOQUEUE: reject: CONNECT from</b> <i>[address]:port</i><b>: too many connections</b>
|
|
</pre>
|
|
|
|
<p> The postscreen_client_connection_count_limit parameter controls this limit. </p>
|
|
|
|
<p> When an SMTP client connects after postscreen(8) has reached a
|
|
connection count limit, postscreen(8) rejects the connection with
|
|
a 421 status code and logs: </p>
|
|
|
|
<pre>
|
|
<b>NOQUEUE: reject: CONNECT from</b> <i>[address]:port</i><b>: all screening ports busy</b>
|
|
<b>NOQUEUE: reject: CONNECT from</b> <i>[address]:port</i><b>: all server ports busy</b>
|
|
</pre>
|
|
|
|
<p> The postscreen_pre_queue_limit and postscreen_post_queue_limit
|
|
parameters control these limits. </p>
|
|
|
|
<h2> <a name="victory">When all tests succeed</a> </h2>
|
|
|
|
<p> When a new SMTP client passes all tests (i.e. it is not allowlisted
|
|
via some mechanism), postscreen(8) logs this as: </p>
|
|
|
|
<pre>
|
|
<b>PASS NEW</b> <i>[address]:port</i>
|
|
</pre>
|
|
|
|
<p> Where <i>[address]:port</i> are the client IP address and port.
|
|
Then, postscreen(8)
|
|
creates a temporary allowlist entry that excludes the client IP
|
|
address from further tests until the temporary allowlist entry
|
|
expires, as controlled with the postscreen_*_ttl parameters. </p>
|
|
|
|
<p> When no "<a href="#after_220">deep protocol tests</a>" are
|
|
configured, postscreen(8) hands off the "live" connection to a Postfix
|
|
SMTP server process. The client can then continue as if postscreen(8)
|
|
never even existed (except for the short postscreen_greet_wait delay).
|
|
</p>
|
|
|
|
<p> When any "<a href="#after_220">deep protocol tests</a>" are
|
|
configured, postscreen(8) cannot hand off the "live" connection to
|
|
a Postfix SMTP server process in the middle of the session. Instead,
|
|
postscreen(8) defers mail delivery attempts with a 4XX status, logs
|
|
the helo/sender/recipient information, and waits for the client to
|
|
disconnect. The next time the client connects it will be allowed
|
|
to talk to a Postfix SMTP server process to deliver its mail.
|
|
postscreen(8) mitigates the impact of this limitation by giving
|
|
<a href="#after_220">deep protocol tests</a> a long expiration
|
|
time. </p>
|
|
|
|
<h2> <a name="config"> Configuring the postscreen(8) service</a>
|
|
</h2>
|
|
|
|
<p> postscreen(8) has been tested on FreeBSD [4-8], Linux 2.[4-6]
|
|
and Solaris 9 systems. </p>
|
|
|
|
<ul>
|
|
|
|
<li> <a href="#enable"> Turning on postscreen(8) without blocking
|
|
mail</a>
|
|
|
|
<li> <a href="#starttls"> postscreen(8) TLS configuration </a>
|
|
|
|
<li> <a href="#blocking"> Blocking mail with postscreen(8) </a>
|
|
|
|
<li> <a href="#turnoff"> Turning off postscreen(8) </a>
|
|
|
|
<li> <a href="#temp_allow_sharing"> Sharing the temporary allowlist
|
|
</a>
|
|
|
|
</ul>
|
|
|
|
<h3> <a name="enable"> Turning on postscreen(8) without blocking mail</a> </h3>
|
|
|
|
<p> To enable the postscreen(8) service and log client information
|
|
without blocking mail: </p>
|
|
|
|
<ol>
|
|
|
|
<li> <p> Make sure that local clients and systems with non-standard
|
|
SMTP implementations are excluded from any postscreen(8) tests. The
|
|
default is to exclude all clients in mynetworks. To exclude additional
|
|
clients, for example, third-party performance monitoring tools (these
|
|
tend to have broken SMTP implementations): </p>
|
|
|
|
<pre>
|
|
/etc/postfix/main.cf:
|
|
# Exclude broken clients by allowlisting. Clients in mynetworks
|
|
# should always be allowlisted.
|
|
postscreen_access_list = permit_mynetworks,
|
|
cidr:/etc/postfix/postscreen_access.cidr
|
|
|
|
/etc/postfix/postscreen_access.cidr:
|
|
192.168.254.0/24 permit
|
|
</pre>
|
|
|
|
<li> <p> Comment out the "<tt>smtp inet ... smtpd</tt>" service
|
|
in master.cf, including any "<tt>-o parameter=value</tt>" entries
|
|
that follow. </p>
|
|
|
|
<pre>
|
|
/etc/postfix/master.cf:
|
|
#smtp inet n - n - - smtpd
|
|
# -o parameter=value ...
|
|
</pre>
|
|
|
|
<li> <p> Uncomment the new "<tt>smtpd pass ... smtpd</tt>" service
|
|
in master.cf, and duplicate any "<tt>-o parameter=value</tt>" entries
|
|
from the smtpd service that was commented out in the previous step.
|
|
</p>
|
|
|
|
<pre>
|
|
/etc/postfix/master.cf:
|
|
smtpd pass - - n - - smtpd
|
|
-o parameter=value ...
|
|
</pre>
|
|
|
|
<li> <p> Uncomment the new "<tt>smtp inet ... postscreen</tt>"
|
|
service in master.cf. </p>
|
|
|
|
<pre>
|
|
/etc/postfix/master.cf:
|
|
smtp inet n - n - 1 postscreen
|
|
</pre>
|
|
|
|
<li> <p> Uncomment the new "<tt>tlsproxy unix ... tlsproxy</tt>"
|
|
service in master.cf. This service implements STARTTLS support for
|
|
postscreen(8). </p>
|
|
|
|
<pre>
|
|
/etc/postfix/master.cf:
|
|
tlsproxy unix - - n - 0 tlsproxy
|
|
</pre>
|
|
|
|
<li> <p> Uncomment the new "<tt>dnsblog unix ... dnsblog</tt>"
|
|
service in master.cf. This service does DNSBL lookups for postscreen(8)
|
|
and logs results. </p>
|
|
|
|
<pre>
|
|
/etc/postfix/master.cf:
|
|
dnsblog unix - - n - 0 dnsblog
|
|
</pre>
|
|
|
|
<li> <p> To enable DNSBL lookups, list some DNS blocklist sites in
|
|
main.cf, separated by whitespace. Different sites can have different
|
|
weights. For example:
|
|
|
|
<pre>
|
|
/etc/postfix/main.cf:
|
|
postscreen_dnsbl_threshold = 2
|
|
postscreen_dnsbl_sites = zen.spamhaus.org*2
|
|
bl.spamcop.net*1 b.barracudacentral.org*1
|
|
</pre>
|
|
|
|
<p> Note: if your DNSBL queries have a "secret" in the domain name,
|
|
you must censor this information from the postscreen(8) SMTP replies.
|
|
For example: </p>
|
|
|
|
<pre>
|
|
/etc/postfix/main.cf:
|
|
postscreen_dnsbl_reply_map = texthash:/etc/postfix/dnsbl_reply
|
|
</pre>
|
|
|
|
<pre>
|
|
/etc/postfix/dnsbl_reply:
|
|
# Secret DNSBL name Name in postscreen(8) replies
|
|
secret.zen.dq.spamhaus.net zen.spamhaus.org
|
|
</pre>
|
|
|
|
<p> The texthash: format is similar to hash: except that there is
|
|
no need to run postmap(1) before the file can be used, and that it
|
|
does not detect changes after the file is read. It is new with
|
|
Postfix version 2.8. </p>
|
|
|
|
<li> <p> Read the new configuration with "<tt>postfix reload</tt>".
|
|
</p>
|
|
|
|
</ol>
|
|
|
|
<p> Notes: </p>
|
|
|
|
<ul>
|
|
|
|
<li> <p> Some postscreen(8) configuration parameters implement
|
|
stress-dependent behavior. This is supported only when the default
|
|
value is stress-dependent (that is, "postconf -d <i>parametername</i>"
|
|
output shows
|
|
"<i>parametername</i> = ${stress?<i>something</i>}${stress:<i>something</i>}" or
|
|
"<i>parametername</i> = ${stress?{<i>something</i>}:{<i>something</i>}}").
|
|
Other parameters always evaluate as if the stress value is the empty
|
|
string. </p>
|
|
|
|
<li> <p> See "<a href="#before_220">Tests before the 220 SMTP server
|
|
greeting</a>" for details about the logging from these
|
|
postscreen(8) tests. </p>
|
|
|
|
<li> <p> If you run Postfix 2.6 or earlier you must stop and start
|
|
the master daemon ("<tt>postfix stop; postfix start</tt>"). This
|
|
is needed because the Postfix "pass" master service type did not
|
|
work reliably on all systems. </p>
|
|
|
|
</ul>
|
|
|
|
<h3> <a name="starttls"> postscreen(8) TLS configuration </a> </h3>
|
|
|
|
<p> postscreen(8) TLS support is available for remote SMTP clients
|
|
that aren't allowlisted, including clients that need to renew their
|
|
temporary allowlist status. When a remote SMTP client requests TLS
|
|
service, postscreen(8) invisibly hands off the connection to a
|
|
tlsproxy(8) process. Then, tlsproxy(8) encrypts and decrypts the
|
|
traffic between postscreen(8) and the remote SMTP client. One
|
|
tlsproxy(8) process can handle multiple SMTP sessions. The number
|
|
of tlsproxy(8) processes slowly increases with server load, but it
|
|
should always be much smaller than the number of postscreen(8) TLS
|
|
sessions. </p>
|
|
|
|
<p> TLS support for postscreen(8) and tlsproxy(8) uses the same
|
|
parameters as with smtpd(8). We recommend that you keep the relevant
|
|
configuration parameters in main.cf. If you must specify "-o
|
|
smtpd_mumble=value" parameter overrides in master.cf for a
|
|
postscreen-protected smtpd(8) service, then you should specify those
|
|
same parameter overrides for the postscreen(8) and tlsproxy(8)
|
|
services. </p>
|
|
|
|
<h3> <a name="blocking"> Blocking mail with postscreen(8) </a> </h3>
|
|
|
|
<p> For compatibility with smtpd(8), postscreen(8) implements the
|
|
soft_bounce safety feature. This causes Postfix to reject mail with
|
|
a "try again" reply code. </p>
|
|
|
|
<ul>
|
|
|
|
<li> <p> To turn this on for all of Postfix, specify "<tt>soft_bounce
|
|
= yes</tt>" in main.cf. </p>
|
|
|
|
<li> <p> To turn this on for postscreen(8) only, append "<tt>-o
|
|
soft_bounce=yes</tt>" (note: NO SPACES around '=') to the postscreen
|
|
entry in master.cf. <p>
|
|
|
|
</ul>
|
|
|
|
<p> Execute "<tt>postfix reload</tt>" to make the change effective. </p>
|
|
|
|
<p> After testing, do not forget to remove the soft_bounce feature,
|
|
otherwise senders won't receive their non-delivery notification
|
|
until many days later. </p>
|
|
|
|
<p> To use the postscreen(8) service to block mail, edit main.cf and
|
|
specify one or more of: </p>
|
|
|
|
<ul>
|
|
|
|
<li> <p> "<tt>postscreen_dnsbl_action = enforce</tt>", to reject
|
|
clients that are on DNS blocklists, and to log the helo/sender/recipient
|
|
information. With good DNSBLs this reduces the amount of load on
|
|
Postfix SMTP servers dramatically. </p>
|
|
|
|
<li> <p> "<tt>postscreen_greet_action = enforce</tt>", to reject
|
|
clients that talk before 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 server. It is backup protection for
|
|
zombies that haven't yet been denylisted. </p>
|
|
|
|
<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. </p>
|
|
|
|
<p> When a good client passes the "<a href="#after_220">deep
|
|
protocol tests</a>",
|
|
postscreen(8) adds the client to the temporary
|
|
allowlist but it cannot hand off the "live" connection to a Postfix
|
|
SMTP server process in the middle of the session. Instead, postscreen(8)
|
|
defers mail delivery attempts with a 4XX status, logs the
|
|
helo/sender/recipient information, and waits for the client to
|
|
disconnect. </p>
|
|
|
|
<p> When the good client comes back in a later session, it is allowed
|
|
to talk directly to a Postfix SMTP server. See "<a href="#after_220">Tests
|
|
after the 220 SMTP server greeting</a>" above for limitations with
|
|
AUTH and other features that clients may need. </p>
|
|
|
|
<p> An unexpected benefit from "<a href="#after_220">deep protocol
|
|
tests</a>" is that some "good" clients don't return after the 4XX
|
|
reply; these clients were not so good after all. </p>
|
|
|
|
<p> Unfortunately, some senders will retry requests from different
|
|
IP addresses, and may never get allowlisted. For this reason,
|
|
Wietse stopped using "<a href="#after_220">deep protocol tests</a>"
|
|
on his own internet-facing mail server. </p>
|
|
|
|
<li> <p> There is also support for permanent denylisting and
|
|
allowlisting; see the description of the postscreen_access_list
|
|
parameter for details. </p>
|
|
|
|
</ul>
|
|
|
|
<h3> <a name="turnoff"> Turning off postscreen(8) </a> </h3>
|
|
|
|
<p> To turn off postscreen(8) and handle mail directly with Postfix
|
|
SMTP server processes: </p>
|
|
|
|
<ol>
|
|
|
|
<li> <p> Comment out the "<tt>smtp inet ... postscreen</tt>" service
|
|
in master.cf, including any "<tt>-o parameter=value</tt>" entries
|
|
that follow. </p>
|
|
|
|
<pre>
|
|
/etc/postfix/master.cf:
|
|
#smtp inet n - n - 1 postscreen
|
|
# -o parameter=value ...
|
|
</pre>
|
|
|
|
<li> <p> Comment out the "<tt>dnsblog unix ... dnsblog</tt>" service
|
|
in master.cf. </p>
|
|
|
|
<pre>
|
|
/etc/postfix/master.cf:
|
|
#dnsblog unix - - n - 0 dnsblog
|
|
</pre>
|
|
|
|
<li> <p> Comment out the "<tt>smtpd pass ... smtpd</tt>" service
|
|
in master.cf, including any "<tt>-o parameter=value</tt>" entries
|
|
that follow. </p>
|
|
|
|
<pre>
|
|
/etc/postfix/master.cf:
|
|
#smtpd pass - - n - - smtpd
|
|
# -o parameter=value ...
|
|
</pre>
|
|
|
|
<li> <p> Comment out the "<tt>tlsproxy unix ... tlsproxy</tt>"
|
|
service in master.cf, including any "<tt>-o parameter=value</tt>"
|
|
entries that follow. </p>
|
|
|
|
<pre>
|
|
/etc/postfix/master.cf:
|
|
#tlsproxy unix - - n - 0 tlsproxy
|
|
# -o parameter=value ...
|
|
</pre>
|
|
|
|
<li> <p> Uncomment the "<tt>smtp inet ... smtpd</tt>" service in
|
|
master.cf, including any "<tt>-o parameter=value</tt>" entries that
|
|
may follow. </p>
|
|
|
|
<pre>
|
|
/etc/postfix/master.cf:
|
|
smtp inet n - n - - smtpd
|
|
-o parameter=value ...
|
|
</pre>
|
|
|
|
<li> <p> Read the new configuration with "<tt>postfix reload</tt>".
|
|
</p>
|
|
|
|
</ol>
|
|
|
|
<h3> <a name="temp_allow_sharing"> Sharing the temporary allowlist </a> </h3>
|
|
|
|
<p> By default, the temporary allowlist is not shared between
|
|
multiple postscreen(8) daemons. To enable sharing, choose one
|
|
of the following options: </p>
|
|
|
|
<ul>
|
|
|
|
<li> <p> A non-persistent memcache: temporary allowlist can be shared
|
|
between postscreen(8) daemons on the same host or different
|
|
hosts. Disable cache cleanup (postscreen_cache_cleanup_interval
|
|
= 0) in all postscreen(8) daemons because memcache: has no
|
|
first-next API (but see example 4 below for memcache: with
|
|
persistent backup). This requires Postfix 2.9 or later. </p>
|
|
|
|
<pre>
|
|
# Example 1: non-persistent memcache: allowlist.
|
|
/etc/postfix/main.cf:
|
|
postscreen_cache_map = memcache:/etc/postfix/postscreen_cache
|
|
postscreen_cache_cleanup_interval = 0
|
|
|
|
/etc/postfix/postscreen_cache:
|
|
memcache = inet:127.0.0.1:11211
|
|
key_format = postscreen:%s
|
|
</pre>
|
|
|
|
<li> <p>
|
|
A persistent lmdb: temporary allowlist can be shared between
|
|
postscreen(8) daemons that run under the same master(8) daemon,
|
|
or under different master(8) daemons on the same host. Disable
|
|
cache cleanup (postscreen_cache_cleanup_interval = 0) in all
|
|
postscreen(8) daemons except one that is responsible for cache
|
|
cleanup. This requires Postfix 2.11 or later. </p>
|
|
|
|
<pre>
|
|
# Example 2: persistent lmdb: allowlist.
|
|
/etc/postfix/main.cf:
|
|
postscreen_cache_map = lmdb:$data_directory/postscreen_cache
|
|
# See note 1 below.
|
|
# postscreen_cache_cleanup_interval = 0
|
|
</pre>
|
|
|
|
<li> <p> Other kinds of persistent temporary allowlist can be shared
|
|
only between postscreen(8) daemons that run under the same
|
|
master(8) daemon. In this case, temporary allowlist access must
|
|
be shared through the proxymap(8) daemon. This requires Postfix
|
|
2.9 or later. </p>
|
|
|
|
<pre>
|
|
# Example 3: proxied btree: allowlist.
|
|
/etc/postfix/main.cf:
|
|
postscreen_cache_map =
|
|
proxy:btree:/var/lib/postfix/postscreen_cache
|
|
# See note 1 below.
|
|
# postscreen_cache_cleanup_interval = 0
|
|
|
|
# Example 4: proxied btree: allowlist with memcache: accelerator.
|
|
/etc/postfix/main.cf:
|
|
postscreen_cache_map = memcache:/etc/postfix/postscreen_cache
|
|
proxy_write_maps =
|
|
proxy:btree:/var/lib/postfix/postscreen_cache
|
|
... other proxied tables ...
|
|
# See note 1 below.
|
|
# postscreen_cache_cleanup_interval = 0
|
|
|
|
/etc/postfix/postscreen_cache:
|
|
# Note: the $data_directory macro is not defined in this context.
|
|
memcache = inet:127.0.0.1:11211
|
|
backup = proxy:btree:/var/lib/postfix/postscreen_cache
|
|
key_format = postscreen:%s
|
|
</pre>
|
|
|
|
<p> Note 1: disable cache cleanup (postscreen_cache_cleanup_interval
|
|
= 0) in all postscreen(8) daemons except one that is responsible
|
|
for cache cleanup. </p>
|
|
|
|
<p> Note 2: postscreen(8) cache sharing via proxymap(8) requires Postfix
|
|
2.9 or later; earlier proxymap(8) implementations don't support
|
|
cache cleanup. </p>
|
|
|
|
</ul>
|
|
|
|
<h2> <a name="historical"> Historical notes and credits </a> </h2>
|
|
|
|
<p> Many ideas in postscreen(8) were explored in earlier work by
|
|
Michael Tokarev, in OpenBSD spamd, and in MailChannels Traffic
|
|
Control. </p>
|
|
|
|
<p> Wietse threw together a crude prototype with pregreet and dnsbl
|
|
support in June 2009, because he needed something new for a Mailserver
|
|
conference presentation in July. Ralf Hildebrandt ran this code on
|
|
several servers to collect real-world statistics. This version used
|
|
the dnsblog(8) ad-hoc DNS client program. </p>
|
|
|
|
<p> Wietse needed new material for a LISA conference presentation
|
|
in November 2010, so he added support for DNSBL weights and filters
|
|
in August, followed by a major code rewrite, deep protocol tests,
|
|
helo/sender/recipient logging, and stress-adaptive behavior in
|
|
September. Ralf Hildebrandt ran this code on several servers to
|
|
collect real-world statistics. This version still used the embarrassing
|
|
dnsblog(8) ad-hoc DNS client program. </p>
|
|
|
|
<p> Wietse added STARTTLS support in December 2010. This makes
|
|
postscreen(8) usable for sites that require TLS support. The
|
|
implementation introduces the tlsproxy(8) event-driven TLS proxy
|
|
that decrypts/encrypts the sessions for multiple SMTP clients. </p>
|
|
|
|
<p> The tlsproxy(8) implementation led to the discovery of a "new"
|
|
class of vulnerability (<a
|
|
href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-0411"
|
|
>CVE-2011-0411</a>) that affected multiple implementations of SMTP,
|
|
POP, IMAP, NNTP, and FTP over TLS. </p>
|
|
|
|
<p> postscreen(8) was officially released as part of the Postfix
|
|
2.8 stable release in January 2011.</p>
|
|
|
|
<p> Noel Jones helped with the Postfix 3.6 transition towards respectful
|
|
documentation. </p>
|
|
|
|
</body>
|
|
</html>
|