MINOR: connection: add pp2-never-send-local to support old PP2 behavior

A bug in the PROXY protocol v2 implementation was present in HAProxy up to
version 2.1, causing it to emit a PROXY command instead of a LOCAL command
for health checks. This is particularly minor but confuses some servers'
logs. Sadly, the bug was discovered very late and revealed that some servers
which possibly only tested their PROXY protocol implementation against
HAProxy fail to properly handle the LOCAL command, and permanently remain in
the "down" state when HAProxy checks them. When this happens, it is possible
to enable this global option to revert to the older (bogus) behavior for the
time it takes to contact the affected components' vendors and get them fixed.
This option is disabled by default and acts on all servers having the
"send-proxy-v2" statement.

Older versions were reverted to the old behavior and should not attempt to
be fixed by default again. However a variant of this patch could possibly
be implemented to ask to explicitly send LOCAL if needed by some servers.

More context here:
   https://www.mail-archive.com/haproxy@formilux.org/msg36890.html
   https://www.mail-archive.com/haproxy@formilux.org/msg37218.html
This commit is contained in:
Willy Tarreau 2020-05-22 13:53:29 +02:00
parent 318adf4364
commit 119e50e0cc
2 changed files with 37 additions and 1 deletions

View File

@ -612,6 +612,7 @@ The following keywords are supported in the "global" section :
- nbthread
- node
- pidfile
- pp2-never-send-local
- presetenv
- resetenv
- uid
@ -1177,6 +1178,19 @@ pidfile <pidfile>
the "-p" command line argument. The file must be accessible to the user
starting the process. See also "daemon".
pp2-never-send-local
A bug in the PROXY protocol v2 implementation was present in HAProxy up to
version 2.1, causing it to emit a PROXY command instead of a LOCAL command
for health checks. This is particularly minor but confuses some servers'
logs. Sadly, the bug was discovered very late and revealed that some servers
which possibly only tested their PROXY protocol implementation against
HAProxy fail to properly handle the LOCAL command, and permanently remain in
the "down" state when HAProxy checks them. When this happens, it is possible
to enable this global option to revert to the older (bogus) behavior for the
time it takes to contact the affected components' vendors and get them fixed.
This option is disabled by default and acts on all servers having the
"send-proxy-v2" statement.
presetenv <name> <value>
Sets environment variable <name> to value <value>. If the variable exists, it
is NOT overwritten. The changes immediately take effect so that the next line

View File

@ -12,6 +12,7 @@
#include <errno.h>
#include <common/cfgparse.h>
#include <common/compat.h>
#include <common/config.h>
#include <common/initcall.h>
@ -41,6 +42,9 @@ struct mux_proto_list mux_proto_list = {
.list = LIST_HEAD_INIT(mux_proto_list.list)
};
/* disables sending of proxy-protocol-v2's LOCAL command */
static int pp2_never_send_local;
int conn_create_mux(struct connection *conn)
{
if (conn_is_back(conn)) {
@ -1383,7 +1387,7 @@ int make_proxy_line_v2(char *buf, int buf_len, struct server *srv, struct connec
/* At least one of src or dst is not of AF_INET or AF_INET6 */
if ( !src
|| !dst
|| conn_is_back(remote)
|| (!pp2_never_send_local && conn_is_back(remote)) // locally initiated connection
|| (src->ss_family != AF_INET && src->ss_family != AF_INET6)
|| (dst->ss_family != AF_INET && dst->ss_family != AF_INET6)) {
if (buf_len < PP2_HDR_LEN_UNSPEC)
@ -1558,6 +1562,17 @@ int make_proxy_line_v2(char *buf, int buf_len, struct server *srv, struct connec
return ret;
}
/* returns 0 on success */
static int cfg_parse_pp2_never_send_local(char **args, int section_type, struct proxy *curpx,
struct proxy *defpx, const char *file, int line,
char **err)
{
if (too_many_args(0, args, err, NULL))
return -1;
pp2_never_send_local = 1;
return 0;
}
/* return the major HTTP version as 1 or 2 depending on how the request arrived
* before being processed.
*/
@ -1658,3 +1673,10 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
}};
INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords);
static struct cfg_kw_list cfg_kws = {ILH, {
{ CFG_GLOBAL, "pp2-never-send-local", cfg_parse_pp2_never_send_local },
{ /* END */ },
}};
INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);