]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: connection: add pp2-never-send-local to support old PP2 behavior
authorWilly Tarreau <w@1wt.eu>
Fri, 22 May 2020 11:53:29 +0000 (13:53 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 22 May 2020 11:55:32 +0000 (13:55 +0200)
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

doc/configuration.txt
src/connection.c

index 011aca4faf3b2784aa4adac4393a1703e2fac3a7..675fb4535f961e20f2723b1852c4ab958cc1fd47 100644 (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
index e9a68a578d56070f99d0faa9727af0f96fd1ccd8..3e27bdad219a67838e0f1d9489b57b71a66ef6db 100644 (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);