1
#include "source/extensions/http/original_ip_detection/xff/xff.h"
2

            
3
#include "source/common/http/utility.h"
4
#include "source/common/network/cidr_range.h"
5

            
6
namespace Envoy {
7
namespace Extensions {
8
namespace Http {
9
namespace OriginalIPDetection {
10
namespace Xff {
11

            
12
absl::StatusOr<std::unique_ptr<XffIPDetection>> XffIPDetection::create(
13
9965
    const envoy::extensions::http::original_ip_detection::xff::v3::XffConfig& config) {
14

            
15
9965
  if (config.has_xff_trusted_cidrs() && config.xff_num_trusted_hops() > 0) {
16
1
    return absl::InvalidArgumentError("Cannot set both xff_num_trusted_hops and xff_trusted_cidrs");
17
1
  }
18
9964
  return std::unique_ptr<XffIPDetection>(new XffIPDetection(config));
19
9965
}
20

            
21
XffIPDetection::XffIPDetection(
22
    const envoy::extensions::http::original_ip_detection::xff::v3::XffConfig& config)
23
9964
    : xff_num_trusted_hops_(config.xff_num_trusted_hops()),
24
9964
      skip_xff_append_(PROTOBUF_GET_WRAPPED_OR_DEFAULT(config, skip_xff_append, true)) {
25
9964
  if (config.has_xff_trusted_cidrs()) {
26
7
    xff_trusted_cidrs_.reserve(config.xff_trusted_cidrs().cidrs().size());
27
21
    for (const envoy::config::core::v3::CidrRange& entry : config.xff_trusted_cidrs().cidrs()) {
28
21
      absl::StatusOr<Network::Address::CidrRange> cidr_or_error =
29
21
          Network::Address::CidrRange::create(entry);
30
21
      if (cidr_or_error.ok()) {
31
21
        xff_trusted_cidrs_.push_back(cidr_or_error.value());
32
21
      }
33
21
    }
34
7
  }
35
9964
}
36

            
37
XffIPDetection::XffIPDetection(uint32_t xff_num_trusted_hops, bool skip_xff_append)
38
377
    : xff_num_trusted_hops_(xff_num_trusted_hops), skip_xff_append_(skip_xff_append) {}
39

            
40
XffIPDetection::XffIPDetection(const std::vector<Network::Address::CidrRange> trusted_cidrs,
41
                               bool skip_xff_append)
42
6
    : xff_num_trusted_hops_(0), xff_trusted_cidrs_(trusted_cidrs),
43
6
      skip_xff_append_(skip_xff_append) {}
44

            
45
Envoy::Http::OriginalIPDetectionResult
46
89367
XffIPDetection::detect(Envoy::Http::OriginalIPDetectionParams& params) {
47
89367
  if (!xff_trusted_cidrs_.empty()) {
48
13
    if (!Envoy::Http::Utility::remoteAddressIsTrustedProxy(*params.downstream_remote_address.get(),
49
13
                                                           xff_trusted_cidrs_)) {
50
2
      return {nullptr, false, absl::nullopt, false};
51
2
    }
52
    // Check XFF for last IP that isn't in `xff_trusted_cidrs`
53
11
    auto ret = Envoy::Http::Utility::getLastNonTrustedAddressFromXFF(params.request_headers,
54
11
                                                                     xff_trusted_cidrs_);
55
11
    return {ret.address_, ret.allow_trusted_address_checks_, absl::nullopt, skip_xff_append_};
56
13
  }
57

            
58
89354
  auto ret =
59
89354
      Envoy::Http::Utility::getLastAddressFromXFF(params.request_headers, xff_num_trusted_hops_);
60
89354
  return {ret.address_, ret.allow_trusted_address_checks_, absl::nullopt, skip_xff_append_};
61
89367
}
62

            
63
} // namespace Xff
64
} // namespace OriginalIPDetection
65
} // namespace Http
66
} // namespace Extensions
67
} // namespace Envoy