Line data Source code
1 : #include "source/extensions/common/proxy_protocol/proxy_protocol_header.h"
2 :
3 : #include <sstream>
4 :
5 : #include "envoy/buffer/buffer.h"
6 : #include "envoy/network/address.h"
7 :
8 : #include "source/common/network/address_impl.h"
9 :
10 : namespace Envoy {
11 : namespace Extensions {
12 : namespace Common {
13 : namespace ProxyProtocol {
14 :
15 : void generateV1Header(const std::string& src_addr, const std::string& dst_addr, uint32_t src_port,
16 : uint32_t dst_port, Network::Address::IpVersion ip_version,
17 0 : Buffer::Instance& out) {
18 0 : std::ostringstream stream;
19 0 : stream << PROXY_PROTO_V1_SIGNATURE;
20 :
21 0 : switch (ip_version) {
22 0 : case Network::Address::IpVersion::v4:
23 0 : stream << PROXY_PROTO_V1_AF_INET << " ";
24 0 : break;
25 0 : case Network::Address::IpVersion::v6:
26 0 : stream << PROXY_PROTO_V1_AF_INET6 << " ";
27 0 : break;
28 0 : }
29 :
30 0 : stream << src_addr << " ";
31 0 : stream << dst_addr << " ";
32 0 : stream << src_port << " ";
33 0 : stream << dst_port << "\r\n";
34 :
35 0 : out.add(stream.str());
36 0 : }
37 :
38 : void generateV1Header(const Network::Address::Ip& source_address,
39 0 : const Network::Address::Ip& dest_address, Buffer::Instance& out) {
40 0 : generateV1Header(source_address.addressAsString(), dest_address.addressAsString(),
41 0 : source_address.port(), dest_address.port(), source_address.version(), out);
42 0 : }
43 :
44 : void generateV2Header(const std::string& src_addr, const std::string& dst_addr, uint32_t src_port,
45 : uint32_t dst_port, Network::Address::IpVersion ip_version,
46 0 : uint16_t extension_length, Buffer::Instance& out) {
47 0 : out.add(PROXY_PROTO_V2_SIGNATURE, PROXY_PROTO_V2_SIGNATURE_LEN);
48 :
49 0 : const uint8_t version_and_command = PROXY_PROTO_V2_VERSION << 4 | PROXY_PROTO_V2_ONBEHALF_OF;
50 0 : out.add(&version_and_command, 1);
51 :
52 0 : uint8_t address_family_and_protocol;
53 0 : switch (ip_version) {
54 0 : case Network::Address::IpVersion::v4:
55 0 : address_family_and_protocol = PROXY_PROTO_V2_AF_INET << 4;
56 0 : break;
57 0 : case Network::Address::IpVersion::v6:
58 0 : address_family_and_protocol = PROXY_PROTO_V2_AF_INET6 << 4;
59 0 : break;
60 0 : }
61 0 : address_family_and_protocol |= PROXY_PROTO_V2_TRANSPORT_STREAM;
62 0 : out.add(&address_family_and_protocol, 1);
63 :
64 : // Number of following bytes part of the header in V2 protocol.
65 0 : uint16_t addr_length;
66 0 : uint16_t addr_length_n; // Network byte order
67 :
68 0 : switch (ip_version) {
69 0 : case Network::Address::IpVersion::v4: {
70 0 : addr_length = PROXY_PROTO_V2_ADDR_LEN_INET + extension_length;
71 0 : addr_length_n = htons(addr_length);
72 0 : out.add(&addr_length_n, 2);
73 0 : const uint32_t net_src_addr =
74 0 : Network::Address::Ipv4Instance(src_addr, src_port).ip()->ipv4()->address();
75 0 : const uint32_t net_dst_addr =
76 0 : Network::Address::Ipv4Instance(dst_addr, dst_port).ip()->ipv4()->address();
77 0 : out.add(&net_src_addr, 4);
78 0 : out.add(&net_dst_addr, 4);
79 0 : break;
80 0 : }
81 0 : case Network::Address::IpVersion::v6: {
82 0 : addr_length = PROXY_PROTO_V2_ADDR_LEN_INET6 + extension_length;
83 0 : addr_length_n = htons(addr_length);
84 0 : out.add(&addr_length_n, 2);
85 0 : const absl::uint128 net_src_addr =
86 0 : Network::Address::Ipv6Instance(src_addr, src_port).ip()->ipv6()->address();
87 0 : const absl::uint128 net_dst_addr =
88 0 : Network::Address::Ipv6Instance(dst_addr, dst_port).ip()->ipv6()->address();
89 0 : out.add(&net_src_addr, 16);
90 0 : out.add(&net_dst_addr, 16);
91 0 : break;
92 0 : }
93 0 : }
94 :
95 0 : const uint16_t net_src_port = htons(static_cast<uint16_t>(src_port));
96 0 : const uint16_t net_dst_port = htons(static_cast<uint16_t>(dst_port));
97 0 : out.add(&net_src_port, 2);
98 0 : out.add(&net_dst_port, 2);
99 0 : }
100 :
101 : void generateV2Header(const std::string& src_addr, const std::string& dst_addr, uint32_t src_port,
102 : uint32_t dst_port, Network::Address::IpVersion ip_version,
103 0 : Buffer::Instance& out) {
104 0 : generateV2Header(src_addr, dst_addr, src_port, dst_port, ip_version, 0, out);
105 0 : }
106 :
107 : void generateV2Header(const Network::Address::Ip& source_address,
108 0 : const Network::Address::Ip& dest_address, Buffer::Instance& out) {
109 0 : generateV2Header(source_address.addressAsString(), dest_address.addressAsString(),
110 0 : source_address.port(), dest_address.port(), source_address.version(), 0, out);
111 0 : }
112 :
113 : bool generateV2Header(const Network::ProxyProtocolData& proxy_proto_data, Buffer::Instance& out,
114 0 : bool pass_all_tlvs, const absl::flat_hash_set<uint8_t>& pass_through_tlvs) {
115 0 : uint64_t extension_length = 0;
116 0 : for (auto&& tlv : proxy_proto_data.tlv_vector_) {
117 0 : if (!pass_all_tlvs && !pass_through_tlvs.contains(tlv.type)) {
118 0 : continue;
119 0 : }
120 0 : extension_length += PROXY_PROTO_V2_TLV_TYPE_LENGTH_LEN + tlv.value.size();
121 0 : if (extension_length > std::numeric_limits<uint16_t>::max()) {
122 0 : ENVOY_LOG_MISC(
123 0 : warn, "Generating Proxy Protocol V2 header: TLVs exceed length limit {}, already got {}",
124 0 : std::numeric_limits<uint16_t>::max(), extension_length);
125 0 : return false;
126 0 : }
127 0 : }
128 :
129 0 : ASSERT(extension_length <= std::numeric_limits<uint16_t>::max());
130 0 : const auto& src = *proxy_proto_data.src_addr_->ip();
131 0 : const auto& dst = *proxy_proto_data.dst_addr_->ip();
132 0 : generateV2Header(src.addressAsString(), dst.addressAsString(), src.port(), dst.port(),
133 0 : src.version(), static_cast<uint16_t>(extension_length), out);
134 :
135 : // Generate the TLV vector.
136 0 : for (auto&& tlv : proxy_proto_data.tlv_vector_) {
137 0 : if (!pass_all_tlvs && !pass_through_tlvs.contains(tlv.type)) {
138 0 : continue;
139 0 : }
140 0 : out.add(&tlv.type, 1);
141 0 : uint16_t size = htons(static_cast<uint16_t>(tlv.value.size()));
142 0 : out.add(&size, sizeof(uint16_t));
143 0 : out.add(&tlv.value.front(), tlv.value.size());
144 0 : }
145 0 : return true;
146 0 : }
147 :
148 : void generateProxyProtoHeader(const envoy::config::core::v3::ProxyProtocolConfig& config,
149 0 : const Network::Connection& connection, Buffer::Instance& out) {
150 0 : const Network::Address::Ip& dest_address =
151 0 : *connection.connectionInfoProvider().localAddress()->ip();
152 0 : const Network::Address::Ip& source_address =
153 0 : *connection.connectionInfoProvider().remoteAddress()->ip();
154 0 : if (config.version() == envoy::config::core::v3::ProxyProtocolConfig::V1) {
155 0 : generateV1Header(source_address, dest_address, out);
156 0 : } else if (config.version() == envoy::config::core::v3::ProxyProtocolConfig::V2) {
157 0 : generateV2Header(source_address, dest_address, out);
158 0 : }
159 0 : }
160 :
161 0 : void generateV2LocalHeader(Buffer::Instance& out) {
162 0 : out.add(PROXY_PROTO_V2_SIGNATURE, PROXY_PROTO_V2_SIGNATURE_LEN);
163 0 : const uint8_t addr_fam_protocol_and_length[4]{PROXY_PROTO_V2_VERSION << 4, 0, 0, 0};
164 0 : out.add(addr_fam_protocol_and_length, 4);
165 0 : }
166 :
167 : } // namespace ProxyProtocol
168 : } // namespace Common
169 : } // namespace Extensions
170 : } // namespace Envoy
|