From bcb028b46d57f72740418a72fe17496cc51b8890 Mon Sep 17 00:00:00 2001
From: Wietse Venema
Specify a list of names and/or name=value pairs, separated by
-whitespace or comma.
+whitespace or comma. The name=value form is supported with
+Postfix 2.1 and later.
@@ -5370,7 +5371,7 @@ ignored.
- This feature is available in Postfix 2.2 and later.
+MASTER(5) MASTER(5)
+
+NAME
+ master - Postfix master process configuration file format
+
+DESCRIPTION
+ The Postfix mail system is implemented by small number of
+ (mostly) client commands that are invoked by users, and by
+ a larger number of services that run in the background.
+
+ Postfix services run under control of the master(8) pro-
+ cess. The master.cf configuration file defines how a
+ client program connects to a service, and what daemon pro-
+ gram runs when a service is requested. Most daemon pro-
+ cesses are short-lived and terminate after serving max_use
+ clients, or after inactivity for max_idle or more units of
+ time.
+
+ All daemons specified here must speak a Postfix-internal
+ protocol. In order to execute non-Postfix software use the
+ local(8), pipe(8) or spawn(8) services, or run the server
+ under control by inetd(8) or equivalent.
+
+ Changes in master.cf requires that "postfix reload" be
+ executed in order to reload the configuration.
+
+SYNTAX
+ The general format of the master.cf file is as follows:
+
+ o Each logical line defines a single Postfix service.
+ Each service is identified by its name and type as
+ described below. When multiple lines specify the
+ same service name and type, only the last one is
+ remembered. Otherwise, the order of master.cf ser-
+ vice definitions does not matter.
+
+ o Empty lines and whitespace-only lines are ignored,
+ as are lines whose first non-whitespace character
+ is a `#'.
+
+ o A logical line starts with non-whitespace text. A
+ line that starts with whitespace continues a logi-
+ cal line.
+
+ Each logical line consists of eight fields separated by
+ whitespace. These are described below in the order as
+ they appear in the master.cf file.
+
+ Where applicable a field of "-" requests that the built-in
+ default value be used. For boolean fields specify "y" or
+ "n" to override the default value.
+
+ Service name
+ The service name syntax depends on the service type
+ as described next.
+
+ Service type
+ Specify one of the following service types:
+
+ inet The service listens on a TCP/IP socket and
+ is therefore accessible via the network.
+
+ The service name is specified as host:port,
+ denoting the host and port on which new con-
+ nections should be accepted. The host part
+ (and colon) may be omitted. Either host or
+ port may be given in symbolic form (host or
+ service name) or in numeric form (IP address
+ or port number).
+
+ Examples: a service name of 127.0.0.1:smtp
+ receives mail via the loopback interface
+ only; and a service name of 10025 accepts
+ connections on TCP port 10025 via all inter-
+ faces configured with the inet_interfaces
+ parameter.
+
+ unix The service listens on a UNIX-domain socket
+ and is accessible for local clients only.
+
+ The service name is a pathname relative to
+ the Postfix queue directory (pathname con-
+ trolled with the queue_directory configura-
+ tion parameter in main.cf).
+
+ On Solaris systems the unix type is imple-
+ mented with streams sockets.
+
+ fifo The service listens on a FIFO (named pipe)
+ and is accessible for local clients only.
+
+ The service name is a pathname relative to
+ the Postfix queue directory (pathname con-
+ trolled with the queue_directory configura-
+ tion parameter in main.cf).
+
+ Private (default: y)
+ Whether or not access is restricted to the mail
+ system. Internet (type inet) services can't be
+ private.
+
+ Unprivileged (default: y)
+ Whether the service runs with root privileges or as
+ the owner of the Postfix system (the owner name is
+ controlled by the mail_owner configuration variable
+ in the main.cf file).
+
+ The local(8), pipe(8), spawn(8), and virtual(8)
+ daemons require privileges.
+
+ Chroot (default: y)
+ Whether or not the service runs chrooted to the
+ mail queue directory (pathname is controlled by the
+ queue_directory configuration variable in the
+ main.cf file).
+
+ Chroot should not be used with the local(8),
+ pipe(8) and spawn(8) daemons. Although the prox-
+ ymap(8) server can run chrooted, doing so defeats
+ most of the purpose of having that service in the
+ first place.
+
+ The files in the examples/chroot-setup subdirectory
+ of the Postfix source archive describe how to set
+ up a Postfix chroot environment for your type of
+ machine, and BASIC_CONFIGURATION_README discusses
+ issues related to running daemons chrooted.
+
+ Wakeup time (default: 0)
+ Automatically wake up the named service after the
+ specified number of seconds. The wake up is imple-
+ mented by connecting to the service and sending a
+ wake up request. A ? at the end of the wake up
+ time field requests that wake up events be sent
+ only to services that are actually being used.
+ Specify 0 for no automatic wake up.
+
+ The pickup(8), qmgr(8) and flush(8) daemons require
+ a wake up timer.
+
+ Process limit (default: $default_process_limit)
+ The maximum number of processes that may execute
+ this service simultaneously. Specify 0 for no pro-
+ cess count limit.
+
+ NOTE: Some Postfix services must be configured as a
+ single-process service (for example, qmgr(8)) and
+ some services must be configured with no process
+ limit (for example, cleanup(8)). These limits must
+ not be changed.
+
+ Command name + arguments
+ The command to be executed. Characters that are
+ special to the shell such as ">" or "|" have no
+ special meaning here, and quotes cannot be used to
+ protect arguments containing whitespace.
+
+ The command name is relative to the Postfix daemon
+ directory (pathname is controlled by the dae-
+ mon_directory configuration variable).
+
+ The command argument syntax for specific commands
+ is specified in the respective daemon manual page.
+
+ The following command-line options have the same
+ effect for all daemon programs:
+
+ -D Run the daemon under control by the command
+ specified with the debugger_command variable
+ in the main.cf configuration file. See
+ DEBUG_README for hints and tips.
+
+ -o name=value
+ Override the named main.cf configuration
+ parameter. The parameter value can refer to
+ other parameters as $name etc., just like in
+ main.cf. See postconf(5) for syntax.
+
+ NOTE 1: do not specify whitespace around the
+ "=". In parameter values, either avoid
+ whitespace altogether, use commas instead of
+ spaces, or consider overrides like "-o
+ name=$override_parameter" with $over-
+ ride_parameter set in main.cf.
+
+ NOTE 2: Over-zealous use of parameter over-
+ rides makes the Postfix configuration hard
+ to understand and maintain. At a certain
+ point, it might be easier to configure mul-
+ tiple instances of Postfix, instead of con-
+ figuring multiple personalities via mas-
+ ter.cf.
+
+ -v Increase the verbose logging level. Specify
+ multiple -v options to make a command more
+ verbose.
+
+SEE ALSO
+ master(8), process manager
+ postconf(5), configuration parameters
+
+README FILES
+ BASIC_CONFIGURATION_README, basic configuration
+ DEBUG_README, Postfix debugging
+
+LICENSE
+ The Secure Mailer license must be distributed with this
+ software.
+
+AUTHOR(S)
+ Initial version by
+ Magnus Baeck
+ Lund Institute of Technology
+ Sweden
+
+ Wietse Venema
+ IBM T.J. Watson Research
+ P.O. Box 704
+ Yorktown Heights, NY 10598, USA
+
+ MASTER(5)
+
diff --git a/postfix/html/master.8.html b/postfix/html/master.8.html
index c3dfc9938..81ef97709 100644
--- a/postfix/html/master.8.html
+++ b/postfix/html/master.8.html
@@ -10,8 +10,7 @@ MASTER(8) MASTER(8)
master - Postfix master process
SYNOPSIS
- master [-Dtv] [-c config_dir]
- [-e exit_time]
+ master [-Dtv] [-c config_dir] [-e exit_time]
DESCRIPTION
The master daemon is the resident process that runs Post-
@@ -27,18 +26,16 @@ MASTER(8) MASTER(8)
address verification server.
The behavior of the master daemon is controlled by the
- master.cf configuration file. The table specifies zero or
- more servers in the UNIX or INET domain, or servers that
- take requests from a FIFO. Precise configuration details
- are given in the master.cf file, and in the manual pages
- of the respective daemons.
+ master.cf configuration file, as described in master(5).
Options:
-c config_dir
Read the main.cf and master.cf configuration files
in the named directory instead of the default con-
- figuration directory.
+ figuration directory. This also overrides the con-
+ figuration files for other Postfix daemon pro-
+ cesses.
-e exit_time
Terminate the master process after exit_time sec-
@@ -173,7 +170,8 @@ MASTER(8) MASTER(8)
SEE ALSO
qmgr(8), queue manager
verify(8), address verification
- postconf(5), configuration parameters
+ master(5), master.cf configuration file syntax
+ postconf(5), main.cf configuration parameter syntax
syslogd(8), system logging
LICENSE
diff --git a/postfix/html/pipe.8.html b/postfix/html/pipe.8.html
index 4b9ca85b6..2f9795c15 100644
--- a/postfix/html/pipe.8.html
+++ b/postfix/html/pipe.8.html
@@ -149,7 +149,11 @@ PIPE(8) PIPE(8)
In the command argument vector, the following
macros are recognized and replaced with correspond-
ing information from the Postfix queue manager
- delivery request:
+ delivery request.
+
+ In addition to the form ${name}, the forms $name
+ and $(name) are also recognized. Specify $$ where
+ a single $ is wanted.
${extension}
This macro expands to the extension part of
@@ -194,90 +198,111 @@ PIPE(8) PIPE(8)
This information is modified by the hqu
flags for quoting and case folding.
+ ${sasl_method}
+ This macro expands to the SASL authentica-
+ tion mechanism used during the reception of
+ the message. An empty string is passed if
+ the message has been received without SASL
+ authentication.
+
+ This is available in Postfix 2.2 and later.
+
+ ${sasl_sender}
+ This macro expands to the SASL sender name
+ (i.e. the original submitter as per RFC
+ 2554) used during the reception of the mes-
+ sage.
+
+ This is available in Postfix 2.2 and later.
+
+ ${sasl_username}
+ This macro expands to the SASL user name
+ used during the reception of the message. An
+ empty string is passed if the message has
+ been received without SASL authentication.
+
+ This is available in Postfix 2.2 and later.
+
${sender}
- This macro expands to the envelope sender
+ This macro expands to the envelope sender
address.
- This information is modified by the q flag
+ This information is modified by the q flag
for quoting.
${size}
- This macro expands to Postfix's idea of the
- message size, which is an approximation of
+ This macro expands to Postfix's idea of the
+ message size, which is an approximation of
the size of the message as delivered.
${user}
This macro expands to the username part of a
- recipient address. For example, with an
+ recipient address. For example, with an
address user+foo@domain the username part is
user.
- A command-line argument that contains
- ${user} expands into as many command-line
+ A command-line argument that contains
+ ${user} expands into as many command-line
arguments as there are recipients.
- This information is modified by the u flag
+ This information is modified by the u flag
for case folding.
- In addition to the form ${name}, the forms $name and
- $(name) are also recognized. Specify $$ where a single $
- is wanted.
-
DIAGNOSTICS
- Command exit status codes are expected to follow the con-
+ Command exit status codes are expected to follow the con-
ventions defined in <sysexits.h>.
- Problems and transactions are logged to syslogd(8). Cor-
- rupted message files are marked so that the queue manager
+ Problems and transactions are logged to syslogd(8). Cor-
+ rupted message files are marked so that the queue manager
can move them to the corrupt queue for further inspection.
SECURITY
- This program needs a dual personality 1) to access the
- private Postfix queue and IPC mechanisms, and 2) to exe-
+ This program needs a dual personality 1) to access the
+ private Postfix queue and IPC mechanisms, and 2) to exe-
cute external commands as the specified user. It is there-
fore security sensitive.
CONFIGURATION PARAMETERS
- Changes to main.cf are picked up automatically as pipe(8)
- processes run for only a limited amount of time. Use the
+ Changes to main.cf are picked up automatically as pipe(8)
+ processes run for only a limited amount of time. Use the
command "postfix reload" to speed up a change.
- The text below provides only a parameter summary. See
+ The text below provides only a parameter summary. See
postconf(5) for more details including examples.
RESOURCE AND RATE CONTROLS
- In the text below, transport is the first field in a mas-
+ In the text below, transport is the first field in a mas-
ter.cf entry.
transport_destination_concurrency_limit ($default_destina-
tion_concurrency_limit)
Limit the number of parallel deliveries to the same
- destination, for delivery via the named transport.
+ destination, for delivery via the named transport.
The limit is enforced by the Postfix queue manager.
transport_destination_recipient_limit ($default_destina-
tion_recipient_limit)
- Limit the number of recipients per message deliv-
- ery, for delivery via the named transport. The
+ Limit the number of recipients per message deliv-
+ ery, for delivery via the named transport. The
limit is enforced by the Postfix queue manager.
transport_time_limit ($command_time_limit)
- Limit the time for delivery to external command,
+ Limit the time for delivery to external command,
for delivery via the named transport. The limit is
enforced by the pipe delivery agent.
MISCELLANEOUS CONTROLS
config_directory (see 'postconf -d' output)
- The default location of the Postfix main.cf and
+ The default location of the Postfix main.cf and
master.cf configuration files.
daemon_timeout (18000s)
- How much time a Postfix daemon process may take to
- handle a request before it is terminated by a
+ How much time a Postfix daemon process may take to
+ handle a request before it is terminated by a
built-in watchdog timer.
export_environment (see 'postconf -d' output)
- The list of environment variables that a Postfix
+ The list of environment variables that a Postfix
process will export to non-Postfix processes.
ipc_timeout (3600s)
@@ -289,24 +314,24 @@ PIPE(8) PIPE(8)
and most Postfix daemon processes.
max_idle (100s)
- The maximum amount of time that an idle Postfix
- daemon process waits for the next service request
+ The maximum amount of time that an idle Postfix
+ daemon process waits for the next service request
before exiting.
max_use (100)
- The maximal number of connection requests before a
+ The maximal number of connection requests before a
Postfix daemon process terminates.
process_id (read-only)
- The process ID of a Postfix command or daemon pro-
+ The process ID of a Postfix command or daemon pro-
cess.
process_name (read-only)
- The process name of a Postfix command or daemon
+ The process name of a Postfix command or daemon
process.
queue_directory (see 'postconf -d' output)
- The location of the Postfix top-level queue direc-
+ The location of the Postfix top-level queue direc-
tory.
recipient_delimiter (empty)
@@ -317,7 +342,7 @@ PIPE(8) PIPE(8)
The syslog facility of Postfix logging.
syslog_name (postfix)
- The mail system name that is prepended to the pro-
+ The mail system name that is prepended to the pro-
cess name in syslog records, so that "smtpd"
becomes, for example, "postfix/smtpd".
@@ -329,7 +354,7 @@ PIPE(8) PIPE(8)
syslogd(8), system logging
LICENSE
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
AUTHOR(S)
diff --git a/postfix/html/postconf.5.html b/postfix/html/postconf.5.html
index 841d702ce..9884581f8 100644
--- a/postfix/html/postconf.5.html
+++ b/postfix/html/postconf.5.html
@@ -2042,7 +2042,8 @@ time keeping on System-V-ish systems.
This feature is available in Postfix 2.2 and later.
+ @@ -5409,6 +5412,8 @@ an unused SMTP client socket is kept open before it is closed. Do not specify larger values without permission from the remote sites. +This feature is available in Postfix 2.2 and later.
+ @@ -6123,8 +6128,8 @@ Example: (default: 50)-How many simultaneous connections any SMTP client is allowed to -make to the SMTP service. By default, the limit is set it to half +How many simultaneous connections any client is allowed to +make to this service. By default, the limit is set to half the default process limit value.
@@ -6138,18 +6143,56 @@ not be used to regulate legitimate mail traffic.-This feature is not part of the stable Postfix 2.1 release. +This feature is available in Postfix 2.2 and later.
+The maximal number of connection attempts any client is allowed to +make to this service per time unit. The time unit is specified +with the anvil_rate_time_unit configuration parameter. +
+ ++By default, a client can make as many connections per time unit as +Postfix can accept. +
+ ++To disable this feature, specify a limit of 0. +
+ ++WARNING: The purpose of this feature is to limit abuse. It must +not be used to regulate legitimate mail traffic. +
+ ++This feature is available in Postfix 2.2 and later. +
+ ++Example: +
+ ++smtpd_client_connection_rate_limit = 1000 ++ + +
-Clients that are excluded from connection count or connection rate -restrictions. +Clients that are excluded from connection count, connection rate, +message rate or recipient rate restrictions.
@@ -6159,25 +6202,25 @@ dot causes the domain to match any name below it).
-This feature is not part of the stable Postfix 2.1 release. +This feature is available in Postfix 2.2 and later.
-The maximal number of connection attempts any client is allowed to -make to this service per time unit. The time unit is specified -with the anvil_rate_time_unit configuration parameter, and defaults -to one minute. +The maximal number of message delivery requests that any client is +allowed to make to this service per time unit, regardless of whether +or not Postfix actually accepts those messages. The time unit is +specified with the anvil_rate_time_unit configuration parameter.
-By default, a client can make as many connections per time unit as -Postfix can accept. +By default, a client can send as many message delivery requests +requests per time unit as Postfix can accept.
@@ -6190,7 +6233,7 @@ not be used to regulate legitimate mail traffic.
-This feature is not part of the stable Postfix 2.1 release. +This feature is available in Postfix 2.2 and later.
@@ -6198,7 +6241,46 @@ Example:
-smtpd_client_connection_rate_limit = 1000 +smtpd_client_message_rate_limit = 1000 ++ + +
+The maximal number of recipient addresses that any client is allowed +to send to this service per time unit, regardless of whether or not +Postfix actually accepts those recipients. The time unit is specified +with the anvil_rate_time_unit configuration parameter. +
+ ++By default, a client can make as many recipient addresses per time +unit as Postfix can accept. +
+ ++To disable this feature, specify a limit of 0. +
+ ++WARNING: The purpose of this feature is to limit abuse. It must +not be used to regulate legitimate mail traffic. +
+ ++This feature is available in Postfix 2.2 and later. +
+ ++Example: +
+ ++smtpd_client_recipient_rate_limit = 1000diff --git a/postfix/html/postfix-manuals.html b/postfix/html/postfix-manuals.html new file mode 100644 index 000000000..e286b3f18 --- /dev/null +++ b/postfix/html/postfix-manuals.html @@ -0,0 +1,208 @@ + + + + + + +
Postfix
+Manual Pages New Postfix users should first look at the following introductory +documents. These introductions are hyperlinked to more advanced +documents and to UNIX-style manual pages. The UNIX-style manual +pages are intended for people who are already familiar with Postfix. +
+ +Each Postfix manual page is numbered after a section of the +UNIX manual: examples are mailq(1) or access(5). Unfortunately, +the organization of manual pages depends on the UNIX version being +used. Postfix documentation assumes the following convention: +
+ ++ ++ ++ +
+ ++ + Section Topic + +
+ + 1 Commands + + 3 Library routines + + 5 File formats + + 8 Daemons
Postfix
+Manual Pages New Postfix users should first look at the following introductory +documents. These introductions are hyperlinked to more advanced +documents and to UNIX-style manual pages. The UNIX-style manual +pages are intended for people who are already familiar with Postfix. +
+ +Each Postfix manual page is numbered after a section of the +UNIX manual: examples are mailq(1) or access(5). Unfortunately, +the organization of manual pages depends on the UNIX version being +used. Postfix documentation assumes the following convention: +
+ ++ ++ +EOF + +srctoman "$@" | awk ' + +NR == 1,/SH "*SEE ALSO"*/ { next } + +/^Other:$/ { print ul; exit } + +/^[A-Z].*:$/ { print ul "+ +
+ ++ + Section Topic + +
+ + 1 Commands + + 3 Library routines + + 5 File formats + + 8 Daemons
Specify a list of names and/or name=value pairs, separated by -whitespace or comma. +whitespace or comma. The name=value form is supported with +Postfix 2.1 and later.
@@ -3244,12 +3245,16 @@ an unused SMTP client socket is kept open before it is closed. Do not specify larger values without permission from the remote sites.
+This feature is available in Postfix 2.2 and later.
+ %PARAM smtp_connection_cache_reuse_limit 10When SMTP session caching is enabled, the number of times that an SMTP session is reused before it is closed.
+This feature is available in Postfix 2.2 and later.
+ %PARAM smtp_connection_cache_destinationsPermanently enable SMTP connection caching for the specified @@ -3280,7 +3285,7 @@ ignored. -
+This feature is available in Postfix 2.2 and later.
%PARAM smtp_connection_cache_on_demand yes @@ -3939,8 +3944,8 @@ smtpd_banner = $myhostname ESMTP $mail_name ($mail_version) %PARAM smtpd_client_connection_count_limit 50-How many simultaneous connections any SMTP client is allowed to -make to the SMTP service. By default, the limit is set it to half +How many simultaneous connections any client is allowed to +make to this service. By default, the limit is set to half the default process limit value.
@@ -3954,14 +3959,14 @@ not be used to regulate legitimate mail traffic.-This feature is not part of the stable Postfix 2.1 release. +This feature is available in Postfix 2.2 and later.
-%PARAM smtpd_client_connection_limit_exceptions $mynetworks +%PARAM smtpd_client_event_limit_exceptions $mynetworks-Clients that are excluded from connection count or connection rate -restrictions. +Clients that are excluded from connection count, connection rate, +message rate or recipient rate restrictions.
@@ -3971,7 +3976,7 @@ dot causes the domain to match any name below it).
-This feature is not part of the stable Postfix 2.1 release. +This feature is available in Postfix 2.2 and later.
%PARAM smtpd_client_connection_rate_limit 0 @@ -3979,8 +3984,7 @@ This feature is not part of the stable Postfix 2.1 release.The maximal number of connection attempts any client is allowed to make to this service per time unit. The time unit is specified -with the anvil_rate_time_unit configuration parameter, and defaults -to one minute. +with the anvil_rate_time_unit configuration parameter.
@@ -3998,7 +4002,7 @@ not be used to regulate legitimate mail traffic.
-This feature is not part of the stable Postfix 2.1 release. +This feature is available in Postfix 2.2 and later.
@@ -4009,6 +4013,76 @@ Example: smtpd_client_connection_rate_limit = 1000 +%PARAM smtpd_client_message_rate_limit 0 + +
+The maximal number of message delivery requests that any client is +allowed to make to this service per time unit, regardless of whether +or not Postfix actually accepts those messages. The time unit is +specified with the anvil_rate_time_unit configuration parameter. +
+ ++By default, a client can send as many message delivery requests +requests per time unit as Postfix can accept. +
+ ++To disable this feature, specify a limit of 0. +
+ ++WARNING: The purpose of this feature is to limit abuse. It must +not be used to regulate legitimate mail traffic. +
+ ++This feature is available in Postfix 2.2 and later. +
+ ++Example: +
+ ++smtpd_client_message_rate_limit = 1000 ++ +%PARAM smtpd_client_recipient_rate_limit 0 + +
+The maximal number of recipient addresses that any client is allowed +to send to this service per time unit, regardless of whether or not +Postfix actually accepts those recipients. The time unit is specified +with the anvil_rate_time_unit configuration parameter. +
+ ++By default, a client can make as many recipient addresses per time +unit as Postfix can accept. +
+ ++To disable this feature, specify a limit of 0. +
+ ++WARNING: The purpose of this feature is to limit abuse. It must +not be used to regulate legitimate mail traffic. +
+ ++This feature is available in Postfix 2.2 and later. +
+ ++Example: +
+ ++smtpd_client_recipient_rate_limit = 1000 ++ %PARAM smtpd_client_restrictions
diff --git a/postfix/src/anvil/anvil.c b/postfix/src/anvil/anvil.c
index 0968e2270..cd541253e 100644
--- a/postfix/src/anvil/anvil.c
+++ b/postfix/src/anvil/anvil.c
@@ -2,21 +2,21 @@
/* NAME
/* anvil 8
/* SUMMARY
-/* Postfix client count and rate management
+/* Postfix client count and request rate management
/* SYNOPSIS
/* \fBanvil\fR [generic Postfix daemon options]
/* DESCRIPTION
/* The Postfix \fBanvil\fR server maintains short-term statistics
/* to defend against clients that hammer a server with either too
-/* many parallel connections or with too many successive connection
-/* attempts within a configurable time interval.
+/* many parallel connections or with too many successive requests
+/* within a configurable time interval.
/* This server is designed to run under control by the Postfix
/* master server.
/*
/* The \fBanvil\fR server maintains no persistent database. Standard
/* library utilities do not meet Postfix performance and robustness
/* requirements.
-/* PROTOCOL
+/* CONNECTION COUNT/RATE LIMITING
/* .ad
/* .fi
/* When a remote client connects, a connection count (or rate) limited
@@ -62,7 +62,64 @@
/* .PP
/* .ti +4
/* \fBstatus=0\fR
+/* MESSAGE RATE LIMITING
+/* .ad
+/* .fi
+/* When a remote client sends a message delivery request, a
+/* message rate limited server should send the following
+/* request to the \fBanvil\fR server:
+/* .PP
+/* .in +4
+/* \fBrequest=message\fR
+/* .br
+/* \fBident=\fIstring\fR
+/* .in
/* .PP
+/* This registers a message delivery request for the (service, client)
+/* combination specified with \fBident\fR. The \fBanvil\fR server
+/* answers with the number of message delivery requests per unit time
+/* for that (service, client) combination:
+/* .PP
+/* .in +4
+/* \fBstatus=0\fR
+/* .br
+/* \fBrate=\fInumber\fR
+/* .in
+/* .PP
+/* In order prevent the anvil server from discarding client
+/* request rates too early or too late, a message rate limited
+/* service should also register connect/disconnect events.
+/* .PP
+/* This feature is available in Postfix 2.2 and later.
+/* RECIPIENT RATE LIMITING
+/* .ad
+/* .fi
+/* When a remote client sends a recipient address, a recipient
+/* rate limited server should send the following request to
+/* the \fBanvil\fR server:
+/* .PP
+/* .in +4
+/* \fBrequest=recipient\fR
+/* .br
+/* \fBident=\fIstring\fR
+/* .in
+/* .PP
+/* This registers a recipient address for the (service, client)
+/* combination specified with \fBident\fR. The \fBanvil\fR server
+/* answers with the number of recipient addresses per unit time
+/* for that (service, client) combination:
+/* .PP
+/* .in +4
+/* \fBstatus=0\fR
+/* .br
+/* \fBrate=\fInumber\fR
+/* .in
+/* .PP
+/* In order prevent the anvil server from discarding client
+/* request rates too early or too late, a recipient rate limited
+/* service should also register connect/disconnect events.
+/* .PP
+/* This feature is available in Postfix 2.2 and later.
/* SECURITY
/* .ad
/* .fi
@@ -82,6 +139,9 @@
/* seconds, the server logs the maximal count and rate values measured,
/* together with (service, client) information and the time of day
/* associated with those events.
+/* In order to avoid unnecessary overhead, no measurements
+/* are done for activity that isn't concurrency limited or
+/* rate limited.
/* BUGS
/* Systems behind network address translating routers or proxies
/* appear to have the same client address and can run into connection
@@ -203,6 +263,14 @@ static int max_rate;
static char *max_rate_user;
static time_t max_rate_time;
+static int max_mail;
+static char *max_mail_user;
+static time_t max_mail_time;
+
+static int max_rcpt;
+static char *max_rcpt_user;
+static time_t max_rcpt_time;
+
/*
* Remote connection state, one instance for each (service, client) pair.
*/
@@ -210,6 +278,8 @@ typedef struct {
char *ident; /* lookup key */
int count; /* connection count */
int rate; /* connection rate */
+ int mail; /* message rate */
+ int rcpt; /* recipient rate */
time_t start; /* time of first rate sample */
} ANVIL_REMOTE;
@@ -242,6 +312,8 @@ typedef struct {
(remote)->ident = mystrdup(id); \
(remote)->count = 1; \
(remote)->rate = 1; \
+ (remote)->mail = 0; \
+ (remote)->rcpt = 0; \
(remote)->start = event_time(); \
} while(0)
@@ -260,6 +332,8 @@ typedef struct {
time_t _now = event_time(); \
if ((remote)->start + var_anvil_time_unit < _now) { \
(remote)->rate = 1; \
+ (remote)->mail = 0; \
+ (remote)->rcpt = 0; \
(remote)->start = _now; \
} else if ((remote)->rate < INT_MAX) { \
(remote)->rate += 1; \
@@ -269,6 +343,32 @@ typedef struct {
(remote)->count++; \
} while(0)
+#define ANVIL_ADD_MAIL(remote) \
+ do { \
+ time_t _now = event_time(); \
+ if ((remote)->start + var_anvil_time_unit < _now) { \
+ (remote)->rate = 0; \
+ (remote)->mail = 1; \
+ (remote)->rcpt = 0; \
+ (remote)->start = _now; \
+ } else if ((remote)->mail < INT_MAX) { \
+ (remote)->mail += 1; \
+ } \
+ } while(0)
+
+#define ANVIL_ADD_RCPT(remote) \
+ do { \
+ time_t _now = event_time(); \
+ if ((remote)->start + var_anvil_time_unit < _now) { \
+ (remote)->rate = 0; \
+ (remote)->mail = 0; \
+ (remote)->rcpt = 1; \
+ (remote)->start = _now; \
+ } else if ((remote)->rcpt < INT_MAX) { \
+ (remote)->rcpt += 1; \
+ } \
+ } while(0)
+
/* Drop connection from (service, client) state. */
#define ANVIL_REMOTE_DROP_ONE(remote) \
@@ -371,6 +471,8 @@ static void anvil_remote_lookup(VSTREAM *client_stream, const char *ident)
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);
@@ -381,23 +483,27 @@ static void anvil_remote_lookup(VSTREAM *client_stream, const char *ident)
ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_FAIL,
ATTR_TYPE_NUM, ANVIL_ATTR_COUNT, 0,
ATTR_TYPE_NUM, ANVIL_ATTR_RATE, 0,
+ ATTR_TYPE_NUM, ANVIL_ATTR_MAIL, 0,
+ ATTR_TYPE_NUM, ANVIL_ATTR_RCPT, 0,
ATTR_TYPE_END);
} else {
attr_print_plain(client_stream, ATTR_FLAG_NONE,
ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_OK,
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);
}
}
-/* anvil_remote_connect - report connection event, query address status */
+/* anvil_remote_conn_update - instantiate or update connection info */
-static void anvil_remote_connect(VSTREAM *client_stream, const char *ident)
+static ANVIL_REMOTE *anvil_remote_conn_update(VSTREAM *client_stream, const char *ident)
{
ANVIL_REMOTE *anvil_remote;
ANVIL_LOCAL *anvil_local;
- char *myname = "anvil_remote_connect";
+ char *myname = "anvil_remote_conn_update";
if (msg_verbose)
msg_info("%s fd=%d stream=0x%lx ident=%s",
@@ -435,6 +541,20 @@ static void anvil_remote_connect(VSTREAM *client_stream, const char *ident)
msg_info("%s: anvil_local 0x%lx",
myname, (unsigned long) anvil_local);
+ return (anvil_remote);
+}
+
+/* anvil_remote_connect - report connection event, query address status */
+
+static void anvil_remote_connect(VSTREAM *client_stream, const char *ident)
+{
+ ANVIL_REMOTE *anvil_remote;
+
+ /*
+ * Update or instantiate connection info.
+ */
+ anvil_remote = anvil_remote_conn_update(client_stream, ident);
+
/*
* Respond to the local client.
*/
@@ -469,6 +589,80 @@ static void anvil_remote_connect(VSTREAM *client_stream, const char *ident)
}
}
+/* anvil_remote_mail - register message delivery request */
+
+static void anvil_remote_mail(VSTREAM *client_stream, const char *ident)
+{
+ ANVIL_REMOTE *anvil_remote;
+
+ /*
+ * Be prepared for "postfix reload" after "connect".
+ */
+ if ((anvil_remote =
+ (ANVIL_REMOTE *) htable_find(anvil_remote_map, ident)) == 0)
+ anvil_remote = anvil_remote_conn_update(client_stream, ident);
+
+ /*
+ * Update message delivery request rate and respond to local client.
+ */
+ ANVIL_ADD_MAIL(anvil_remote);
+ attr_print_plain(client_stream, ATTR_FLAG_NONE,
+ ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_OK,
+ ATTR_TYPE_NUM, ANVIL_ATTR_RATE, anvil_remote->mail,
+ ATTR_TYPE_END);
+
+ /*
+ * Update local statistics.
+ */
+ if (anvil_remote->mail > max_mail) {
+ max_mail = anvil_remote->mail;
+ 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 */
+
+static void anvil_remote_rcpt(VSTREAM *client_stream, const char *ident)
+{
+ ANVIL_REMOTE *anvil_remote;
+
+ /*
+ * Be prepared for "postfix reload" after "connect".
+ */
+ if ((anvil_remote =
+ (ANVIL_REMOTE *) htable_find(anvil_remote_map, ident)) == 0)
+ anvil_remote = anvil_remote_conn_update(client_stream, ident);
+
+ /*
+ * Update recipient address rate and respond to local client.
+ */
+ ANVIL_ADD_RCPT(anvil_remote);
+ attr_print_plain(client_stream, ATTR_FLAG_NONE,
+ ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, ANVIL_STAT_OK,
+ ATTR_TYPE_NUM, ANVIL_ATTR_RATE, anvil_remote->rcpt,
+ ATTR_TYPE_END);
+
+ /*
+ * Update local statistics.
+ */
+ if (anvil_remote->rcpt > max_rcpt) {
+ max_rcpt = anvil_remote->rcpt;
+ 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_disconnect - report disconnect event */
static void anvil_remote_disconnect(VSTREAM *client_stream, const char *ident)
@@ -562,6 +756,10 @@ static void anvil_service(VSTREAM *client_stream, char *unused_service, char **a
ATTR_TYPE_END) == 2) {
if (STREQ(STR(request), ANVIL_REQ_CONN)) {
anvil_remote_connect(client_stream, STR(ident));
+ } 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_DISC)) {
anvil_remote_disconnect(client_stream, STR(ident));
} else if (STREQ(STR(request), ANVIL_REQ_LOOKUP)) {
@@ -621,6 +819,18 @@ static void anvil_status_dump(char *unused_name, char **unused_argv)
max_count, max_count_user, ctime(&max_count_time) + 4);
max_count = 0;
}
+ if (max_mail > 1) {
+ 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 > 1) {
+ 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;
+ }
}
/* anvil_status_update - log and reset extreme usage periodically */
diff --git a/postfix/src/global/anvil_clnt.c b/postfix/src/global/anvil_clnt.c
index 3ff1556db..cfa84550d 100644
--- a/postfix/src/global/anvil_clnt.c
+++ b/postfix/src/global/anvil_clnt.c
@@ -19,18 +19,32 @@
/* int *count;
/* int *rate;
/*
+/* int anvil_clnt_mail(anvil_clnt, service, addr, msgs)
+/* ANVIL_CLNT *anvil_clnt;
+/* const char *service;
+/* const char *addr;
+/* int *msgs;
+/*
+/* int anvil_clnt_rcpt(anvil_clnt, service, addr, rcpts)
+/* ANVIL_CLNT *anvil_clnt;
+/* const char *service;
+/* const char *addr;
+/* int *rcpts;
+/*
/* int anvil_clnt_disconnect(anvil_clnt, service, addr)
/* ANVIL_CLNT *anvil_clnt;
/* const char *service;
/* const char *addr;
/*
/* int anvil_clnt_lookup(anvil_clnt, service, addr,
-/* count, rate)
+/* count, rate, msgs, rcpts)
/* ANVIL_CLNT *anvil_clnt;
/* const char *service;
/* const char *addr;
/* int *count;
/* int *rate;
+/* int *msgs;
+/* int *rcpts;
/* DESCRIPTION
/* anvil_clnt_create() instantiates an anvil service client endpoint.
/*
@@ -38,6 +52,12 @@
/* client has connected, and returns the current connection
/* count and connection rate for that client.
/*
+/* anvil_clnt_mail() registers a MAIL FROM event and returns
+/* the current MAIL FROM rate for the specified client.
+/*
+/* anvil_clnt_rcpt() registers a RCPT TO event and returns
+/* the current RCPT TO rate for the specified client.
+/*
/* anvil_clnt_disconnect() informs the anvil server that a
/* client has disconnected.
/*
@@ -59,6 +79,12 @@
/* .IP rate
/* Pointer to storage for the current connection rate for this
/* remote client.
+/* .IP msgs
+/* Pointer to storage for the current message rate for this
+/* remote client.
+/* .IP rcpts
+/* Pointer to storage for the current recipient rate for this
+/* remote client.
/* DIAGNOSTICS
/* anvil_clnt_connect() and anvil_clnt_disconnect() return
/* ANVIL_STAT_OK in case of success, ANVIL_STAT_FAIL otherwise
@@ -120,15 +146,16 @@ ANVIL_CLNT *anvil_clnt_create(void)
/* anvil_clnt_free - destroy connection rate service client */
-void anvil_clnt_free(ANVIL_CLNT * anvil_clnt)
+void anvil_clnt_free(ANVIL_CLNT *anvil_clnt)
{
attr_clnt_free((ATTR_CLNT *) anvil_clnt);
}
/* anvil_clnt_lookup - status query */
-int anvil_clnt_lookup(ANVIL_CLNT * anvil_clnt, const char *service,
- const char *addr, int *count, int *rate)
+int anvil_clnt_lookup(ANVIL_CLNT *anvil_clnt, const char *service,
+ const char *addr, int *count, int *rate,
+ int *msgs, int *rcpts)
{
char *ident = ANVIL_IDENT(service, addr);
int status;
@@ -142,7 +169,9 @@ int anvil_clnt_lookup(ANVIL_CLNT * anvil_clnt, const char *service,
ATTR_TYPE_NUM, ANVIL_ATTR_STATUS, &status,
ATTR_TYPE_NUM, ANVIL_ATTR_COUNT, count,
ATTR_TYPE_NUM, ANVIL_ATTR_RATE, rate,
- ATTR_TYPE_END) != 3)
+ ATTR_TYPE_NUM, ANVIL_ATTR_MAIL, msgs,
+ ATTR_TYPE_NUM, ANVIL_ATTR_RCPT, rcpts,
+ ATTR_TYPE_END) != 5)
status = ANVIL_STAT_FAIL;
else if (status != ANVIL_STAT_OK)
status = ANVIL_STAT_FAIL;
@@ -152,7 +181,7 @@ int anvil_clnt_lookup(ANVIL_CLNT * anvil_clnt, const char *service,
/* anvil_clnt_connect - heads-up and policy 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)
{
char *ident = ANVIL_IDENT(service, addr);
@@ -175,9 +204,57 @@ int anvil_clnt_connect(ANVIL_CLNT * anvil_clnt, const char *service,
return (status);
}
+/* anvil_clnt_mail - heads-up and policy query */
+
+int anvil_clnt_mail(ANVIL_CLNT *anvil_clnt, const char *service,
+ const char *addr, int *msgs)
+{
+ 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_MAIL,
+ 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, msgs,
+ ATTR_TYPE_END) != 2)
+ status = ANVIL_STAT_FAIL;
+ else if (status != ANVIL_STAT_OK)
+ status = ANVIL_STAT_FAIL;
+ myfree(ident);
+ return (status);
+}
+
+/* anvil_clnt_rcpt - heads-up and policy query */
+
+int anvil_clnt_rcpt(ANVIL_CLNT *anvil_clnt, const char *service,
+ const char *addr, int *rcpts)
+{
+ 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_RCPT,
+ 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, rcpts,
+ ATTR_TYPE_END) != 2)
+ status = ANVIL_STAT_FAIL;
+ else if (status != ANVIL_STAT_OK)
+ status = ANVIL_STAT_FAIL;
+ myfree(ident);
+ return (status);
+}
+
/* anvil_clnt_disconnect - heads-up only */
-int anvil_clnt_disconnect(ANVIL_CLNT * anvil_clnt, const char *service,
+int anvil_clnt_disconnect(ANVIL_CLNT *anvil_clnt, const char *service,
const char *addr)
{
char *ident = ANVIL_IDENT(service, addr);
@@ -210,15 +287,26 @@ int anvil_clnt_disconnect(ANVIL_CLNT * anvil_clnt, const char *service,
#include