Skip to content

Commit

Permalink
Merge pull request #4420 from cyrusimap/proxy_protocol
Browse files Browse the repository at this point in the history
Add support for HAProxy protocol
  • Loading branch information
ksmurchison committed Apr 15, 2024
2 parents 19961c5 + ac9b5cf commit e40d901
Show file tree
Hide file tree
Showing 21 changed files with 343 additions and 25 deletions.
2 changes: 2 additions & 0 deletions Makefile.am
Expand Up @@ -1037,6 +1037,8 @@ imap_libcyrus_imap_la_SOURCES = \
imap/duplicate.h \
imap/global.c \
imap/global.h \
imap/haproxy.c \
imap/haproxy.h \
imap/http_client.c \
imap/http_client.h \
imap/idle.c \
Expand Down
22 changes: 22 additions & 0 deletions changes/next/proxy_protocol
@@ -0,0 +1,22 @@

Description:

Add support for the HAProxy protocol.

https://github.com/haproxy/haproxy/blob/master/doc/proxy-protocol.txt


Config changes:

None.


Upgrade instructions:

To enable support for the HAProxy protocol in imapd, pop3d, lmtpd, nntpd, httpd, or
timesieved, add the 'H' command line option to the service in cyrus.conf.


GitHub issue:

None.
6 changes: 5 additions & 1 deletion docsrc/assets/man-imapdproxyd.rst
Expand Up @@ -8,7 +8,7 @@ Synopsis
.. parsed-literal::
**imapd** [ **-C** *config-file* ] [ **-U** *uses* ] [ **-T** *timeout* ] [ **-D** ]
[ **-s** ] [ **-N** ] [ **-p** *ssf* ]
[ **-H** ] [ **-s** ] [ **-N** ] [ **-p** *ssf* ]
Description
===========
Expand Down Expand Up @@ -66,6 +66,10 @@ Options

Run external debugger specified in debug_command.

.. option:: -H

Tell **imapd** to expect a HAProxy protocol header from the sender.

.. option:: -s

Serve IMAP over SSL (imaps). All data to and from **imapd** is
Expand Down
10 changes: 9 additions & 1 deletion docsrc/assets/man-imtest.rst
Expand Up @@ -7,7 +7,8 @@ Synopsis
[ **-a** *userid* ] [ **-u** *userid* ] [ **-k** *num* ] [ **-l** *num* ]
[ **-r** *realm* ] [ **-f** *file* ] [ **-n** *num* ] [ **-s** ] [ **-q** ]
[ **-c** ] [ **-i** ] [ **-z** ] [ **-v** ] [ **-I** *file* ] [ **-x** *file* ]
[ **-X** *file* ] [ **-w** *passwd* ] [ **-o** *option*\ =\ *value* ] *hostname*
[ **-X** *file* ] [ **-w** *passwd* ] [ **-o** *option*\ =\ *value* ]
[ **-H** *client-ip* ] *hostname*
Description
===========
Expand Down Expand Up @@ -132,6 +133,13 @@ Options

Set the SASL *option* to *value*.

.. option:: -H client-ip

Enable the HAProxy protocol and send the specified client IP
address in a v1 header. If the address is "unknown", a v1 header
with UNKNOWN protocol will be sent. If the address is "local",
a v2 header with LOCAL command will be sent.

Examples
========

Expand Down
7 changes: 6 additions & 1 deletion docsrc/assets/man-lmtpd.rst
Expand Up @@ -3,7 +3,8 @@ Synopsis

.. parsed-literal::
**lmtpd** [ **-C** *config-file* ] [ **-U** *uses* ] [ **-T** *timeout* ] [ **-D** ] [ **-a** ]
**lmtpd** [ **-C** *config-file* ] [ **-U** *uses* ] [ **-T** *timeout* ] [ **-D** ]
[ **-H** ] [ **-a** ]
Description
===========
Expand Down Expand Up @@ -39,6 +40,10 @@ Options

Run external debugger specified in debug_command.

.. option:: -H

Tell **lmtpd** to expect a HAProxy protocol header from the sender.

.. option:: -a

Preauthorize connections initiated on an internet socket, instead
Expand Down
6 changes: 5 additions & 1 deletion docsrc/imap/reference/manpages/systemcommands/httpd.rst
Expand Up @@ -16,7 +16,7 @@ Synopsis
.. parsed-literal::
**httpd** [ **-C** *config-file* ] [ **-U** *uses* ] [ **-T** *timeout* ] [ **-D** ]
[ **-s** ] [ **-p** *ssf* ] [ **-q** ]
[ **-H** ] [ **-s** ] [ **-p** *ssf* ] [ **-q** ]
Description
===========
Expand Down Expand Up @@ -57,6 +57,10 @@ Options

Run external debugger specified in debug_command.

.. option:: -H

Tell **httpd** to expect a HAProxy protocol header from the sender.

.. option:: -s

Serve HTTP over SSL (https). All data to and from **httpd**
Expand Down
6 changes: 5 additions & 1 deletion docsrc/imap/reference/manpages/systemcommands/nntpd.rst
Expand Up @@ -16,7 +16,7 @@ Synopsis
.. parsed-literal::
**nntpd** [ **-C** *config-file* ] [ **-U** *uses* ] [ **-T** *timeout* ] [ **-D** ]
[ **-s** ] [ **-r** ] [ **-f** ] [ **-p** *ssf* ]
[ **-H** ] [ **-s** ] [ **-r** ] [ **-f** ] [ **-p** *ssf* ]
Description
===========
Expand Down Expand Up @@ -68,6 +68,10 @@ Options

Run external debugger specified in debug_command.

.. option:: -H

Tell **nntpd** to expect a HAProxy protocol header from the sender.

.. option:: -s

Serve NNTP over SSL (https). All data to and from **nntpd**
Expand Down
6 changes: 5 additions & 1 deletion docsrc/imap/reference/manpages/systemcommands/pop3d.rst
Expand Up @@ -16,7 +16,7 @@ Synopsis
.. parsed-literal::
**pop3d** [ **-C** *config-file* ] [ **-U** *uses* ] [ **-T** *timeout* ] [ **-D** ]
[ **-s** ] [ **-k** ] [ **-p** *ssf* ]
[ **-H** ] [ **-s** ] [ **-k** ] [ **-p** *ssf* ]
Description
===========
Expand Down Expand Up @@ -59,6 +59,10 @@ Options

Run external debugger specified in debug_command.

.. option:: -H

Tell **httpd** to expect a HAProxy protocol header from the sender.

.. option:: -s

Serve POP3 over SSL (pop3s). All data to and from **pop3d** is
Expand Down
Expand Up @@ -9,4 +9,4 @@

This is a hard linked copy of :cyrusman:`pop3d(8)`, retained for backwards compatibility from when a murder frontend used its own pop3d binaries.

.. include:: /assets/man-lmtpd.rst
.. include:: /assets/man-pop3d.rst
6 changes: 5 additions & 1 deletion docsrc/imap/reference/manpages/systemcommands/timsieved.rst
Expand Up @@ -17,7 +17,7 @@ Synopsis

.. parsed-literal::
**timsieved** [ **-C** *config-file* ]
**timsieved** [ **-C** *config-file* ] [ **-H** ]
Description
===========
Expand All @@ -40,6 +40,10 @@ Options

.. option:: -C config-file

.. option:: -H

Tell **timsievedd** to expect a HAProxy protocol header from the sender.

|cli-dash-c-text|

Examples
Expand Down
23 changes: 20 additions & 3 deletions imap/global.c
Expand Up @@ -66,6 +66,7 @@
#include "charset.h"
#include "cyr_lock.h"
#include "gmtoff.h"
#include "haproxy.h"
#include "iptostring.h"
#include "global.h"
#include "ical_support.h"
Expand Down Expand Up @@ -119,6 +120,7 @@ EXPORTED size_t config_search_maxsize;
EXPORTED int config_httpprettytelemetry;
EXPORTED int config_take_globallock;
EXPORTED char *config_skip_userlock;
EXPORTED int haproxy_protocol = 0;

static char session_id_buf[MAX_SESSIONID_SIZE];
static int session_id_time = 0;
Expand Down Expand Up @@ -1054,21 +1056,31 @@ EXPORTED const char *get_clienthost(int s, const char **localip, const char **re
{
#define IPBUF_SIZE (NI_MAXHOST+NI_MAXSERV+2)
socklen_t salen;
struct sockaddr_storage localaddr, remoteaddr;
struct sockaddr_storage localaddr = { 0 }, remoteaddr = { 0 };
struct sockaddr *localsock = (struct sockaddr *)&localaddr;
struct sockaddr *remotesock = (struct sockaddr *)&remoteaddr;
static struct buf clientbuf = BUF_INITIALIZER;
static char lipbuf[IPBUF_SIZE], ripbuf[IPBUF_SIZE];
char hbuf[NI_MAXHOST];
int niflags;
int r = 0;

buf_reset(&clientbuf);
*localip = *remoteip = NULL;

/* determine who we're talking to */

salen = sizeof(struct sockaddr_storage);
if (getpeername(s, remotesock, &salen) == 0 &&

if (haproxy_protocol && haproxy_read_hdr(s, localsock, remotesock) != 0) {
fatal("unable to read HAProxy protocol header", EX_IOERR);
}

if (remotesock->sa_family == PF_UNSPEC) {
r = getpeername(s, remotesock, &salen);
}

if (r == 0 &&
(remotesock->sa_family == AF_INET ||
remotesock->sa_family == AF_INET6)) {
/* connected to an internet socket */
Expand All @@ -1089,7 +1101,12 @@ EXPORTED const char *get_clienthost(int s, const char **localip, const char **re
buf_printf(&clientbuf, "[%s]", hbuf);

salen = sizeof(struct sockaddr_storage);
if (getsockname(s, localsock, &salen) == 0) {

if (localsock->sa_family == PF_UNSPEC) {
r = getsockname(s, localsock, &salen);
}

if (r == 0) {
/* set the ip addresses here */
if (iptostring(localsock, salen,
lipbuf, sizeof(lipbuf)) == 0) {
Expand Down
1 change: 1 addition & 0 deletions imap/global.h
Expand Up @@ -185,6 +185,7 @@ extern int config_httpprettytelemetry;
extern int charset_flags;
extern int charset_snippet_flags;
extern size_t config_search_maxsize;
extern int haproxy_protocol;

/* Session ID */
extern void session_new_id(void);
Expand Down

0 comments on commit e40d901

Please sign in to comment.