diff options
-rw-r--r-- | doc/doc-txt/experimental-spec.txt | 2 | ||||
-rw-r--r-- | src/src/smtp_in.c | 34 | ||||
-rw-r--r-- | src/src/string.c | 2 | ||||
-rw-r--r-- | src/util/proxy_protocol_client.pl | 6 |
4 files changed, 30 insertions, 14 deletions
diff --git a/doc/doc-txt/experimental-spec.txt b/doc/doc-txt/experimental-spec.txt index 018bfddb9..d8c26bf93 100644 --- a/doc/doc-txt/experimental-spec.txt +++ b/doc/doc-txt/experimental-spec.txt @@ -1025,6 +1025,8 @@ 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 diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c index aad778eef..b7e60bfab 100644 --- a/src/src/smtp_in.c +++ b/src/src/smtp_in.c @@ -623,10 +623,9 @@ union { } 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; @@ -657,7 +656,7 @@ struct sockaddr_in6 tmpaddr6; 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; @@ -693,16 +692,32 @@ if (ret == -1) } 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) @@ -772,8 +787,7 @@ if (ret >= 16 && 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; } } diff --git a/src/src/string.c b/src/src/string.c index 914390255..0f657dcca 100644 --- a/src/src/string.c +++ b/src/src/string.c @@ -304,7 +304,7 @@ if (nonprintcount == 0) return s; /* 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. */ diff --git a/src/util/proxy_protocol_client.pl b/src/util/proxy_protocol_client.pl index 7cfc13ddc..feae3ca90 100644 --- a/src/util/proxy_protocol_client.pl +++ b/src/util/proxy_protocol_client.pl @@ -82,10 +82,10 @@ sub generate_preamble { 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, |