BUG/MINOR: connection: make sure to correctly tag local PROXY connections

As reported in issue #511, when sending an outgoing local connection
(e.g. health check) we must set the "local" tag and not a "proxy" tag.
The issue comes from historic support on v1 which required to steal the
address on the outgoing connection for such ones, creating confusion in
the v2 code which believes it sees the incoming connection.

In order not to risk to break existing setups which might rely on seeing
the LB's address in the connection's source field, let's just change the
connection type from proxy to local and keep the addresses. The protocol
spec states that for local, the addresses must be ignored anyway.

This problem has always existed, this can be backported as far as 1.5,
though it's probably not a good idea to change such setups, thus maybe
2.0 would be more reasonable.
This commit is contained in:
Willy Tarreau 2020-02-19 15:10:00 +01:00
parent d1c847abbc
commit 7f26391bc5
1 changed files with 8 additions and 2 deletions

View File

@ -1318,11 +1318,18 @@ int make_proxy_line_v2(char *buf, int buf_len, struct server *srv, struct connec
ret = PP2_HDR_LEN_UNSPEC; ret = PP2_HDR_LEN_UNSPEC;
} }
else { else {
/* Note: due to historic compatibility with V1 which required
* to send "PROXY" with local addresses for local connections,
* we can end up here with the remote in fact being our outgoing
* connection. We still want to send real addresses and LOCAL on
* it.
*/
hdr->ver_cmd = PP2_VERSION;
hdr->ver_cmd |= conn_is_back(remote) ? PP2_CMD_LOCAL : PP2_CMD_PROXY;
/* IPv4 for both src and dst */ /* IPv4 for both src and dst */
if (src->ss_family == AF_INET && dst->ss_family == AF_INET) { if (src->ss_family == AF_INET && dst->ss_family == AF_INET) {
if (buf_len < PP2_HDR_LEN_INET) if (buf_len < PP2_HDR_LEN_INET)
return 0; return 0;
hdr->ver_cmd = PP2_VERSION | PP2_CMD_PROXY;
hdr->fam = PP2_FAM_INET | PP2_TRANS_STREAM; hdr->fam = PP2_FAM_INET | PP2_TRANS_STREAM;
hdr->addr.ip4.src_addr = ((struct sockaddr_in *)src)->sin_addr.s_addr; hdr->addr.ip4.src_addr = ((struct sockaddr_in *)src)->sin_addr.s_addr;
hdr->addr.ip4.src_port = ((struct sockaddr_in *)src)->sin_port; hdr->addr.ip4.src_port = ((struct sockaddr_in *)src)->sin_port;
@ -1336,7 +1343,6 @@ int make_proxy_line_v2(char *buf, int buf_len, struct server *srv, struct connec
if (buf_len < PP2_HDR_LEN_INET6) if (buf_len < PP2_HDR_LEN_INET6)
return 0; return 0;
hdr->ver_cmd = PP2_VERSION | PP2_CMD_PROXY;
hdr->fam = PP2_FAM_INET6 | PP2_TRANS_STREAM; hdr->fam = PP2_FAM_INET6 | PP2_TRANS_STREAM;
if (src->ss_family == AF_INET) { if (src->ss_family == AF_INET) {
v4tov6(&tmp, &((struct sockaddr_in *)src)->sin_addr); v4tov6(&tmp, &((struct sockaddr_in *)src)->sin_addr);