From fca3ebc35cd70d6b27dc1bb107af5859578b4f6f Mon Sep 17 00:00:00 2001 From: Herman Banken Date: Thu, 29 Apr 2021 08:57:03 +0200 Subject: [PATCH 1/7] Support PROXY v1 https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt > Version 1 senders MAY only produce the human-readable header format. Version 2 > senders MAY only produce the binary header format. Version 1 receivers MUST at > least implement the human-readable header format. Version 2 receivers MUST at > least implement the binary header format, and it is recommended that they also > implement the human-readable header format for better interoperability and ease > of upgrade when facing version 1 senders. --- src/ProxyParser.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/ProxyParser.h b/src/ProxyParser.h index 95ee3d119..4d807968c 100644 --- a/src/ProxyParser.h +++ b/src/ProxyParser.h @@ -15,7 +15,11 @@ * limitations under the License. */ -/* This module implements The PROXY Protocol v2 */ +/* + * Modified by Herman Banken, 2021 to add PROXY v1. + */ + +/* This module implements The PROXY Protocol v1 & v2 */ #ifndef UWS_PROXY_PARSER_H #define UWS_PROXY_PARSER_H From 993ef2085c997a5e26bc48497a5e473952f16366 Mon Sep 17 00:00:00 2001 From: Herman Banken Date: Thu, 29 Apr 2021 09:02:31 +0200 Subject: [PATCH 2/7] Debug --- src/ProxyParser.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ProxyParser.h b/src/ProxyParser.h index 4d807968c..ec11d60b1 100644 --- a/src/ProxyParser.h +++ b/src/ProxyParser.h @@ -146,14 +146,15 @@ struct ProxyParser { return {false, 0}; } - //printf("Family: %d\n", (header.fam & 0xf0) >> 4); - //printf("Transport: %d\n", (header.fam & 0x0f)); + printf("Family: %d\n", (header.fam & 0xf0) >> 4); + printf("Transport: %d\n", (header.fam & 0x0f)); /* We have 0 family by default, and UNSPEC is 0 as well */ family = header.fam; /* Copy payload */ memcpy(&addr, data.data() + 16, hostLength); + printf("Result: %s\n", getSourceAddress()); /* We consumed everything */ return {true, 16 + hostLength}; From 0a4215c0a7f1ea97de3c2ad76e27b722d8bf4a1f Mon Sep 17 00:00:00 2001 From: Herman Banken Date: Thu, 29 Apr 2021 09:36:56 +0200 Subject: [PATCH 3/7] fixup! Support PROXY v1 --- src/ProxyParser.h | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/src/ProxyParser.h b/src/ProxyParser.h index ec11d60b1..948ab1618 100644 --- a/src/ProxyParser.h +++ b/src/ProxyParser.h @@ -103,7 +103,52 @@ struct ProxyParser { return {false, 0}; } - /* HTTP can never start with "\r\n\r\n", but PROXY always does */ + /* HTTP can never start with "PROX", but PROXY v1 always does */ + if (memcmp(data.data(), "\x50\x52\x4F\x58", 4) == 0) { + return parseV1(data); + } + + return parseV2(data); + } + + + std::pair parseV1(std::string_view data) { + + /* Check for the full "PROXY" */ + if (data.length() >= 8 && memcmp(data.data(), "PROXY", 5)) { + return {false, 0}; + } + + /* Header is at most 108 bytes */ + unsigned int len = (unsigned int) data.length() - 1; + if (data.length() > 108) { + len = 108; + } + char line[108]; + int size; + memcpy(&line, data.data(), len); + + /* locate \r in header */ + char *end = memchr(line, '\r', len); + if (!end || end[1] != '\n') { + /* partial or invalid header */ + return {false, 0}; + } + *end = '\0'; /* terminate the string to ease parsing */ + size = end + 2 - line; /* skip header + CRLF */ + + /* parse the V1 header using favorite address parsers like inet_pton. + * return -1 upon error, or simply fall through to accept. + */ + printf("v1 line: %s\n", line); + + /* We consumed the whole header */ + return {true, size}; + } + + std::pair parseV2(std::string_view data) { + + /* HTTP can never start with "\r\n\r\n", but PROXY v2 always does */ if (memcmp(data.data(), "\r\n\r\n", 4)) { /* This is HTTP, so be done */ return {true, 0}; From 1953ad13b8aa98dc0a311e611f41019ed24ccbc9 Mon Sep 17 00:00:00 2001 From: Herman Banken Date: Thu, 29 Apr 2021 09:39:36 +0200 Subject: [PATCH 4/7] Build from fork Trigger --- .github/workflows/cpp.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cpp.yml b/.github/workflows/cpp.yml index cfcdf49bf..7716a3dea 100644 --- a/.github/workflows/cpp.yml +++ b/.github/workflows/cpp.yml @@ -9,7 +9,7 @@ jobs: steps: - name: Clone source - run: git clone --recursive https://github.com/uNetworking/uWebSockets.git + run: git clone --recursive https://github.com/Q42Philips/uWebSockets.git - name: Build source run: make -C uWebSockets - name: List binaries @@ -23,7 +23,7 @@ jobs: steps: - name: Clone source - run: git clone --recursive https://github.com/uNetworking/uWebSockets.git + run: git clone --recursive https://github.com/Q42Philips/uWebSockets.git - name: Build source run: make -C uWebSockets - name: List binaries From 6e07a8c3a705b2e979f4dede6152a24ad82a2373 Mon Sep 17 00:00:00 2001 From: Herman Banken Date: Thu, 29 Apr 2021 10:44:16 +0200 Subject: [PATCH 5/7] fixup! Support PROXY v1 --- src/ProxyParser.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ProxyParser.h b/src/ProxyParser.h index 948ab1618..7da007e9d 100644 --- a/src/ProxyParser.h +++ b/src/ProxyParser.h @@ -129,7 +129,7 @@ struct ProxyParser { memcpy(&line, data.data(), len); /* locate \r in header */ - char *end = memchr(line, '\r', len); + char *end = (char*)memchr(line, '\r', len); if (!end || end[1] != '\n') { /* partial or invalid header */ return {false, 0}; @@ -199,7 +199,7 @@ struct ProxyParser { /* Copy payload */ memcpy(&addr, data.data() + 16, hostLength); - printf("Result: %s\n", getSourceAddress()); + std::cout << "Result: '" << getSourceAddress() << "'\n"; /* We consumed everything */ return {true, 16 + hostLength}; From 690dae3019077c79cf903419f04a0fc6b87c7833 Mon Sep 17 00:00:00 2001 From: Herman Banken Date: Thu, 29 Apr 2021 10:45:49 +0200 Subject: [PATCH 6/7] fixup! Support PROXY v1 --- src/ProxyParser.h | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/ProxyParser.h b/src/ProxyParser.h index 7da007e9d..d4d8da1da 100644 --- a/src/ProxyParser.h +++ b/src/ProxyParser.h @@ -114,8 +114,8 @@ struct ProxyParser { std::pair parseV1(std::string_view data) { - /* Check for the full "PROXY" */ - if (data.length() >= 8 && memcmp(data.data(), "PROXY", 5)) { + /* Check for the full "PROXY TCP4 " or "PROXY TCP6 " */ + if (data.length() < 11 || memcmp(data.data(), "PROXY", 5)) { return {false, 0}; } @@ -136,14 +136,28 @@ struct ProxyParser { } *end = '\0'; /* terminate the string to ease parsing */ size = end + 2 - line; /* skip header + CRLF */ - - /* parse the V1 header using favorite address parsers like inet_pton. - * return -1 upon error, or simply fall through to accept. - */ printf("v1 line: %s\n", line); - /* We consumed the whole header */ - return {true, size}; + if (memcmp(data.data(), "PROXY TCP4 ", 11) == 0) { + // PROXY TCP4 255.255.255.255 255.255.255.255 65535 65535\r\n + uint32_t *b = &addr.ipv4_addr.src_addr; + uint32_t *c = &addr.ipv4_addr.dst_addr; + sscanf(line + 11, "%u.%u.%u.%u %u.%u.%u.%u %d %d", + b, b + 1, b + 2, b + 3, + c, c + 1, c + 2, c + 3, + &addr.ipv4_addr.src_port, + &addr.ipv4_addr.dst_port); + } else if (memcmp(data.data(), "PROXY TCP6 ", 11) == 0) { + // PROXY TCP6 ffff:f...f:ffff ffff:f...f:ffff 65535 65535\r\n + // TODO + } else if (data.length() >= 13 && memcmp(data.data(), "PROXY UNKNOWN", 13)) { + /* Read UNKNOWN but don't do anything with it */ + /* We consumed the whole header */ + return {true, size}; + } + + /* Invalid/unhandled format */ + return {false, 0}; } std::pair parseV2(std::string_view data) { From c15896e43913bb608f020b5dcfbe6a0090bdf89b Mon Sep 17 00:00:00 2001 From: Herman Banken Date: Thu, 29 Apr 2021 10:53:07 +0200 Subject: [PATCH 7/7] fixup! Debug --- src/ProxyParser.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/ProxyParser.h b/src/ProxyParser.h index d4d8da1da..65db21bec 100644 --- a/src/ProxyParser.h +++ b/src/ProxyParser.h @@ -189,8 +189,8 @@ struct ProxyParser { return {false, 0}; } - //printf("Version: %d\n", (header.ver_cmd & 0xf0) >> 4); - //printf("Command: %d\n", (header.ver_cmd & 0x0f)); + printf("Version: %d\n", (header.ver_cmd & 0xf0) >> 4); + printf("Command: %d\n", (header.ver_cmd & 0x0f)); /* We get length in network byte order (todo: share this function with the rest) */ uint16_t hostLength = _cond_byte_swap(header.len); @@ -213,7 +213,6 @@ struct ProxyParser { /* Copy payload */ memcpy(&addr, data.data() + 16, hostLength); - std::cout << "Result: '" << getSourceAddress() << "'\n"; /* We consumed everything */ return {true, 16 + hostLength};