59. Proxies
Author: The Exim Project. <https://www.exim.org/>
Description: Exim is a message transfer agent (MTA) developed at the University of Cambridge for use on Unix systems connected to the Internet.
Keywords: exim,smtp,mta,email

# Exim Internet Mailer

<-previous next->

## Chapter 59 - Proxies

A proxy is an intermediate system through which communication is passed. Proxies may provide a security, availability or load-distribution function.

### 1. Inbound proxies

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 the HAProxy specification, found at https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt.

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. Exim supports both version 1 and version 2 of the Proxy Protocol and automatically determines which version is in use.

The Proxy Protocol header is the first data received on a TCP connection and is inserted before any TLS-on-connect handshake from the client; Exim negotiates TLS between Exim-as-server and the remote client, not between Exim and the proxy server. The Proxy Protocol header must be received within proxy_protocol_timeout, which defaults to 3s.

The following expansion variables are usable (“internal” and “external” here refer to the interfaces of the proxy):

$proxy_external_address | IP of host being proxied or IP of remote interface of proxy
$proxy_external_port | Port of host being proxied or Port on remote interface of proxy
$proxy_local_address | IP of proxy server inbound or IP of local interface of proxy
$proxy_local_port | Port of proxy server inbound or Port on local interface of proxy
$proxy_session | boolean: SMTP connection via proxy

If $proxy_session is set but $proxy_external_address is empty there was a protocol error. The variables $sender_host_address and $sender_host_port will have values for the actual client system, not the proxy.

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:

      # 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   ratelimit      = LIMIT / 5s / per_conn / strict
              message        = Too many connections from this IP right now

### 2. Outbound proxies

Exim has support for sending outbound SMTP via a proxy using a protocol called SOCKS5 (defined by RFC 1928). 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 option on an smtp transport.

If unset (or empty after expansion) then proxying is not done.

Otherwise, expansion should result in a list (colon-separated by default) of proxy specifiers. Each proxy specifier is a list (space-separated by default) where the initial element is an IP address and any subsequent elements are options.

Each option is a string of form <name>=<value>. The list of options is in the following table:

auth | authentication method
name | authentication username
pass | authentication password
port | tcp port
tmo | connection timeout
pri | priority
weight | selection bias

More details on each of these options follows:

- auth: Either “none” (default) or “name”. Using “name” selects username/password authentication per RFC 1929 for access to the proxy. Default is “none”.

- name: sets the username for the “name” authentication method. Default is empty.

- pass: sets the password for the “name” authentication method. Default is empty.

- port: the TCP port number to use for the connection to the proxy. Default is 1080.

- tmo: sets a connection timeout in seconds for this proxy. Default is 5.

- pri: specifies a priority for the proxy within the list, higher values being tried first. The default priority is 1.

- weight: specifies a selection bias. Within a priority set servers are queried in a random fashion, weighted by this value. The default value for selection bias is 1.

Proxies from the list are tried according to their priority and weight settings until one responds. The timeout for the overall connection applies to the set of proxied attempts.

### 3. Logging

To log the (local) IP of a proxy in the incoming or delivery logline, add “+proxy” to the log_selector option. This will add a component tagged with “PRX=” to the line.

<-previous Table of Contents next->