diff --git a/postfix/HISTORY b/postfix/HISTORY
index 82b4f56cc..3192c07e7 100644
--- a/postfix/HISTORY
+++ b/postfix/HISTORY
@@ -7068,6 +7068,13 @@ Apologies for any names omitted.
TO addresses. Some remnant of code that someone put in
there long ago. File: lmtp/lmtp_proto.c.
+20021024
+
+ Feature: proxy_interfaces parameter. Specify your NAT or
+ other proxy addresses here to avoid mail delivery loops.
+ Files: global/mail_params.[hc] global/own_inet_addr.[hc]
+ global/resolve_local.c smtp/smtp_addr.c smtpd/smtpd_check.c.
+
Open problems:
Low: smtpd should log queue ID with reject/warn/hold/discard
diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES
index dae0deefc..5899fdc9c 100644
--- a/postfix/RELEASE_NOTES
+++ b/postfix/RELEASE_NOTES
@@ -12,6 +12,13 @@ snapshot release). Patches change the patchlevel and the release
date. Snapshots change only the release date, unless they include
the same bugfixes as a patch release.
+Major changes with Postfix snapshot 1.1.11-20021024
+===================================================
+
+New proxy_interfaces parameter, for sites behind a network address
+translation gateway or other type of proxy. Specify all the proxy
+network addresses here, to avoid avoid mail delivery loops.
+
Incompatible changes with Postfix snapshot 1.1.11-20021015
==========================================================
diff --git a/postfix/conf/main.cf b/postfix/conf/main.cf
index f3528a70c..fcdc43fbc 100644
--- a/postfix/conf/main.cf
+++ b/postfix/conf/main.cf
@@ -97,10 +97,25 @@ mail_owner = postfix
# the software claims all active interfaces on the machine. The
# parameter also controls delivery of mail to user@[ip.address].
#
+# See also the proxy_interfaces parameter, for network addresses that
+# are forwarded to us via a proxy or network address translator.
+#
#inet_interfaces = all
#inet_interfaces = $myhostname
#inet_interfaces = $myhostname, localhost
+# The proxy_interfaces parameter specifies the network interface
+# addresses that this mail system receives mail on by way of a
+# proxy or network address translation unit. This setting extends
+# the address list specified with the inet_interfaces parameter.
+#
+# You must specify your proxy/NAT addresses when your system is a
+# backup MX host for other domains, otherwise mail delivery loops
+# will happen when the primary MX host is down.
+#
+#proxy_interfaces =
+#proxy_interfaces = 1.2.3.4
+
# The mydestination parameter specifies the list of domains that this
# machine considers itself the final destination for. That includes
# Sendmail-style virtual domains hosted on this machine.
diff --git a/postfix/conf/sample-misc.cf b/postfix/conf/sample-misc.cf
index 420600211..ed098b77b 100644
--- a/postfix/conf/sample-misc.cf
+++ b/postfix/conf/sample-misc.cf
@@ -119,8 +119,23 @@ import_environment = MAIL_CONFIG MAIL_DEBUG MAIL_LOGTAG TZ XAUTHORITY DISPLAY
# the software claims all active interfaces on the machine. The
# parameter also controls delivery of mail to user@[ip.address].
#
+# See also the proxy_interfaces parameter, for network addresses that
+# are forwarded to us by way of a proxy or address translator.
+#
inet_interfaces = all
+# The proxy_interfaces parameter specifies the network interface
+# addresses that this mail system receives mail on by way of a
+# proxy or network address translation unit. This setting extends
+# the address list specified with the inet_interfaces parameter.
+#
+# You must specify your proxy/NAT addresses when your system is a
+# backup MX host for other domains, otherwise mail delivery loops
+# will happen when the primary MX host is down.
+#
+#proxy_interfaces =
+#proxy_interfaces = 1.2.3.4
+
# The ipc_idle parameter bounds the idle time for internal communication
# channels after which a client disconnects voluntarily. The purpose
# is to allow servers to terminate voluntarily after they become
diff --git a/postfix/html/basic.html b/postfix/html/basic.html
index 9081e79e3..553f87299 100644
--- a/postfix/html/basic.html
+++ b/postfix/html/basic.html
@@ -55,6 +55,18 @@ to the local postmaster:
+Be sure to set the following correctly if you're behind a proxy or
+network address translator, and you are running a backup MX host
+for some other domain:
+
+
+
+
+
By the way, if you change parameters of a running Postfix system,
don't forget to issue a postfix reload command.
@@ -261,6 +273,43 @@ due to software problems.
+ Proxy/NAT network addresses
+
+The proxy_interfaces parameter specifies all network addresses
+that the Postfix receives mail on by way of a proxy or network
+address translation unit. You may specify symbolic hostnames instead
+of network addresses.
+
+
+
+You must specify your proxy/NAT addresses when your system is a
+backup MX host for other domains, otherwise mail delivery loops
+will happen when the primary MX host is down.
+
+
+
+
+
+- Examples:
+
+
+
+
+
+- Default:
+
+
- proxy_interfaces =
+
+
+
+
- Host running backup MTA:
+
+
- proxy_interfaces = 1.2.3.4 (the proxy/NAT network address)
+
+
+
+
+
My own hostname
The myhostname parameter describes the fully-qualified domain
diff --git a/postfix/html/smtp.8.html b/postfix/html/smtp.8.html
index ff460841c..d6f733457 100644
--- a/postfix/html/smtp.8.html
+++ b/postfix/html/smtp.8.html
@@ -107,13 +107,22 @@ SMTP(8) SMTP(8)
tem receives mail on. When any of those addresses
appears in the list of mail exchangers for a remote
destination, the list is truncated to avoid mail
- delivery loops.
+ delivery loops. See also the proxy_interfaces
+ parameter.
notify_classes
- When this parameter includes the protocol class,
- send mail to the postmaster with transcripts of
+ When this parameter includes the protocol class,
+ send mail to the postmaster with transcripts of
SMTP sessions with protocol errors.
+ proxy_interfaces
+ Network interfaces that this mail system receives
+ mail on by way of a proxy or network address trans-
+ lator. When any of those addresses appears in the
+ list of mail exchangers for a remote destination,
+ the list is truncated to avoid mail delivery loops.
+ See also the inet_interfaces parameter.
+
smtp_always_send_ehlo
Always send EHLO at the start of a connection.
diff --git a/postfix/man/man8/smtp.8 b/postfix/man/man8/smtp.8
index a17ba48f7..018a6f6b7 100644
--- a/postfix/man/man8/smtp.8
+++ b/postfix/man/man8/smtp.8
@@ -108,9 +108,16 @@ The network interface addresses that this mail system receives
mail on. When any of those addresses appears in the list of mail
exchangers for a remote destination, the list is truncated to
avoid mail delivery loops.
+See also the \fBproxy_interfaces\fR parameter.
.IP \fBnotify_classes\fR
When this parameter includes the \fBprotocol\fR class, send mail to the
postmaster with transcripts of SMTP sessions with protocol errors.
+.IP \fBproxy_interfaces\fR
+Network interfaces that this mail system receives mail on by way
+of a proxy or network address translator. When any of those addresses
+appears in the list of mail exchangers for a remote destination, the
+list is truncated to avoid mail delivery loops.
+See also the \fBinet_interfaces\fR parameter.
.IP \fBsmtp_always_send_ehlo\fR
Always send EHLO at the start of a connection.
.IP \fBsmtp_never_send_ehlo\fR
diff --git a/postfix/src/global/mail_params.c b/postfix/src/global/mail_params.c
index 1135e6aaf..dc788d5ae 100644
--- a/postfix/src/global/mail_params.c
+++ b/postfix/src/global/mail_params.c
@@ -37,6 +37,7 @@
/* char *var_pid_dir;
/* int var_dont_remove;
/* char *var_inet_interfaces;
+/* char *var_proxy_interfaces;
/* char *var_mynetworks;
/* char *var_double_bounce_sender;
/* int var_line_limit;
@@ -190,6 +191,7 @@ int var_ipc_timeout;
char *var_pid_dir;
int var_dont_remove;
char *var_inet_interfaces;
+char *var_proxy_interfaces;
char *var_mynetworks;
char *var_double_bounce_sender;
int var_line_limit;
@@ -439,6 +441,7 @@ void mail_params_init()
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, 1, 0,
+ VAR_PROXY_INTERFACES, DEF_PROXY_INTERFACES, &var_proxy_interfaces, 0, 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, 0, 0,
diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h
index 558c44a44..738414c4f 100644
--- a/postfix/src/global/mail_params.h
+++ b/postfix/src/global/mail_params.h
@@ -118,6 +118,10 @@ extern char *var_error_rcpt;
#define DEF_INET_INTERFACES "all"
extern char *var_inet_interfaces;
+#define VAR_PROXY_INTERFACES "proxy_interfaces" /* proxies, NATs */
+#define DEF_PROXY_INTERFACES ""
+extern char *var_proxy_interfaces;
+
/*
* Masquerading (i.e. subdomain stripping).
*/
diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h
index 24195af10..476dbc4fb 100644
--- a/postfix/src/global/mail_version.h
+++ b/postfix/src/global/mail_version.h
@@ -20,7 +20,7 @@
* Patches change the patchlevel and the release date. Snapshots change the
* release date only, unless they include the same bugfix as a patch release.
*/
-#define MAIL_RELEASE_DATE "20021015"
+#define MAIL_RELEASE_DATE "20021024"
#define VAR_MAIL_VERSION "mail_version"
#define DEF_MAIL_VERSION "1.1.11-" MAIL_RELEASE_DATE
diff --git a/postfix/src/global/own_inet_addr.c b/postfix/src/global/own_inet_addr.c
index 1dc8aaf4f..3239d6e56 100644
--- a/postfix/src/global/own_inet_addr.c
+++ b/postfix/src/global/own_inet_addr.c
@@ -12,6 +12,11 @@
/* INET_ADDR_LIST *own_inet_addr_list()
/*
/* INET_ADDR_LIST *own_inet_mask_list()
+/*
+/* int proxy_inet_addr(addr)
+/* struct in_addr *addr;
+/*
+/* INET_ADDR_LIST *proxy_inet_addr_list()
/* DESCRIPTION
/* own_inet_addr() determines if the specified IP address belongs
/* to this mail system instance, i.e. if this mail system instance
@@ -22,6 +27,12 @@
/*
/* own_inet_mask_list() returns the list of all corresponding
/* netmasks.
+/*
+/* proxy_inet_addr() determines if the specified IP address is
+/* listed with the proxy_interfaces configuration parameter.
+/*
+/* proxy_inet_addr_list() returns the list of all addresses that
+/* belong to proxy network interfaces.
/* LICENSE
/* .ad
/* .fi
@@ -62,6 +73,7 @@
static INET_ADDR_LIST addr_list;
static INET_ADDR_LIST mask_list;
+static INET_ADDR_LIST proxy_list;
/* own_inet_addr_init - initialize my own address list */
@@ -171,3 +183,58 @@ INET_ADDR_LIST *own_inet_mask_list(void)
return (&mask_list);
}
+
+/* proxy_inet_addr_init - initialize my proxy interface list */
+
+static void proxy_inet_addr_init(INET_ADDR_LIST *addr_list)
+{
+ char *hosts;
+ char *host;
+ char *sep = " \t,";
+ char *bufp;
+
+ /*
+ * Parse the proxy_interfaces parameter, and expand any symbolic
+ * hostnames into IP addresses.
+ */
+ inet_addr_list_init(addr_list);
+ bufp = hosts = mystrdup(var_proxy_interfaces);
+ while ((host = mystrtok(&bufp, sep)) != 0)
+ if (inet_addr_host(addr_list, host) == 0)
+ msg_fatal("config variable %s: host not found: %s",
+ VAR_PROXY_INTERFACES, host);
+ myfree(hosts);
+
+ /*
+ * Weed out duplicate IP addresses.
+ */
+ inet_addr_list_uniq(addr_list);
+}
+
+/* proxy_inet_addr - is this my proxy internet address */
+
+int proxy_inet_addr(struct in_addr * addr)
+{
+ int i;
+
+ if (*var_proxy_interfaces == 0)
+ return (0);
+
+ if (proxy_list.used == 0)
+ proxy_inet_addr_init(&proxy_list);
+
+ for (i = 0; i < proxy_list.used; i++)
+ if (addr->s_addr == proxy_list.addrs[i].s_addr)
+ return (1);
+ return (0);
+}
+
+/* proxy_inet_addr_list - return list of addresses */
+
+INET_ADDR_LIST *proxy_inet_addr_list(void)
+{
+ if (*var_proxy_interfaces != 0 && proxy_list.used == 0)
+ proxy_inet_addr_init(&proxy_list);
+
+ return (&proxy_list);
+}
diff --git a/postfix/src/global/own_inet_addr.h b/postfix/src/global/own_inet_addr.h
index 5a38b58f7..94fbac6a6 100644
--- a/postfix/src/global/own_inet_addr.h
+++ b/postfix/src/global/own_inet_addr.h
@@ -22,6 +22,8 @@
extern int own_inet_addr(struct in_addr *);
extern struct INET_ADDR_LIST *own_inet_addr_list(void);
extern struct INET_ADDR_LIST *own_inet_mask_list(void);
+extern int proxy_inet_addr(struct in_addr *);
+extern struct INET_ADDR_LIST *proxy_inet_addr_list(void);
/* LICENSE
/* .ad
diff --git a/postfix/src/global/resolve_local.c b/postfix/src/global/resolve_local.c
index 0f2d318b2..bad7abf12 100644
--- a/postfix/src/global/resolve_local.c
+++ b/postfix/src/global/resolve_local.c
@@ -14,7 +14,8 @@
/* resolve_local() determines if the named domain resolves to the
/* local mail system, either by case-insensitive exact match
/* against the domains, files or tables listed in $mydestination,
-/* or by any of the network addresses listed in $inet_interfaces.
+/* or by any of the network addresses listed in $inet_interfaces
+/* or in $proxy_interfaces.
/*
/* resolve_local_init() performs initialization. If this routine is
/* not called explicitly ahead of time, it will be called on the fly.
@@ -118,7 +119,7 @@ int resolve_local(const char *addr)
dest++;
dest[len -= 2] = 0;
if ((ipaddr.s_addr = inet_addr(dest)) != INADDR_NONE
- && own_inet_addr(&ipaddr))
+ && (own_inet_addr(&ipaddr) || proxy_inet_addr(&ipaddr)))
RETURN(1);
}
diff --git a/postfix/src/smtp/smtp.c b/postfix/src/smtp/smtp.c
index 86071fad9..a251e9774 100644
--- a/postfix/src/smtp/smtp.c
+++ b/postfix/src/smtp/smtp.c
@@ -92,9 +92,16 @@
/* mail on. When any of those addresses appears in the list of mail
/* exchangers for a remote destination, the list is truncated to
/* avoid mail delivery loops.
+/* See also the \fBproxy_interfaces\fR parameter.
/* .IP \fBnotify_classes\fR
/* When this parameter includes the \fBprotocol\fR class, send mail to the
/* postmaster with transcripts of SMTP sessions with protocol errors.
+/* .IP \fBproxy_interfaces\fR
+/* Network interfaces that this mail system receives mail on by way
+/* of a proxy or network address translator. When any of those addresses
+/* appears in the list of mail exchangers for a remote destination, the
+/* list is truncated to avoid mail delivery loops.
+/* See also the \fBinet_interfaces\fR parameter.
/* .IP \fBsmtp_always_send_ehlo\fR
/* Always send EHLO at the start of a connection.
/* .IP \fBsmtp_never_send_ehlo\fR
diff --git a/postfix/src/smtp/smtp_addr.c b/postfix/src/smtp/smtp_addr.c
index 9be6cd8b9..e5bc30e2d 100644
--- a/postfix/src/smtp/smtp_addr.c
+++ b/postfix/src/smtp/smtp_addr.c
@@ -268,6 +268,19 @@ static DNS_RR *smtp_find_self(DNS_RR *addr_list)
}
}
+ /*
+ * Find out if this mail system has a proxy listening on this address.
+ */
+ self = proxy_inet_addr_list();
+ for (addr = addr_list; addr; addr = addr->next) {
+ for (i = 0; i < self->used; i++)
+ if (INADDRP(addr->data)->s_addr == self->addrs[i].s_addr) {
+ if (msg_verbose)
+ msg_info("%s: found at pref %d", myname, addr->pref);
+ return (addr);
+ }
+ }
+
/*
* Didn't find myself.
*/
diff --git a/postfix/src/smtpd/smtpd_check.c b/postfix/src/smtpd/smtpd_check.c
index 6bb1a2379..a3fb09752 100644
--- a/postfix/src/smtpd/smtpd_check.c
+++ b/postfix/src/smtpd/smtpd_check.c
@@ -1388,6 +1388,8 @@ static int has_my_addr(SMTPD_STATE *state, const char *host,
msg_info("%s: addr %s", myname, inet_ntoa(addr));
if (own_inet_addr(&addr))
return (YUP);
+ if (proxy_inet_addr(&addr))
+ return (YUP);
}
if (msg_verbose)
msg_info("%s: host %s: no match", myname, host);