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);