This is an automated email from the ASF dual-hosted git repository.
maskit pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push:
new ef802ccdbc Accept PROXY protocol header that carries UDP address info
(#12011)
ef802ccdbc is described below
commit ef802ccdbc808d53da9649d2bd248934e857a763
Author: Masakazu Kitajo <[email protected]>
AuthorDate: Mon Feb 3 17:31:19 2025 -0700
Accept PROXY protocol header that carries UDP address info (#12011)
* Accept PROXY protocol header that carries UDP address info
* Add tests
---
include/iocore/net/ProxyProtocol.h | 5 +-
src/iocore/net/ProxyProtocol.cc | 60 ++++++++++++++----------
src/iocore/net/unit_tests/test_ProxyProtocol.cc | 62 +++++++++++++++++++++++++
3 files changed, 102 insertions(+), 25 deletions(-)
diff --git a/include/iocore/net/ProxyProtocol.h
b/include/iocore/net/ProxyProtocol.h
index f7cbb1aa28..7ff570162a 100644
--- a/include/iocore/net/ProxyProtocol.h
+++ b/include/iocore/net/ProxyProtocol.h
@@ -64,10 +64,13 @@ public:
{
}
~ProxyProtocol() { ats_free(additional_data); }
- int set_additional_data(std::string_view data);
+ int set_additional_data(std::string_view data);
+ void set_ipv4_addrs(in_addr_t src_addr, uint16_t src_port, in_addr_t
dst_addr, uint16_t dst_port);
+ void set_ipv6_addrs(const in6_addr &src_addr, uint16_t src_port, const
in6_addr &dst_addr, uint16_t dst_port);
ProxyProtocolVersion version =
ProxyProtocolVersion::UNDEFINED;
uint16_t ip_family = AF_UNSPEC;
+ int type = 0;
IpEndpoint src_addr = {};
IpEndpoint dst_addr = {};
std::unordered_map<uint8_t, std::string_view> tlv;
diff --git a/src/iocore/net/ProxyProtocol.cc b/src/iocore/net/ProxyProtocol.cc
index c2c6444307..76e7a3ddef 100644
--- a/src/iocore/net/ProxyProtocol.cc
+++ b/src/iocore/net/ProxyProtocol.cc
@@ -251,44 +251,32 @@ proxy_protocol_v2_parse(ProxyProtocol *pp_info, const
swoc::TextView &msg)
}
case PPv2_CMD_PROXY: {
switch (hdr_v2->fam) {
- case PPv2_PROTO_TCP4: {
+ case PPv2_PROTO_TCP4:
+ case PPv2_PROTO_UDP4:
if (len < PPv2_ADDR_LEN_INET) {
return 0;
}
tlv_len = len - PPv2_ADDR_LEN_INET;
- IpAddr src_addr(reinterpret_cast<in_addr_t>(hdr_v2->addr.ip4.src_addr));
- pp_info->src_addr.assign(src_addr, hdr_v2->addr.ip4.src_port);
-
- IpAddr dst_addr(reinterpret_cast<in_addr_t>(hdr_v2->addr.ip4.dst_addr));
- pp_info->dst_addr.assign(dst_addr, hdr_v2->addr.ip4.dst_port);
-
- pp_info->version = ProxyProtocolVersion::V2;
- pp_info->ip_family = AF_INET;
+
pp_info->set_ipv4_addrs(reinterpret_cast<in_addr_t>(hdr_v2->addr.ip4.src_addr),
hdr_v2->addr.ip4.src_port,
+
reinterpret_cast<in_addr_t>(hdr_v2->addr.ip4.dst_addr),
hdr_v2->addr.ip4.dst_port);
+ pp_info->type = hdr_v2->fam == PPv2_PROTO_TCP4 ? SOCK_STREAM :
SOCK_DGRAM;
+ pp_info->version = ProxyProtocolVersion::V2;
break;
- }
- case PPv2_PROTO_TCP6: {
+ case PPv2_PROTO_TCP6:
+ case PPv2_PROTO_UDP6:
if (len < PPv2_ADDR_LEN_INET6) {
return 0;
}
tlv_len = len - PPv2_ADDR_LEN_INET6;
- IpAddr src_addr(reinterpret_cast<in6_addr const
&>(hdr_v2->addr.ip6.src_addr));
- pp_info->src_addr.assign(src_addr, hdr_v2->addr.ip6.src_port);
-
- IpAddr dst_addr(reinterpret_cast<in6_addr const
&>(hdr_v2->addr.ip6.dst_addr));
- pp_info->dst_addr.assign(dst_addr, hdr_v2->addr.ip6.dst_port);
-
- pp_info->version = ProxyProtocolVersion::V2;
- pp_info->ip_family = AF_INET6;
+ pp_info->set_ipv6_addrs(reinterpret_cast<in6_addr const
&>(hdr_v2->addr.ip6.src_addr), hdr_v2->addr.ip6.src_port,
+ reinterpret_cast<in6_addr const
&>(hdr_v2->addr.ip6.dst_addr), hdr_v2->addr.ip6.dst_port);
+ pp_info->type = hdr_v2->fam == PPv2_PROTO_TCP6 ? SOCK_STREAM :
SOCK_DGRAM;
+ pp_info->version = ProxyProtocolVersion::V2;
break;
- }
- case PPv2_PROTO_UDP4:
- [[fallthrough]];
- case PPv2_PROTO_UDP6:
- [[fallthrough]];
case PPv2_PROTO_UNIX_STREAM:
[[fallthrough]];
case PPv2_PROTO_UNIX_DATAGRAM:
@@ -513,6 +501,30 @@ proxy_protocol_version_cast(int i)
}
}
+void
+ProxyProtocol::set_ipv4_addrs(in_addr_t src_addr, uint16_t src_port, in_addr_t
dst_addr, uint16_t dst_port)
+{
+ IpAddr src(src_addr);
+ IpAddr dst(dst_addr);
+
+ this->src_addr.assign(src, src_port);
+ this->dst_addr.assign(dst, dst_port);
+
+ this->ip_family = AF_INET;
+}
+
+void
+ProxyProtocol::set_ipv6_addrs(const in6_addr &src_addr, uint16_t src_port,
const in6_addr &dst_addr, uint16_t dst_port)
+{
+ IpAddr src(src_addr);
+ IpAddr dst(dst_addr);
+
+ this->src_addr.assign(src, src_port);
+ this->dst_addr.assign(dst, dst_port);
+
+ this->ip_family = AF_INET6;
+}
+
int
ProxyProtocol::set_additional_data(std::string_view data)
{
diff --git a/src/iocore/net/unit_tests/test_ProxyProtocol.cc
b/src/iocore/net/unit_tests/test_ProxyProtocol.cc
index 4f9c3a316d..7345f858a3 100644
--- a/src/iocore/net/unit_tests/test_ProxyProtocol.cc
+++ b/src/iocore/net/unit_tests/test_ProxyProtocol.cc
@@ -150,6 +150,7 @@ TEST_CASE("PROXY Protocol v2 Parser",
"[ProxyProtocol][ProxyProtocolv2]")
CHECK(pp_info.version == ProxyProtocolVersion::V2);
CHECK(pp_info.ip_family == AF_INET);
+ CHECK(pp_info.type == SOCK_STREAM);
CHECK(pp_info.src_addr == src_addr);
CHECK(pp_info.dst_addr == dst_addr);
}
@@ -180,6 +181,67 @@ TEST_CASE("PROXY Protocol v2 Parser",
"[ProxyProtocol][ProxyProtocolv2]")
CHECK(pp_info.version == ProxyProtocolVersion::V2);
CHECK(pp_info.ip_family == AF_INET6);
+ CHECK(pp_info.type == SOCK_STREAM);
+ CHECK(pp_info.src_addr == src_addr);
+ CHECK(pp_info.dst_addr == dst_addr);
+ }
+
+ SECTION("UDP over IPv4 without TLVs")
+ {
+ uint8_t raw_data[] = {
+ 0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, ///< preface
+ 0x55, 0x49, 0x54, 0x0A, ///<
+ 0x21, ///< version & command
+ 0x12, ///< protocol & family
+ 0x00, 0x0C, ///< len
+ 0xC0, 0x00, 0x02, 0x01, ///< src_addr
+ 0xC6, 0x33, 0x64, 0x01, ///< dst_addr
+ 0xC3, 0x50, ///< src_port
+ 0x01, 0xBB, ///< dst_port
+ };
+
+ swoc::TextView tv(reinterpret_cast<char *>(raw_data), sizeof(raw_data));
+
+ ProxyProtocol pp_info;
+ REQUIRE(proxy_protocol_parse(&pp_info, tv) == tv.size());
+
+ REQUIRE(ats_ip_pton("192.0.2.1:50000", src_addr) == 0);
+ REQUIRE(ats_ip_pton("198.51.100.1:443", dst_addr) == 0);
+
+ CHECK(pp_info.version == ProxyProtocolVersion::V2);
+ CHECK(pp_info.ip_family == AF_INET);
+ CHECK(pp_info.type == SOCK_DGRAM);
+ CHECK(pp_info.src_addr == src_addr);
+ CHECK(pp_info.dst_addr == dst_addr);
+ }
+
+ SECTION("UDP over IPv6 without TLVs")
+ {
+ uint8_t raw_data[] = {
+ 0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, ///< preface
+ 0x55, 0x49, 0x54, 0x0A, ///<
+ 0x21, ///< version & command
+ 0x22, ///< protocol & family
+ 0x00, 0x24, ///< len
+ 0x20, 0x01, 0x0D, 0xB8, 0x00, 0x00, 0x00, 0x01, ///< src_addr
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ///<
+ 0x20, 0x01, 0x0D, 0xB8, 0x00, 0x00, 0x00, 0x02, ///< dst_addr
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ///<
+ 0xC3, 0x50, ///< src_port
+ 0x01, 0xBB, ///< dst_port
+ };
+
+ swoc::TextView tv(reinterpret_cast<char *>(raw_data), sizeof(raw_data));
+
+ ProxyProtocol pp_info;
+ REQUIRE(proxy_protocol_parse(&pp_info, tv) == tv.size());
+
+ REQUIRE(ats_ip_pton("[2001:db8:0:1::]:50000", src_addr) == 0);
+ REQUIRE(ats_ip_pton("[2001:db8:0:2::]:443", dst_addr) == 0);
+
+ CHECK(pp_info.version == ProxyProtocolVersion::V2);
+ CHECK(pp_info.ip_family == AF_INET6);
+ CHECK(pp_info.type == SOCK_DGRAM);
CHECK(pp_info.src_addr == src_addr);
CHECK(pp_info.dst_addr == dst_addr);
}