mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-30 13:48:06 +00:00
postfix-2.3-20051010
This commit is contained in:
parent
14313fe35c
commit
88a2e39fc7
2
postfix/.indent.pro
vendored
2
postfix/.indent.pro
vendored
@ -3,7 +3,9 @@
|
|||||||
-TALIAS_TOKEN
|
-TALIAS_TOKEN
|
||||||
-TANVIL_CLNT
|
-TANVIL_CLNT
|
||||||
-TANVIL_LOCAL
|
-TANVIL_LOCAL
|
||||||
|
-TANVIL_MAX
|
||||||
-TANVIL_REMOTE
|
-TANVIL_REMOTE
|
||||||
|
-TANVIL_REQ_TABLE
|
||||||
-TARGV
|
-TARGV
|
||||||
-TATTR_CLNT
|
-TATTR_CLNT
|
||||||
-TATTR_TABLE
|
-TATTR_TABLE
|
||||||
|
@ -11148,19 +11148,47 @@ Apologies for any names omitted.
|
|||||||
others. Files: local/local.c, local/aliases.c, local/dotforward.c,
|
others. Files: local/local.c, local/aliases.c, local/dotforward.c,
|
||||||
local/mailbox.c, local/maildir.c.
|
local/mailbox.c, local/maildir.c.
|
||||||
|
|
||||||
Cleanup: while expanding a local(8) alias that has an owner
|
|
||||||
alias, don't reset the owner-alias information when recursing
|
|
||||||
into an alias that has no owner alias. This produces better
|
|
||||||
error reports when delivering mail to nested aliases that
|
|
||||||
have an owner alias only at the top level. To get the old
|
|
||||||
behavior, specify "sticky_owner_alias = no". Problem
|
|
||||||
reported by Victor Duchovni. File: local/alias.c.
|
|
||||||
|
|
||||||
Logging: additional SASL debug logging by Andreas Winkelmann.
|
Logging: additional SASL debug logging by Andreas Winkelmann.
|
||||||
Files: */*sasl_glue.c.
|
Files: */*sasl_glue.c.
|
||||||
|
|
||||||
|
20050929
|
||||||
|
|
||||||
|
Paranoia: don't ignore garbage in SMTP or LMTP server replies
|
||||||
|
when ESMTP command pipelining is turned on. For example,
|
||||||
|
after sending ".<CR><LF>QUIT<CR><LF>", Postfix could recognize
|
||||||
|
the server's 2XX QUIT reply as a 2XX END-OF-DATA reply after
|
||||||
|
garbage, causing mail to be lost. The SMTP and LMTP clients
|
||||||
|
now report a remote protocol error and defer delivery.
|
||||||
|
Files: smtp/smtp_chat.c, smtp/smtp_trouble.c, lmtp/lmtp_chat.c,
|
||||||
|
lmtp/lmtp_trouble.c.
|
||||||
|
|
||||||
|
Performance: specify "smtpd_peername_lookup = no" to disable
|
||||||
|
client hostname lookups in the SMTP server. All clients are
|
||||||
|
treated as "unknown". This should be used only under extreme
|
||||||
|
conditions where DNS lookup latencies are critical. File:
|
||||||
|
smtpd/smtpd_peer.c.
|
||||||
|
|
||||||
|
20051010
|
||||||
|
|
||||||
|
Feature: smtpd_client_new_tls_session_rate_limit parameter
|
||||||
|
to limit the number of new (i.e. uncached) TLS sessions
|
||||||
|
that a remote SMTP client may negotiate per unit time. This
|
||||||
|
feature, which is off by default, can limit the CPU load
|
||||||
|
due to expensive crypto operations. Files: global/anvil_clnt.c,
|
||||||
|
anvil/anvil.c, smtpd/smtpd.c.
|
||||||
|
|
||||||
|
Cleanup: eliminated code duplicatiom in the anvil server
|
||||||
|
that resulted from adding similar features one at a time.
|
||||||
|
File: anvil/anvil.c.
|
||||||
|
|
||||||
Open problems:
|
Open problems:
|
||||||
|
|
||||||
|
Try to recognize that Resent- headers appear in blocks,
|
||||||
|
newest block first. But don't break on incorrect header
|
||||||
|
block organization.
|
||||||
|
|
||||||
|
Hard limits on cache sizes (anvil, specifically).
|
||||||
|
|
||||||
Look for systems with XPG basename() declared in <libgen.h>,
|
Look for systems with XPG basename() declared in <libgen.h>,
|
||||||
and prepare for phasing out the Postfix-supplied one.
|
and prepare for phasing out the Postfix-supplied one.
|
||||||
Beware, however, that XPG basename() takes (char *), and
|
Beware, however, that XPG basename() takes (char *), and
|
||||||
|
@ -17,7 +17,8 @@ Postfix source code, in the directory examples/smtpd-policy.
|
|||||||
Policy delegation is now the preferred method for adding policies to Postfix.
|
Policy delegation is now the preferred method for adding policies to Postfix.
|
||||||
It's much easier to develop a new feature in few lines of Perl, than trying to
|
It's much easier to develop a new feature in few lines of Perl, than trying to
|
||||||
do the same in C code. The difference in performance will be unnoticeable
|
do the same in C code. The difference in performance will be unnoticeable
|
||||||
except in the most demanding environments.
|
except in the most demanding environments. On active systems a policy daemon
|
||||||
|
process is used multiple times, for up to 100 incoming SMTP connections.
|
||||||
|
|
||||||
This document covers the following topics:
|
This document covers the following topics:
|
||||||
|
|
||||||
|
@ -26,12 +26,9 @@ files. With deeply nested aliases or .forward files, this can greatly
|
|||||||
reduce the number of queue files and cleanup process instances. To
|
reduce the number of queue files and cleanup process instances. To
|
||||||
get the earlier behavior, specify "frozen_delivered_to = no".
|
get the earlier behavior, specify "frozen_delivered_to = no".
|
||||||
|
|
||||||
While expanding an alias that has an owner alias, the Postfix
|
The frozen_delivered_to feature also fixes an old problem with
|
||||||
local(8) delivery agent no longer resets the owner information when
|
duplicate deliveries to recipients that are listed in multiple
|
||||||
it expands a subordinate alias that has no owner alias. This
|
nested aliases.
|
||||||
produces better error reporting with nested aliases that have an
|
|
||||||
owner alias only at the top level. To get the earlier behavior,
|
|
||||||
specify "sticky_owner_alias = no".
|
|
||||||
|
|
||||||
Incompatibility with snapshot 20050828
|
Incompatibility with snapshot 20050828
|
||||||
======================================
|
======================================
|
||||||
|
@ -36,7 +36,8 @@ the Postfix source code, in the directory examples/smtpd-policy.
|
|||||||
to Postfix. It's much easier to develop a new feature in few lines
|
to Postfix. It's much easier to develop a new feature in few lines
|
||||||
of Perl, than trying to do the same in C code. The difference in
|
of Perl, than trying to do the same in C code. The difference in
|
||||||
performance will be unnoticeable except in the most demanding
|
performance will be unnoticeable except in the most demanding
|
||||||
environments. </p>
|
environments. On active systems a policy daemon process is used
|
||||||
|
multiple times, for up to 100 incoming SMTP connections. </p>
|
||||||
|
|
||||||
<p> This document covers the following topics: </p>
|
<p> This document covers the following topics: </p>
|
||||||
|
|
||||||
|
@ -13,107 +13,115 @@ ANVIL(8) ANVIL(8)
|
|||||||
<b>anvil</b> [generic Postfix daemon options]
|
<b>anvil</b> [generic Postfix daemon options]
|
||||||
|
|
||||||
<b>DESCRIPTION</b>
|
<b>DESCRIPTION</b>
|
||||||
The Postfix <a href="anvil.8.html"><b>anvil</b>(8)</a> server maintains short-term statis-
|
The Postfix <a href="anvil.8.html"><b>anvil</b>(8)</a> server maintains statistics about
|
||||||
tics to defend against clients that hammer a server with
|
client connection counts or client request rates. This
|
||||||
either too many simultaneous sessions, or with too many
|
information can be used to defend against clients that
|
||||||
successive requests within a configurable time interval.
|
hammer a server with either too many simultaneous ses-
|
||||||
This server is designed to run under control by the Post-
|
sions, or with too many successive requests within a con-
|
||||||
fix <a href="master.8.html"><b>master</b>(8)</a> server.
|
figurable time interval. This server is designed to run
|
||||||
|
under control by the Postfix <a href="master.8.html"><b>master</b>(8)</a> server.
|
||||||
|
|
||||||
The <a href="anvil.8.html"><b>anvil</b>(8)</a> server maintains no persistent database.
|
In the following text, <b>ident</b> specifies a (service, client)
|
||||||
Standard library utilities do not meet Postfix performance
|
combination. The exact syntax of that information is
|
||||||
and robustness requirements.
|
application-dependent; the <a href="anvil.8.html"><b>anvil</b>(8)</a> server does not care.
|
||||||
|
|
||||||
<b>CONNECTION COUNT/RATE LIMITING</b>
|
<b>CONNECTION COUNT/RATE CONTROL</b>
|
||||||
When a remote client connects, a connection count (or
|
To register a new connection send the following request to
|
||||||
rate) limited server should send the following request to
|
|
||||||
the <a href="anvil.8.html"><b>anvil</b>(8)</a> server:
|
the <a href="anvil.8.html"><b>anvil</b>(8)</a> server:
|
||||||
|
|
||||||
<b>request=connect</b>
|
<b>request=connect</b>
|
||||||
<b>ident=</b><i>string</i>
|
<b>ident=</b><i>string</i>
|
||||||
|
|
||||||
This registers a new connection for the (service, client)
|
The <a href="anvil.8.html"><b>anvil</b>(8)</a> server answers with the number of simultane-
|
||||||
combination specified with <b>ident</b>. The <a href="anvil.8.html"><b>anvil</b>(8)</a> server
|
ous connections and the number of connections per unit
|
||||||
answers with the number of simultaneous connections and
|
time for the (service, client) combination specified with
|
||||||
the number of connections per unit time for that (service,
|
<b>ident</b>:
|
||||||
client) combination:
|
|
||||||
|
|
||||||
<b>status=0</b>
|
<b>status=0</b>
|
||||||
<b>count=</b><i>number</i>
|
<b>count=</b><i>number</i>
|
||||||
<b>rate=</b><i>number</i>
|
<b>rate=</b><i>number</i>
|
||||||
|
|
||||||
The <b>rate</b> is computed as the number of connections that
|
To register a disconnect event send the following request
|
||||||
were registered in the current "time unit" interval. It
|
to the <a href="anvil.8.html"><b>anvil</b>(8)</a> server:
|
||||||
is left up to the server to decide if the remote client
|
|
||||||
exceeds the connection count (or rate) limit.
|
|
||||||
|
|
||||||
When a remote client disconnects, a connection count (or
|
|
||||||
rate) limited server should send the following request to
|
|
||||||
the <a href="anvil.8.html"><b>anvil</b>(8)</a> server:
|
|
||||||
|
|
||||||
<b>request=disconnect</b>
|
<b>request=disconnect</b>
|
||||||
<b>ident=</b><i>string</i>
|
<b>ident=</b><i>string</i>
|
||||||
|
|
||||||
This registers a disconnect event for the (service,
|
The <a href="anvil.8.html"><b>anvil</b>(8)</a> server replies with:
|
||||||
client) combination specified with <b>ident</b>. The <a href="anvil.8.html"><b>anvil</b>(8)</a>
|
|
||||||
server replies with:
|
|
||||||
|
|
||||||
<b>status=0</b>
|
<b>status=0</b>
|
||||||
|
|
||||||
<b>MESSAGE RATE LIMITING</b>
|
<b>MESSAGE RATE CONTROL</b>
|
||||||
When a remote client sends a message delivery request, a
|
To register a message delivery request send the following
|
||||||
message rate limited server should send the following
|
|
||||||
request to the <a href="anvil.8.html"><b>anvil</b>(8)</a> server:
|
request to the <a href="anvil.8.html"><b>anvil</b>(8)</a> server:
|
||||||
|
|
||||||
<b>request=message</b>
|
<b>request=message</b>
|
||||||
<b>ident=</b><i>string</i>
|
<b>ident=</b><i>string</i>
|
||||||
|
|
||||||
This registers a message delivery request for the (ser-
|
The <a href="anvil.8.html"><b>anvil</b>(8)</a> server answers with the number of message
|
||||||
vice, client) combination specified with <b>ident</b>. The
|
delivery requests per unit time for the (service, client)
|
||||||
<a href="anvil.8.html"><b>anvil</b>(8)</a> server answers with the number of message deliv-
|
combination specified with <b>ident</b>:
|
||||||
ery requests per unit time for that (service, client) com-
|
|
||||||
bination:
|
|
||||||
|
|
||||||
<b>status=0</b>
|
<b>status=0</b>
|
||||||
<b>rate=</b><i>number</i>
|
<b>rate=</b><i>number</i>
|
||||||
|
|
||||||
In order to prevent the <a href="anvil.8.html"><b>anvil</b>(8)</a> server from discarding
|
<b>RECIPIENT RATE CONTROL</b>
|
||||||
client request rates too early or too late, a message rate
|
To register a recipient request send the following request
|
||||||
limited service should also register connect/disconnect
|
|
||||||
events.
|
|
||||||
|
|
||||||
<b>RECIPIENT RATE LIMITING</b>
|
|
||||||
When a remote client sends a recipient address, a recipi-
|
|
||||||
ent rate limited server should send the following request
|
|
||||||
to the <a href="anvil.8.html"><b>anvil</b>(8)</a> server:
|
to the <a href="anvil.8.html"><b>anvil</b>(8)</a> server:
|
||||||
|
|
||||||
<b>request=recipient</b>
|
<b>request=recipient</b>
|
||||||
<b>ident=</b><i>string</i>
|
<b>ident=</b><i>string</i>
|
||||||
|
|
||||||
This registers a recipient request for the (service,
|
The <a href="anvil.8.html"><b>anvil</b>(8)</a> server answers with the number of recipient
|
||||||
client) combination specified with <b>ident</b>. The <a href="anvil.8.html"><b>anvil</b>(8)</a>
|
addresses per unit time for the (service, client) combina-
|
||||||
server answers with the number of recipient addresses per
|
tion specified with <b>ident</b>:
|
||||||
unit time for that (service, client) combination:
|
|
||||||
|
|
||||||
<b>status=0</b>
|
<b>status=0</b>
|
||||||
<b>rate=</b><i>number</i>
|
<b>rate=</b><i>number</i>
|
||||||
|
|
||||||
In order to prevent the <a href="anvil.8.html"><b>anvil</b>(8)</a> server from discarding
|
<b>TLS SESSION NEGOTIATION RATE CONTROL</b>
|
||||||
client request rates too early or too late, a recipient
|
The features described in this section are available with
|
||||||
rate limited service should also register connect/discon-
|
Postfix 2.3 and later.
|
||||||
nect events.
|
|
||||||
|
To register a request for a new (i.e. not cached) TLS ses-
|
||||||
|
sion send the following request to the <a href="anvil.8.html"><b>anvil</b>(8)</a> server:
|
||||||
|
|
||||||
|
<b>request=newtls</b>
|
||||||
|
<b>ident=</b><i>string</i>
|
||||||
|
|
||||||
|
The <a href="anvil.8.html"><b>anvil</b>(8)</a> server answers with the number of new TLS
|
||||||
|
session requests per unit time for the (service, client)
|
||||||
|
combination specified with <b>ident</b>:
|
||||||
|
|
||||||
|
<b>status=0</b>
|
||||||
|
<b>rate=</b><i>number</i>
|
||||||
|
|
||||||
|
To retrieve new TLS session request rate information with-
|
||||||
|
out updating the counter information, use:
|
||||||
|
|
||||||
|
<b>request=newtls_report</b>
|
||||||
|
<b>ident=</b><i>string</i>
|
||||||
|
|
||||||
|
The <a href="anvil.8.html"><b>anvil</b>(8)</a> server answers with the number of new TLS
|
||||||
|
session requests per unit time for the (service, client)
|
||||||
|
combination specified with <b>ident</b>.
|
||||||
|
|
||||||
|
<b>status=0</b>
|
||||||
|
<b>rate=</b><i>number</i>
|
||||||
|
|
||||||
<b>SECURITY</b>
|
<b>SECURITY</b>
|
||||||
The <a href="anvil.8.html"><b>anvil</b>(8)</a> server does not talk to the network or to
|
The <a href="anvil.8.html"><b>anvil</b>(8)</a> server does not talk to the network or to
|
||||||
local users, and can run chrooted at fixed low privilege.
|
local users, and can run chrooted at fixed low privilege.
|
||||||
|
|
||||||
The <a href="anvil.8.html"><b>anvil</b>(8)</a> server maintains an in-memory table with
|
The <a href="anvil.8.html"><b>anvil</b>(8)</a> server maintains an in-memory table with
|
||||||
information about recent clients of a connection count (or
|
information about recent clients requests. No persistent
|
||||||
rate) limited service. Although state is kept only tempo-
|
state is kept because standard system library routines are
|
||||||
rarily, this may require a lot of memory on systems that
|
not sufficiently robust for update-intensive applications.
|
||||||
handle connections from many remote clients. To reduce
|
|
||||||
memory usage, reduce the time unit over which state is
|
Although the in-memory state is kept only temporarily,
|
||||||
kept.
|
this may require a lot of memory on systems that handle
|
||||||
|
connections from many remote clients. To reduce memory
|
||||||
|
usage, reduce the time unit over which state is kept.
|
||||||
|
|
||||||
<b>DIAGNOSTICS</b>
|
<b>DIAGNOSTICS</b>
|
||||||
Problems and transactions are logged to <b>syslogd</b>(8).
|
Problems and transactions are logged to <b>syslogd</b>(8).
|
||||||
@ -135,10 +143,18 @@ ANVIL(8) ANVIL(8)
|
|||||||
a server reports multiple simultaneous clients, all but
|
a server reports multiple simultaneous clients, all but
|
||||||
the last reported client are ignored.
|
the last reported client are ignored.
|
||||||
|
|
||||||
|
The <a href="anvil.8.html"><b>anvil</b>(8)</a> server automatically discards client request
|
||||||
|
information after it expires. To prevent the <a href="anvil.8.html"><b>anvil</b>(8)</a>
|
||||||
|
server from discarding client request rate information too
|
||||||
|
early or too late, a rate limited service should always
|
||||||
|
register connect/disconnect events even when it does not
|
||||||
|
explicitly limit them.
|
||||||
|
|
||||||
<b>CONFIGURATION PARAMETERS</b>
|
<b>CONFIGURATION PARAMETERS</b>
|
||||||
Changes to <b>main.cf</b> are picked up automatically as <a href="anvil.8.html"><b>anvil</b>(8)</a>
|
On low-traffic mail systems, changes to <b>main.cf</b> are picked
|
||||||
processes run for only a limited amount of time. Use the
|
up automatically as <a href="anvil.8.html"><b>anvil</b>(8)</a> processes run for only a lim-
|
||||||
command "<b>postfix reload</b>" to speed up a change.
|
ited amount of time. On other mail systems, use the com-
|
||||||
|
mand "<b>postfix reload</b>" to speed up a 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.
|
<a href="postconf.5.html"><b>postconf</b>(5)</a> for more details including examples.
|
||||||
|
@ -386,13 +386,6 @@ LOCAL(8) LOCAL(8)
|
|||||||
attempt; do not update the Delivered-To: address
|
attempt; do not update the Delivered-To: address
|
||||||
while expanding aliases or .forward files.
|
while expanding aliases or .forward files.
|
||||||
|
|
||||||
<b><a href="postconf.5.html#sticky_owner_alias">sticky_owner_alias</a> (yes)</b>
|
|
||||||
When expanding a <a href="local.8.html"><b>local</b>(8)</a> alias that has an owner
|
|
||||||
alias (see owner-<i>name</i> discussion in <a href="aliases.5.html"><b>aliases</b>(5)</a>),
|
|
||||||
use the owner information even when the expansion
|
|
||||||
invokes a subordinate alias that has no owner
|
|
||||||
alias.
|
|
||||||
|
|
||||||
<b>DELIVERY METHOD CONTROLS</b>
|
<b>DELIVERY METHOD CONTROLS</b>
|
||||||
The precedence of <a href="local.8.html"><b>local</b>(8)</a> delivery methods from high to
|
The precedence of <a href="local.8.html"><b>local</b>(8)</a> delivery methods from high to
|
||||||
low is: aliases, .forward files, <a href="postconf.5.html#mailbox_transport">mailbox_transport</a>, <a href="postconf.5.html#mailbox_command_maps">mail</a>-
|
low is: aliases, .forward files, <a href="postconf.5.html#mailbox_transport">mailbox_transport</a>, <a href="postconf.5.html#mailbox_command_maps">mail</a>-
|
||||||
|
@ -7205,6 +7205,47 @@ Example:
|
|||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
||||||
|
</DD>
|
||||||
|
|
||||||
|
<DT><b><a name="smtpd_client_new_tls_session_rate_limit">smtpd_client_new_tls_session_rate_limit</a>
|
||||||
|
(default: 0)</b></DT><DD>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The maximal number of new (i.e., uncached) TLS sessions that a
|
||||||
|
remote SMTP client is allowed to negotiate with this service per
|
||||||
|
time unit. The time unit is specified with the <a href="postconf.5.html#anvil_rate_time_unit">anvil_rate_time_unit</a>
|
||||||
|
configuration parameter.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
By default, a remote SMTP client can negotiate as many new TLS
|
||||||
|
sessions per time unit as Postfix can accept.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
To disable this feature, specify a limit of 0. Otherwise, specify
|
||||||
|
a limit that is at least the per-client concurrent session limit,
|
||||||
|
or else legitimate client sessions may be rejected.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
WARNING: The purpose of this feature is to limit abuse. It must
|
||||||
|
not be used to regulate legitimate mail traffic.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This feature is available in Postfix 2.3 and later.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Example:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
<a href="postconf.5.html#smtpd_client_new_tls_session_rate_limit">smtpd_client_new_tls_session_rate_limit</a> = 100
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
|
||||||
</DD>
|
</DD>
|
||||||
|
|
||||||
<DT><b><a name="smtpd_client_recipient_rate_limit">smtpd_client_recipient_rate_limit</a>
|
<DT><b><a name="smtpd_client_recipient_rate_limit">smtpd_client_recipient_rate_limit</a>
|
||||||
@ -7924,6 +7965,18 @@ null sender address.
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
</DD>
|
||||||
|
|
||||||
|
<DT><b><a name="smtpd_peername_lookup">smtpd_peername_lookup</a>
|
||||||
|
(default: yes)</b></DT><DD>
|
||||||
|
|
||||||
|
<p> Attempt to look up the SMTP client hostname, and verify that
|
||||||
|
the name matches the client IP address. A client name is set to
|
||||||
|
"unknown" when it cannot be looked up or verified, or when name
|
||||||
|
lookup is disabled. Turning off name lookup reduces delays due to
|
||||||
|
DNS lookup and increases the maximal inbound delivery rate. </p>
|
||||||
|
|
||||||
|
|
||||||
</DD>
|
</DD>
|
||||||
|
|
||||||
<DT><b><a name="smtpd_policy_service_max_idle">smtpd_policy_service_max_idle</a>
|
<DT><b><a name="smtpd_policy_service_max_idle">smtpd_policy_service_max_idle</a>
|
||||||
@ -9149,22 +9202,6 @@ The default time unit is s (seconds).
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
</DD>
|
|
||||||
|
|
||||||
<DT><b><a name="sticky_owner_alias">sticky_owner_alias</a>
|
|
||||||
(default: yes)</b></DT><DD>
|
|
||||||
|
|
||||||
<p> When expanding a <a href="local.8.html">local(8)</a> alias that has an owner alias (see
|
|
||||||
owner-<i>name</i> discussion in <a href="aliases.5.html">aliases(5)</a>), use the owner information
|
|
||||||
even when the expansion invokes a subordinate alias that has no
|
|
||||||
owner alias. </p>
|
|
||||||
|
|
||||||
<p> This feature is available in Postfix 2.3 and later. With older
|
|
||||||
Postfix releases, the behavior is as if this parameter is set to
|
|
||||||
"no". The old setting provides poorer error reporting with nested
|
|
||||||
aliases that only have an owner alias at the top level. </p>
|
|
||||||
|
|
||||||
|
|
||||||
</DD>
|
</DD>
|
||||||
|
|
||||||
<DT><b><a name="strict_7bit_headers">strict_7bit_headers</a>
|
<DT><b><a name="strict_7bit_headers">strict_7bit_headers</a>
|
||||||
|
@ -548,6 +548,12 @@ SMTPD(8) SMTPD(8)
|
|||||||
server command history before it is flushed upon
|
server command history before it is flushed upon
|
||||||
receipt of EHLO, RSET, or end of DATA.
|
receipt of EHLO, RSET, or end of DATA.
|
||||||
|
|
||||||
|
Available in Postfix version 2.3 and later:
|
||||||
|
|
||||||
|
<b><a href="postconf.5.html#smtpd_peername_lookup">smtpd_peername_lookup</a> (yes)</b>
|
||||||
|
Attempt to look up the SMTP client hostname, and
|
||||||
|
verify that the name matches the client IP address.
|
||||||
|
|
||||||
The per SMTP client connection count and request rate lim-
|
The per SMTP client connection count and request rate lim-
|
||||||
its are implemented in co-operation with the <a href="anvil.8.html"><b>anvil</b>(8)</a> ser-
|
its are implemented in co-operation with the <a href="anvil.8.html"><b>anvil</b>(8)</a> ser-
|
||||||
vice, and are available in Postfix version 2.2 and later.
|
vice, and are available in Postfix version 2.2 and later.
|
||||||
@ -577,6 +583,13 @@ SMTPD(8) SMTPD(8)
|
|||||||
Clients that are excluded from connection count,
|
Clients that are excluded from connection count,
|
||||||
connection rate, or SMTP request rate restrictions.
|
connection rate, or SMTP request rate restrictions.
|
||||||
|
|
||||||
|
Available in Postfix version 2.3 and later:
|
||||||
|
|
||||||
|
<b><a href="postconf.5.html#smtpd_client_new_tls_session_rate_limit">smtpd_client_new_tls_session_rate_limit</a> (0)</b>
|
||||||
|
The maximal number of new (i.e., uncached) TLS ses-
|
||||||
|
sions that any client is allowed to negotiate with
|
||||||
|
this service per time unit.
|
||||||
|
|
||||||
<b>TARPIT CONTROLS</b>
|
<b>TARPIT CONTROLS</b>
|
||||||
When a remote SMTP client makes errors, the Postfix SMTP
|
When a remote SMTP client makes errors, the Postfix SMTP
|
||||||
server can insert delays before responding. This can help
|
server can insert delays before responding. This can help
|
||||||
|
@ -4070,6 +4070,33 @@ smtpd_client_message_rate_limit = 1000
|
|||||||
.fi
|
.fi
|
||||||
.ad
|
.ad
|
||||||
.ft R
|
.ft R
|
||||||
|
.SH smtpd_client_new_tls_session_rate_limit (default: 0)
|
||||||
|
The maximal number of new (i.e., uncached) TLS sessions that a
|
||||||
|
remote SMTP client is allowed to negotiate with this service per
|
||||||
|
time unit. The time unit is specified with the anvil_rate_time_unit
|
||||||
|
configuration parameter.
|
||||||
|
.PP
|
||||||
|
By default, a remote SMTP client can negotiate as many new TLS
|
||||||
|
sessions per time unit as Postfix can accept.
|
||||||
|
.PP
|
||||||
|
To disable this feature, specify a limit of 0. Otherwise, specify
|
||||||
|
a limit that is at least the per-client concurrent session limit,
|
||||||
|
or else legitimate client sessions may be rejected.
|
||||||
|
.PP
|
||||||
|
WARNING: The purpose of this feature is to limit abuse. It must
|
||||||
|
not be used to regulate legitimate mail traffic.
|
||||||
|
.PP
|
||||||
|
This feature is available in Postfix 2.3 and later.
|
||||||
|
.PP
|
||||||
|
Example:
|
||||||
|
.PP
|
||||||
|
.nf
|
||||||
|
.na
|
||||||
|
.ft C
|
||||||
|
smtpd_client_new_tls_session_rate_limit = 100
|
||||||
|
.fi
|
||||||
|
.ad
|
||||||
|
.ft R
|
||||||
.SH smtpd_client_recipient_rate_limit (default: 0)
|
.SH smtpd_client_recipient_rate_limit (default: 0)
|
||||||
The maximal number of recipient addresses that any client is allowed
|
The maximal number of recipient addresses that any client is allowed
|
||||||
to send to this service per time unit, regardless of whether or not
|
to send to this service per time unit, regardless of whether or not
|
||||||
@ -4540,6 +4567,12 @@ This list overrides any commands built into the Postfix SMTP server.
|
|||||||
.SH smtpd_null_access_lookup_key (default: <>)
|
.SH smtpd_null_access_lookup_key (default: <>)
|
||||||
The lookup key to be used in SMTP \fBaccess\fR(5) tables instead of the
|
The lookup key to be used in SMTP \fBaccess\fR(5) tables instead of the
|
||||||
null sender address.
|
null sender address.
|
||||||
|
.SH smtpd_peername_lookup (default: yes)
|
||||||
|
Attempt to look up the SMTP client hostname, and verify that
|
||||||
|
the name matches the client IP address. A client name is set to
|
||||||
|
"unknown" when it cannot be looked up or verified, or when name
|
||||||
|
lookup is disabled. Turning off name lookup reduces delays due to
|
||||||
|
DNS lookup and increases the maximal inbound delivery rate.
|
||||||
.SH smtpd_policy_service_max_idle (default: 300s)
|
.SH smtpd_policy_service_max_idle (default: 300s)
|
||||||
The time after which an idle SMTPD policy service connection is
|
The time after which an idle SMTPD policy service connection is
|
||||||
closed.
|
closed.
|
||||||
@ -5349,16 +5382,6 @@ This is used for delivery to file or mailbox.
|
|||||||
.PP
|
.PP
|
||||||
Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).
|
Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).
|
||||||
The default time unit is s (seconds).
|
The default time unit is s (seconds).
|
||||||
.SH sticky_owner_alias (default: yes)
|
|
||||||
When expanding a \fBlocal\fR(8) alias that has an owner alias (see
|
|
||||||
owner-\fIname\fR discussion in \fBaliases\fR(5)), use the owner information
|
|
||||||
even when the expansion invokes a subordinate alias that has no
|
|
||||||
owner alias.
|
|
||||||
.PP
|
|
||||||
This feature is available in Postfix 2.3 and later. With older
|
|
||||||
Postfix releases, the behavior is as if this parameter is set to
|
|
||||||
"no". The old setting provides poorer error reporting with nested
|
|
||||||
aliases that only have an owner alias at the top level.
|
|
||||||
.SH strict_7bit_headers (default: no)
|
.SH strict_7bit_headers (default: no)
|
||||||
Reject mail with 8-bit text in message headers. This blocks mail
|
Reject mail with 8-bit text in message headers. This blocks mail
|
||||||
from poorly written applications.
|
from poorly written applications.
|
||||||
|
@ -12,23 +12,25 @@ Postfix session count and request rate control
|
|||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
.ad
|
.ad
|
||||||
.fi
|
.fi
|
||||||
The Postfix \fBanvil\fR(8) server maintains short-term statistics
|
The Postfix \fBanvil\fR(8) server maintains statistics about
|
||||||
to defend against clients that hammer a server with either too
|
client connection counts or client request rates. This
|
||||||
many simultaneous sessions, or with too many successive requests
|
information can be used to defend against clients that
|
||||||
within a configurable time interval.
|
hammer a server with either too many simultaneous sessions,
|
||||||
This server is designed to run under control by the Postfix
|
or with too many successive requests within a configurable
|
||||||
\fBmaster\fR(8) server.
|
time interval. This server is designed to run under control
|
||||||
|
by the Postfix \fBmaster\fR(8) server.
|
||||||
|
|
||||||
The \fBanvil\fR(8) server maintains no persistent database. Standard
|
In the following text, \fBident\fR specifies a (service,
|
||||||
library utilities do not meet Postfix performance and robustness
|
client) combination. The exact syntax of that information
|
||||||
requirements.
|
is application-dependent; the \fBanvil\fR(8) server does
|
||||||
.SH "CONNECTION COUNT/RATE LIMITING"
|
not care.
|
||||||
|
.SH "CONNECTION COUNT/RATE CONTROL"
|
||||||
.na
|
.na
|
||||||
.nf
|
.nf
|
||||||
.ad
|
.ad
|
||||||
.fi
|
.fi
|
||||||
When a remote client connects, a connection count (or rate) limited
|
To register a new connection send the following request to
|
||||||
server should send the following request to the \fBanvil\fR(8) server:
|
the \fBanvil\fR(8) server:
|
||||||
.PP
|
.PP
|
||||||
.in +4
|
.in +4
|
||||||
\fBrequest=connect\fR
|
\fBrequest=connect\fR
|
||||||
@ -36,11 +38,10 @@ server should send the following request to the \fBanvil\fR(8) server:
|
|||||||
\fBident=\fIstring\fR
|
\fBident=\fIstring\fR
|
||||||
.in
|
.in
|
||||||
.PP
|
.PP
|
||||||
This registers a new connection for the (service, client)
|
The \fBanvil\fR(8) server answers with the number of
|
||||||
combination specified with \fBident\fR. The \fBanvil\fR(8) server
|
simultaneous connections and the number of connections per
|
||||||
answers with the number of simultaneous connections and the
|
unit time for the (service, client) combination specified
|
||||||
number of connections per unit time for that (service, client)
|
with \fBident\fR:
|
||||||
combination:
|
|
||||||
.PP
|
.PP
|
||||||
.in +4
|
.in +4
|
||||||
\fBstatus=0\fR
|
\fBstatus=0\fR
|
||||||
@ -50,13 +51,8 @@ combination:
|
|||||||
\fBrate=\fInumber\fR
|
\fBrate=\fInumber\fR
|
||||||
.in
|
.in
|
||||||
.PP
|
.PP
|
||||||
The \fBrate\fR is computed as the number of connections
|
To register a disconnect event send the following request
|
||||||
that were registered in the current "time unit" interval.
|
to the \fBanvil\fR(8) server:
|
||||||
It is left up to the server to decide if the remote client
|
|
||||||
exceeds the connection count (or rate) limit.
|
|
||||||
.PP
|
|
||||||
When a remote client disconnects, a connection count (or rate) limited
|
|
||||||
server should send the following request to the \fBanvil\fR(8) server:
|
|
||||||
.PP
|
.PP
|
||||||
.in +4
|
.in +4
|
||||||
\fBrequest=disconnect\fR
|
\fBrequest=disconnect\fR
|
||||||
@ -64,19 +60,16 @@ server should send the following request to the \fBanvil\fR(8) server:
|
|||||||
\fBident=\fIstring\fR
|
\fBident=\fIstring\fR
|
||||||
.in
|
.in
|
||||||
.PP
|
.PP
|
||||||
This registers a disconnect event for the (service, client)
|
The \fBanvil\fR(8) server replies with:
|
||||||
combination specified with \fBident\fR. The \fBanvil\fR(8)
|
|
||||||
server replies with:
|
|
||||||
.PP
|
.PP
|
||||||
.ti +4
|
.ti +4
|
||||||
\fBstatus=0\fR
|
\fBstatus=0\fR
|
||||||
.SH "MESSAGE RATE LIMITING"
|
.SH "MESSAGE RATE CONTROL"
|
||||||
.na
|
.na
|
||||||
.nf
|
.nf
|
||||||
.ad
|
.ad
|
||||||
.fi
|
.fi
|
||||||
When a remote client sends a message delivery request, a
|
To register a message delivery request send the following
|
||||||
message rate limited server should send the following
|
|
||||||
request to the \fBanvil\fR(8) server:
|
request to the \fBanvil\fR(8) server:
|
||||||
.PP
|
.PP
|
||||||
.in +4
|
.in +4
|
||||||
@ -85,28 +78,22 @@ request to the \fBanvil\fR(8) server:
|
|||||||
\fBident=\fIstring\fR
|
\fBident=\fIstring\fR
|
||||||
.in
|
.in
|
||||||
.PP
|
.PP
|
||||||
This registers a message delivery request for the (service, client)
|
The \fBanvil\fR(8) server answers with the number of message
|
||||||
combination specified with \fBident\fR. The \fBanvil\fR(8) server
|
delivery requests per unit time for the (service, client)
|
||||||
answers with the number of message delivery requests per unit time
|
combination specified with \fBident\fR:
|
||||||
for that (service, client) combination:
|
|
||||||
.PP
|
.PP
|
||||||
.in +4
|
.in +4
|
||||||
\fBstatus=0\fR
|
\fBstatus=0\fR
|
||||||
.br
|
.br
|
||||||
\fBrate=\fInumber\fR
|
\fBrate=\fInumber\fR
|
||||||
.in
|
.in
|
||||||
.PP
|
.SH "RECIPIENT RATE CONTROL"
|
||||||
In order to prevent the \fBanvil\fR(8) server from discarding client
|
|
||||||
request rates too early or too late, a message rate limited
|
|
||||||
service should also register connect/disconnect events.
|
|
||||||
.SH "RECIPIENT RATE LIMITING"
|
|
||||||
.na
|
.na
|
||||||
.nf
|
.nf
|
||||||
.ad
|
.ad
|
||||||
.fi
|
.fi
|
||||||
When a remote client sends a recipient address, a recipient
|
To register a recipient request send the following request
|
||||||
rate limited server should send the following request to
|
to the \fBanvil\fR(8) server:
|
||||||
the \fBanvil\fR(8) server:
|
|
||||||
.PP
|
.PP
|
||||||
.in +4
|
.in +4
|
||||||
\fBrequest=recipient\fR
|
\fBrequest=recipient\fR
|
||||||
@ -114,10 +101,35 @@ the \fBanvil\fR(8) server:
|
|||||||
\fBident=\fIstring\fR
|
\fBident=\fIstring\fR
|
||||||
.in
|
.in
|
||||||
.PP
|
.PP
|
||||||
This registers a recipient request for the (service, client)
|
The \fBanvil\fR(8) server answers with the number of recipient
|
||||||
combination specified with \fBident\fR. The \fBanvil\fR(8) server
|
addresses per unit time for the (service, client) combination
|
||||||
answers with the number of recipient addresses per unit time
|
specified with \fBident\fR:
|
||||||
for that (service, client) combination:
|
.PP
|
||||||
|
.in +4
|
||||||
|
\fBstatus=0\fR
|
||||||
|
.br
|
||||||
|
\fBrate=\fInumber\fR
|
||||||
|
.in
|
||||||
|
.SH "TLS SESSION NEGOTIATION RATE CONTROL"
|
||||||
|
.na
|
||||||
|
.nf
|
||||||
|
.ad
|
||||||
|
.fi
|
||||||
|
The features described in this section are available with
|
||||||
|
Postfix 2.3 and later.
|
||||||
|
|
||||||
|
To register a request for a new (i.e. not cached) TLS session
|
||||||
|
send the following request to the \fBanvil\fR(8) server:
|
||||||
|
.PP
|
||||||
|
.in +4
|
||||||
|
\fBrequest=newtls\fR
|
||||||
|
.br
|
||||||
|
\fBident=\fIstring\fR
|
||||||
|
.in
|
||||||
|
.PP
|
||||||
|
The \fBanvil\fR(8) server answers with the number of new
|
||||||
|
TLS session requests per unit time for the (service, client)
|
||||||
|
combination specified with \fBident\fR:
|
||||||
.PP
|
.PP
|
||||||
.in +4
|
.in +4
|
||||||
\fBstatus=0\fR
|
\fBstatus=0\fR
|
||||||
@ -125,9 +137,24 @@ for that (service, client) combination:
|
|||||||
\fBrate=\fInumber\fR
|
\fBrate=\fInumber\fR
|
||||||
.in
|
.in
|
||||||
.PP
|
.PP
|
||||||
In order to prevent the \fBanvil\fR(8) server from discarding client
|
To retrieve new TLS session request rate information without
|
||||||
request rates too early or too late, a recipient rate limited
|
updating the counter information, use:
|
||||||
service should also register connect/disconnect events.
|
.PP
|
||||||
|
.in +4
|
||||||
|
\fBrequest=newtls_report\fR
|
||||||
|
.br
|
||||||
|
\fBident=\fIstring\fR
|
||||||
|
.in
|
||||||
|
.PP
|
||||||
|
The \fBanvil\fR(8) server answers with the number of new
|
||||||
|
TLS session requests per unit time for the (service, client)
|
||||||
|
combination specified with \fBident\fR.
|
||||||
|
.PP
|
||||||
|
.in +4
|
||||||
|
\fBstatus=0\fR
|
||||||
|
.br
|
||||||
|
\fBrate=\fInumber\fR
|
||||||
|
.in
|
||||||
.SH "SECURITY"
|
.SH "SECURITY"
|
||||||
.na
|
.na
|
||||||
.nf
|
.nf
|
||||||
@ -136,12 +163,15 @@ service should also register connect/disconnect events.
|
|||||||
The \fBanvil\fR(8) server does not talk to the network or to local
|
The \fBanvil\fR(8) server does not talk to the network or to local
|
||||||
users, and can run chrooted at fixed low privilege.
|
users, and can run chrooted at fixed low privilege.
|
||||||
|
|
||||||
The \fBanvil\fR(8) server maintains an in-memory table with information
|
The \fBanvil\fR(8) server maintains an in-memory table with
|
||||||
about recent clients of a connection count (or rate) limited service.
|
information about recent clients requests. No persistent
|
||||||
Although state is kept only temporarily, this may require a lot of
|
state is kept because standard system library routines are
|
||||||
memory on systems that handle connections from many remote clients.
|
not sufficiently robust for update-intensive applications.
|
||||||
To reduce memory usage, reduce the time unit over which state
|
|
||||||
is kept.
|
Although the in-memory state is kept only temporarily, this
|
||||||
|
may require a lot of memory on systems that handle connections
|
||||||
|
from many remote clients. To reduce memory usage, reduce
|
||||||
|
the time unit over which state is kept.
|
||||||
.SH DIAGNOSTICS
|
.SH DIAGNOSTICS
|
||||||
.ad
|
.ad
|
||||||
.fi
|
.fi
|
||||||
@ -165,14 +195,22 @@ In this preliminary implementation, a count (or rate) limited server
|
|||||||
can have only one remote client at a time. If a server reports
|
can have only one remote client at a time. If a server reports
|
||||||
multiple simultaneous clients, all but the last reported client
|
multiple simultaneous clients, all but the last reported client
|
||||||
are ignored.
|
are ignored.
|
||||||
|
|
||||||
|
The \fBanvil\fR(8) server automatically discards client
|
||||||
|
request information after it expires. To prevent the
|
||||||
|
\fBanvil\fR(8) server from discarding client request rate
|
||||||
|
information too early or too late, a rate limited service
|
||||||
|
should always register connect/disconnect events even when
|
||||||
|
it does not explicitly limit them.
|
||||||
.SH "CONFIGURATION PARAMETERS"
|
.SH "CONFIGURATION PARAMETERS"
|
||||||
.na
|
.na
|
||||||
.nf
|
.nf
|
||||||
.ad
|
.ad
|
||||||
.fi
|
.fi
|
||||||
Changes to \fBmain.cf\fR are picked up automatically as \fBanvil\fR(8)
|
On low-traffic mail systems, changes to \fBmain.cf\fR are
|
||||||
processes run for only a limited amount of time. Use the command
|
picked up automatically as \fBanvil\fR(8) processes run for
|
||||||
"\fBpostfix reload\fR" to speed up a change.
|
only a limited amount of time. On other mail systems, use
|
||||||
|
the command "\fBpostfix reload\fR" to speed up a change.
|
||||||
|
|
||||||
The text below provides only a parameter summary. See
|
The text below provides only a parameter summary. See
|
||||||
\fBpostconf\fR(5) for more details including examples.
|
\fBpostconf\fR(5) for more details including examples.
|
||||||
|
@ -399,11 +399,6 @@ Update the \fBlocal\fR(8) delivery agent's idea of the Delivered-To:
|
|||||||
address (see prepend_delivered_header) only once, at the start of
|
address (see prepend_delivered_header) only once, at the start of
|
||||||
a delivery attempt; do not update the Delivered-To: address while
|
a delivery attempt; do not update the Delivered-To: address while
|
||||||
expanding aliases or .forward files.
|
expanding aliases or .forward files.
|
||||||
.IP "\fBsticky_owner_alias (yes)\fR"
|
|
||||||
When expanding a \fBlocal\fR(8) alias that has an owner alias (see
|
|
||||||
owner-\fIname\fR discussion in \fBaliases\fR(5)), use the owner information
|
|
||||||
even when the expansion invokes a subordinate alias that has no
|
|
||||||
owner alias.
|
|
||||||
.SH "DELIVERY METHOD CONTROLS"
|
.SH "DELIVERY METHOD CONTROLS"
|
||||||
.na
|
.na
|
||||||
.nf
|
.nf
|
||||||
|
@ -453,6 +453,11 @@ receiving a remote SMTP client request.
|
|||||||
The maximal number of lines in the Postfix SMTP server command history
|
The maximal number of lines in the Postfix SMTP server command history
|
||||||
before it is flushed upon receipt of EHLO, RSET, or end of DATA.
|
before it is flushed upon receipt of EHLO, RSET, or end of DATA.
|
||||||
.PP
|
.PP
|
||||||
|
Available in Postfix version 2.3 and later:
|
||||||
|
.IP "\fBsmtpd_peername_lookup (yes)\fR"
|
||||||
|
Attempt to look up the SMTP client hostname, and verify that
|
||||||
|
the name matches the client IP address.
|
||||||
|
.PP
|
||||||
The per SMTP client connection count and request rate limits are
|
The per SMTP client connection count and request rate limits are
|
||||||
implemented in co-operation with the \fBanvil\fR(8) service, and
|
implemented in co-operation with the \fBanvil\fR(8) service, and
|
||||||
are available in Postfix version 2.2 and later.
|
are available in Postfix version 2.2 and later.
|
||||||
@ -473,6 +478,11 @@ Postfix actually accepts those recipients.
|
|||||||
.IP "\fBsmtpd_client_event_limit_exceptions ($mynetworks)\fR"
|
.IP "\fBsmtpd_client_event_limit_exceptions ($mynetworks)\fR"
|
||||||
Clients that are excluded from connection count, connection rate,
|
Clients that are excluded from connection count, connection rate,
|
||||||
or SMTP request rate restrictions.
|
or SMTP request rate restrictions.
|
||||||
|
.PP
|
||||||
|
Available in Postfix version 2.3 and later:
|
||||||
|
.IP "\fBsmtpd_client_new_tls_session_rate_limit (0)\fR"
|
||||||
|
The maximal number of new (i.e., uncached) TLS sessions that any
|
||||||
|
client is allowed to negotiate with this service per time unit.
|
||||||
.SH "TARPIT CONTROLS"
|
.SH "TARPIT CONTROLS"
|
||||||
.na
|
.na
|
||||||
.nf
|
.nf
|
||||||
|
@ -372,6 +372,7 @@ while (<>) {
|
|||||||
s;\bsmtpd_client_connection_rate_limit\b;<a href="postconf.5.html#smtpd_client_connection_rate_limit">$&</a>;g;
|
s;\bsmtpd_client_connection_rate_limit\b;<a href="postconf.5.html#smtpd_client_connection_rate_limit">$&</a>;g;
|
||||||
s;\bsmtpd_client_message_rate_limit\b;<a href="postconf.5.html#smtpd_client_message_rate_limit">$&</a>;g;
|
s;\bsmtpd_client_message_rate_limit\b;<a href="postconf.5.html#smtpd_client_message_rate_limit">$&</a>;g;
|
||||||
s;\bsmtpd_client_recipient_rate_limit\b;<a href="postconf.5.html#smtpd_client_recipient_rate_limit">$&</a>;g;
|
s;\bsmtpd_client_recipient_rate_limit\b;<a href="postconf.5.html#smtpd_client_recipient_rate_limit">$&</a>;g;
|
||||||
|
s;\bsmtpd_client_new_tls_session_rate_limit\b;<a href="postconf.5.html#smtpd_client_new_tls_session_rate_limit">$&</a>;g;
|
||||||
s;\bsmtpd_client_restrictions\b;<a href="postconf.5.html#smtpd_client_restrictions">$&</a>;g;
|
s;\bsmtpd_client_restrictions\b;<a href="postconf.5.html#smtpd_client_restrictions">$&</a>;g;
|
||||||
s;\bsmtpd_data_restrictions\b;<a href="postconf.5.html#smtpd_data_restrictions">$&</a>;g;
|
s;\bsmtpd_data_restrictions\b;<a href="postconf.5.html#smtpd_data_restrictions">$&</a>;g;
|
||||||
s;\bsmtpd_delay_reject\b;<a href="postconf.5.html#smtpd_delay_reject">$&</a>;g;
|
s;\bsmtpd_delay_reject\b;<a href="postconf.5.html#smtpd_delay_reject">$&</a>;g;
|
||||||
@ -390,6 +391,7 @@ while (<>) {
|
|||||||
s;\bsmtpd_noop_commands\b;<a href="postconf.5.html#smtpd_noop_commands">$&</a>;g;
|
s;\bsmtpd_noop_commands\b;<a href="postconf.5.html#smtpd_noop_commands">$&</a>;g;
|
||||||
s;\bsmtpd_null_access_lookup_key\b;<a href="postconf.5.html#smtpd_null_access_lookup_key">$&</a>;g;
|
s;\bsmtpd_null_access_lookup_key\b;<a href="postconf.5.html#smtpd_null_access_lookup_key">$&</a>;g;
|
||||||
s;\bsmtpd_recipient_overshoot_limit\b;<a href="postconf.5.html#smtpd_recipient_overshoot_limit">$&</a>;g;
|
s;\bsmtpd_recipient_overshoot_limit\b;<a href="postconf.5.html#smtpd_recipient_overshoot_limit">$&</a>;g;
|
||||||
|
s;\bsmtpd_peername_lookup\b;<a href="postconf.5.html#smtpd_peername_lookup">$&</a>;g;
|
||||||
s;\bsmtpd_policy_service_max_idle\b;<a href="postconf.5.html#smtpd_policy_service_max_idle">$&</a>;g;
|
s;\bsmtpd_policy_service_max_idle\b;<a href="postconf.5.html#smtpd_policy_service_max_idle">$&</a>;g;
|
||||||
s;\bsmtpd_policy_service_max_ttl\b;<a href="postconf.5.html#smtpd_policy_service_max_ttl">$&</a>;g;
|
s;\bsmtpd_policy_service_max_ttl\b;<a href="postconf.5.html#smtpd_policy_service_max_ttl">$&</a>;g;
|
||||||
s;\bsmtpd_policy_service_timeout\b;<a href="postconf.5.html#smtpd_policy_service_timeout">$&</a>;g;
|
s;\bsmtpd_policy_service_timeout\b;<a href="postconf.5.html#smtpd_policy_service_timeout">$&</a>;g;
|
||||||
@ -502,7 +504,6 @@ while (<>) {
|
|||||||
s;\btls_ran[-</Bb>]*\n* *[<Bb>]*dom_source\b;<a href="postconf.5.html#tls_random_source">$&</a>;g;
|
s;\btls_ran[-</Bb>]*\n* *[<Bb>]*dom_source\b;<a href="postconf.5.html#tls_random_source">$&</a>;g;
|
||||||
|
|
||||||
s;\bfrozen_delivered_to\b;<a href="postconf.5.html#frozen_delivered_to">$&</a>;g;
|
s;\bfrozen_delivered_to\b;<a href="postconf.5.html#frozen_delivered_to">$&</a>;g;
|
||||||
s;\bsticky_owner_alias\b;<a href="postconf.5.html#sticky_owner_alias">$&</a>;g;
|
|
||||||
|
|
||||||
# Undo hyperlinks of manual pages with the same name as parameters.
|
# Undo hyperlinks of manual pages with the same name as parameters.
|
||||||
|
|
||||||
|
@ -36,7 +36,8 @@ the Postfix source code, in the directory examples/smtpd-policy.
|
|||||||
to Postfix. It's much easier to develop a new feature in few lines
|
to Postfix. It's much easier to develop a new feature in few lines
|
||||||
of Perl, than trying to do the same in C code. The difference in
|
of Perl, than trying to do the same in C code. The difference in
|
||||||
performance will be unnoticeable except in the most demanding
|
performance will be unnoticeable except in the most demanding
|
||||||
environments. </p>
|
environments. On active systems a policy daemon process is used
|
||||||
|
multiple times, for up to 100 incoming SMTP connections. </p>
|
||||||
|
|
||||||
<p> This document covers the following topics: </p>
|
<p> This document covers the following topics: </p>
|
||||||
|
|
||||||
|
@ -4399,6 +4399,43 @@ Example:
|
|||||||
smtpd_client_recipient_rate_limit = 1000
|
smtpd_client_recipient_rate_limit = 1000
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
%PARAM smtpd_client_new_tls_session_rate_limit 0
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The maximal number of new (i.e., uncached) TLS sessions that a
|
||||||
|
remote SMTP client is allowed to negotiate with this service per
|
||||||
|
time unit. The time unit is specified with the anvil_rate_time_unit
|
||||||
|
configuration parameter.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
By default, a remote SMTP client can negotiate as many new TLS
|
||||||
|
sessions per time unit as Postfix can accept.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
To disable this feature, specify a limit of 0. Otherwise, specify
|
||||||
|
a limit that is at least the per-client concurrent session limit,
|
||||||
|
or else legitimate client sessions may be rejected.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
WARNING: The purpose of this feature is to limit abuse. It must
|
||||||
|
not be used to regulate legitimate mail traffic.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This feature is available in Postfix 2.3 and later.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Example:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
smtpd_client_new_tls_session_rate_limit = 100
|
||||||
|
</pre>
|
||||||
|
|
||||||
%PARAM smtpd_client_restrictions
|
%PARAM smtpd_client_restrictions
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@ -8542,18 +8579,6 @@ message_strip_characters = \0
|
|||||||
|
|
||||||
<p> This feature is available in Postfix 2.3 and later. </p>
|
<p> This feature is available in Postfix 2.3 and later. </p>
|
||||||
|
|
||||||
%PARAM sticky_owner_alias yes
|
|
||||||
|
|
||||||
<p> When expanding a local(8) alias that has an owner alias (see
|
|
||||||
owner-<i>name</i> discussion in aliases(5)), use the owner information
|
|
||||||
even when the expansion invokes a subordinate alias that has no
|
|
||||||
owner alias. </p>
|
|
||||||
|
|
||||||
<p> This feature is available in Postfix 2.3 and later. With older
|
|
||||||
Postfix releases, the behavior is as if this parameter is set to
|
|
||||||
"no". The old setting provides poorer error reporting with nested
|
|
||||||
aliases that only have an owner alias at the top level. </p>
|
|
||||||
|
|
||||||
%PARAM frozen_delivered_to yes
|
%PARAM frozen_delivered_to yes
|
||||||
|
|
||||||
<p> Update the local(8) delivery agent's idea of the Delivered-To:
|
<p> Update the local(8) delivery agent's idea of the Delivered-To:
|
||||||
@ -8567,3 +8592,11 @@ Postfix releases, the behavior is as if this parameter is set to
|
|||||||
or .forward files. When an alias or .forward file changes the
|
or .forward files. When an alias or .forward file changes the
|
||||||
Delivered-To: address, it ties up one queue file and one cleanup
|
Delivered-To: address, it ties up one queue file and one cleanup
|
||||||
process instance while mail is being forwarded. </p>
|
process instance while mail is being forwarded. </p>
|
||||||
|
|
||||||
|
%PARAM smtpd_peername_lookup yes
|
||||||
|
|
||||||
|
<p> Attempt to look up the SMTP client hostname, and verify that
|
||||||
|
the name matches the client IP address. A client name is set to
|
||||||
|
"unknown" when it cannot be looked up or verified, or when name
|
||||||
|
lookup is disabled. Turning off name lookup reduces delays due to
|
||||||
|
DNS lookup and increases the maximal inbound delivery rate. </p>
|
||||||
|
@ -6,21 +6,23 @@
|
|||||||
/* SYNOPSIS
|
/* SYNOPSIS
|
||||||
/* \fBanvil\fR [generic Postfix daemon options]
|
/* \fBanvil\fR [generic Postfix daemon options]
|
||||||
/* DESCRIPTION
|
/* DESCRIPTION
|
||||||
/* The Postfix \fBanvil\fR(8) server maintains short-term statistics
|
/* The Postfix \fBanvil\fR(8) server maintains statistics about
|
||||||
/* to defend against clients that hammer a server with either too
|
/* client connection counts or client request rates. This
|
||||||
/* many simultaneous sessions, or with too many successive requests
|
/* information can be used to defend against clients that
|
||||||
/* within a configurable time interval.
|
/* hammer a server with either too many simultaneous sessions,
|
||||||
/* This server is designed to run under control by the Postfix
|
/* or with too many successive requests within a configurable
|
||||||
/* \fBmaster\fR(8) server.
|
/* time interval. This server is designed to run under control
|
||||||
|
/* by the Postfix \fBmaster\fR(8) server.
|
||||||
/*
|
/*
|
||||||
/* The \fBanvil\fR(8) server maintains no persistent database. Standard
|
/* In the following text, \fBident\fR specifies a (service,
|
||||||
/* library utilities do not meet Postfix performance and robustness
|
/* client) combination. The exact syntax of that information
|
||||||
/* requirements.
|
/* is application-dependent; the \fBanvil\fR(8) server does
|
||||||
/* CONNECTION COUNT/RATE LIMITING
|
/* not care.
|
||||||
|
/* CONNECTION COUNT/RATE CONTROL
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
/* When a remote client connects, a connection count (or rate) limited
|
/* To register a new connection send the following request to
|
||||||
/* server should send the following request to the \fBanvil\fR(8) server:
|
/* the \fBanvil\fR(8) server:
|
||||||
/* .PP
|
/* .PP
|
||||||
/* .in +4
|
/* .in +4
|
||||||
/* \fBrequest=connect\fR
|
/* \fBrequest=connect\fR
|
||||||
@ -28,11 +30,10 @@
|
|||||||
/* \fBident=\fIstring\fR
|
/* \fBident=\fIstring\fR
|
||||||
/* .in
|
/* .in
|
||||||
/* .PP
|
/* .PP
|
||||||
/* This registers a new connection for the (service, client)
|
/* The \fBanvil\fR(8) server answers with the number of
|
||||||
/* combination specified with \fBident\fR. The \fBanvil\fR(8) server
|
/* simultaneous connections and the number of connections per
|
||||||
/* answers with the number of simultaneous connections and the
|
/* unit time for the (service, client) combination specified
|
||||||
/* number of connections per unit time for that (service, client)
|
/* with \fBident\fR:
|
||||||
/* combination:
|
|
||||||
/* .PP
|
/* .PP
|
||||||
/* .in +4
|
/* .in +4
|
||||||
/* \fBstatus=0\fR
|
/* \fBstatus=0\fR
|
||||||
@ -42,13 +43,8 @@
|
|||||||
/* \fBrate=\fInumber\fR
|
/* \fBrate=\fInumber\fR
|
||||||
/* .in
|
/* .in
|
||||||
/* .PP
|
/* .PP
|
||||||
/* The \fBrate\fR is computed as the number of connections
|
/* To register a disconnect event send the following request
|
||||||
/* that were registered in the current "time unit" interval.
|
/* to the \fBanvil\fR(8) server:
|
||||||
/* It is left up to the server to decide if the remote client
|
|
||||||
/* exceeds the connection count (or rate) limit.
|
|
||||||
/* .PP
|
|
||||||
/* When a remote client disconnects, a connection count (or rate) limited
|
|
||||||
/* server should send the following request to the \fBanvil\fR(8) server:
|
|
||||||
/* .PP
|
/* .PP
|
||||||
/* .in +4
|
/* .in +4
|
||||||
/* \fBrequest=disconnect\fR
|
/* \fBrequest=disconnect\fR
|
||||||
@ -56,17 +52,14 @@
|
|||||||
/* \fBident=\fIstring\fR
|
/* \fBident=\fIstring\fR
|
||||||
/* .in
|
/* .in
|
||||||
/* .PP
|
/* .PP
|
||||||
/* This registers a disconnect event for the (service, client)
|
/* The \fBanvil\fR(8) server replies with:
|
||||||
/* combination specified with \fBident\fR. The \fBanvil\fR(8)
|
|
||||||
/* server replies with:
|
|
||||||
/* .PP
|
/* .PP
|
||||||
/* .ti +4
|
/* .ti +4
|
||||||
/* \fBstatus=0\fR
|
/* \fBstatus=0\fR
|
||||||
/* MESSAGE RATE LIMITING
|
/* MESSAGE RATE CONTROL
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
/* When a remote client sends a message delivery request, a
|
/* To register a message delivery request send the following
|
||||||
/* message rate limited server should send the following
|
|
||||||
/* request to the \fBanvil\fR(8) server:
|
/* request to the \fBanvil\fR(8) server:
|
||||||
/* .PP
|
/* .PP
|
||||||
/* .in +4
|
/* .in +4
|
||||||
@ -75,26 +68,20 @@
|
|||||||
/* \fBident=\fIstring\fR
|
/* \fBident=\fIstring\fR
|
||||||
/* .in
|
/* .in
|
||||||
/* .PP
|
/* .PP
|
||||||
/* This registers a message delivery request for the (service, client)
|
/* The \fBanvil\fR(8) server answers with the number of message
|
||||||
/* combination specified with \fBident\fR. The \fBanvil\fR(8) server
|
/* delivery requests per unit time for the (service, client)
|
||||||
/* answers with the number of message delivery requests per unit time
|
/* combination specified with \fBident\fR:
|
||||||
/* for that (service, client) combination:
|
|
||||||
/* .PP
|
/* .PP
|
||||||
/* .in +4
|
/* .in +4
|
||||||
/* \fBstatus=0\fR
|
/* \fBstatus=0\fR
|
||||||
/* .br
|
/* .br
|
||||||
/* \fBrate=\fInumber\fR
|
/* \fBrate=\fInumber\fR
|
||||||
/* .in
|
/* .in
|
||||||
/* .PP
|
/* RECIPIENT RATE CONTROL
|
||||||
/* In order to prevent the \fBanvil\fR(8) server from discarding client
|
|
||||||
/* request rates too early or too late, a message rate limited
|
|
||||||
/* service should also register connect/disconnect events.
|
|
||||||
/* RECIPIENT RATE LIMITING
|
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
/* When a remote client sends a recipient address, a recipient
|
/* To register a recipient request send the following request
|
||||||
/* rate limited server should send the following request to
|
/* to the \fBanvil\fR(8) server:
|
||||||
/* the \fBanvil\fR(8) server:
|
|
||||||
/* .PP
|
/* .PP
|
||||||
/* .in +4
|
/* .in +4
|
||||||
/* \fBrequest=recipient\fR
|
/* \fBrequest=recipient\fR
|
||||||
@ -102,10 +89,33 @@
|
|||||||
/* \fBident=\fIstring\fR
|
/* \fBident=\fIstring\fR
|
||||||
/* .in
|
/* .in
|
||||||
/* .PP
|
/* .PP
|
||||||
/* This registers a recipient request for the (service, client)
|
/* The \fBanvil\fR(8) server answers with the number of recipient
|
||||||
/* combination specified with \fBident\fR. The \fBanvil\fR(8) server
|
/* addresses per unit time for the (service, client) combination
|
||||||
/* answers with the number of recipient addresses per unit time
|
/* specified with \fBident\fR:
|
||||||
/* for that (service, client) combination:
|
/* .PP
|
||||||
|
/* .in +4
|
||||||
|
/* \fBstatus=0\fR
|
||||||
|
/* .br
|
||||||
|
/* \fBrate=\fInumber\fR
|
||||||
|
/* .in
|
||||||
|
/* TLS SESSION NEGOTIATION RATE CONTROL
|
||||||
|
/* .ad
|
||||||
|
/* .fi
|
||||||
|
/* The features described in this section are available with
|
||||||
|
/* Postfix 2.3 and later.
|
||||||
|
/*
|
||||||
|
/* To register a request for a new (i.e. not cached) TLS session
|
||||||
|
/* send the following request to the \fBanvil\fR(8) server:
|
||||||
|
/* .PP
|
||||||
|
/* .in +4
|
||||||
|
/* \fBrequest=newtls\fR
|
||||||
|
/* .br
|
||||||
|
/* \fBident=\fIstring\fR
|
||||||
|
/* .in
|
||||||
|
/* .PP
|
||||||
|
/* The \fBanvil\fR(8) server answers with the number of new
|
||||||
|
/* TLS session requests per unit time for the (service, client)
|
||||||
|
/* combination specified with \fBident\fR:
|
||||||
/* .PP
|
/* .PP
|
||||||
/* .in +4
|
/* .in +4
|
||||||
/* \fBstatus=0\fR
|
/* \fBstatus=0\fR
|
||||||
@ -113,21 +123,39 @@
|
|||||||
/* \fBrate=\fInumber\fR
|
/* \fBrate=\fInumber\fR
|
||||||
/* .in
|
/* .in
|
||||||
/* .PP
|
/* .PP
|
||||||
/* In order to prevent the \fBanvil\fR(8) server from discarding client
|
/* To retrieve new TLS session request rate information without
|
||||||
/* request rates too early or too late, a recipient rate limited
|
/* updating the counter information, use:
|
||||||
/* service should also register connect/disconnect events.
|
/* .PP
|
||||||
|
/* .in +4
|
||||||
|
/* \fBrequest=newtls_report\fR
|
||||||
|
/* .br
|
||||||
|
/* \fBident=\fIstring\fR
|
||||||
|
/* .in
|
||||||
|
/* .PP
|
||||||
|
/* The \fBanvil\fR(8) server answers with the number of new
|
||||||
|
/* TLS session requests per unit time for the (service, client)
|
||||||
|
/* combination specified with \fBident\fR.
|
||||||
|
/* .PP
|
||||||
|
/* .in +4
|
||||||
|
/* \fBstatus=0\fR
|
||||||
|
/* .br
|
||||||
|
/* \fBrate=\fInumber\fR
|
||||||
|
/* .in
|
||||||
/* SECURITY
|
/* SECURITY
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
/* The \fBanvil\fR(8) server does not talk to the network or to local
|
/* The \fBanvil\fR(8) server does not talk to the network or to local
|
||||||
/* users, and can run chrooted at fixed low privilege.
|
/* users, and can run chrooted at fixed low privilege.
|
||||||
/*
|
/*
|
||||||
/* The \fBanvil\fR(8) server maintains an in-memory table with information
|
/* The \fBanvil\fR(8) server maintains an in-memory table with
|
||||||
/* about recent clients of a connection count (or rate) limited service.
|
/* information about recent clients requests. No persistent
|
||||||
/* Although state is kept only temporarily, this may require a lot of
|
/* state is kept because standard system library routines are
|
||||||
/* memory on systems that handle connections from many remote clients.
|
/* not sufficiently robust for update-intensive applications.
|
||||||
/* To reduce memory usage, reduce the time unit over which state
|
/*
|
||||||
/* is kept.
|
/* Although the in-memory state is kept only temporarily, this
|
||||||
|
/* may require a lot of memory on systems that handle connections
|
||||||
|
/* from many remote clients. To reduce memory usage, reduce
|
||||||
|
/* the time unit over which state is kept.
|
||||||
/* DIAGNOSTICS
|
/* DIAGNOSTICS
|
||||||
/* Problems and transactions are logged to \fBsyslogd\fR(8).
|
/* Problems and transactions are logged to \fBsyslogd\fR(8).
|
||||||
/*
|
/*
|
||||||
@ -147,12 +175,20 @@
|
|||||||
/* can have only one remote client at a time. If a server reports
|
/* can have only one remote client at a time. If a server reports
|
||||||
/* multiple simultaneous clients, all but the last reported client
|
/* multiple simultaneous clients, all but the last reported client
|
||||||
/* are ignored.
|
/* are ignored.
|
||||||
|
/*
|
||||||
|
/* The \fBanvil\fR(8) server automatically discards client
|
||||||
|
/* request information after it expires. To prevent the
|
||||||
|
/* \fBanvil\fR(8) server from discarding client request rate
|
||||||
|
/* information too early or too late, a rate limited service
|
||||||
|
/* should always register connect/disconnect events even when
|
||||||
|
/* it does not explicitly limit them.
|
||||||
/* CONFIGURATION PARAMETERS
|
/* CONFIGURATION PARAMETERS
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
/* Changes to \fBmain.cf\fR are picked up automatically as \fBanvil\fR(8)
|
/* On low-traffic mail systems, changes to \fBmain.cf\fR are
|
||||||
/* processes run for only a limited amount of time. Use the command
|
/* picked up automatically as \fBanvil\fR(8) processes run for
|
||||||
/* "\fBpostfix reload\fR" to speed up a change.
|
/* only a limited amount of time. On other mail systems, use
|
||||||
|
/* the command "\fBpostfix reload\fR" to speed up a change.
|
||||||
/*
|
/*
|
||||||
/* The text below provides only a parameter summary. See
|
/* The text below provides only a parameter summary. See
|
||||||
/* \fBpostconf\fR(5) for more details including examples.
|
/* \fBpostconf\fR(5) for more details including examples.
|
||||||
@ -252,28 +288,53 @@ static HTABLE *anvil_remote_map; /* indexed by service+ remote client */
|
|||||||
* Absent a real-time query interface, these are logged at process exit time
|
* Absent a real-time query interface, these are logged at process exit time
|
||||||
* and at regular intervals.
|
* and at regular intervals.
|
||||||
*/
|
*/
|
||||||
static int max_count;
|
typedef struct {
|
||||||
static char *max_count_user;
|
int value; /* peak value */
|
||||||
static time_t max_count_time;
|
char *ident; /* lookup key */
|
||||||
|
time_t when; /* time of peak value */
|
||||||
|
} ANVIL_MAX;
|
||||||
|
|
||||||
static int max_rate;
|
static ANVIL_MAX max_conn_count; /* peak connection count */
|
||||||
static char *max_rate_user;
|
static ANVIL_MAX max_conn_rate; /* peak connection rate */
|
||||||
static time_t max_rate_time;
|
static ANVIL_MAX max_mail_rate; /* peak message rate */
|
||||||
|
static ANVIL_MAX max_rcpt_rate; /* peak recipient rate */
|
||||||
|
static ANVIL_MAX max_ntls_rate; /* peak new TLS session rate */
|
||||||
|
|
||||||
static int max_mail;
|
static int max_cache_size; /* peak cache size */
|
||||||
static char *max_mail_user;
|
static time_t max_cache_time; /* time of peak size */
|
||||||
static time_t max_mail_time;
|
|
||||||
|
|
||||||
static int max_rcpt;
|
/* Update/report peak usage. */
|
||||||
static char *max_rcpt_user;
|
|
||||||
static time_t max_rcpt_time;
|
|
||||||
|
|
||||||
static int max_newtls;
|
#define ANVIL_MAX_UPDATE(_max, _value, _ident) \
|
||||||
static char *max_newtls_user;
|
do { \
|
||||||
static time_t max_newtls_time;
|
_max.value = _value; \
|
||||||
|
if (_max.ident == 0) { \
|
||||||
|
_max.ident = mystrdup(_ident); \
|
||||||
|
} else if (!STREQ(_max.ident, _ident)) { \
|
||||||
|
myfree(_max.ident); \
|
||||||
|
_max.ident = mystrdup(_ident); \
|
||||||
|
} \
|
||||||
|
_max.when = event_time(); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
static int max_cache;
|
#define ANVIL_MAX_RATE_REPORT(_max, _name) \
|
||||||
static time_t max_cache_time;
|
do { \
|
||||||
|
if (_max.value > 0) { \
|
||||||
|
msg_info("statistics: max " _name " rate %d/%ds for (%s) at %.15s", \
|
||||||
|
_max.value, var_anvil_time_unit, \
|
||||||
|
_max.ident, ctime(&_max.when) + 4); \
|
||||||
|
_max.value = 0; \
|
||||||
|
} \
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
#define ANVIL_MAX_COUNT_REPORT(_max, _name) \
|
||||||
|
do { \
|
||||||
|
if (_max.value > 0) { \
|
||||||
|
msg_info("statistics: max " _name " count %d for (%s) at %.15s", \
|
||||||
|
_max.value, _max.ident, ctime(&_max.when) + 4); \
|
||||||
|
_max.value = 0; \
|
||||||
|
} \
|
||||||
|
} while (0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remote connection state, one instance for each (service, client) pair.
|
* Remote connection state, one instance for each (service, client) pair.
|
||||||
@ -284,7 +345,7 @@ typedef struct {
|
|||||||
int rate; /* connection rate */
|
int rate; /* connection rate */
|
||||||
int mail; /* message rate */
|
int mail; /* message rate */
|
||||||
int rcpt; /* recipient rate */
|
int rcpt; /* recipient rate */
|
||||||
int newtls; /* newtls rate */
|
int ntls; /* new TLS session rate */
|
||||||
time_t start; /* time of first rate sample */
|
time_t start; /* time of first rate sample */
|
||||||
} ANVIL_REMOTE;
|
} ANVIL_REMOTE;
|
||||||
|
|
||||||
@ -296,12 +357,6 @@ typedef struct {
|
|||||||
ANVIL_REMOTE *anvil_remote; /* XXX should be list */
|
ANVIL_REMOTE *anvil_remote; /* XXX should be list */
|
||||||
} ANVIL_LOCAL;
|
} ANVIL_LOCAL;
|
||||||
|
|
||||||
/*
|
|
||||||
* Silly little macros.
|
|
||||||
*/
|
|
||||||
#define STR(x) vstring_str(x)
|
|
||||||
#define STREQ(x,y) (strcmp((x), (y)) == 0)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following operations are implemented as macros with recognizable
|
* The following operations are implemented as macros with recognizable
|
||||||
* names so that we don't lose sight of what the code is trying to do.
|
* names so that we don't lose sight of what the code is trying to do.
|
||||||
@ -312,14 +367,14 @@ typedef struct {
|
|||||||
|
|
||||||
/* Create new (service, client) state. */
|
/* Create new (service, client) state. */
|
||||||
|
|
||||||
#define ANVIL_REMOTE_FIRST(remote, id) \
|
#define ANVIL_REMOTE_FIRST_CONN(remote, id) \
|
||||||
do { \
|
do { \
|
||||||
(remote)->ident = mystrdup(id); \
|
(remote)->ident = mystrdup(id); \
|
||||||
(remote)->count = 1; \
|
(remote)->count = 1; \
|
||||||
(remote)->rate = 1; \
|
(remote)->rate = 1; \
|
||||||
(remote)->mail = 0; \
|
(remote)->mail = 0; \
|
||||||
(remote)->rcpt = 0; \
|
(remote)->rcpt = 0; \
|
||||||
(remote)->newtls = 0; \
|
(remote)->ntls = 0; \
|
||||||
(remote)->start = event_time(); \
|
(remote)->start = event_time(); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
@ -331,66 +386,41 @@ typedef struct {
|
|||||||
myfree((char *) (remote)); \
|
myfree((char *) (remote)); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
/* Add connection to (service, client) state. */
|
/* Reset event rate counters and start of data collection interval. */
|
||||||
|
|
||||||
#define ANVIL_REMOTE_NEXT(remote) \
|
#define ANVIL_REMOTE_RSET_RATE(remote, _start) \
|
||||||
do { \
|
do { \
|
||||||
time_t _now = event_time(); \
|
(remote)->rate = 0; \
|
||||||
if ((remote)->start + var_anvil_time_unit < _now) { \
|
|
||||||
(remote)->rate = 1; \
|
|
||||||
(remote)->mail = 0; \
|
(remote)->mail = 0; \
|
||||||
(remote)->rcpt = 0; \
|
(remote)->rcpt = 0; \
|
||||||
(remote)->newtls = 0; \
|
(remote)->ntls = 0; \
|
||||||
(remote)->start = _now; \
|
(remote)->start = _start; \
|
||||||
} else if ((remote)->rate < INT_MAX) { \
|
} while(0)
|
||||||
(remote)->rate += 1; \
|
|
||||||
} \
|
/* Add connection to (service, client) state. */
|
||||||
|
|
||||||
|
#define ANVIL_REMOTE_INCR_RATE(remote, _what) \
|
||||||
|
do { \
|
||||||
|
time_t _now = event_time(); \
|
||||||
|
if ((remote)->start + var_anvil_time_unit < _now) \
|
||||||
|
ANVIL_REMOTE_RSET_RATE((remote), _now); \
|
||||||
|
if ((remote)->_what < INT_MAX) \
|
||||||
|
(remote)->_what += 1; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define ANVIL_REMOTE_NEXT_CONN(remote) \
|
||||||
|
do { \
|
||||||
|
ANVIL_REMOTE_INCR_RATE((remote), rate); \
|
||||||
if ((remote)->count == 0) \
|
if ((remote)->count == 0) \
|
||||||
event_cancel_timer(anvil_remote_expire, (char *) remote); \
|
event_cancel_timer(anvil_remote_expire, (char *) remote); \
|
||||||
(remote)->count++; \
|
(remote)->count++; \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
#define ANVIL_ADD_MAIL(remote) \
|
#define ANVIL_REMOTE_INCR_MAIL(remote) ANVIL_REMOTE_INCR_RATE((remote), mail)
|
||||||
do { \
|
|
||||||
time_t _now = event_time(); \
|
|
||||||
if ((remote)->start + var_anvil_time_unit < _now) { \
|
|
||||||
(remote)->rate = 0; \
|
|
||||||
(remote)->mail = 1; \
|
|
||||||
(remote)->rcpt = 0; \
|
|
||||||
(remote)->newtls = 0; \
|
|
||||||
(remote)->start = _now; \
|
|
||||||
} else if ((remote)->mail < INT_MAX) { \
|
|
||||||
(remote)->mail += 1; \
|
|
||||||
} \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
#define ANVIL_ADD_RCPT(remote) \
|
#define ANVIL_REMOTE_INCR_RCPT(remote) ANVIL_REMOTE_INCR_RATE((remote), rcpt)
|
||||||
do { \
|
|
||||||
time_t _now = event_time(); \
|
|
||||||
if ((remote)->start + var_anvil_time_unit < _now) { \
|
|
||||||
(remote)->rate = 0; \
|
|
||||||
(remote)->mail = 0; \
|
|
||||||
(remote)->rcpt = 1; \
|
|
||||||
(remote)->newtls = 0; \
|
|
||||||
(remote)->start = _now; \
|
|
||||||
} else if ((remote)->rcpt < INT_MAX) { \
|
|
||||||
(remote)->rcpt += 1; \
|
|
||||||
} \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
#define ANVIL_ADD_STARTTLS(remote) \
|
#define ANVIL_REMOTE_INCR_NTLS(remote) ANVIL_REMOTE_INCR_RATE((remote), ntls)
|
||||||
do { \
|
|
||||||
time_t _now = event_time(); \
|
|
||||||
if ((remote)->start + var_anvil_time_unit < _now) { \
|
|
||||||
(remote)->rate = 0; \
|
|
||||||
(remote)->mail = 0; \
|
|
||||||
(remote)->rcpt = 0; \
|
|
||||||
(remote)->newtls = 1; \
|
|
||||||
(remote)->start = _now; \
|
|
||||||
} else if ((remote)->newtls < INT_MAX) { \
|
|
||||||
(remote)->newtls += 1; \
|
|
||||||
} \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
/* Drop connection from (service, client) state. */
|
/* Drop connection from (service, client) state. */
|
||||||
|
|
||||||
@ -443,6 +473,20 @@ typedef struct {
|
|||||||
anvil_remote_disconnect((stream), (local)->anvil_remote->ident); \
|
anvil_remote_disconnect((stream), (local)->anvil_remote->ident); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lookup table to map request names to action routines.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
const char *name;
|
||||||
|
void (*action) (VSTREAM *, const char *);
|
||||||
|
} ANVIL_REQ_TABLE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Silly little macros.
|
||||||
|
*/
|
||||||
|
#define STR(x) vstring_str(x)
|
||||||
|
#define STREQ(x,y) (strcmp((x), (y)) == 0)
|
||||||
|
|
||||||
/* anvil_remote_expire - purge expired connection state */
|
/* anvil_remote_expire - purge expired connection state */
|
||||||
|
|
||||||
static void anvil_remote_expire(int unused_event, char *context)
|
static void anvil_remote_expire(int unused_event, char *context)
|
||||||
@ -472,8 +516,6 @@ static void anvil_remote_lookup(VSTREAM *client_stream, const char *ident)
|
|||||||
{
|
{
|
||||||
ANVIL_REMOTE *anvil_remote;
|
ANVIL_REMOTE *anvil_remote;
|
||||||
char *myname = "anvil_remote_lookup";
|
char *myname = "anvil_remote_lookup";
|
||||||
HTABLE_INFO **ht_info;
|
|
||||||
HTABLE_INFO **ht;
|
|
||||||
|
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_info("%s fd=%d stream=0x%lx ident=%s",
|
msg_info("%s fd=%d stream=0x%lx ident=%s",
|
||||||
@ -483,39 +525,31 @@ static void anvil_remote_lookup(VSTREAM *client_stream, const char *ident)
|
|||||||
/*
|
/*
|
||||||
* Look up remote client information.
|
* Look up remote client information.
|
||||||
*/
|
*/
|
||||||
if (STREQ(ident, "*")) {
|
if ((anvil_remote =
|
||||||
attr_print_plain(client_stream, ATTR_FLAG_MORE,
|
|
||||||
ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_OK,
|
|
||||||
ATTR_TYPE_END);
|
|
||||||
ht_info = htable_list(anvil_remote_map);
|
|
||||||
for (ht = ht_info; *ht; ht++) {
|
|
||||||
anvil_remote = (ANVIL_REMOTE *) ht[0]->value;
|
|
||||||
attr_print_plain(client_stream, ATTR_FLAG_MORE,
|
|
||||||
ATTR_TYPE_STR, ANVIL_ATTR_IDENT, ht[0]->key,
|
|
||||||
ATTR_TYPE_NUM, ANVIL_ATTR_COUNT, anvil_remote->count,
|
|
||||||
ATTR_TYPE_NUM, ANVIL_ATTR_RATE, anvil_remote->rate,
|
|
||||||
ATTR_TYPE_NUM, ANVIL_ATTR_MAIL, anvil_remote->mail,
|
|
||||||
ATTR_TYPE_NUM, ANVIL_ATTR_RCPT, anvil_remote->rcpt,
|
|
||||||
ATTR_TYPE_END);
|
|
||||||
}
|
|
||||||
attr_print_plain(client_stream, ATTR_FLAG_NONE, ATTR_TYPE_END);
|
|
||||||
myfree((char *) ht_info);
|
|
||||||
} else if ((anvil_remote =
|
|
||||||
(ANVIL_REMOTE *) htable_find(anvil_remote_map, ident)) == 0) {
|
(ANVIL_REMOTE *) htable_find(anvil_remote_map, ident)) == 0) {
|
||||||
attr_print_plain(client_stream, ATTR_FLAG_NONE,
|
attr_print_plain(client_stream, ATTR_FLAG_NONE,
|
||||||
ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_FAIL,
|
ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_OK,
|
||||||
ATTR_TYPE_NUM, ANVIL_ATTR_COUNT, 0,
|
ATTR_TYPE_NUM, ANVIL_ATTR_COUNT, 0,
|
||||||
ATTR_TYPE_NUM, ANVIL_ATTR_RATE, 0,
|
ATTR_TYPE_NUM, ANVIL_ATTR_RATE, 0,
|
||||||
ATTR_TYPE_NUM, ANVIL_ATTR_MAIL, 0,
|
ATTR_TYPE_NUM, ANVIL_ATTR_MAIL, 0,
|
||||||
ATTR_TYPE_NUM, ANVIL_ATTR_RCPT, 0,
|
ATTR_TYPE_NUM, ANVIL_ATTR_RCPT, 0,
|
||||||
|
ATTR_TYPE_NUM, ANVIL_ATTR_NTLS, 0,
|
||||||
ATTR_TYPE_END);
|
ATTR_TYPE_END);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do not report stale information.
|
||||||
|
*/
|
||||||
|
if (anvil_remote->start != 0
|
||||||
|
&& anvil_remote->start + var_anvil_time_unit < event_time())
|
||||||
|
ANVIL_REMOTE_RSET_RATE(anvil_remote, 0);
|
||||||
attr_print_plain(client_stream, ATTR_FLAG_NONE,
|
attr_print_plain(client_stream, ATTR_FLAG_NONE,
|
||||||
ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_OK,
|
ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_OK,
|
||||||
ATTR_TYPE_NUM, ANVIL_ATTR_COUNT, anvil_remote->count,
|
ATTR_TYPE_NUM, ANVIL_ATTR_COUNT, anvil_remote->count,
|
||||||
ATTR_TYPE_NUM, ANVIL_ATTR_RATE, anvil_remote->rate,
|
ATTR_TYPE_NUM, ANVIL_ATTR_RATE, anvil_remote->rate,
|
||||||
ATTR_TYPE_NUM, ANVIL_ATTR_MAIL, anvil_remote->mail,
|
ATTR_TYPE_NUM, ANVIL_ATTR_MAIL, anvil_remote->mail,
|
||||||
ATTR_TYPE_NUM, ANVIL_ATTR_RCPT, anvil_remote->rcpt,
|
ATTR_TYPE_NUM, ANVIL_ATTR_RCPT, anvil_remote->rcpt,
|
||||||
|
ATTR_TYPE_NUM, ANVIL_ATTR_NTLS, anvil_remote->ntls,
|
||||||
ATTR_TYPE_END);
|
ATTR_TYPE_END);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -542,14 +576,14 @@ static ANVIL_REMOTE *anvil_remote_conn_update(VSTREAM *client_stream, const char
|
|||||||
if ((anvil_remote =
|
if ((anvil_remote =
|
||||||
(ANVIL_REMOTE *) htable_find(anvil_remote_map, ident)) == 0) {
|
(ANVIL_REMOTE *) htable_find(anvil_remote_map, ident)) == 0) {
|
||||||
anvil_remote = (ANVIL_REMOTE *) mymalloc(sizeof(*anvil_remote));
|
anvil_remote = (ANVIL_REMOTE *) mymalloc(sizeof(*anvil_remote));
|
||||||
ANVIL_REMOTE_FIRST(anvil_remote, ident);
|
ANVIL_REMOTE_FIRST_CONN(anvil_remote, ident);
|
||||||
htable_enter(anvil_remote_map, ident, (char *) anvil_remote);
|
htable_enter(anvil_remote_map, ident, (char *) anvil_remote);
|
||||||
if (max_cache < anvil_remote_map->used) {
|
if (max_cache_size < anvil_remote_map->used) {
|
||||||
max_cache = anvil_remote_map->used;
|
max_cache_size = anvil_remote_map->used;
|
||||||
max_cache_time = event_time();
|
max_cache_time = event_time();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ANVIL_REMOTE_NEXT(anvil_remote);
|
ANVIL_REMOTE_NEXT_CONN(anvil_remote);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -592,28 +626,12 @@ static void anvil_remote_connect(VSTREAM *client_stream, const char *ident)
|
|||||||
ATTR_TYPE_END);
|
ATTR_TYPE_END);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update local statistics.
|
* Update peak statistics.
|
||||||
*/
|
*/
|
||||||
if (anvil_remote->rate > max_rate) {
|
if (anvil_remote->rate > max_conn_rate.value)
|
||||||
max_rate = anvil_remote->rate;
|
ANVIL_MAX_UPDATE(max_conn_rate, anvil_remote->rate, anvil_remote->ident);
|
||||||
if (max_rate_user == 0) {
|
if (anvil_remote->count > max_conn_count.value)
|
||||||
max_rate_user = mystrdup(anvil_remote->ident);
|
ANVIL_MAX_UPDATE(max_conn_count, anvil_remote->count, anvil_remote->ident);
|
||||||
} else if (!STREQ(max_rate_user, anvil_remote->ident)) {
|
|
||||||
myfree(max_rate_user);
|
|
||||||
max_rate_user = mystrdup(anvil_remote->ident);
|
|
||||||
}
|
|
||||||
max_rate_time = event_time();
|
|
||||||
}
|
|
||||||
if (anvil_remote->count > max_count) {
|
|
||||||
max_count = anvil_remote->count;
|
|
||||||
if (max_count_user == 0) {
|
|
||||||
max_count_user = mystrdup(anvil_remote->ident);
|
|
||||||
} else if (!STREQ(max_count_user, anvil_remote->ident)) {
|
|
||||||
myfree(max_count_user);
|
|
||||||
max_count_user = mystrdup(anvil_remote->ident);
|
|
||||||
}
|
|
||||||
max_count_time = event_time();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* anvil_remote_mail - register message delivery request */
|
/* anvil_remote_mail - register message delivery request */
|
||||||
@ -632,25 +650,17 @@ static void anvil_remote_mail(VSTREAM *client_stream, const char *ident)
|
|||||||
/*
|
/*
|
||||||
* Update message delivery request rate and respond to local client.
|
* Update message delivery request rate and respond to local client.
|
||||||
*/
|
*/
|
||||||
ANVIL_ADD_MAIL(anvil_remote);
|
ANVIL_REMOTE_INCR_MAIL(anvil_remote);
|
||||||
attr_print_plain(client_stream, ATTR_FLAG_NONE,
|
attr_print_plain(client_stream, ATTR_FLAG_NONE,
|
||||||
ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_OK,
|
ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_OK,
|
||||||
ATTR_TYPE_NUM, ANVIL_ATTR_RATE, anvil_remote->mail,
|
ATTR_TYPE_NUM, ANVIL_ATTR_RATE, anvil_remote->mail,
|
||||||
ATTR_TYPE_END);
|
ATTR_TYPE_END);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update local statistics.
|
* Update peak statistics.
|
||||||
*/
|
*/
|
||||||
if (anvil_remote->mail > max_mail) {
|
if (anvil_remote->mail > max_mail_rate.value)
|
||||||
max_mail = anvil_remote->mail;
|
ANVIL_MAX_UPDATE(max_mail_rate, anvil_remote->mail, anvil_remote->ident);
|
||||||
if (max_mail_user == 0) {
|
|
||||||
max_mail_user = mystrdup(anvil_remote->ident);
|
|
||||||
} else if (!STREQ(max_mail_user, anvil_remote->ident)) {
|
|
||||||
myfree(max_mail_user);
|
|
||||||
max_mail_user = mystrdup(anvil_remote->ident);
|
|
||||||
}
|
|
||||||
max_mail_time = event_time();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* anvil_remote_rcpt - register recipient address event */
|
/* anvil_remote_rcpt - register recipient address event */
|
||||||
@ -669,25 +679,17 @@ static void anvil_remote_rcpt(VSTREAM *client_stream, const char *ident)
|
|||||||
/*
|
/*
|
||||||
* Update recipient address rate and respond to local client.
|
* Update recipient address rate and respond to local client.
|
||||||
*/
|
*/
|
||||||
ANVIL_ADD_RCPT(anvil_remote);
|
ANVIL_REMOTE_INCR_RCPT(anvil_remote);
|
||||||
attr_print_plain(client_stream, ATTR_FLAG_NONE,
|
attr_print_plain(client_stream, ATTR_FLAG_NONE,
|
||||||
ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_OK,
|
ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_OK,
|
||||||
ATTR_TYPE_NUM, ANVIL_ATTR_RATE, anvil_remote->rcpt,
|
ATTR_TYPE_NUM, ANVIL_ATTR_RATE, anvil_remote->rcpt,
|
||||||
ATTR_TYPE_END);
|
ATTR_TYPE_END);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update local statistics.
|
* Update peak statistics.
|
||||||
*/
|
*/
|
||||||
if (anvil_remote->rcpt > max_rcpt) {
|
if (anvil_remote->rcpt > max_rcpt_rate.value)
|
||||||
max_rcpt = anvil_remote->rcpt;
|
ANVIL_MAX_UPDATE(max_rcpt_rate, anvil_remote->rcpt, anvil_remote->ident);
|
||||||
if (max_rcpt_user == 0) {
|
|
||||||
max_rcpt_user = mystrdup(anvil_remote->ident);
|
|
||||||
} else if (!STREQ(max_rcpt_user, anvil_remote->ident)) {
|
|
||||||
myfree(max_rcpt_user);
|
|
||||||
max_rcpt_user = mystrdup(anvil_remote->ident);
|
|
||||||
}
|
|
||||||
max_rcpt_time = event_time();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* anvil_remote_newtls - register newtls event */
|
/* anvil_remote_newtls - register newtls event */
|
||||||
@ -706,25 +708,51 @@ static void anvil_remote_newtls(VSTREAM *client_stream, const char *ident)
|
|||||||
/*
|
/*
|
||||||
* Update newtls rate and respond to local client.
|
* Update newtls rate and respond to local client.
|
||||||
*/
|
*/
|
||||||
ANVIL_ADD_STARTTLS(anvil_remote);
|
ANVIL_REMOTE_INCR_NTLS(anvil_remote);
|
||||||
attr_print_plain(client_stream, ATTR_FLAG_NONE,
|
attr_print_plain(client_stream, ATTR_FLAG_NONE,
|
||||||
ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_OK,
|
ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_OK,
|
||||||
ATTR_TYPE_NUM, ANVIL_ATTR_RATE, anvil_remote->newtls,
|
ATTR_TYPE_NUM, ANVIL_ATTR_RATE, anvil_remote->ntls,
|
||||||
ATTR_TYPE_END);
|
ATTR_TYPE_END);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update local statistics.
|
* Update peak statistics.
|
||||||
*/
|
*/
|
||||||
if (anvil_remote->newtls > max_newtls) {
|
if (anvil_remote->ntls > max_ntls_rate.value)
|
||||||
max_newtls = anvil_remote->newtls;
|
ANVIL_MAX_UPDATE(max_ntls_rate, anvil_remote->ntls, anvil_remote->ident);
|
||||||
if (max_newtls_user == 0) {
|
|
||||||
max_newtls_user = mystrdup(anvil_remote->ident);
|
|
||||||
} else if (!STREQ(max_newtls_user, anvil_remote->ident)) {
|
|
||||||
myfree(max_newtls_user);
|
|
||||||
max_newtls_user = mystrdup(anvil_remote->ident);
|
|
||||||
}
|
}
|
||||||
max_newtls_time = event_time();
|
|
||||||
|
/* anvil_remote_newtls_stat - report newtls stats */
|
||||||
|
|
||||||
|
static void anvil_remote_newtls_stat(VSTREAM *client_stream, const char *ident)
|
||||||
|
{
|
||||||
|
ANVIL_REMOTE *anvil_remote;
|
||||||
|
int rate;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Be prepared for "postfix reload" after "connect".
|
||||||
|
*/
|
||||||
|
if ((anvil_remote =
|
||||||
|
(ANVIL_REMOTE *) htable_find(anvil_remote_map, ident)) == 0) {
|
||||||
|
rate = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do not report stale information.
|
||||||
|
*/
|
||||||
|
else {
|
||||||
|
if (anvil_remote->start != 0
|
||||||
|
&& anvil_remote->start + var_anvil_time_unit < event_time())
|
||||||
|
ANVIL_REMOTE_RSET_RATE(anvil_remote, 0);
|
||||||
|
rate = anvil_remote->ntls;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Respond to local client.
|
||||||
|
*/
|
||||||
|
attr_print_plain(client_stream, ATTR_FLAG_NONE,
|
||||||
|
ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_OK,
|
||||||
|
ATTR_TYPE_NUM, ANVIL_ATTR_RATE, rate,
|
||||||
|
ATTR_TYPE_END);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* anvil_remote_disconnect - report disconnect event */
|
/* anvil_remote_disconnect - report disconnect event */
|
||||||
@ -796,8 +824,19 @@ static void anvil_service_done(VSTREAM *client_stream, char *unused_service,
|
|||||||
|
|
||||||
static void anvil_service(VSTREAM *client_stream, char *unused_service, char **argv)
|
static void anvil_service(VSTREAM *client_stream, char *unused_service, char **argv)
|
||||||
{
|
{
|
||||||
VSTRING *request = vstring_alloc(10);
|
static VSTRING *request;
|
||||||
VSTRING *ident = vstring_alloc(10);
|
static VSTRING *ident;
|
||||||
|
static ANVIL_REQ_TABLE request_table[] = {
|
||||||
|
ANVIL_REQ_CONN, anvil_remote_connect,
|
||||||
|
ANVIL_REQ_MAIL, anvil_remote_mail,
|
||||||
|
ANVIL_REQ_RCPT, anvil_remote_rcpt,
|
||||||
|
ANVIL_REQ_NTLS, anvil_remote_newtls,
|
||||||
|
ANVIL_REQ_DISC, anvil_remote_disconnect,
|
||||||
|
ANVIL_REQ_NTLS_STAT, anvil_remote_newtls_stat,
|
||||||
|
ANVIL_REQ_LOOKUP, anvil_remote_lookup,
|
||||||
|
0, 0,
|
||||||
|
};
|
||||||
|
ANVIL_REQ_TABLE *rp;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sanity check. This service takes no command-line arguments.
|
* Sanity check. This service takes no command-line arguments.
|
||||||
@ -805,6 +844,14 @@ static void anvil_service(VSTREAM *client_stream, char *unused_service, char **a
|
|||||||
if (argv[0])
|
if (argv[0])
|
||||||
msg_fatal("unexpected command-line argument: %s", argv[0]);
|
msg_fatal("unexpected command-line argument: %s", argv[0]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize.
|
||||||
|
*/
|
||||||
|
if (request == 0) {
|
||||||
|
request = vstring_alloc(10);
|
||||||
|
ident = vstring_alloc(10);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This routine runs whenever a client connects to the socket dedicated
|
* This routine runs whenever a client connects to the socket dedicated
|
||||||
* to the client connection rate management service. All
|
* to the client connection rate management service. All
|
||||||
@ -818,23 +865,18 @@ static void anvil_service(VSTREAM *client_stream, char *unused_service, char **a
|
|||||||
ATTR_TYPE_STR, ANVIL_ATTR_REQ, request,
|
ATTR_TYPE_STR, ANVIL_ATTR_REQ, request,
|
||||||
ATTR_TYPE_STR, ANVIL_ATTR_IDENT, ident,
|
ATTR_TYPE_STR, ANVIL_ATTR_IDENT, ident,
|
||||||
ATTR_TYPE_END) == 2) {
|
ATTR_TYPE_END) == 2) {
|
||||||
if (STREQ(STR(request), ANVIL_REQ_CONN)) {
|
for (rp = request_table; /* see below */ ; rp++) {
|
||||||
anvil_remote_connect(client_stream, STR(ident));
|
if (rp->name == 0) {
|
||||||
} else if (STREQ(STR(request), ANVIL_REQ_MAIL)) {
|
|
||||||
anvil_remote_mail(client_stream, STR(ident));
|
|
||||||
} else if (STREQ(STR(request), ANVIL_REQ_RCPT)) {
|
|
||||||
anvil_remote_rcpt(client_stream, STR(ident));
|
|
||||||
} else if (STREQ(STR(request), ANVIL_REQ_NEWTLS)) {
|
|
||||||
anvil_remote_newtls(client_stream, STR(ident));
|
|
||||||
} else if (STREQ(STR(request), ANVIL_REQ_DISC)) {
|
|
||||||
anvil_remote_disconnect(client_stream, STR(ident));
|
|
||||||
} else if (STREQ(STR(request), ANVIL_REQ_LOOKUP)) {
|
|
||||||
anvil_remote_lookup(client_stream, STR(ident));
|
|
||||||
} else {
|
|
||||||
msg_warn("unrecognized request: \"%s\", ignored", STR(request));
|
msg_warn("unrecognized request: \"%s\", ignored", STR(request));
|
||||||
attr_print_plain(client_stream, ATTR_FLAG_NONE,
|
attr_print_plain(client_stream, ATTR_FLAG_NONE,
|
||||||
ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_FAIL,
|
ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_FAIL,
|
||||||
ATTR_TYPE_END);
|
ATTR_TYPE_END);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (STREQ(rp->name, STR(request))) {
|
||||||
|
rp->action(client_stream, STR(ident));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
vstream_fflush(client_stream);
|
vstream_fflush(client_stream);
|
||||||
} else {
|
} else {
|
||||||
@ -843,8 +885,6 @@ static void anvil_service(VSTREAM *client_stream, char *unused_service, char **a
|
|||||||
}
|
}
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_info("--- end request ---");
|
msg_info("--- end request ---");
|
||||||
vstring_free(ident);
|
|
||||||
vstring_free(request);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* post_jail_init - post-jail initialization */
|
/* post_jail_init - post-jail initialization */
|
||||||
@ -874,39 +914,16 @@ static void post_jail_init(char *unused_name, char **unused_argv)
|
|||||||
|
|
||||||
static void anvil_status_dump(char *unused_name, char **unused_argv)
|
static void anvil_status_dump(char *unused_name, char **unused_argv)
|
||||||
{
|
{
|
||||||
if (max_rate > 0) {
|
ANVIL_MAX_RATE_REPORT(max_conn_rate, "connection");
|
||||||
msg_info("statistics: max connection rate %d/%ds for (%s) at %.15s",
|
ANVIL_MAX_COUNT_REPORT(max_conn_count, "connection");
|
||||||
max_rate, var_anvil_time_unit,
|
ANVIL_MAX_RATE_REPORT(max_mail_rate, "message");
|
||||||
max_rate_user, ctime(&max_rate_time) + 4);
|
ANVIL_MAX_RATE_REPORT(max_rcpt_rate, "recipient");
|
||||||
max_rate = 0;
|
ANVIL_MAX_RATE_REPORT(max_ntls_rate, "newtls");
|
||||||
}
|
|
||||||
if (max_count > 0) {
|
if (max_cache_size > 0) {
|
||||||
msg_info("statistics: max connection count %d for (%s) at %.15s",
|
|
||||||
max_count, max_count_user, ctime(&max_count_time) + 4);
|
|
||||||
max_count = 0;
|
|
||||||
}
|
|
||||||
if (max_mail > 0) {
|
|
||||||
msg_info("statistics: max message rate %d/%ds for (%s) at %.15s",
|
|
||||||
max_mail, var_anvil_time_unit,
|
|
||||||
max_mail_user, ctime(&max_mail_time) + 4);
|
|
||||||
max_mail = 0;
|
|
||||||
}
|
|
||||||
if (max_rcpt > 0) {
|
|
||||||
msg_info("statistics: max recipient rate %d/%ds for (%s) at %.15s",
|
|
||||||
max_rcpt, var_anvil_time_unit,
|
|
||||||
max_rcpt_user, ctime(&max_rcpt_time) + 4);
|
|
||||||
max_rcpt = 0;
|
|
||||||
}
|
|
||||||
if (max_newtls > 0) {
|
|
||||||
msg_info("statistics: max newtls rate %d/%ds for (%s) at %.15s",
|
|
||||||
max_newtls, var_anvil_time_unit,
|
|
||||||
max_newtls_user, ctime(&max_newtls_time) + 4);
|
|
||||||
max_newtls = 0;
|
|
||||||
}
|
|
||||||
if (max_cache > 0) {
|
|
||||||
msg_info("statistics: max cache size %d at %.15s",
|
msg_info("statistics: max cache size %d at %.15s",
|
||||||
max_cache, ctime(&max_cache_time) + 4);
|
max_cache_size, ctime(&max_cache_time) + 4);
|
||||||
max_cache = 0;
|
max_cache_size = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,6 +37,12 @@
|
|||||||
/* const char *addr;
|
/* const char *addr;
|
||||||
/* int *newtls;
|
/* int *newtls;
|
||||||
/*
|
/*
|
||||||
|
/* int anvil_clnt_newtls_stat(anvil_clnt, service, addr, newtls)
|
||||||
|
/* ANVIL_CLNT *anvil_clnt;
|
||||||
|
/* const char *service;
|
||||||
|
/* const char *addr;
|
||||||
|
/* int *newtls;
|
||||||
|
/*
|
||||||
/* int anvil_clnt_disconnect(anvil_clnt, service, addr)
|
/* int anvil_clnt_disconnect(anvil_clnt, service, addr)
|
||||||
/* ANVIL_CLNT *anvil_clnt;
|
/* ANVIL_CLNT *anvil_clnt;
|
||||||
/* const char *service;
|
/* const char *service;
|
||||||
@ -52,29 +58,36 @@
|
|||||||
/* int *msgs;
|
/* int *msgs;
|
||||||
/* int *rcpts;
|
/* int *rcpts;
|
||||||
/* DESCRIPTION
|
/* DESCRIPTION
|
||||||
/* anvil_clnt_create() instantiates an anvil service client endpoint.
|
/* anvil_clnt_create() instantiates a local anvil service
|
||||||
|
/* client endpoint.
|
||||||
/*
|
/*
|
||||||
/* anvil_clnt_connect() informs the anvil server that a
|
/* anvil_clnt_connect() informs the anvil server that a
|
||||||
/* client has connected, and returns the current connection
|
/* remote client has connected, and returns the current
|
||||||
/* count and connection rate for that client.
|
/* connection count and connection rate for that remote client.
|
||||||
/*
|
/*
|
||||||
/* anvil_clnt_mail() registers a MAIL FROM event and returns
|
/* anvil_clnt_mail() registers a MAIL FROM event and
|
||||||
/* the current MAIL FROM rate for the specified client.
|
/* returns the current MAIL FROM rate for the specified remote
|
||||||
|
/* client.
|
||||||
/*
|
/*
|
||||||
/* anvil_clnt_rcpt() registers a RCPT TO event and returns
|
/* anvil_clnt_rcpt() registers a RCPT TO event and
|
||||||
/* the current RCPT TO rate for the specified client.
|
/* returns the current RCPT TO rate for the specified remote
|
||||||
|
/* client.
|
||||||
/*
|
/*
|
||||||
/* anvil_clnt_newtls() registers a request to negotiate a new
|
/* anvil_clnt_newtls() registers a remote client request
|
||||||
/* (uncached) TLS session and returns the current request rate
|
/* to negotiate a new (uncached) TLS session and returns the
|
||||||
/* for the specified client.
|
/* current newtls request rate for the specified remote client.
|
||||||
/*
|
/*
|
||||||
/* anvil_clnt_disconnect() informs the anvil server that a
|
/* anvil_clnt_newtls_stat() returns the current newtls request
|
||||||
|
/* rate for the specified remote client.
|
||||||
|
/*
|
||||||
|
/* anvil_clnt_disconnect() informs the anvil server that a remote
|
||||||
/* client has disconnected.
|
/* client has disconnected.
|
||||||
/*
|
/*
|
||||||
/* anvil_clnt_lookup() looks up the current connection
|
/* anvil_clnt_lookup() returns the current count and rate
|
||||||
/* count and connection rate for that client.
|
/* information for the specified client.
|
||||||
/*
|
/*
|
||||||
/* anvil_clnt_free() destroys an anvil service client endpoint.
|
/* anvil_clnt_free() destroys a local anvil service client
|
||||||
|
/* endpoint.
|
||||||
/*
|
/*
|
||||||
/* Arguments:
|
/* Arguments:
|
||||||
/* .IP anvil_clnt
|
/* .IP anvil_clnt
|
||||||
@ -99,7 +112,7 @@
|
|||||||
/* Pointer to storage for the current "new TLS session" rate
|
/* Pointer to storage for the current "new TLS session" rate
|
||||||
/* for this remote client.
|
/* for this remote client.
|
||||||
/* DIAGNOSTICS
|
/* DIAGNOSTICS
|
||||||
/* anvil_clnt_connect() and anvil_clnt_disconnect() return
|
/* The update and status query routines return
|
||||||
/* ANVIL_STAT_OK in case of success, ANVIL_STAT_FAIL otherwise
|
/* ANVIL_STAT_OK in case of success, ANVIL_STAT_FAIL otherwise
|
||||||
/* (either the communication with the server is broken or the
|
/* (either the communication with the server is broken or the
|
||||||
/* server experienced a problem).
|
/* server experienced a problem).
|
||||||
@ -168,7 +181,7 @@ void anvil_clnt_free(ANVIL_CLNT *anvil_clnt)
|
|||||||
|
|
||||||
int anvil_clnt_lookup(ANVIL_CLNT *anvil_clnt, const char *service,
|
int anvil_clnt_lookup(ANVIL_CLNT *anvil_clnt, const char *service,
|
||||||
const char *addr, int *count, int *rate,
|
const char *addr, int *count, int *rate,
|
||||||
int *msgs, int *rcpts)
|
int *msgs, int *rcpts, int *newtls)
|
||||||
{
|
{
|
||||||
char *ident = ANVIL_IDENT(service, addr);
|
char *ident = ANVIL_IDENT(service, addr);
|
||||||
int status;
|
int status;
|
||||||
@ -184,7 +197,8 @@ int anvil_clnt_lookup(ANVIL_CLNT *anvil_clnt, const char *service,
|
|||||||
ATTR_TYPE_NUM, ANVIL_ATTR_RATE, rate,
|
ATTR_TYPE_NUM, ANVIL_ATTR_RATE, rate,
|
||||||
ATTR_TYPE_NUM, ANVIL_ATTR_MAIL, msgs,
|
ATTR_TYPE_NUM, ANVIL_ATTR_MAIL, msgs,
|
||||||
ATTR_TYPE_NUM, ANVIL_ATTR_RCPT, rcpts,
|
ATTR_TYPE_NUM, ANVIL_ATTR_RCPT, rcpts,
|
||||||
ATTR_TYPE_END) != 5)
|
ATTR_TYPE_NUM, ANVIL_ATTR_NTLS, newtls,
|
||||||
|
ATTR_TYPE_END) != 6)
|
||||||
status = ANVIL_STAT_FAIL;
|
status = ANVIL_STAT_FAIL;
|
||||||
else if (status != ANVIL_STAT_OK)
|
else if (status != ANVIL_STAT_OK)
|
||||||
status = ANVIL_STAT_FAIL;
|
status = ANVIL_STAT_FAIL;
|
||||||
@ -192,7 +206,7 @@ int anvil_clnt_lookup(ANVIL_CLNT *anvil_clnt, const char *service,
|
|||||||
return (status);
|
return (status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* anvil_clnt_connect - heads-up and policy query */
|
/* anvil_clnt_connect - heads-up and status query */
|
||||||
|
|
||||||
int anvil_clnt_connect(ANVIL_CLNT *anvil_clnt, const char *service,
|
int anvil_clnt_connect(ANVIL_CLNT *anvil_clnt, const char *service,
|
||||||
const char *addr, int *count, int *rate)
|
const char *addr, int *count, int *rate)
|
||||||
@ -217,7 +231,7 @@ int anvil_clnt_connect(ANVIL_CLNT *anvil_clnt, const char *service,
|
|||||||
return (status);
|
return (status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* anvil_clnt_mail - heads-up and policy query */
|
/* anvil_clnt_mail - heads-up and status query */
|
||||||
|
|
||||||
int anvil_clnt_mail(ANVIL_CLNT *anvil_clnt, const char *service,
|
int anvil_clnt_mail(ANVIL_CLNT *anvil_clnt, const char *service,
|
||||||
const char *addr, int *msgs)
|
const char *addr, int *msgs)
|
||||||
@ -241,7 +255,7 @@ int anvil_clnt_mail(ANVIL_CLNT *anvil_clnt, const char *service,
|
|||||||
return (status);
|
return (status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* anvil_clnt_rcpt - heads-up and policy query */
|
/* anvil_clnt_rcpt - heads-up and status query */
|
||||||
|
|
||||||
int anvil_clnt_rcpt(ANVIL_CLNT *anvil_clnt, const char *service,
|
int anvil_clnt_rcpt(ANVIL_CLNT *anvil_clnt, const char *service,
|
||||||
const char *addr, int *rcpts)
|
const char *addr, int *rcpts)
|
||||||
@ -265,7 +279,7 @@ int anvil_clnt_rcpt(ANVIL_CLNT *anvil_clnt, const char *service,
|
|||||||
return (status);
|
return (status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* anvil_clnt_newtls - heads-up and policy query */
|
/* anvil_clnt_newtls - heads-up and status query */
|
||||||
|
|
||||||
int anvil_clnt_newtls(ANVIL_CLNT *anvil_clnt, const char *service,
|
int anvil_clnt_newtls(ANVIL_CLNT *anvil_clnt, const char *service,
|
||||||
const char *addr, int *newtls)
|
const char *addr, int *newtls)
|
||||||
@ -275,7 +289,31 @@ int anvil_clnt_newtls(ANVIL_CLNT *anvil_clnt, const char *service,
|
|||||||
|
|
||||||
if (attr_clnt_request((ATTR_CLNT *) anvil_clnt,
|
if (attr_clnt_request((ATTR_CLNT *) anvil_clnt,
|
||||||
ATTR_FLAG_NONE, /* Query attributes. */
|
ATTR_FLAG_NONE, /* Query attributes. */
|
||||||
ATTR_TYPE_STR, ANVIL_ATTR_REQ, ANVIL_REQ_NEWTLS,
|
ATTR_TYPE_STR, ANVIL_ATTR_REQ, ANVIL_REQ_NTLS,
|
||||||
|
ATTR_TYPE_STR, ANVIL_ATTR_IDENT, ident,
|
||||||
|
ATTR_TYPE_END,
|
||||||
|
ATTR_FLAG_MISSING, /* Reply attributes. */
|
||||||
|
ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, &status,
|
||||||
|
ATTR_TYPE_NUM, ANVIL_ATTR_RATE, newtls,
|
||||||
|
ATTR_TYPE_END) != 2)
|
||||||
|
status = ANVIL_STAT_FAIL;
|
||||||
|
else if (status != ANVIL_STAT_OK)
|
||||||
|
status = ANVIL_STAT_FAIL;
|
||||||
|
myfree(ident);
|
||||||
|
return (status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* anvil_clnt_newtls_stat - status query */
|
||||||
|
|
||||||
|
int anvil_clnt_newtls_stat(ANVIL_CLNT *anvil_clnt, const char *service,
|
||||||
|
const char *addr, int *newtls)
|
||||||
|
{
|
||||||
|
char *ident = ANVIL_IDENT(service, addr);
|
||||||
|
int status;
|
||||||
|
|
||||||
|
if (attr_clnt_request((ATTR_CLNT *) anvil_clnt,
|
||||||
|
ATTR_FLAG_NONE, /* Query attributes. */
|
||||||
|
ATTR_TYPE_STR, ANVIL_ATTR_REQ, ANVIL_REQ_NTLS_STAT,
|
||||||
ATTR_TYPE_STR, ANVIL_ATTR_IDENT, ident,
|
ATTR_TYPE_STR, ANVIL_ATTR_IDENT, ident,
|
||||||
ATTR_TYPE_END,
|
ATTR_TYPE_END,
|
||||||
ATTR_FLAG_MISSING, /* Reply attributes. */
|
ATTR_FLAG_MISSING, /* Reply attributes. */
|
||||||
@ -326,10 +364,14 @@ int anvil_clnt_disconnect(ANVIL_CLNT *anvil_clnt, const char *service,
|
|||||||
|
|
||||||
static void usage(void)
|
static void usage(void)
|
||||||
{
|
{
|
||||||
vstream_printf("usage: %s service addr | %s service addr |"
|
vstream_printf("usage: "
|
||||||
" %s service addr | %s service addr\n",
|
ANVIL_REQ_CONN " service addr | "
|
||||||
ANVIL_REQ_CONN, ANVIL_REQ_DISC,
|
ANVIL_REQ_DISC " service addr | "
|
||||||
ANVIL_REQ_MAIL, ANVIL_REQ_RCPT);
|
ANVIL_REQ_MAIL " service addr | "
|
||||||
|
ANVIL_REQ_RCPT " service addr | "
|
||||||
|
ANVIL_REQ_NTLS " service addr | "
|
||||||
|
ANVIL_REQ_NTLS_STAT " service addr | "
|
||||||
|
ANVIL_REQ_LOOKUP " service addr\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int unused_argc, char **argv)
|
int main(int unused_argc, char **argv)
|
||||||
@ -344,6 +386,7 @@ int main(int unused_argc, char **argv)
|
|||||||
int rate;
|
int rate;
|
||||||
int msgs;
|
int msgs;
|
||||||
int rcpts;
|
int rcpts;
|
||||||
|
int newtls;
|
||||||
ANVIL_CLNT *anvil;
|
ANVIL_CLNT *anvil;
|
||||||
|
|
||||||
msg_vstream_init(argv[0], VSTREAM_ERR);
|
msg_vstream_init(argv[0], VSTREAM_ERR);
|
||||||
@ -384,6 +427,16 @@ int main(int unused_argc, char **argv)
|
|||||||
msg_warn("error!");
|
msg_warn("error!");
|
||||||
else
|
else
|
||||||
vstream_printf("rate=%d\n", rcpts);
|
vstream_printf("rate=%d\n", rcpts);
|
||||||
|
} else if (strncmp(cmd, ANVIL_REQ_NTLS, cmd_len) == 0) {
|
||||||
|
if (anvil_clnt_newtls(anvil, service, addr, &newtls) != ANVIL_STAT_OK)
|
||||||
|
msg_warn("error!");
|
||||||
|
else
|
||||||
|
vstream_printf("rate=%d\n", newtls);
|
||||||
|
} else if (strncmp(cmd, ANVIL_REQ_NTLS_STAT, cmd_len) == 0) {
|
||||||
|
if (anvil_clnt_newtls_stat(anvil, service, addr, &newtls) != ANVIL_STAT_OK)
|
||||||
|
msg_warn("error!");
|
||||||
|
else
|
||||||
|
vstream_printf("rate=%d\n", newtls);
|
||||||
} else if (strncmp(cmd, ANVIL_REQ_DISC, cmd_len) == 0) {
|
} else if (strncmp(cmd, ANVIL_REQ_DISC, cmd_len) == 0) {
|
||||||
if (anvil_clnt_disconnect(anvil, service, addr) != ANVIL_STAT_OK)
|
if (anvil_clnt_disconnect(anvil, service, addr) != ANVIL_STAT_OK)
|
||||||
msg_warn("error!");
|
msg_warn("error!");
|
||||||
@ -391,11 +444,11 @@ int main(int unused_argc, char **argv)
|
|||||||
vstream_printf("OK\n");
|
vstream_printf("OK\n");
|
||||||
} else if (strncmp(cmd, ANVIL_REQ_LOOKUP, cmd_len) == 0) {
|
} else if (strncmp(cmd, ANVIL_REQ_LOOKUP, cmd_len) == 0) {
|
||||||
if (anvil_clnt_lookup(anvil, service, addr, &count, &rate,
|
if (anvil_clnt_lookup(anvil, service, addr, &count, &rate,
|
||||||
&msgs, &rcpts) != ANVIL_STAT_OK)
|
&msgs, &rcpts, &newtls) != ANVIL_STAT_OK)
|
||||||
msg_warn("error!");
|
msg_warn("error!");
|
||||||
else
|
else
|
||||||
vstream_printf("count=%d, rate=%d msgs=%d rcpts=%d\n",
|
vstream_printf("count=%d, rate=%d msgs=%d rcpts=%d newtls=%d\n",
|
||||||
count, rate, msgs, rcpts);
|
count, rate, msgs, rcpts, newtls);
|
||||||
} else {
|
} else {
|
||||||
vstream_printf("bad command: \"%s\"\n", cmd);
|
vstream_printf("bad command: \"%s\"\n", cmd);
|
||||||
usage();
|
usage();
|
||||||
|
@ -32,13 +32,15 @@
|
|||||||
#define ANVIL_REQ_DISC "disconnect"
|
#define ANVIL_REQ_DISC "disconnect"
|
||||||
#define ANVIL_REQ_MAIL "message"
|
#define ANVIL_REQ_MAIL "message"
|
||||||
#define ANVIL_REQ_RCPT "recipient"
|
#define ANVIL_REQ_RCPT "recipient"
|
||||||
#define ANVIL_REQ_NEWTLS "newtls"
|
#define ANVIL_REQ_NTLS "newtls"
|
||||||
|
#define ANVIL_REQ_NTLS_STAT "newtls_status"
|
||||||
#define ANVIL_REQ_LOOKUP "lookup"
|
#define ANVIL_REQ_LOOKUP "lookup"
|
||||||
#define ANVIL_ATTR_IDENT "ident"
|
#define ANVIL_ATTR_IDENT "ident"
|
||||||
#define ANVIL_ATTR_COUNT "count"
|
#define ANVIL_ATTR_COUNT "count"
|
||||||
#define ANVIL_ATTR_RATE "rate"
|
#define ANVIL_ATTR_RATE "rate"
|
||||||
#define ANVIL_ATTR_MAIL "mail"
|
#define ANVIL_ATTR_MAIL "mail"
|
||||||
#define ANVIL_ATTR_RCPT "rcpt"
|
#define ANVIL_ATTR_RCPT "rcpt"
|
||||||
|
#define ANVIL_ATTR_NTLS "newtls"
|
||||||
#define ANVIL_ATTR_STATUS "status"
|
#define ANVIL_ATTR_STATUS "status"
|
||||||
|
|
||||||
#define ANVIL_STAT_OK 0
|
#define ANVIL_STAT_OK 0
|
||||||
@ -54,7 +56,8 @@ extern int anvil_clnt_connect(ANVIL_CLNT *, const char *, const char *, int *, i
|
|||||||
extern int anvil_clnt_mail(ANVIL_CLNT *, const char *, const char *, int *);
|
extern int anvil_clnt_mail(ANVIL_CLNT *, const char *, const char *, int *);
|
||||||
extern int anvil_clnt_rcpt(ANVIL_CLNT *, const char *, const char *, int *);
|
extern int anvil_clnt_rcpt(ANVIL_CLNT *, const char *, const char *, int *);
|
||||||
extern int anvil_clnt_newtls(ANVIL_CLNT *, const char *, const char *, int *);
|
extern int anvil_clnt_newtls(ANVIL_CLNT *, const char *, const char *, int *);
|
||||||
extern int anvil_clnt_lookup(ANVIL_CLNT *, const char *, const char *, int *, int *, int *, int *);
|
extern int anvil_clnt_newtls_stat(ANVIL_CLNT *, const char *, const char *, int *);
|
||||||
|
extern int anvil_clnt_lookup(ANVIL_CLNT *, const char *, const char *, int *, int *, int *, int *, int *);
|
||||||
extern int anvil_clnt_disconnect(ANVIL_CLNT *, const char *, const char *);
|
extern int anvil_clnt_disconnect(ANVIL_CLNT *, const char *, const char *);
|
||||||
extern void anvil_clnt_free(ANVIL_CLNT *);
|
extern void anvil_clnt_free(ANVIL_CLNT *);
|
||||||
|
|
||||||
|
@ -355,6 +355,7 @@ static DELIVER_REQUEST *deliver_request_alloc(void)
|
|||||||
request->sasl_username = 0;
|
request->sasl_username = 0;
|
||||||
request->sasl_sender = 0;
|
request->sasl_sender = 0;
|
||||||
request->rewrite_context = 0;
|
request->rewrite_context = 0;
|
||||||
|
request->dsn_envid = 0;
|
||||||
return (request);
|
return (request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1728,6 +1728,10 @@ ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`\
|
|||||||
abcdefghijklmnopqrstuvwxyz{|}~"
|
abcdefghijklmnopqrstuvwxyz{|}~"
|
||||||
extern char *var_smtpd_exp_filter;
|
extern char *var_smtpd_exp_filter;
|
||||||
|
|
||||||
|
#define VAR_SMTPD_PEERNAME_LOOKUP "smtpd_peername_lookup"
|
||||||
|
#define DEF_SMTPD_PEERNAME_LOOKUP 1
|
||||||
|
extern bool var_smtpd_peername_lookup;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Heuristic to reject unknown local recipients at the SMTP port.
|
* Heuristic to reject unknown local recipients at the SMTP port.
|
||||||
*/
|
*/
|
||||||
@ -2301,6 +2305,10 @@ extern int var_smtpd_cmail_limit;
|
|||||||
#define DEF_SMTPD_CRCPT_LIMIT 0
|
#define DEF_SMTPD_CRCPT_LIMIT 0
|
||||||
extern int var_smtpd_crcpt_limit;
|
extern int var_smtpd_crcpt_limit;
|
||||||
|
|
||||||
|
#define VAR_SMTPD_CNTLS_LIMIT "smtpd_client_new_tls_session_rate_limit"
|
||||||
|
#define DEF_SMTPD_CNTLS_LIMIT 0
|
||||||
|
extern int var_smtpd_cntls_limit;
|
||||||
|
|
||||||
#define VAR_SMTPD_HOGGERS "smtpd_client_event_limit_exceptions"
|
#define VAR_SMTPD_HOGGERS "smtpd_client_event_limit_exceptions"
|
||||||
#define DEF_SMTPD_HOGGERS "${smtpd_client_connection_limit_exceptions:$" VAR_MYNETWORKS "}"
|
#define DEF_SMTPD_HOGGERS "${smtpd_client_connection_limit_exceptions:$" VAR_MYNETWORKS "}"
|
||||||
extern char *var_smtpd_hoggers;
|
extern char *var_smtpd_hoggers;
|
||||||
@ -2380,10 +2388,6 @@ extern char *var_msg_strip_chars;
|
|||||||
#define DEF_FROZEN_DELIVERED 1
|
#define DEF_FROZEN_DELIVERED 1
|
||||||
extern bool var_frozen_delivered;
|
extern bool var_frozen_delivered;
|
||||||
|
|
||||||
#define VAR_STICKY_OWNER_ALIAS "sticky_owner_alias"
|
|
||||||
#define DEF_STICKY_OWNER_ALIAS 1
|
|
||||||
extern bool var_sticky_owner_alias;
|
|
||||||
|
|
||||||
/* LICENSE
|
/* LICENSE
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
|
@ -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 "20050923"
|
#define MAIL_RELEASE_DATE "20051010"
|
||||||
#define MAIL_VERSION_NUMBER "2.3"
|
#define MAIL_VERSION_NUMBER "2.3"
|
||||||
|
|
||||||
#ifdef SNAPSHOT
|
#ifdef SNAPSHOT
|
||||||
|
@ -95,6 +95,9 @@
|
|||||||
/* An I/O error happened, or the peer has disconnected unexpectedly.
|
/* An I/O error happened, or the peer has disconnected unexpectedly.
|
||||||
/* .IP SMTP_ERR_TIME
|
/* .IP SMTP_ERR_TIME
|
||||||
/* The time limit specified to smtp_timeout_setup() was exceeded.
|
/* The time limit specified to smtp_timeout_setup() was exceeded.
|
||||||
|
/* .IP SMTP_ERR_PROTO
|
||||||
|
/* This error is never generated by the smtp_stream(3) module, but
|
||||||
|
/* is defined for application-specific use.
|
||||||
/* BUGS
|
/* BUGS
|
||||||
/* The timeout deadline affects all I/O on the named stream, not
|
/* The timeout deadline affects all I/O on the named stream, not
|
||||||
/* just the I/O done on behalf of this module.
|
/* just the I/O done on behalf of this module.
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
*/
|
*/
|
||||||
#define SMTP_ERR_EOF 1 /* unexpected client disconnect */
|
#define SMTP_ERR_EOF 1 /* unexpected client disconnect */
|
||||||
#define SMTP_ERR_TIME 2 /* time out */
|
#define SMTP_ERR_TIME 2 /* time out */
|
||||||
|
#define SMTP_ERR_PROTO 3 /* protocol (application) */
|
||||||
|
|
||||||
extern void smtp_timeout_setup(VSTREAM *, int);
|
extern void smtp_timeout_setup(VSTREAM *, int);
|
||||||
extern void PRINTFLIKE(2, 3) smtp_printf(VSTREAM *, const char *,...);
|
extern void PRINTFLIKE(2, 3) smtp_printf(VSTREAM *, const char *,...);
|
||||||
|
@ -231,7 +231,21 @@ LMTP_RESP *lmtp_chat_resp(LMTP_STATE *state)
|
|||||||
if (*cp == ' ' || *cp == 0)
|
if (*cp == ' ' || *cp == 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX Do not ignore garbage when ESMTP command pipelining is turned
|
||||||
|
* on. After sending ".<CR><LF>QUIT<CR><LF>", Postfix might recognize
|
||||||
|
* the server's 2XX QUIT reply as a 2XX END-OF-DATA reply after
|
||||||
|
* garbage, causing mail to be lost. Instead, make a long jump so
|
||||||
|
* that all recipients of multi-recipient mail get consistent
|
||||||
|
* treatment.
|
||||||
|
*/
|
||||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||||
|
if (state->features & LMTP_FEATURE_PIPELINING) {
|
||||||
|
msg_warn("non-SMTP response from %s: %s",
|
||||||
|
session->namaddr, STR(state->buffer));
|
||||||
|
vstream_longjmp(session->stream, SMTP_ERR_PROTO);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -378,6 +378,12 @@ int lmtp_stream_except(LMTP_STATE *state, int code, const char *description)
|
|||||||
"conversation with %s timed out while %s",
|
"conversation with %s timed out while %s",
|
||||||
session->namaddr, description);
|
session->namaddr, description);
|
||||||
break;
|
break;
|
||||||
|
case SMTP_ERR_PROTO:
|
||||||
|
lmtp_fill_dsn(state, &dsn, DSN_BY_LOCAL_MTA,
|
||||||
|
"4.5.0", "403 remote protocol error",
|
||||||
|
"protocol error in reply from %s while %s",
|
||||||
|
session->namaddr, description);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return (lmtp_bulk_fail(state, &dsn, LMTP_THROTTLE));
|
return (lmtp_bulk_fail(state, &dsn, LMTP_THROTTLE));
|
||||||
}
|
}
|
||||||
|
@ -263,7 +263,6 @@ int deliver_alias(LOCAL_STATE state, USER_ATTR usr_attr,
|
|||||||
SET_OWNER_ATTR(state.msg_attr, STR(canon_owner), state.level);
|
SET_OWNER_ATTR(state.msg_attr, STR(canon_owner), state.level);
|
||||||
} else {
|
} else {
|
||||||
canon_owner = 0;
|
canon_owner = 0;
|
||||||
if (var_sticky_owner_alias == 0)
|
|
||||||
RESET_OWNER_ATTR(state.msg_attr, state.level);
|
RESET_OWNER_ATTR(state.msg_attr, state.level);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -367,11 +367,6 @@
|
|||||||
/* address (see prepend_delivered_header) only once, at the start of
|
/* address (see prepend_delivered_header) only once, at the start of
|
||||||
/* a delivery attempt; do not update the Delivered-To: address while
|
/* a delivery attempt; do not update the Delivered-To: address while
|
||||||
/* expanding aliases or .forward files.
|
/* expanding aliases or .forward files.
|
||||||
/* .IP "\fBsticky_owner_alias (yes)\fR"
|
|
||||||
/* When expanding a \fBlocal\fR(8) alias that has an owner alias (see
|
|
||||||
/* owner-\fIname\fR discussion in \fBaliases\fR(5)), use the owner information
|
|
||||||
/* even when the expansion invokes a subordinate alias that has no
|
|
||||||
/* owner alias.
|
|
||||||
/* DELIVERY METHOD CONTROLS
|
/* DELIVERY METHOD CONTROLS
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
@ -620,7 +615,6 @@ int var_mailtool_compat;
|
|||||||
char *var_mailbox_lock;
|
char *var_mailbox_lock;
|
||||||
int var_mailbox_limit;
|
int var_mailbox_limit;
|
||||||
bool var_frozen_delivered;
|
bool var_frozen_delivered;
|
||||||
bool var_sticky_owner_alias;
|
|
||||||
|
|
||||||
int local_cmd_deliver_mask;
|
int local_cmd_deliver_mask;
|
||||||
int local_file_deliver_mask;
|
int local_file_deliver_mask;
|
||||||
@ -861,7 +855,6 @@ int main(int argc, char **argv)
|
|||||||
VAR_STAT_HOME_DIR, DEF_STAT_HOME_DIR, &var_stat_home_dir,
|
VAR_STAT_HOME_DIR, DEF_STAT_HOME_DIR, &var_stat_home_dir,
|
||||||
VAR_MAILTOOL_COMPAT, DEF_MAILTOOL_COMPAT, &var_mailtool_compat,
|
VAR_MAILTOOL_COMPAT, DEF_MAILTOOL_COMPAT, &var_mailtool_compat,
|
||||||
VAR_FROZEN_DELIVERED, DEF_FROZEN_DELIVERED, &var_frozen_delivered,
|
VAR_FROZEN_DELIVERED, DEF_FROZEN_DELIVERED, &var_frozen_delivered,
|
||||||
VAR_STICKY_OWNER_ALIAS, DEF_STICKY_OWNER_ALIAS, &var_sticky_owner_alias,
|
|
||||||
0,
|
0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -251,7 +251,21 @@ SMTP_RESP *smtp_chat_resp(SMTP_SESSION *session)
|
|||||||
if (*cp == ' ' || *cp == 0)
|
if (*cp == ' ' || *cp == 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX Do not ignore garbage when ESMTP command pipelining is turned
|
||||||
|
* on. After sending ".<CR><LF>QUIT<CR><LF>", Postfix might recognize
|
||||||
|
* the server's 2XX QUIT reply as a 2XX END-OF-DATA reply after
|
||||||
|
* garbage, causing mail to be lost. Instead, make a long jump so
|
||||||
|
* that all recipients of multi-recipient mail get consistent
|
||||||
|
* treatment.
|
||||||
|
*/
|
||||||
session->error_mask |= MAIL_ERROR_PROTOCOL;
|
session->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||||
|
if (session->features & SMTP_FEATURE_PIPELINING) {
|
||||||
|
msg_warn("non-SMTP response from %s: %s",
|
||||||
|
session->namaddr, STR(session->buffer));
|
||||||
|
vstream_longjmp(session->stream, SMTP_ERR_PROTO);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -432,6 +432,12 @@ int smtp_stream_except(SMTP_STATE *state, int code, const char *description)
|
|||||||
"conversation with %s timed out while %s",
|
"conversation with %s timed out while %s",
|
||||||
session->namaddr, description);
|
session->namaddr, description);
|
||||||
break;
|
break;
|
||||||
|
case SMTP_ERR_PROTO:
|
||||||
|
smtp_fill_dsn(state, &dsn, DSN_BY_LOCAL_MTA,
|
||||||
|
"4.5.0", "403 remote protocol error",
|
||||||
|
"protocol error in reply from %s while %s",
|
||||||
|
session->namaddr, description);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return (smtp_bulk_fail(state, &dsn, SMTP_THROTTLE));
|
return (smtp_bulk_fail(state, &dsn, SMTP_THROTTLE));
|
||||||
}
|
}
|
||||||
|
@ -275,6 +275,7 @@ smtpd_peer.o: ../../include/argv.h
|
|||||||
smtpd_peer.o: ../../include/attr.h
|
smtpd_peer.o: ../../include/attr.h
|
||||||
smtpd_peer.o: ../../include/inet_proto.h
|
smtpd_peer.o: ../../include/inet_proto.h
|
||||||
smtpd_peer.o: ../../include/iostuff.h
|
smtpd_peer.o: ../../include/iostuff.h
|
||||||
|
smtpd_peer.o: ../../include/mail_params.h
|
||||||
smtpd_peer.o: ../../include/mail_proto.h
|
smtpd_peer.o: ../../include/mail_proto.h
|
||||||
smtpd_peer.o: ../../include/mail_stream.h
|
smtpd_peer.o: ../../include/mail_stream.h
|
||||||
smtpd_peer.o: ../../include/msg.h
|
smtpd_peer.o: ../../include/msg.h
|
||||||
|
@ -415,6 +415,11 @@
|
|||||||
/* The maximal number of lines in the Postfix SMTP server command history
|
/* The maximal number of lines in the Postfix SMTP server command history
|
||||||
/* before it is flushed upon receipt of EHLO, RSET, or end of DATA.
|
/* before it is flushed upon receipt of EHLO, RSET, or end of DATA.
|
||||||
/* .PP
|
/* .PP
|
||||||
|
/* Available in Postfix version 2.3 and later:
|
||||||
|
/* .IP "\fBsmtpd_peername_lookup (yes)\fR"
|
||||||
|
/* Attempt to look up the SMTP client hostname, and verify that
|
||||||
|
/* the name matches the client IP address.
|
||||||
|
/* .PP
|
||||||
/* The per SMTP client connection count and request rate limits are
|
/* The per SMTP client connection count and request rate limits are
|
||||||
/* implemented in co-operation with the \fBanvil\fR(8) service, and
|
/* implemented in co-operation with the \fBanvil\fR(8) service, and
|
||||||
/* are available in Postfix version 2.2 and later.
|
/* are available in Postfix version 2.2 and later.
|
||||||
@ -435,6 +440,11 @@
|
|||||||
/* .IP "\fBsmtpd_client_event_limit_exceptions ($mynetworks)\fR"
|
/* .IP "\fBsmtpd_client_event_limit_exceptions ($mynetworks)\fR"
|
||||||
/* Clients that are excluded from connection count, connection rate,
|
/* Clients that are excluded from connection count, connection rate,
|
||||||
/* or SMTP request rate restrictions.
|
/* or SMTP request rate restrictions.
|
||||||
|
/* .PP
|
||||||
|
/* Available in Postfix version 2.3 and later:
|
||||||
|
/* .IP "\fBsmtpd_client_new_tls_session_rate_limit (0)\fR"
|
||||||
|
/* The maximal number of new (i.e., uncached) TLS sessions that any
|
||||||
|
/* client is allowed to negotiate with this service per time unit.
|
||||||
/* TARPIT CONTROLS
|
/* TARPIT CONTROLS
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
@ -912,6 +922,7 @@ int var_smtpd_crate_limit;
|
|||||||
int var_smtpd_cconn_limit;
|
int var_smtpd_cconn_limit;
|
||||||
int var_smtpd_cmail_limit;
|
int var_smtpd_cmail_limit;
|
||||||
int var_smtpd_crcpt_limit;
|
int var_smtpd_crcpt_limit;
|
||||||
|
int var_smtpd_cntls_limit;
|
||||||
char *var_smtpd_hoggers;
|
char *var_smtpd_hoggers;
|
||||||
char *var_local_rwr_clients;
|
char *var_local_rwr_clients;
|
||||||
char *var_smtpd_ehlo_dis_words;
|
char *var_smtpd_ehlo_dis_words;
|
||||||
@ -933,6 +944,8 @@ char *var_smtpd_sasl_tls_opts;
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool var_smtpd_peername_lookup;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Silly little macros.
|
* Silly little macros.
|
||||||
*/
|
*/
|
||||||
@ -982,6 +995,7 @@ int smtpd_input_transp_mask;
|
|||||||
static void helo_reset(SMTPD_STATE *);
|
static void helo_reset(SMTPD_STATE *);
|
||||||
static void mail_reset(SMTPD_STATE *);
|
static void mail_reset(SMTPD_STATE *);
|
||||||
static void rcpt_reset(SMTPD_STATE *);
|
static void rcpt_reset(SMTPD_STATE *);
|
||||||
|
static void tls_reset(SMTPD_STATE *);
|
||||||
static void chat_reset(SMTPD_STATE *, int);
|
static void chat_reset(SMTPD_STATE *, int);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3025,6 +3039,25 @@ static void chat_reset(SMTPD_STATE *state, int threshold)
|
|||||||
|
|
||||||
static void smtpd_start_tls(SMTPD_STATE *state)
|
static void smtpd_start_tls(SMTPD_STATE *state)
|
||||||
{
|
{
|
||||||
|
int rate;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX The client event count/rate control must be consistent in its use
|
||||||
|
* of client address information in connect and disconnect events. For
|
||||||
|
* now we exclude xclient authorized hosts from event count/rate control.
|
||||||
|
*/
|
||||||
|
if (SMTPD_STAND_ALONE(state) == 0
|
||||||
|
&& !xclient_allowed
|
||||||
|
&& anvil_clnt
|
||||||
|
&& var_smtpd_cntls_limit > 0
|
||||||
|
&& !namadr_list_match(hogger_list, state->name, state->addr)
|
||||||
|
&& anvil_clnt_newtls_stat(anvil_clnt, state->service, state->addr,
|
||||||
|
&rate) == ANVIL_STAT_OK
|
||||||
|
&& rate > var_smtpd_cntls_limit) {
|
||||||
|
msg_warn("Refusing STARTTLS request from %s for service %s",
|
||||||
|
state->namaddr, state->service);
|
||||||
|
vstream_longjmp(state->client, SMTP_ERR_EOF);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wrapper mode uses a dedicated port and always requires TLS.
|
* Wrapper mode uses a dedicated port and always requires TLS.
|
||||||
@ -3041,6 +3074,27 @@ static void smtpd_start_tls(SMTPD_STATE *state)
|
|||||||
var_smtpd_starttls_tmout, state->name, state->addr,
|
var_smtpd_starttls_tmout, state->name, state->addr,
|
||||||
(var_smtpd_tls_req_ccert && state->tls_enforce_tls));
|
(var_smtpd_tls_req_ccert && state->tls_enforce_tls));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX The client event count/rate control must be consistent in its use
|
||||||
|
* of client address information in connect and disconnect events. For
|
||||||
|
* now we exclude xclient authorized hosts from event count/rate control.
|
||||||
|
*/
|
||||||
|
if (state->tls_context
|
||||||
|
&& state->tls_context->session_reused == 0
|
||||||
|
&& SMTPD_STAND_ALONE(state) == 0
|
||||||
|
&& !xclient_allowed
|
||||||
|
&& anvil_clnt
|
||||||
|
&& var_smtpd_cntls_limit > 0
|
||||||
|
&& !namadr_list_match(hogger_list, state->name, state->addr)
|
||||||
|
&& anvil_clnt_newtls(anvil_clnt, state->service, state->addr,
|
||||||
|
&rate) == ANVIL_STAT_OK
|
||||||
|
&& rate > var_smtpd_cntls_limit) {
|
||||||
|
msg_warn("Too many uncached TLS sessions: "
|
||||||
|
"%d from %s for service %s",
|
||||||
|
rate, state->namaddr, state->service);
|
||||||
|
tls_reset(state);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When the TLS handshake fails, the conversation is in an unknown state.
|
* When the TLS handshake fails, the conversation is in an unknown state.
|
||||||
* There is nothing we can do except to disconnect from the client.
|
* There is nothing we can do except to disconnect from the client.
|
||||||
@ -3587,7 +3641,8 @@ static void post_jail_init(char *unused_name, char **unused_argv)
|
|||||||
* Connection rate management.
|
* Connection rate management.
|
||||||
*/
|
*/
|
||||||
if (var_smtpd_crate_limit || var_smtpd_cconn_limit
|
if (var_smtpd_crate_limit || var_smtpd_cconn_limit
|
||||||
|| var_smtpd_cmail_limit || var_smtpd_crcpt_limit)
|
|| var_smtpd_cmail_limit || var_smtpd_crcpt_limit
|
||||||
|
|| var_smtpd_cntls_limit)
|
||||||
anvil_clnt = anvil_clnt_create();
|
anvil_clnt = anvil_clnt_create();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3625,6 +3680,7 @@ int main(int argc, char **argv)
|
|||||||
VAR_SMTPD_CCONN_LIMIT, DEF_SMTPD_CCONN_LIMIT, &var_smtpd_cconn_limit, 0, 0,
|
VAR_SMTPD_CCONN_LIMIT, DEF_SMTPD_CCONN_LIMIT, &var_smtpd_cconn_limit, 0, 0,
|
||||||
VAR_SMTPD_CMAIL_LIMIT, DEF_SMTPD_CMAIL_LIMIT, &var_smtpd_cmail_limit, 0, 0,
|
VAR_SMTPD_CMAIL_LIMIT, DEF_SMTPD_CMAIL_LIMIT, &var_smtpd_cmail_limit, 0, 0,
|
||||||
VAR_SMTPD_CRCPT_LIMIT, DEF_SMTPD_CRCPT_LIMIT, &var_smtpd_crcpt_limit, 0, 0,
|
VAR_SMTPD_CRCPT_LIMIT, DEF_SMTPD_CRCPT_LIMIT, &var_smtpd_crcpt_limit, 0, 0,
|
||||||
|
VAR_SMTPD_CNTLS_LIMIT, DEF_SMTPD_CNTLS_LIMIT, &var_smtpd_cntls_limit, 0, 0,
|
||||||
#ifdef USE_TLS
|
#ifdef USE_TLS
|
||||||
VAR_SMTPD_TLS_CCERT_VD, DEF_SMTPD_TLS_CCERT_VD, &var_smtpd_tls_ccert_vd, 0, 0,
|
VAR_SMTPD_TLS_CCERT_VD, DEF_SMTPD_TLS_CCERT_VD, &var_smtpd_tls_ccert_vd, 0, 0,
|
||||||
#endif
|
#endif
|
||||||
@ -3664,6 +3720,7 @@ int main(int argc, char **argv)
|
|||||||
VAR_SMTPD_TLS_RCERT, DEF_SMTPD_TLS_RCERT, &var_smtpd_tls_req_ccert,
|
VAR_SMTPD_TLS_RCERT, DEF_SMTPD_TLS_RCERT, &var_smtpd_tls_req_ccert,
|
||||||
VAR_SMTPD_TLS_RECHEAD, DEF_SMTPD_TLS_RECHEAD, &var_smtpd_tls_received_header,
|
VAR_SMTPD_TLS_RECHEAD, DEF_SMTPD_TLS_RECHEAD, &var_smtpd_tls_received_header,
|
||||||
#endif
|
#endif
|
||||||
|
VAR_SMTPD_PEERNAME_LOOKUP, DEF_SMTPD_PEERNAME_LOOKUP, &var_smtpd_peername_lookup,
|
||||||
0,
|
0,
|
||||||
};
|
};
|
||||||
static CONFIG_STR_TABLE str_table[] = {
|
static CONFIG_STR_TABLE str_table[] = {
|
||||||
|
@ -118,6 +118,7 @@
|
|||||||
|
|
||||||
#include <mail_proto.h>
|
#include <mail_proto.h>
|
||||||
#include <valid_mailhost_addr.h>
|
#include <valid_mailhost_addr.h>
|
||||||
|
#include <mail_params.h>
|
||||||
|
|
||||||
/* Application-specific. */
|
/* Application-specific. */
|
||||||
|
|
||||||
@ -251,7 +252,18 @@ void smtpd_peer_init(SMTPD_STATE *state)
|
|||||||
state->name_status = code; \
|
state->name_status = code; \
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((aierr = sockaddr_to_hostname(sa, sa_len, &client_name,
|
if (var_smtpd_peername_lookup == 0) {
|
||||||
|
state->name = mystrdup(CLIENT_NAME_UNKNOWN);
|
||||||
|
state->reverse_name = mystrdup(CLIENT_NAME_UNKNOWN);
|
||||||
|
#ifdef FORWARD_CLIENT_NAME
|
||||||
|
state->forward_name = mystrdup(CLIENT_NAME_UNKNOWN);
|
||||||
|
#endif
|
||||||
|
state->name_status = SMTPD_PEER_CODE_PERM;
|
||||||
|
state->reverse_name_status = SMTPD_PEER_CODE_PERM;
|
||||||
|
#ifdef FORWARD_CLIENT_NAME
|
||||||
|
state->forward_name_status = SMTPD_PEER_CODE_PERM;
|
||||||
|
#endif
|
||||||
|
} else if ((aierr = sockaddr_to_hostname(sa, sa_len, &client_name,
|
||||||
(MAI_SERVNAME_STR *) 0, 0)) != 0) {
|
(MAI_SERVNAME_STR *) 0, 0)) != 0) {
|
||||||
state->name = mystrdup(CLIENT_NAME_UNKNOWN);
|
state->name = mystrdup(CLIENT_NAME_UNKNOWN);
|
||||||
state->reverse_name = mystrdup(CLIENT_NAME_UNKNOWN);
|
state->reverse_name = mystrdup(CLIENT_NAME_UNKNOWN);
|
||||||
|
@ -56,7 +56,8 @@ typedef struct {
|
|||||||
const char *cipher_name;
|
const char *cipher_name;
|
||||||
int cipher_usebits;
|
int cipher_usebits;
|
||||||
int cipher_algbits;
|
int cipher_algbits;
|
||||||
int log_level;
|
int log_level; /* TLS library logging level */
|
||||||
|
int session_reused; /* this session was reused */
|
||||||
} TLScontext_t;
|
} TLScontext_t;
|
||||||
|
|
||||||
#define TLS_BIO_BUFSIZE 8192
|
#define TLS_BIO_BUFSIZE 8192
|
||||||
|
@ -693,6 +693,12 @@ TLScontext_t *tls_client_start(SSL_CTX *client_ctx, VSTREAM *stream,
|
|||||||
if (var_smtp_tls_loglevel < 4)
|
if (var_smtp_tls_loglevel < 4)
|
||||||
BIO_set_callback(SSL_get_rbio(TLScontext->con), 0);
|
BIO_set_callback(SSL_get_rbio(TLScontext->con), 0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The caller may want to know if this session was reused or if a new
|
||||||
|
* session was negotiated.
|
||||||
|
*/
|
||||||
|
TLScontext->session_reused = SSL_session_reused(TLScontext->con);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do peername verification if requested and extract useful information
|
* Do peername verification if requested and extract useful information
|
||||||
* from the certificate for later use.
|
* from the certificate for later use.
|
||||||
|
@ -564,6 +564,12 @@ TLScontext_t *tls_server_start(SSL_CTX *server_ctx, VSTREAM *stream,
|
|||||||
if (var_smtpd_tls_loglevel < 4)
|
if (var_smtpd_tls_loglevel < 4)
|
||||||
BIO_set_callback(SSL_get_rbio(TLScontext->con), 0);
|
BIO_set_callback(SSL_get_rbio(TLScontext->con), 0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The caller may want to know if this session was reused or if a new
|
||||||
|
* session was negotiated.
|
||||||
|
*/
|
||||||
|
TLScontext->session_reused = SSL_session_reused(TLScontext->con);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Let's see whether a peer certificate is available and what is the
|
* Let's see whether a peer certificate is available and what is the
|
||||||
* actual information. We want to save it for later use.
|
* actual information. We want to save it for later use.
|
||||||
@ -618,6 +624,8 @@ TLScontext_t *tls_server_start(SSL_CTX *server_ctx, VSTREAM *stream,
|
|||||||
*/
|
*/
|
||||||
if (requirecert) {
|
if (requirecert) {
|
||||||
if (!TLScontext->peer_verified || !TLScontext->peer_CN) {
|
if (!TLScontext->peer_verified || !TLScontext->peer_CN) {
|
||||||
|
if (TLScontext->session_reused == 0)
|
||||||
|
msg_panic("tls_server_start: peer was not verified");
|
||||||
msg_info("Re-used session without peer certificate removed");
|
msg_info("Re-used session without peer certificate removed");
|
||||||
uncache_session(server_ctx, TLScontext);
|
uncache_session(server_ctx, TLScontext);
|
||||||
tls_free_context(TLScontext);
|
tls_free_context(TLScontext);
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
/* DICT *ptr;
|
/* DICT *ptr;
|
||||||
/* DESCRIPTION
|
/* DESCRIPTION
|
||||||
/* dict_alloc() allocates memory for a dictionary structure of
|
/* dict_alloc() allocates memory for a dictionary structure of
|
||||||
/* \fIsize\fR bytes, initializes all properties to default settings,
|
/* \fIsize\fR bytes, initializes all generic dictionary
|
||||||
|
/* properties to default settings,
|
||||||
/* and installs default methods that do not support any operation.
|
/* and installs default methods that do not support any operation.
|
||||||
/* The caller is supposed to override the default methods with
|
/* The caller is supposed to override the default methods with
|
||||||
/* ones that it supports.
|
/* ones that it supports.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user