No testsuite coverage yet.
qualified host name. See also &$smtp_active_hostname$&.
+.new
+.vitem &$proxy_host_address$& &&&
+ &$proxy_host_port$& &&&
+ &$proxy_target_address$& &&&
+ &$proxy_target_port$& &&&
+ &$proxy_session$&
+These variables are only available when built with Proxy Protocol support
+For details see chapter &<<SECTproxyInbound>>&.
+.wen
+
.new
.vitem &$prdr_requested$&
.cindex "PRDR" "variable for"
.row &%helo_verify_hosts%& "HELO hard-checked for these hosts"
.row &%host_lookup%& "host name looked up for these hosts"
.row &%host_lookup_order%& "order of DNS and local name lookups"
+.row &%hosts_proxy%& "use proxy protocol for these hosts"
.row &%host_reject_connection%& "reject connection from these hosts"
.row &%hosts_treat_as_local%& "useful in some cluster configurations"
.row &%local_scan_timeout%& "timeout for &[local_scan()]&"
+.new
+.option hosts_proxy main "host list&!!" unset
+.cindex proxy "proxy protocol"
+This option enables use of Proxy Protocol proxies for incoming
+connections. For details see &<<SECTproxyInbound>>&.
+.wen
+
+
.option hosts_treat_as_local main "domain list&!!" unset
.cindex "local host" "domains treated as"
.cindex "host" "treated as local"
&` queue_time `& time on queue for one recipient
&` queue_time_overall `& time on queue for whole message
&` pid `& Exim process id
+.new
+&` proxy `& proxy address on <= lines
+.wen
&` received_recipients `& recipients on <= lines
&` received_sender `& sender on <= lines
&`*rejected_header `& header contents on reject log
The latter can be disabled by turning off the &%outgoing_interface%& option.
.wen
.next
+.new
+.cindex log "incoming proxy address"
+.cindex proxy "logging proxy address"
+.cindex "TCP/IP" "logging proxy address"
+&%proxy%&: The internal (closest to the system running Exim) IP address
+of the proxy, tagged by PRX=, on the &"<="& line for a message accepted
+on a proxied connection.
+See &<<SECTproxyInbound>>& for more information.
+.wen
+.next
.cindex "log" "incoming remote port"
.cindex "port" "logging remote"
.cindex "TCP/IP" "logging incoming remote port"
A proxy is an intermediate system through which communication is passed.
Proxies may provide a security, availability or load-distribution function.
+
+.section "Inbound proxies" SECTproxyInbound
+.cindex proxy inbound
+.cindex proxy "server side"
+.cindex proxy "Proxy protocol"
+.cindex "Proxy protocol" proxy
+
+Exim has support for receiving inbound SMTP connections via a proxy
+that uses &"Proxy Protocol"& to speak to it.
+To include this support, include &"SUPPORT_PROXY=yes"&
+in Local/Makefile.
+
+It was built on specifications from:
+http://haproxy.1wt.eu/download/1.5/doc/proxy-protocol.txt
+That URL was revised in May 2014 to version 2 spec:
+http://git.1wt.eu/web?p=haproxy.git;a=commitdiff;h=afb768340c9d7e50d8e
+
+The purpose of this facility is so that an application load balancer,
+such as HAProxy, can sit in front of several Exim servers
+to distribute load.
+Exim uses the local protocol communication with the proxy to obtain
+the remote SMTP system IP address and port information.
+There is no logging if a host passes or
+fails Proxy Protocol negotiation, but it can easily be determined and
+recorded in an ACL (example is below).
+
+Use of a proxy is enabled by setting the &%hosts_proxy%&
+main configuration option to a hostlist; connections from these
+hosts will use Proxy Protocol.
+
+To log the IP of the proxy in the incoming logline, add &"+proxy"&
+to the &%log_selector%& option.
+This will add a component tagged with &"PRX="& to the line.
+
+The following expansion variables are usable
+(&"internal"& and &"external"& here refer to the interfaces
+of the proxy):
+.display
+&'proxy_host_address '& internal IP address of the proxy
+&'proxy_host_port '& internal TCP port of the proxy
+&'proxy_target_address '& external IP address of the proxy
+&'proxy_target_port '& external TCP port of the proxy
+&'proxy_session '& boolean: SMTP connection via proxy
+.endd
+If &$proxy_session$& is set but &$proxy_host_address$& is empty
+there was a protocol error.
+
+Since the real connections are all coming from the proxy, and the
+per host connection tracking is done before Proxy Protocol is
+evaluated, &%smtp_accept_max_per_host%& must be set high enough to
+handle all of the parallel volume you expect per inbound proxy.
+With the option set so high, you lose the ability
+to protect your server from many connections from one IP.
+In order to prevent your server from overload, you
+need to add a per connection ratelimit to your connect ACL.
+A possible solution is:
+.display
+ # Set max number of connections per host
+ LIMIT = 5
+ # Or do some kind of IP lookup in a flat file or database
+ # LIMIT = ${lookup{$sender_host_address}iplsearch{/etc/exim/proxy_limits}}
+
+ defer message = Too many connections from this IP right now
+ ratelimit = LIMIT / 5s / per_conn / strict
+.endd
+
+
+
.section "Outbound proxies" SECTproxySOCKS
.cindex proxy outbound
.cindex proxy "client side"
The support can be optionally included by defining SUPPORT_SOCKS=yes in
Local/Makefile.
-Use of a proxy is enabled by setting the &%socks_proxy%& on an smtp transport.
+Use of a proxy is enabled by setting the &%socks_proxy%& option
+on an smtp transport.
The option value is expanded and should then be a list
(colon-separated by default) of proxy specifiers.
Each proxy specifier is a list
JH/23 Move SOCKS5 support from Experimental to mainline, enabled for a build
by defining SUPPORT_SOCKS.
+JH/26 Move PROXY support from Experimental to mainline, enabled for a build
+ by defining SUPPORT_PROXY. Note that the proxy_required_hosts option
+ is renamed to hosts_proxy.
+
Exim version 4.86
-----------------
set acl_c_spam_host = ${lookup redis{GET...}}
-Proxy Protocol Support
---------------------------------------------------------------
-
-Exim now has Experimental "Proxy Protocol" support. It was built on
-specifications from:
-http://haproxy.1wt.eu/download/1.5/doc/proxy-protocol.txt
-Above URL revised May 2014 to change version 2 spec:
-http://git.1wt.eu/web?p=haproxy.git;a=commitdiff;h=afb768340c9d7e50d8e
-
-The purpose of this function is so that an application load balancer,
-such as HAProxy, can sit in front of several Exim servers and Exim
-will log the IP that is connecting to the proxy server instead of
-the IP of the proxy server when it connects to Exim. It resets the
-$sender_address_host and $sender_address_port to the IP:port of the
-connection to the proxy. It also re-queries the DNS information for
-this new IP address so that the original sender's hostname and IP
-get logged in the Exim logfile. There is no logging if a host passes or
-fails Proxy Protocol negotiation, but it can easily be determined and
-recorded in an ACL (example is below).
-
-1. To compile Exim with Proxy Protocol support, put this in
-Local/Makefile:
-
-EXPERIMENTAL_PROXY=yes
-
-2. Global configuration settings:
-
-proxy_required_hosts = HOSTLIST
-
-The proxy_required_hosts option will require any IP in that hostlist
-to use Proxy Protocol. The specification of Proxy Protocol is very
-strict, and if proxy negotiation fails, Exim will not allow any SMTP
-command other than QUIT. (See end of this section for an example.)
-The option is expanded when used, so it can be a hostlist as well as
-string of IP addresses. Since it is expanded, specifying an alternate
-separator is supported for ease of use with IPv6 addresses.
-
-To log the IP of the proxy in the incoming logline, add:
- log_selector = +proxy
-
-A default incoming logline (wrapped for appearance) will look like this:
-
- 2013-11-04 09:25:06 1VdNti-0001OY-1V <= me@example.net
- H=mail.example.net [1.2.3.4] P=esmtp S=433
-
-With the log selector enabled, an email that was proxied through a
-Proxy Protocol server at 192.168.1.2 will look like this:
-
- 2013-11-04 09:25:06 1VdNti-0001OY-1V <= me@example.net
- H=mail.example.net [1.2.3.4] P=esmtp PRX=192.168.1.2 S=433
-
-3. In the ACL's the following expansion variables are available.
-
-proxy_host_address The (internal) src IP of the proxy server
- making the connection to the Exim server.
-proxy_host_port The (internal) src port the proxy server is
- using to connect to the Exim server.
-proxy_target_address The dest (public) IP of the remote host to
- the proxy server.
-proxy_target_port The dest port the remote host is using to
- connect to the proxy server.
-proxy_session Boolean, yes/no, the connected host is required
- to use Proxy Protocol.
-
-There is no expansion for a failed proxy session, however you can detect
-it by checking if $proxy_session is true but $proxy_host is empty. As
-an example, in my connect ACL, I have:
-
- warn condition = ${if and{ {bool{$proxy_session}} \
- {eq{$proxy_host_address}{}} } }
- log_message = Failed required proxy protocol negotiation \
- from $sender_host_name [$sender_host_address]
-
- warn condition = ${if and{ {bool{$proxy_session}} \
- {!eq{$proxy_host_address}{}} } }
- # But don't log health probes from the proxy itself
- condition = ${if eq{$proxy_host_address}{$sender_host_address} \
- {false}{true}}
- log_message = Successfully proxied from $sender_host_name \
- [$sender_host_address] through proxy protocol \
- host $proxy_host_address
-
- # Possibly more clear
- warn logwrite = Remote Source Address: $sender_host_address:$sender_host_port
- logwrite = Proxy Target Address: $proxy_target_address:$proxy_target_port
- logwrite = Proxy Internal Address: $proxy_host_address:$proxy_host_port
- logwrite = Internal Server Address: $received_ip_address:$received_port
-
-
-4. Recommended ACL additions:
- - Since the real connections are all coming from your proxy, and the
- per host connection tracking is done before Proxy Protocol is
- evaluated, smtp_accept_max_per_host must be set high enough to
- handle all of the parallel volume you expect per inbound proxy.
- - With the smtp_accept_max_per_host set so high, you lose the ability
- to protect your server from massive numbers of inbound connections
- from one IP. In order to prevent your server from being DOS'd, you
- need to add a per connection ratelimit to your connect ACL. I
- suggest something like this:
-
- # Set max number of connections per host
- LIMIT = 5
- # Or do some kind of IP lookup in a flat file or database
- # LIMIT = ${lookup{$sender_host_address}iplsearch{/etc/exim/proxy_limits}}
-
- defer message = Too many connections from this IP right now
- ratelimit = LIMIT / 5s / per_conn / strict
-
-
-5. Runtime issues to be aware of:
- - The proxy has 3 seconds (hard-coded in the source code) to send the
- required Proxy Protocol header after it connects. If it does not,
- the response to any commands will be:
- "503 Command refused, required Proxy negotiation failed"
- - If the incoming connection is configured in Exim to be a Proxy
- Protocol host, but the proxy is not sending the header, the banner
- does not get sent until the timeout occurs. If the sending host
- sent any input (before the banner), this causes a standard Exim
- synchronization error (i.e. trying to pipeline before PIPELINING
- was advertised).
- - This is not advised, but is mentioned for completeness if you have
- a specific internal configuration that you want this: If the Exim
- server only has an internal IP address and no other machines in your
- organization will connect to it to try to send email, you may
- simply set the hostlist to "*", however, this will prevent local
- mail programs from working because that would require mail from
- localhost to use Proxy Protocol. Again, not advised!
-
-6. Example of a refused connection because the Proxy Protocol header was
-not sent from a host configured to use Proxy Protocol. In the example,
-the 3 second timeout occurred (when a Proxy Protocol banner should have
-been sent), the banner was displayed to the user, but all commands are
-rejected except for QUIT:
-
-# nc mail.example.net 25
-220-mail.example.net, ESMTP Exim 4.82+proxy, Mon, 04 Nov 2013 10:45:59
-220 -0800 RFC's enforced
-EHLO localhost
-503 Command refused, required Proxy negotiation failed
-QUIT
-221 mail.example.net closing connection
-
-
-
-
DANE
------------------------------------------------------------
DNS-based Authentication of Named Entities, as applied
#
# WITH_OLD_CLAMAV_STREAM=yes
+
#------------------------------------------------------------------------------
# By default Exim includes code to support DKIM (DomainKeys Identified
# Mail, RFC4871) signing and verification. Verification of signatures is
# CFLAGS += -I/usr/local/include
# LDFLAGS += -lhiredis
-# Uncomment the following line to enable Experimental Proxy Protocol
-# EXPERIMENTAL_PROXY=yes
-
# Uncomment the following line to enable support for checking certificate
# ownership
# EXPERIMENTAL_CERTNAMES=yes
#------------------------------------------------------------------------------
# Proxying.
-# If you may want to use outbound (client-side) proxying, uncomment the SOCKS
-# line below.
+#
+# If you may want to use outbound (client-side) proxying, using Socks5,
+# uncomment the line below.
# SUPPORT_SOCKS=yes
+# If you may want to use inbound (server-side) proxying, using Proxy Protocol,
+# uncomment the line below.
+
+# SUPPORT_PROXY=yes
+
+
#------------------------------------------------------------------------------
# Support for authentication via Radius is also available. The Exim support,
#define SUPPORT_MBX
#define SUPPORT_MOVE_FROZEN_MESSAGES
#define SUPPORT_PAM
+#define SUPPORT_PROXY
#define SUPPORT_SOCKS
#define SUPPORT_TLS
#define SUPPORT_TRANSLATE_IP_ADDRESS
#define EXPERIMENTAL_DMARC
#define EXPERIMENTAL_EVENT
#define EXPERIMENTAL_INTERNATIONAL
-#define EXPERIMENTAL_PROXY
#define EXPERIMENTAL_REDIS
#define EXPERIMENTAL_SPF
#define EXPERIMENTAL_SRS
#ifndef DISABLE_PRDR
fprintf(f, " PRDR");
#endif
+#ifdef SUPPORT_PROXY
+ fprintf(f, " PROXY");
+#endif
#ifdef SUPPORT_SOCKS
fprintf(f, " SOCKS");
#endif
#ifdef EXPERIMENTAL_INTERNATIONAL
fprintf(f, " Experimental_International");
#endif
-#ifdef EXPERIMENTAL_PROXY
- fprintf(f, " Experimental_Proxy");
-#endif
#ifdef EXPERIMENTAL_EVENT
fprintf(f, " Experimental_Event");
#endif
{ "prdr_requested", vtype_bool, &prdr_requested },
#endif
{ "primary_hostname", vtype_stringptr, &primary_hostname },
-#ifdef EXPERIMENTAL_PROXY
+#ifdef SUPPORT_PROXY
{ "proxy_host_address", vtype_stringptr, &proxy_host_address },
{ "proxy_host_port", vtype_int, &proxy_host_port },
{ "proxy_session", vtype_bool, &proxy_session },
BIT_TABLE(L, outgoing_interface),
BIT_TABLE(L, outgoing_port),
BIT_TABLE(L, pid),
-#ifdef EXPERIMENTAL_PROXY
+#ifdef SUPPORT_PROXY
BIT_TABLE(L, proxy),
#endif
BIT_TABLE(L, queue_run),
uschar *process_log_path = NULL;
BOOL prod_requires_admin = TRUE;
-#ifdef EXPERIMENTAL_PROXY
+#ifdef SUPPORT_PROXY
+uschar *hosts_proxy = US"";
uschar *proxy_host_address = US"";
int proxy_host_port = 0;
-uschar *proxy_required_hosts = US"";
BOOL proxy_session = FALSE;
BOOL proxy_session_failed = FALSE;
uschar *proxy_target_address = US"";
extern uschar *process_log_path; /* Alternate path */
extern BOOL prod_requires_admin; /* TRUE if prodding requires admin */
-#ifdef EXPERIMENTAL_PROXY
+#ifdef SUPPORT_PROXY
+extern uschar *hosts_proxy; /* Hostlist which (require) use proxy protocol */
extern uschar *proxy_host_address; /* IP of host being proxied */
extern int proxy_host_port; /* Port of host being proxied */
-extern uschar *proxy_required_hosts; /* Hostlist which (require) use proxy protocol */
extern BOOL proxy_session; /* TRUE if receiving mail from valid proxy */
extern BOOL proxy_session_failed; /* TRUE if required proxy negotiation failed */
extern uschar *proxy_target_address; /* IP of proxy server inbound */
/* Wait this long before determining that a Proxy Protocol configured
host isn't speaking the protocol, and so is disallowed. Can be moved to
runtime configuration if per site settings become needed. */
-#ifdef EXPERIMENTAL_PROXY
+#ifdef SUPPORT_PROXY
#define PROXY_NEGOTIATION_TIMEOUT_SEC 3
#define PROXY_NEGOTIATION_TIMEOUT_USEC 0
#endif
{ "host_lookup_order", opt_stringptr, &host_lookup_order },
{ "host_reject_connection", opt_stringptr, &host_reject_connection },
{ "hosts_connection_nolog", opt_stringptr, &hosts_connection_nolog },
+#ifdef SUPPORT_PROXY
+ { "hosts_proxy", opt_stringptr, &proxy_required_hosts },
+#endif
{ "hosts_treat_as_local", opt_stringptr, &hosts_treat_as_local },
#ifdef LOOKUP_IBASE
{ "ibase_servers", opt_stringptr, &ibase_servers },
{ "print_topbitchars", opt_bool, &print_topbitchars },
{ "process_log_path", opt_stringptr, &process_log_path },
{ "prod_requires_admin", opt_bool, &prod_requires_admin },
-#ifdef EXPERIMENTAL_PROXY
- { "proxy_required_hosts", opt_stringptr, &proxy_required_hosts },
-#endif
{ "qualify_domain", opt_stringptr, &qualify_domain_sender },
{ "qualify_recipient", opt_stringptr, &qualify_domain_recipient },
{ "queue_domains", opt_stringptr, &queue_domains },
s = string_append(s, &size, &sptr, 1, US" PRDR");
#endif
-#ifdef EXPERIMENTAL_PROXY
+#ifdef SUPPORT_PROXY
if (proxy_session && LOGGING(proxy))
s = string_append(s, &size, &sptr, 2, US" PRX=", proxy_host_address);
#endif
QUIT_CMD, HELP_CMD,
-#ifdef EXPERIMENTAL_PROXY
+#ifdef SUPPORT_PROXY
PROXY_FAIL_IGNORE_CMD,
#endif
-#ifdef EXPERIMENTAL_PROXY
+#ifdef SUPPORT_PROXY
/*************************************************
* Restore socket timeout to previous value *
*************************************************/
/* Cannot configure local connection as a proxy inbound */
if (sender_host_address == NULL) return proxy_session;
-rc = verify_check_this_host(&proxy_required_hosts, NULL, NULL,
+rc = verify_check_this_host(&hosts_proxy, NULL, NULL,
sender_host_address, NULL);
if (rc == OK)
{
for (p = cmd_list; p < cmd_list_end; p++)
{
- #ifdef EXPERIMENTAL_PROXY
+ #ifdef SUPPORT_PROXY
/* Only allow QUIT command if Proxy Protocol parsing failed */
if (proxy_session && proxy_session_failed)
{
}
}
-#ifdef EXPERIMENTAL_PROXY
+#ifdef SUPPORT_PROXY
/* Only allow QUIT command if Proxy Protocol parsing failed */
if (proxy_session && proxy_session_failed)
return PROXY_FAIL_IGNORE_CMD;
if (smtp_batched_input) return TRUE;
-#ifdef EXPERIMENTAL_PROXY
+#ifdef SUPPORT_PROXY
/* If valid Proxy Protocol source is connecting, set up session.
* Failure will not allow any SMTP function other than QUIT. */
proxy_session = FALSE;
done = 1; /* Pretend eof - drops connection */
break;
- #ifdef EXPERIMENTAL_PROXY
+#ifdef SUPPORT_PROXY
case PROXY_FAIL_IGNORE_CMD:
smtp_printf("503 Command refused, required Proxy negotiation failed\r\n");
break;
- #endif
+#endif
default:
if (unknown_command_count++ >= smtp_max_unknown_commands)