diff --git a/doc/configuration.txt b/doc/configuration.txt index 011aca4fa..675fb4535 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -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 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 Sets environment variable to value . If the variable exists, it is NOT overwritten. The changes immediately take effect so that the next line diff --git a/src/connection.c b/src/connection.c index e9a68a578..3e27bdad2 100644 --- a/src/connection.c +++ b/src/connection.c @@ -12,6 +12,7 @@ #include +#include #include #include #include @@ -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);