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 diff --git a/src/ProxyParser.h b/src/ProxyParser.h index 95ee3d119..65db21bec 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 @@ -99,7 +103,66 @@ 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 TCP4 " or "PROXY TCP6 " */ + if (data.length() < 11 || 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 = (char*)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 */ + printf("v1 line: %s\n", line); + + 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) { + + /* 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}; @@ -126,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); @@ -142,8 +205,8 @@ 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;