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
} v1;
struct {
uschar sig[12];
- uschar ver;
- uschar cmd;
- uschar fam;
- uschar len;
+ uint8_t ver_cmd;
+ uint8_t fam;
+ uint16_t len;
union {
struct { /* TCP/UDP over IPv4, len = 12 */
uint32_t src_addr;
int get_ok = 0;
int size, ret, fd;
-const char v2sig[13] = "\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A\x02";
+const char v2sig[12] = "\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A";
uschar *iptype; /* To display debug info */
struct timeval tv;
socklen_t vslen = 0;
}
if (ret >= 16 &&
- memcmp(&hdr.v2, v2sig, 13) == 0)
+ memcmp(&hdr.v2, v2sig, 12) == 0)
{
+ uint8_t ver, cmd;
+
+ /* May 2014: haproxy combined the version and command into one byte to
+ allow two full bytes for the length field in order to proxy SSL
+ connections. SSL Proxy is not supported in this version of Exim, but
+ must still seperate values here. */
+ ver = (hdr.v2.ver_cmd & 0xf0) >> 4;
+ cmd = (hdr.v2.ver_cmd & 0x0f);
+
+ if (ver != 0x02)
+ {
+ DEBUG(D_receive) debug_printf("Invalid Proxy Protocol version: %d\n", ver);
+ goto proxyfail;
+ }
DEBUG(D_receive) debug_printf("Detected PROXYv2 header\n");
+ /* The v2 header will always be 16 bytes per the spec. */
size = 16 + hdr.v2.len;
if (ret < size)
{
- DEBUG(D_receive) debug_printf("Truncated or too large PROXYv2 header\n");
+ DEBUG(D_receive) debug_printf("Truncated or too large PROXYv2 header (%d/%d)\n",
+ ret, size);
goto proxyfail;
}
- switch (hdr.v2.cmd)
+ switch (cmd)
{
case 0x01: /* PROXY command */
switch (hdr.v2.fam)
break;
default:
DEBUG(D_receive)
- debug_printf("Unsupported PROXYv2 command: 0x%02x\n",
- hdr.v2.cmd);
+ debug_printf("Unsupported PROXYv2 command: 0x%x\n", cmd);
goto proxyfail;
}
}
/* Get a new block of store guaranteed big enough to hold the
expanded string. */
-ss = store_get(length + nonprintcount * 4 + 1);
+ss = store_get(length + nonprintcount * 3 + 1);
/* Copy everying, escaping non printers. */
if (!$opts{version} || $opts{version} == 2) {
@preamble = (
"\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A", # 12 byte v2 header
- "\x02", # declares v2
- "\x01", # connection is proxied
+ "\x21", # top 4 bits declares v2
+ # bottom 4 bits is command
$opts{6} ? "\x21" : "\x11", # inet6/4 and TCP (stream)
- $opts{6} ? "\x24" : "\x0b", # 36 bytes / 12 bytes
+ $opts{6} ? "\x00\x24" : "\x00\x0b", # 36 bytes / 12 bytes
$source_ip,
$dest_ip,
$source_port,