+++ /dev/null
-LINUX SYSLOGD PERFORMANCE
-=========================
-
-LINUX syslogd uses synchronous writes by default, which is very
-expensive. For services such as mail it is recommended that you
-disable synchronous logfile writes by prepending a - to the logfile
-name:
-
- mail.* -/var/log/mail.log
-
-SPAM BLOCKING SOURCE ROUTED ADDRESSES
-=====================================
-
-If you relay mail for other domains, you must prevent unauthorized
-relay of addresses such as:
-
- user@elsewhere@the.other.domain
- user%elsewhere@the.other.domain
- elsewhere!user@the.other.domain
-
-The simplest solution is to install a regular expression filter:
-
- /etc/postfix/main.cf:
- smtpd_recipient_restrictions = regexp:/etc/postfix/regexp_access
-
- /etc/postfix/regexp_access:
- /[%!@].*@/ 550 Sender specified routing is not supported here.
-
-For the local domain, Postfix will do the right thing with:
-
- user@elsewhere@my.own.domain
- user%elsewhere@my.own.domain
- elsewhere!user@my.own.domain
-
-That is, it bounces the first form because "user@elsewhere" is not
-a valid local user, and it accepts the second and third forms only
-when user@elsewhere is a valid relay destination.
-
19990410
Bugfix: auto-detection of changes to DB or DBM lookup
- tables wan't done for TCP connections.
+ tables wasn't done for TCP connections.
19990410
19991217
- Cleanup: no more UCE checks for VRFY commands.
+ Cleanup: no more UCE checks for VRFY commands. It still
+ reports unknown local/virtual users. File: smtpd/smtpd_check.c.
+
+ Robustness: upon Postfix startup, report discrepancies
+ between system files inside and outside the chroot jail.
+ Files: conf/postfix-script-nosgid, conf/postfix-script-sgid.
19991218
19991219
Documentation: completely reorganized the FAQ and added
- many new entries.
+ many new entries. Rewrote the UCE html documentation.
Cleanup: INSTALL.sh uses a configurable directory for
scratch files, so that it can install from a file system
that is not writable by the super-user.
+ Cleanup: INSTALL.sh gives helpful hints when the "mv"
+ command is unable to move symlinks across file system
+ boundaries.
+
19991220
Cleanup: it is no longer necessary to list $virtual_maps
as part of the relay_domains definition. The SMTP server
- now by default accepts mail for domains that match
- $mydestination or $virtual_maps, or that resolve to a mail
- delivery transport that is listed in $local_transport.
- Files: smtpd/smtpd_check.c and lots of documentation.
+ now by default accepts mail for destinations that match
+ $inet_interfaces, $mydestination or $virtual_maps, whether
+ or not these are specified in relay_domains. We still need
+ the ugly "virtual.domain whatever" hack in the virtual
+ maps. Files: smtpd/smtpd_check.c and lots of documentation
+ and sample config files.
+
+19991221
+
+ Removed cyrus -q flag (ignore quotas) from the sample
+ master.cf file.
+
+19991223
+
+ Bugfix: smtpd should not check for unknown users when
+ running in stand-alone (sendmail -bs) mode. Problem
+ experienced by Chuck Mead. File: smtpd/smtpd.c.
+
+ Retraction: the "local_transports" configuration parameter
+ is gone. Adjusted code and documentation accordingly.
+ Instead, use just one "local_transport" parameter with the
+ name of the default local transport. Files: smtpd/smtpd_check.c,
+ qmgr/qmgr_message.c, trivial-rewrite/ resolve.c, local/resolve.c.
+
+ Feature: Postfix SMTPD now insists that the smtpd recipient
+ restrictions contain at least one restriction that by
+ default rejects mail. This should make it much more difficult
+ to change Postfix into an open relay. File: smtpd/smtpd_check.c.
+
+ Retraction: null-length inet_interfaces is too confusing.
Most definitions will be remembered, so you have to specify them
only once. All definitions have a reasonable default value.
- tempdir - where to write scratch files
-
install_root - prefix for installed file names (for package building)
+ tempdir - where to write scratch files
+
config_directory - directory with Postfix configuration files.
daemon_directory - directory with Postfix daemon programs.
command_directory - directory with Postfix administrative commands.
rm -f $tempdir/junk || exit 1
target=`echo $1 | sed '
s;^'$install_root';;
- s;//;/;g
s;/\./;/;g
- s;^/*;;
+ s;//*;/;g
+ s;^/;;
H
s;/[^/]*$;/;
s;[^/]*/;../;g
ln -s $target $tempdir/junk || exit 1
mv -f $tempdir/junk $2 || {
echo Error: your mv command is unable to rename symlinks. 1>&2
- echo If you run Linux, upgrade to GNU fileutils-4.0 or better. 1>&2
+ echo If you run Linux, upgrade to GNU fileutils-4.0 or better, 1>&2
+ echo or choose a tempdir that is in the same file system as $2. 1>&2
exit 1
}
}
# Default settings. Most are clobbered by remembered settings.
-tempdir=`pwd`
install_root=/
+tempdir=`pwd`
config_directory=/etc/postfix
daemon_directory=/usr/libexec/postfix
command_directory=/usr/sbin
# Find out the location of configuration files.
-for name in tempdir install_root config_directory
+for name in install_root tempdir config_directory
do
while :
do
tidy: clean
rm -f Makefile */Makefile
cp Makefile.init Makefile
- -rm -f *core */*core .nfs* .pure bin/* lib/* include/* libexec/* \
+ -rm -f junk *core */*core .nfs* .pure bin/* lib/* include/* libexec/* \
*/.nfs* */.pure *.out */*.out */*.db */*.a *~ */*~ *- */*- *.orig \
*/*.orig *.bak */*.bak make.err conf/main.cf.default
find . -type s -print | xargs rm -f
-Incompatible changes with snapshot 19991219
+Incompatible changes with snapshot 19991223
===========================================
-- The experimental permit_recipient_map feature is gone. It was
-never part of an official release. It is replaced by a
-"local_recipient_map" parameter that allows the SMTP server to
-reject mail for unknown local users (see below).
+- The experimental permit_recipient_map and local_transports features
+are gone. They were never part of an official release. Both are
+replaced by a "local_recipient_map" parameter that allows the SMTP
+server to reject mail for unknown local users (see below).
- In an SMTPD access map, an all-numeric right-hand side now means
OK. This is for better cooperation with out-of-band authentication
SMTPD access control tables. Use the local_recipient_maps feature
instead.
-- transport_maps entries override mydestination. For every
-$mydestination domain that matches a transport map entry, or a
-parent domain of a transport map entry, you must now add a
-corresponding "domain.name local:" entry in your transport_maps.
-See the html/faq.html sections for firewalls and intranets.
+- transport_maps entries override mydestination. If you use
+transport maps, it is better to always have explicit entries for
+all domain names you have in $mydestination. See the html/faq.html
+sections for firewalls and intranets.
-Major changes with snapshot 19991219
+Major changes with snapshot 19991223
====================================
+- It is now much more difficult to configure Postfix as an open
+relay. The SMTP server requires that "smtpd_recipient_restrictions"
+contains at least one restriction that by default refuses mail (as
+is the default). There were too many accidents with changes to
+the UCE restrictions.
+
+- The relay_domains parameter no longer needs to contain $virtual_maps.
+
- Overhauled FAQ (html/faq.html) with many more examples.
+- Updated UCE documentation (html/uce.html) with more examples.
+More UCE configuration examples in sample configuration files.
+
- Several little improvements to the installation procedure:
-relative symlinks, configurable directory for scratch files.
+relative symlinks, configurable directory for scratch files so the
+installation can be done without write access to the build tree.
- Updated LDAP client code (John Hensley).
# mail to. See the smtpd_recipient_restrictions restriction in the
# file sample-smtpd.cf.
#
-# By default, Postfix relays mail from clients whose IP address
-# matches $mynetworks, and from clients or to destination domains
-# matching $relay_domains or subdomains thereof. The default
-# relay_domains value is $mydestination.
+# By default, Postfix relays mail
+# - from clients whose IP address matches $mynetworks,
+# - from clients matching $relay_domains or subdomains thereof,
+# - to destinations that match $relay_domains or subdomains thereof.
+# The default relay_domains value is $mydestination.
#
-# By default, the Postfix SMTP server accepts mail for domains listed
-# in $mydestination and in $virtual_maps, and for destinations that
-# resolve to a mail delivery transport listed in $local_transports.
+# In addition to the above, the Postfix SMTP server by default accepts mail
+# that Postfix is final destination for:
+# - destinations that match $inet_interfaces,
+# - destinations that match $mydestination
+# - destinations that match $virtual_maps.
# These destinations do not need to be listed in $relay_domains.
#
# Specify a list of hosts or domains, /file/name patterns or type:name
error unix - - n - - error
local unix - n n - - local
cyrus unix - n n - - pipe
- flags=R user=cyrus argv=/cyrus/bin/deliver -e -q -m ${extension} ${user}
+ flags=R user=cyrus argv=/cyrus/bin/deliver -e -m ${extension} ${user}
uucp unix - n n - - pipe
flags=F user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)
ifmail unix - n n - - pipe
# See the sample-aliases.cf file for parameters that are specific to
# alias database lookup.
+#
+# OVERRIDE LOCAL TRANSPORT
+#
+
+# The local_transport parameter specifies the name of the transport
+# for delivery to destinations that match $mydestination or
+# $inet_interfaces.
+#
+# By default, local mail is delivered to the transport called "local",
+# which is just the name of a service that is defined the master.cf file.
+#
+local_transport = local
+
#
# SECURITY CONTROLS
#
# permit_mynetworks: permit if the client address matches $mynetworks.
# check_client_access maptype:mapname
# maptype:mapname: look up client name, parent domains, client address,
-# or networks obtained by stripping octets.
-# Reject if result is REJECT or "[45]xx text"
-# Permit otherwise.
+# or networks obtained by stripping octets.
+# Reject if result is REJECT or "[45]xx text"
+# Permit otherwise.
# reject_maps_rbl: reject if the client is listed under $maps_rbl_domains.
# reject: reject the request. Place this at the end of a restriction.
# permit: permit the request. Place this at the end of a restriction.
# permit_mynetworks: permit if the client address matches $mynetworks.
# check_client_access maptype:mapname
# maptype:mapname: look up client name, parent domains, client address,
-# or networks obtained by stripping octets.
-# Reject if result is REJECT or "[45]xx text"
-# Permit otherwise.
+# or networks obtained by stripping octets.
+# Reject if result is REJECT or "[45]xx text"
+# Permit otherwise.
# reject_maps_rbl: reject if the client is listed under $maps_rbl_domains.
# reject: reject the request. Place this at the end of a restriction.
# permit: permit the request. Place this at the end of a restriction.
# Specify a list of restrictions, separated by commas and/or whitespace.
# Continue long lines by starting the next line with whitespace.
#
+#smtpd_client_restrictions = permit_mynetworks, reject_unknown_client
+#smtpd_client_restrictions = reject_maps_rbl, reject_unknown_client
smtpd_client_restrictions =
# The smtpd_helo_required parameter optionally turns on the requirement
# reject_non_fqdn_hostname: reject HELO hostname that is not in FQDN form
# check_helo_access maptype:mapname
# maptype:mapname: look up HELO hostname or parent domains.
-# Reject if result is REJECT or "[45]xx text"
-# Permit otherwise.
+# Reject if result is REJECT or "[45]xx text"
+# Permit otherwise.
# check_client_access maptype:mapname: see smtpd_client_restrictions.
# reject: reject the request. Place this at the end of a restriction.
# permit: permit the request. Place this at the end of a restriction.
# Specify a list of restrictions, separated by commas and/or whitespace.
# Continue long lines by starting the next line with whitespace.
#
-# smtpd_helo_restrictions = reject_invalid_hostname
+# smtpd_helo_restrictions = permit_mynetworks, reject_invalid_hostname
# smtpd_helo_restrictions = permit_mynetworks, reject_unknown_hostname
smtpd_helo_restrictions =
# reject_unknown_sender_domain: reject sender domain without A or MX record.
# check_sender_access maptype:mapname
# maptype:mapname: look up sender address, parent domain, or localpart@.
-# Reject if result is REJECT or "[45]xx text"
-# Permit otherwise.
+# Reject if result is REJECT or "[45]xx text"
+# Permit otherwise.
# check_client_access maptype:mapname: see smtpd_client_restrictions.
# check_helo_access maptype:mapname: see smtpd_helo_restrictions.
# reject_non_fqdn_hostname: reject HELO hostname that is not in FQDN form
# The smtpd_recipient_restrictions parameter specifies restrictions on
# recipient addresses that SMTP clients can send in RCPT TO commands.
#
-# By default, Postfix relays mail from clients whose IP address
-# matches $mynetworks, and from clients or to destination domains
-# matching $relay_domains or subdomains thereof. The default
-# relay_domains value is $mydestination.
-#
-# By default, the Postfix SMTP server accepts mail for domains listed
-# in $mydestination and in $virtual_maps, and for destinations that
-# resolve to a mail delivery transport listed in $local_transports.
+# By default, Postfix relays mail
+# - from clients whose IP address matches $mynetworks,
+# - from clients matching $relay_domains or subdomains thereof,
+# - to destinations that match $relay_domains or subdomains thereof.
+# The default relay_domains value is $mydestination.
+#
+# In addition to the above, the Postfix SMTP server by default accepts mail
+# that Postfix is final destination for:
+# - destinations that match $inet_interfaces,
+# - destinations that match $mydestination
+# - destinations that match $virtual_maps.
# These destinations do not need to be listed in $relay_domains.
#
# The following restrictions are available (* is part of default setting):
# reject_invalid_hostname: reject HELO hostname with bad syntax.
# reject_unknown_hostname: reject HELO hostname without DNS A or MX record.
# reject_unknown_sender_domain: reject sender domain without A or MX record.
-# *check_relay_domains: permit only mail from clients/to domains matching
-# $relay_domains, or to $mydestination, $virtual_maps or $local_transports
-# permit_auth_destination: permit mail to domains matching $relay_domains,
-# or to $mydestination, $virtual_maps or $local_transports.
-# reject_unauth_destination: reject mail not to $relay_domains or to
-# $mydestination, $virtual_maps or $local_transports.
+# *check_relay_domains: permit only mail
+# - from clients matching $relay_domains or subdomain thereof,
+# - to destinations matching $relay_domains or subdomain thereof,
+# - to destinations matching $inet_interfaces, $mydestination,
+# or $virtual_maps.
+# Reject anything else.
+# permit_auth_destination: permit mail
+# - to destinations matching $relay_domains or subdomain thereof,
+# - to destinations matching $inet_interfaces, $mydestination,
+# or $virtual_maps.
+# reject_unauth_destination: reject mail unless it is sent
+# - to destinations matching $relay_domains or subdomain thereof,
+# - to destinations matching $inet_interfaces, $mydestination,
+# or $virtual_maps.
# reject_unauth_pipelining: reject mail from improperly pipelining spamware
# permit_mx_backup: accept mail for sites that list me as MX host.
# reject_unknown_recipient_domain: reject domains without A or MX record.
# check_recipient_access maptype:mapname
# maptype:mapname: look up recipient address, parent domain, or localpart@.
-# Reject if result is REJECT or "[45]xx text"
-# Permit otherwise.
+# Reject if result is REJECT or "[45]xx text"
+# Permit otherwise.
# check_client_access maptype:mapname: see smtpd_client_restrictions.
# check_helo_access maptype:mapname: see smtpd_helo_restrictions.
# check_sender_access maptype:mapname: see smtpd_sender_restrictions.
# Specify a list of restrictions, separated by commas and/or whitespace.
# Continue long lines by starting the next line with whitespace.
#
+# NOTE: YOU MUST SPECIFY AT LEAST ONE OF THE FOLLOWING RESTRICTIONS
+# OTHERWISE POSTFIX REFUSES TO RECEIVE MAIL:
+# reject, check_relay_domains, reject_unauth_destination
+#
smtpd_recipient_restrictions = permit_mynetworks,check_relay_domains
#
# and restricts what destination domains (and subdomains thereof)
# this system will relay mail to.
#
-# By default, Postfix relays mail from clients whose IP address
-# matches $mynetworks, and from clients or to destination domains
-# matching $relay_domains or subdomains thereof. The default
-# relay_domains value is $mydestination.
-#
-# By default, the Postfix SMTP server accepts mail for domains listed
-# in $mydestination and in $virtual_maps, and for destinations that
-# resolve to a mail delivery transport listed in $local_transports.
+# By default, Postfix relays mail
+# - from clients whose IP address matches $mynetworks,
+# - from clients matching $relay_domains or subdomains thereof,
+# - to destinations that match $relay_domains or subdomains thereof.
+# The default relay_domains value is $mydestination.
+#
+# In addition to the above, the Postfix SMTP server by default accepts mail
+# that Postfix is final destination for:
+# - destinations that match $inet_interfaces,
+# - destinations that match $mydestination
+# - destinations that match $virtual_maps.
# These destinations do not need to be listed in $relay_domains.
#
# Specify a list of hosts or domains, /file/name patterns or type:name
# This file contains example settings of Postfix configuration
# parameters that control the optional transport table lookups.
-# The local_transports parameter defines the name of the default
-# transport for local mail delivery, plus zero or more names of
-# additional transports that are known to deliver locally. By default,
-# the SMTP server's UCE restrictions permit mail for any destination
-# that resolves to a mail delivery transport in $local_transports.
-#
-local_transports = local,cyrus
-
# The transport_maps parameter specifies optional tables with domain
# to (transport, nexthop) mappings. See transport(5) for syntax details.
#
debug_peer.c debug_process.c defer.c deliver_completed.c \
deliver_flock.c deliver_pass.c deliver_request.c domain_list.c \
dot_lockfile.c dot_lockfile_as.c ext_prop.c file_id.c \
- header_opts.c is_header.c local_transport.c mail_addr.c \
+ header_opts.c is_header.c mail_addr.c \
mail_addr_crunch.c mail_addr_find.c mail_addr_map.c \
mail_command_read.c mail_command_write.c mail_conf.c \
mail_conf_bool.c mail_conf_int.c mail_conf_raw.c mail_conf_str.c \
debug_peer.o debug_process.o defer.o deliver_completed.o \
deliver_flock.o deliver_pass.o deliver_request.o domain_list.o \
dot_lockfile.o dot_lockfile_as.o ext_prop.o file_id.o \
- header_opts.o is_header.o local_transport.o mail_addr.o \
+ header_opts.o is_header.o mail_addr.o \
mail_addr_crunch.o mail_addr_find.o mail_addr_map.o \
mail_command_read.o mail_command_write.o mail_conf.o \
mail_conf_bool.o mail_conf_int.o mail_conf_raw.o mail_conf_str.o \
config.h debug_peer.h debug_process.h defer.h deliver_completed.h \
deliver_flock.h deliver_pass.h deliver_request.h domain_list.h \
dot_lockfile.h dot_lockfile_as.h ext_prop.h file_id.h \
- header_opts.h is_header.h local_transport.h mail_addr.h \
+ header_opts.h is_header.h mail_addr.h \
mail_addr_crunch.h mail_addr_find.h mail_addr_map.h mail_conf.h \
mail_copy.h mail_date.h mail_error.h mail_flush.h mail_open_ok.h \
mail_params.h mail_proto.h mail_queue.h mail_run.h mail_scan_dir.h \
* XXX Solaris workaround for ECONNREFUSED on a busy socket.
*/
while ((stream = mail_connect(class, name, BLOCKING)) == 0) {
- if (errno == ECONNREFUSED || errno == ENOENT) {
- if (count++ >= 10) {
- msg_fatal("connect #%d to subsystem %s/%s: %m",
- count, class, name);
- } else {
- msg_warn("connect #%d to subsystem %s/%s: %m",
- count, class, name);
- }
+ if (count++ >= 10) {
+ msg_fatal("connect #%d to subsystem %s/%s: %m",
+ count, class, name);
+ } else {
+ msg_warn("connect #%d to subsystem %s/%s: %m",
+ count, class, name);
}
sleep(10); /* XXX make configurable */
}
/* time_t var_starttime;
/* int var_ownreq_special;
/* int var_daemon_timeout;
-/* char *var_local_transports;
/*
/* void mail_params_init()
/* DESCRIPTION
time_t var_starttime;
int var_ownreq_special;
int var_daemon_timeout;
-char *var_local_transports;
/* check_myhostname - lookup hostname and validate */
VAR_COMMAND_DIR, DEF_COMMAND_DIR, &var_command_dir, 1, 0,
VAR_QUEUE_DIR, DEF_QUEUE_DIR, &var_queue_dir, 1, 0,
VAR_PID_DIR, DEF_PID_DIR, &var_pid_dir, 1, 0,
- VAR_INET_INTERFACES, DEF_INET_INTERFACES, &var_inet_interfaces, 0, 0,
+ VAR_INET_INTERFACES, DEF_INET_INTERFACES, &var_inet_interfaces, 1, 0,
VAR_DOUBLE_BOUNCE, DEF_DOUBLE_BOUNCE, &var_double_bounce_sender, 1, 0,
VAR_DEFAULT_PRIVS, DEF_DEFAULT_PRIVS, &var_default_privs, 1, 0,
VAR_ALIAS_DB_MAP, DEF_ALIAS_DB_MAP, &var_alias_db_map, 1, 0,
VAR_DB_TYPE, DEF_DB_TYPE, &var_db_type, 1, 0,
VAR_HASH_QUEUE_NAMES, DEF_HASH_QUEUE_NAMES, &var_hash_queue_names, 1, 0,
VAR_RCPT_DELIM, DEF_RCPT_DELIM, &var_rcpt_delim, 0, 1,
- VAR_LOCAL_TRANSP, DEF_LOCAL_TRANSP, &var_local_transports, 1, 0,
0,
};
static CONFIG_STR_FN_TABLE function_str_defaults_2[] = {
extern char *var_mydomain;
/*
- * Transports that deliver locally. Order matters.
+ * The default local delivery transport.
*/
-#define VAR_LOCAL_TRANSP "local_transports"
-#define DEF_LOCAL_TRANSP "local,cyrus"
-extern char *var_local_transports;
+#define VAR_LOCAL_TRANSPORT "local_transport"
+#define DEF_LOCAL_TRANSPORT "local"
+extern char *var_local_transport;
/*
* Where to send postmaster copies of bounced mail, and other notices.
* Version of this program.
*/
#define VAR_MAIL_VERSION "mail_version"
-#define DEF_MAIL_VERSION "Snapshot-19991220"
+#define DEF_MAIL_VERSION "Snapshot-19991223"
extern char *var_mail_version;
/* LICENSE
<li><a href="#verbose">Postfix breaks "sendmail -v"</a>
+<li><a href="#delayed">Postfix sends no "delayed mail" notices</a>
+
<li><a href="#root">Root's mail is delivered to nobody</a>
+<li><a href="#bogus">Postfix accepts mail for non-existing users</a>
+
<li><a href="#duplicate">Postfix sends duplicate mail</a>
<li><a href="#metoo">Postfix sends mail to every member of a
<ul>
+<li><a href="#open_relay">Help! Postfix is an open relay</a>
+
<li><a href="#mobile">Relaying mail for mobile users</a>
<li><a href="#relay_virtual">Postfix refuses to receive mail for some
<li><a href="#root">Root's mail is delivered to nobody</a>
+<li><a href="#bogus">Postfix accepts mail for non-existing users</a>
+
<li><a href="#some_local">Delivering some users locally while
sending mail as user@domain</a>
<hr>
+<a name="delayed"><h3>Postfix sends no "delayed mail" notices</h3>
+
+<blockquote>
+
+When I was using Sendmail, after 4 hours, it would always send a receipt
+back to the sender saying mail delivery is delayed.
+
+</blockquote>
+
+<p>
+
+In order to make Postfix send "delayed mail" notifications after
+four hours, specify:
+
+<p>
+
+<pre>
+ <b>/etc/postfix/main.cf</b>
+ delay_warning_time = 4
+</pre>
+
+<p>
+
+
+With Postfix, delayed mail notices are turned off by default -
+people get enough mail already.
+
+<hr>
+
<a name="duplicate"><h3>Postfix sends duplicate mail</h3> </a>
Some people will complain that Postfix sends duplicate messages.
<hr>
+<a name="open_relay"><h3>Help! Postfix is an open relay</h3>
+
+According to some relay checking software, Postfix accepts
+mail for arbitrary non-local destinations:
+
+<p>
+
+<pre>
+ >>> MAIL FROM:<someone@some.where>
+ <<< 250 Ok
+ >>> RCPT TO:<test@some.other.site@your.site>
+ <<< 250 Ok
+ >>> DATA
+ <<< 354 End data with <CR><LF>.<CR><LF>
+ >>> (message body)
+ <<< 250 Ok: queued as A958F5A15
+</pre>
+
+
+<p>
+
+Don't Panic!
+
+<p>
+
+If the mail for domain <i>your.site</i> is handled by a Postfix
+machine, the mail bounces because <i>test@some.other.site</i> is
+not a known user in domain <i>your.site</i>. In fact, the above
+mail is rejected immediately when the Postfix SMTP server is
+configured to <a href="#bogus">reject mail for unknown local
+users</a>.
+
+<p>
+
+However, there will be a problem when you are backup MX host for
+a domain that runs Sendmail, because many Sendmail configurations
+will forward the above mail to <i>test@some.other.site</i>. The
+bad news is that your machine will be put on the black list because
+it accepted the mail, even though the problem is with the configuration
+of a Sendmail machine that is not under your control.
+
+<p>
+
+So, if you're MX relay for other sites it is prudent to block
+addresses with multiple address operators at the SMTP port, even
+though you would also block legitimate addresses.
+
+<p>
+
+<pre>
+ <b>/etc/postfix/main.cf:</b>
+ smtpd_recipient_restrictions =
+ regexp:/etc/postfix/regexp_access
+ ...other UCE restrictions...
+
+ <b>/etc/postfix/regexp_access</b>:
+ /[%!@].*[%!@]/ 550 Sender specified routing is not supported here.
+</pre>
+
+<hr>
+
<a name="mobile"><h3>Relaying mail for mobile users </h3>
<blockquote>
<hr>
+<a name="bogus"><h3>Postfix accepts mail for non-existing users</h3>
+
+The information in this section applies to Postfix versions 19991216
+and later.
+
+<p>
+
+By default, the Postfix SMTP server does not know what local users
+exist, and will happily accept mail for <i>unknown@your.site</i>.
+The reason is that different local delivery agents have different
+types of user databases.
+
+<p>
+
+Of course mail for a non-existent local user will eventually bounce
+as undeliverable, but why accept such mail in the first place? You
+can tell the Postfix SMTP server how find out if a user exists by
+listing all tables with local addresses in the <b>local_recipient_maps</b>
+parameter:
+
+<p>
+
+<pre>
+ <b>/etc/postfix/main.cf</b>
+ local_recipient_maps = $alias_maps, unix:passwd.byname
+</pre>
+
+<p>
+
+The above should work on UNIX systems, provided that you use the
+Postfix local delivery agent. However, if you run the Postfix SMTP
+server chrooted, on some systems it will be necessary to have a
+copy of the passwd file inside the chroot jail (typically: in
+<b>/var/spool/postfix/etc</b>).
+
+<p>
+
+By default, the Postfix SMTP server does know about Postfix <a
+href="virtual.5.html">virtual</a> maps, and will reject mail for
+<i>unknown@virtual.domain</i> without further configuration.
+
+<hr>
+
<a name="some_local"><h3>Delivering some users locally while sending
mail as user@domain</h3></a>
<p>
-<li>Verify that
-the <a
-href="uce.html#relay_domains">relay_domains</a> parameter contains
-<b>$virtual_maps</b>. This is the default setting.
-
-<p>
-
<li>Verify that the <a
href="uce.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a>
parameter contains a restriction that depends on <a
<pre>
<b>/etc/postfix/main.cf</b>:
- relay_domains = some.domain $mydestination $virtual_maps ...
+ relay_domains = some.domain $mydestination ...
</pre>
<p>
<dt>Default:
+<dd><b>smtpd_client_restrictions =</b>
+
+<p>
+
<dd>Allow SMTP connections from any client.
<p>
<dt>Default:
+<dd><b>smtpd_helo_required = no</b>
+
+<p>
+
<dd>By default, the Postfix <a href="smtpd.8.html">SMTP server</a>
does not require the use of <b>HELO</b> (<b>EHLO</b>).
<dt>Default:
+<dd><b>smtpd_helo_restrictions =</b>
+
+<p>
+
<dd>By default, the Postfix <a href="smtpd.8.html">SMTP server</a>
-accepts any garbage in the <b>HELO</b> (<b>EHLO</b>) command.
+accepts any garbage in the <b>HELO</b> (<b>EHLO</b>) command. There
+is a lot of broken or misconfigured software on the Internet.
<p>
<dt>Example:
-<dd> <b>smtpd_helo_restrictions = reject_invalid_hostname</b>
+<dd> <b>smtpd_helo_restrictions = permit_mynetworks,
+reject_invalid_hostname</b>
<p>
The <b>strict_rfc821_envelopes</b> parameter controls how tolerant
Postfix is with respect to addresses given in MAIL FROM or RCPT TO
-commands. Being strict to the RFC not only stops unwanted mail,
-but also blocks legitimate mail from poorly-written mail applications.
+commands. Unfortunately, the widely-used Sendmail program tolerates
+lots of non-standard behavior, so a lot of software expects to get
+away with it. Being strict to the RFC not only stops unwanted
+mail, it also blocks legitimate mail from poorly-written mail
+applications.
<p>
<dt> Default:
+<dd><b>strict_rfc821_envelopes = no</b>
+
+<p>
+
<dd>By default, the Postfix <a href="smtpd.8.html">SMTP server</a>
-accepts any address form that it can make sense of, including forms
-that contain RFC 822-style comments, or addresses not enclosed in
-<>.
+accepts any address form that it can make sense of, including
+address forms that contain RFC 822-style comments, or addresses
+not enclosed in <>. There is a lot of broken or misconfigured
+software out there on the Internet.
<p>
<dt> Default:
+<dd><b>smtpd_sender_restrictions =</b>
+
+<p>
+
<dd>By default, the Postfix <a href="smtpd.8.html">SMTP server</a>
accepts any sender address.
<dt> Example:
-<dd> <b>smtpd_sender_restrictions = reject_unknown_sender_domain</b>
+<dd> <b>smtpd_sender_restrictions = hash:/etc/postfix/access,
+reject_unknown_sender_domain</b>
<p>
<dl>
-<dt>Default:
+<dt>Default:
+
+<dd><b>smtpd_recipient_restrictions = permit_mynetworks, check_relay_domains</b>
+
+<p>
<dd>By default, the Postfix <a href="smtpd.8.html">SMTP server</a>
-relays mail from any client whose IP address matches <a
-href="basic.html#mynetworks">$mynetworks</a> or whose hostname
-matches <a href="#relay_domains">$relay_domains</a> or a subdomain
-thereof, and relays mail to any destination that matches <a
-href="#relay_domains"> $relay_domains</a> or a subdomain thereof.
+relays mail:
<p>
-In addition, the Postfix <a href="smtpd.8.html">SMTP server</a> by
-default accepts mail for which Postfix is the final destination:
-anything that matches <a href="basic.html#mydomain">$mydomain</a>,
-<a href="basic.html#mynetworks">$mynetworks</a> or <a
-href="virtual.5.html">$virtual_maps</a>, or anything that resolves
-to a mail delivery transport whose name is listed in $local_transports.
+<ul>
+
+<li>from clients whose IP address matches <a
+href="basic.html#mynetworks">$mynetworks</a>,
+
+<li>from clients whose hostname matches <a
+href="#relay_domains">$relay_domains</a> or a subdomain thereof,
+
+<li>to destinations that match <a href="#relay_domains">
+$relay_domains</a> or a subdomain thereof.
+
+</ul>
+
+<p>
+
+In addition to the above, the Postfix <a href="smtpd.8.html">SMTP
+server</a> by default accepts mail for which Postfix is the final
+destination:
+
+<p>
+
+<ul>
+
+<li>to destinations that match <a
+href="basic.html#inet_interfaces">$inet_interfaces</a>,
+
+<li>to destinations that match <a
+href="basic.html#mydestination">$mydestination</a>,
+
+<li>to destinations that match <a href="virtual.5.html">$virtual_maps</a>.
+
+</ul>
<p>
<p>
+<dd><i>Note: you must specify at least one of the following
+restrictions: </i><b>reject</b>, <b>check_relay_domains</b> or
+<b>reject_unauth_destination</b>. <i>Postfix will refuse to
+receive mail otherwise. </i>
+
+<p>
+
<dt> Restrictions:
<dl>
<a name="check_relay_domains">
-<dt> <b>check_relay_domains</b> <dd> Permit the request when the
-client hostname matches <a href="#relay_domains">$relay_domains</a>
-or a subdomain thereof, or when the resolved destination address
-matches <a href="#relay_domains">$relay_domains</a> or a subdomain
-thereof, or when Postfix is the final destination: anything that
-matches <a href="basic.html#mydomain">$mydomain</a>, <a
-href="basic.html#mynetworks">$mynetworks</a> or <a
-href="virtual.5.html">$virtual_maps</a>, or anything that resolves
-to a mail delivery transport whose name is listed in $local_transports.
+<dt> <b>check_relay_domains</b> <dd> Permit the request when
+
+<ul>
+
+<li>the client hostname matches <a href="#relay_domains">$relay_domains</a>
+or a subdomain thereof,
+
+<li>the resolved destination address matches <a
+href="#relay_domains">$relay_domains</a> or a subdomain thereof,
+
+<li>Postfix is the final destination: any destination that matches
+<a href="basic.html#mydestination">$mydestination</a>, <a
+href="basic.html#inet_interfaces">$inet_interfaces</a> or <a
+href="virtual.5.html">$virtual_maps</a>.
+
+</ul>
+
Otherwise reject the request. The <b>relay_domains_reject_code</b>
parameter specifies the response code for rejected requests (default:
<b>554</b>).
<a name="permit_auth_destination">
<dt> <b>permit_auth_destination</b> <dd> Ignore the client hostname.
-Permit the request when the resolved destination address matches
-<a href="#relay_domains"> $relay_domains</a> or a subdomain thereof,
-or when Postfix is the final destination: anything that matches
-<a href="basic.html#mydomain">$mydomain</a>, <a
-href="basic.html#mynetworks">$mynetworks</a> or <a
-href="virtual.5.html">$virtual_maps</a>, or anything that resolves
-to a mail delivery transport whose name is listed in $local_transports.
+Permit the request when:
+
+<ul>
+
+<li>the resolved destination address matches <a
+href="#relay_domains">$relay_domains</a> or a subdomain thereof,
+
+<li>Postfix is the final destination: any destination that matches
+<a href="basic.html#mydestination">$mydestination</a>, <a
+href="basic.html#inet_interfaces">$inet_interfaces</a> or <a
+href="virtual.5.html">$virtual_maps</a>.
+
+</ul>
+
+Otherwise proceed with the next restriction.
<p>
<a name="reject_unauth_destination">
<dt> <b>reject_unauth_destination</b> <dd> Ignore the client
-hostname. Reject the request when the resolved destination address
-does not match <a href="#relay_domains"> $relay_domains</a> or a
-subdomain thereof, and when Postfix is not the final destination.
-Postfix is final destination for anything that matches <a
-href="basic.html#mydomain">$mydomain</a>, <a
-href="basic.html#mynetworks">$mynetworks</a> or <a
-href="virtual.5.html">$virtual_maps</a>, or anything that resolves
-to a mail delivery transport whose name is listed in $local_transports.
+hostname. Reject the request unless:
+
+<ul>
+
+<li>the resolved destination address matches <a
+href="#relay_domains">$relay_domains</a> or a subdomain thereof,
+
+<li>Postfix is the final destination: any destination that matches
+<a href="basic.html#mydestination">$mydestination</a>, <a
+href="basic.html#inet_interfaces">$inet_interfaces</a> or <a
+href="virtual.5.html">$virtual_maps</a>.
+
+</ul>
+
The <b>relay_domains_reject_code</b> parameter specifies the response
code for rejected requests (default: <b>554</b>).
<h2> ETRN command restrictions</h2>
Not really an UCE restriction, the <b>smtpd_etrn_restrictions</b>
-parameter restricts what domains may be specified in ETRN commands,
-and what clients may issue ETRN commands.
+parameter restricts what domains can be specified in ETRN commands,
+and what clients can issue ETRN commands.
<dl>
<dt>Default:
+<dd><b>smtpd_etrn_restrictions =</b>
+
+<p>
+
<dd>By default, the Postfix <a href="smtpd.8.html">SMTP server</a>
accepts any ETRN command from any client.
<dt> Example:
-<dd> <b>smtpd_etrn_restrictions = permit_mynetworks, reject</b>
+<dd> <b>smtpd_etrn_restrictions = permit_mynetworks,
+hash:/etc/postfix/etrn_access, reject</b>
<p>
<dt>Default:
<dd><b>relay_domains = <a href="basic.html#mydestination">
-$mydestination</a>, <a href="rewrite.html#virtual">$virtual_maps</a>.</b>
+$mydestination</a></b>
+
+<p>
+
+<dd>By default, the Postfix <a href="smtpd.8.html">SMTP server</a>
+relays mail:
+
+<p>
+
+<ul>
+
+<li>from clients whose IP address matches <a
+href="basic.html#mynetworks">$mynetworks</a>,
+
+<li>from clients whose hostname matches <a
+href="#relay_domains">$relay_domains</a> or a subdomain thereof,
+
+<li>to destinations that match <a href="#relay_domains">
+$relay_domains</a> or a subdomain thereof.
+
+</ul>
<p>
resolve.o: ../include/rewrite_clnt.h
resolve.o: ../include/tok822.h
resolve.o: ../include/mail_params.h
-resolve.o: ../include/local_transport.h
resolve.o: local.h
resolve.o: ../include/been_here.h
resolve.o: ../include/deliver_request.h
#include <rewrite_clnt.h>
#include <tok822.h>
#include <mail_params.h>
-#include <local_transport.h>
/* Application-specific. */
* ugly code to force local recursive alias expansions on a host with no
* authority over the local domain, but that code was just too unclean.
*/
- if (match_def_local_transport(STR(reply.transport))) {
+ if (strcmp(state.msg_attr.relay, STR(reply.transport)) == 0) {
status = deliver_recipient(state, usr_attr);
} else {
status = deliver_indirect(state);
qmgr_message.o: ../include/mail_addr_find.h
qmgr_message.o: ../include/maps.h
qmgr_message.o: ../include/opened.h
-qmgr_message.o: ../include/local_transport.h
+qmgr_message.o: ../include/resolve_local.h
qmgr_message.o: ../include/resolve_clnt.h
qmgr_message.o: qmgr.h
qmgr_message.o: ../include/scan_dir.h
#include <deliver_completed.h>
#include <mail_addr_find.h>
#include <opened.h>
-#include <local_transport.h>
+#include <resolve_local.h>
/* Client stubs. */
* job requires knowledge of local aliases. Yuck! I don't want to
* duplicate delivery-agent specific knowledge in the queue manager.
*/
- if (match_def_local_transport(STR(reply.transport))) {
+ if ((at = strrchr(STR(reply.recipient), '@')) == 0
+ || resolve_local(at + 1)) {
vstring_strcpy(reply.nexthop, STR(reply.recipient));
(void) split_at_right(STR(reply.nexthop), '@');
#if 0
smtpd_check.o: ../include/mail_conf.h
smtpd_check.o: ../include/maps.h
smtpd_check.o: ../include/mail_addr_find.h
-smtpd_check.o: ../include/local_transport.h
smtpd_check.o: smtpd.h
smtpd_check.o: ../include/mail_stream.h
smtpd_check.o: smtpd_check.h
smtpd_chat_reply(state, "452 Error: too many recipients");
return (-1);
}
- if (SMTPD_STAND_ALONE(state) == 0
- && (err = smtpd_check_rcpt(state, argv[2].strval)) != 0) {
- smtpd_chat_reply(state, "%s", err);
- return (-1);
- }
- if ((err = smtpd_check_rcptmap(state, argv[2].strval)) != 0) {
- smtpd_chat_reply(state, "%s", err);
- return (-1);
+ if (SMTPD_STAND_ALONE(state) == 0) {
+ if ((err = smtpd_check_rcpt(state, argv[2].strval)) != 0) {
+ smtpd_chat_reply(state, "%s", err);
+ return (-1);
+ }
+ if ((err = smtpd_check_rcptmap(state, argv[2].strval)) != 0) {
+ smtpd_chat_reply(state, "%s", err);
+ return (-1);
+ }
}
/*
smtpd_chat_reply(state, "%s", err);
return (-1);
}
- if ((err = smtpd_check_rcptmap(state, argv[1].strval)) != 0) {
+ if (SMTPD_STAND_ALONE(state) == 0
+ && (err = smtpd_check_rcptmap(state, argv[1].strval)) != 0) {
smtpd_chat_reply(state, "%s", err);
return (-1);
}
/* Allow the request when either the client hostname or the resolved
/* recipient domain matches the \fIrelay_domains\fR configuration
/* parameter or a subdomain therereof, or when the destination somehow
-/* resolves locally (see $mydestination, $virtual_maps or
-/* $local_transports). Reject the request otherwise.
+/* resolves locally ($inet_interfaces, $mydestination or $virtual_maps).
+/* Reject the request otherwise.
/* The \fIrelay_domains_reject_code\fR configuration parameter specifies
/* the reject status code (default: 554).
/* .IP permit_auth_destination
/* Permit the request when the resolved recipient domain matches the
/* \fIrelay_domains\fR configuration parameter or a subdomain therereof,
-/* or when the destination somehow resolves locally (see $mydestination,
-/* $virtual_maps or $local_transports).
+/* or when the destination somehow resolves locally ($inet_interfaces,
+/* $mydestination or $virtual_maps).
/* .IP reject_unauth_destination
/* Reject the request when the resolved recipient domain does not match
/* the \fIrelay_domains\fR configuration parameter or a subdomain
/* therereof, and when the destination does not somehow resolve locally
-/* (see $mydestination, $virtual_maps or $local_transports).
+/* ($inet_interfaces, $mydestination or $virtual_maps).
/* Same error code as check_relay_domains.
/* .IP reject_unauth_pipelining
/* Reject the request when the client has already sent the next request
#include <mail_conf.h>
#include <maps.h>
#include <mail_addr_find.h>
-#include <local_transport.h>
/* Application-specific. */
static VSTRING *error_text;
/*
- * Pre-opened SMTP recipient maps.
+ * Pre-opened SMTP recipient maps so we can reject mail for unknown users.
+ * XXX This does not belong here and will eventually become part of the
+ * trivial-rewrite resolver.
*/
static MAPS *local_rcpt_maps;
static MAPS *rcpt_canon_maps;
return (argv);
}
+/* check_required - make sure minimally-required restriction is present */
+
+static void check_required(char *name, ARGV *restrictions, char **required)
+{
+ char **rest;
+ char **reqd;
+ VSTRING *example;
+
+ for (rest = restrictions->argv; *rest; rest++)
+ for (reqd = required; *reqd; reqd++)
+ if (strcmp(*rest, *reqd) == 0)
+ return;
+ example = vstring_alloc(10);
+ for (reqd = required; *reqd; reqd++)
+ vstring_sprintf_append(example, "%s ", *reqd);
+ msg_fatal("%s requires at least one of %s", name, STR(example));
+}
+
/* smtpd_check_init - initialize once during process lifetime */
void smtpd_check_init(void)
const char *name;
const char *value;
char *cp;
+ static char *rcpt_required[] = {
+ CHECK_RELAY_DOMAINS,
+ REJECT_UNAUTH_DEST,
+ REJECT_ALL,
+ 0,
+ };
/*
* Pre-open access control lists before going to jail.
rcpt_restrctions = smtpd_check_parse(var_rcpt_checks);
etrn_restrctions = smtpd_check_parse(var_etrn_checks);
+ /*
+ * People screw up the relay restrictions too often. Require that they
+ * list at least one restriction that rejects mail by default.
+ */
+ check_required(VAR_RCPT_CHECKS, rcpt_restrctions, rcpt_required);
+
/*
* Parse the pre-defined restriction classes.
*/
* as check_relay_domains in terms of more elementary restrictions.
*/
#if 0
- htable_enter("check_relay_domains",
+ htable_enter(smtpd_rest_classes, "check_relay_domains",
smtpd_check_parse("permit_mydomain reject_unauth_destination"));
#endif
}
* mydestination or virtual_maps, or it resolves to any transport that
* delivers locally.
*/
- if (match_any_local_transport(STR(reply.transport))
- || (domain = strrchr(STR(reply.recipient), '@')) == 0)
+ if ((domain = strrchr(STR(reply.recipient), '@')) == 0)
return (SMTPD_CHECK_OK);
domain += 1;
if (resolve_local(domain)
* mydestination or virtual_maps, or it resolves to any transport that
* delivers locally.
*/
- if (match_any_local_transport(STR(reply.transport))
- || (domain = strrchr(STR(reply.recipient), '@')) == 0)
+ if ((domain = strrchr(STR(reply.recipient), '@')) == 0)
return (SMTPD_CHECK_OK);
domain += 1;
if (resolve_local(domain)
* mydestination or virtual_maps, or it resolves to any transport that
* delivers locally.
*/
- if (match_any_local_transport(STR(reply.transport))
- || (domain = strrchr(STR(reply.recipient), '@')) == 0)
+ if ((domain = strrchr(STR(reply.recipient), '@')) == 0)
return (SMTPD_CHECK_DUNNO);
domain += 1;
if (resolve_local(domain)
* If the destination is local, it is acceptable, because we are
* supposedly MX for our own address.
*/
- if (match_any_local_transport(STR(reply.transport))
- || (domain = strrchr(STR(reply.recipient), '@')) == 0)
+ if ((domain = strrchr(STR(reply.recipient), '@')) == 0)
return (SMTPD_CHECK_OK);
domain += 1;
if (resolve_local(domain)
/*
* Skip local destinations and non-DNS forms.
*/
- if (match_any_local_transport(STR(reply.transport))
- || (domain = strrchr(STR(reply.recipient), '@')) == 0)
+ if ((domain = strrchr(STR(reply.recipient), '@')) == 0)
return (SMTPD_CHECK_DUNNO);
domain += 1;
if (resolve_local(domain)
char *domain;
/*
- * XXX This module does a lot of unnecessary guessing. The SMTP server
- * (and presumably, pickup daemon) should run the envelopes through a
- * rewriting service that does all the canonical and virtual mapping.
+ * XXX This module does a lot of unnecessary guessing. This functionality
+ * will eventually become part of the trivial-rewrite resolver, including
+ * the canonical and virtual mapping.
*/
if (msg_verbose)
msg_info("%s: %s", myname, recipient);
resolve.o: ../include/quote_822_local.h
resolve.o: ../include/tok822.h
resolve.o: ../include/resolve_clnt.h
-resolve.o: ../include/local_transport.h
resolve.o: trivial-rewrite.h
resolve.o: transport.h
rewrite.o: rewrite.c
#include <mail_conf.h>
#include <quote_822_local.h>
#include <tok822.h>
-#include <local_transport.h>
/* Application-specific. */
/*
* Non-local delivery, presumably. Set up the default remote transport
- * specified with var_local_transports. Use the destination's mail
- * exchanger unless a default mail relay is specified with var_relayhost.
+ * specified with var_def_transport. Use the destination's mail exchanger
+ * unless a default mail relay is specified with var_relayhost.
*/
else if (domain != 0) {
vstring_strcpy(channel, var_def_transport);
* next-hop hostname (myself).
*/
else {
- vstring_strcpy(channel, get_def_local_transport());
+ vstring_strcpy(channel, var_local_transport);
vstring_strcpy(nexthop, var_myhostname);
}
bool var_append_dot_mydomain;
bool var_append_at_myorigin;
bool var_percent_hack;
+char *var_local_transport;
/* rewrite_service - read request and send reply */
static CONFIG_STR_TABLE str_table[] = {
VAR_TRANSPORT_MAPS, DEF_TRANSPORT_MAPS, &var_transport_maps, 0, 0,
VAR_DEF_TRANSPORT, DEF_DEF_TRANSPORT, &var_def_transport, 0, 0,
+ VAR_LOCAL_TRANSPORT, DEF_LOCAL_TRANSPORT, &var_local_transport, 0, 0,
0,
};
static CONFIG_BOOL_TABLE bool_table[] = {