You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by zw...@apache.org on 2018/02/12 05:05:48 UTC
[trafficserver] branch master updated: Adds a new header_rewrite
condition %{CIDR}
This is an automated email from the ASF dual-hosted git repository.
zwoop 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 f14efb4 Adds a new header_rewrite condition %{CIDR}
f14efb4 is described below
commit f14efb4fe11e4751a042c39a7e931f5745148e88
Author: Leif Hedstrom <zw...@apache.org>
AuthorDate: Fri Feb 9 22:22:35 2018 -0700
Adds a new header_rewrite condition %{CIDR}
This can be used to produced a header (typically an @ header) which
can then be used in a custom log format to anonymize the client IP
address. But, one could for example put this into a header that gets
sent to the Origin server as well, again anonymized.
---
doc/admin-guide/plugins/header_rewrite.en.rst | 33 +++++++++
plugins/header_rewrite/conditions.cc | 99 +++++++++++++++++++++++++++
plugins/header_rewrite/conditions.h | 32 +++++++++
plugins/header_rewrite/factory.cc | 2 +
4 files changed, 166 insertions(+)
diff --git a/doc/admin-guide/plugins/header_rewrite.en.rst b/doc/admin-guide/plugins/header_rewrite.en.rst
index 8275853..ef0d38e 100644
--- a/doc/admin-guide/plugins/header_rewrite.en.rst
+++ b/doc/admin-guide/plugins/header_rewrite.en.rst
@@ -288,6 +288,39 @@ arguments to another operator. For example::
set-header ATS-Req-UUID %{ID:UNIQUE}
+CIDR
+~~
+::
+
+ set-header @Client-CIDR %{CIDR:24,48}
+
+This condition takes the client IP, and applies the provided CIDR style masks
+to the IP, before producing a string. The typical use of this conditions is as
+above, producing a header that contains a IP representation which has some
+privacy properties. It can of course also be used as a regular condition, and
+the output is a string that can be compared against. The two optional
+arguments are as follows:
+
+ IPv4-Mask Length, in bits, of the IPv4 address to preserve. Default: 24
+ IPv6-Mask Length, in bits, of the IPv6 address to preserve. Default: 48
+
+The two arguments, if provided, are comma separated. Valid syntax includes
+
+ %{CIDR} Defaults to 24,48 (as above)
+ %{CIDR:16} IPv4 CIDR mask is 16 bits, IPv6 mask is 48
+ %{CIDR:18,42} IPv4 CIDR mask is 18 bits, IPv6 mask is 42 bits
+
+A typical use case is to insert the @-prefixed header as above, and then use
+this header in a custom log format, rather than logging the full client
+IP. Another use case could be to make a special condition on a sub-net,
+e.g. ::
+
+ cond %{CIDR:8} ="8.0.0.0"
+ set-header X-Is-Eight "Yes"
+
+This condition has no requirements other than access to the Client IP, hence,
+it should work in any and all hooks.
+
INBOUND
~~~~~~~
::
diff --git a/plugins/header_rewrite/conditions.cc b/plugins/header_rewrite/conditions.cc
index b316fca..75fec11 100644
--- a/plugins/header_rewrite/conditions.cc
+++ b/plugins/header_rewrite/conditions.cc
@@ -1185,6 +1185,105 @@ ConditionId::eval(const Resources &res)
}
void
+ConditionCidr::initialize(Parser &p)
+{
+ Condition::initialize(p);
+
+ MatcherType *match = new MatcherType(_cond_op);
+
+ match->set(p.get_arg());
+ _matcher = match;
+}
+
+void
+ConditionCidr::set_qualifier(const std::string &q)
+{
+ bool ok = true;
+ int cidr;
+ char *endp;
+
+ Condition::set_qualifier(q);
+
+ TSDebug(PLUGIN_NAME, "\tParsing %%{CIDR:%s} qualifier", q.c_str());
+ cidr = strtol(q.c_str(), &endp, 10);
+ if (cidr >= 0 && cidr <= 32) {
+ _v4_mask.s_addr = UINT32_MAX >> (32 - cidr);
+ _v4_cidr = cidr;
+ if (endp && (*endp == ',' || *endp == '/' || *endp == ':')) {
+ cidr = strtol(endp + 1, nullptr, 10);
+ if (cidr >= 0 && cidr <= 128) {
+ _v6_cidr = cidr;
+ } else {
+ TSError("[%s] Bad CIDR mask for IPv6: %s", PLUGIN_NAME, q.c_str());
+ ok = false;
+ }
+ }
+ } else {
+ TSError("[%s] Bad CIDR mask for IPv4: %s", PLUGIN_NAME, q.c_str());
+ ok = false;
+ }
+
+ // Update the bit-masks
+ if (ok) {
+ _create_masks();
+ }
+}
+
+bool
+ConditionCidr::eval(const Resources &res)
+{
+ std::string s;
+
+ append_value(s, res);
+ TSDebug(PLUGIN_NAME, "Evaluating CIDR()");
+
+ return static_cast<MatcherType *>(_matcher)->test(s);
+}
+
+void
+ConditionCidr::append_value(std::string &s, const Resources &res)
+{
+ struct sockaddr const *addr = TSHttpTxnClientAddrGet(res.txnp);
+
+ switch (addr->sa_family) {
+ case AF_INET: {
+ char res[INET_ADDRSTRLEN];
+ struct in_addr ipv4 = reinterpret_cast<const struct sockaddr_in *>(addr)->sin_addr;
+
+ ipv4.s_addr &= _v4_mask.s_addr;
+ inet_ntop(AF_INET, &ipv4, res, INET_ADDRSTRLEN);
+ if (res[0]) {
+ s += res;
+ }
+ } break;
+ case AF_INET6: {
+ char res[INET6_ADDRSTRLEN];
+ struct in6_addr ipv6 = reinterpret_cast<const struct sockaddr_in6 *>(addr)->sin6_addr;
+
+ if (_v6_zero_bytes > 0) {
+ memset(&ipv6.s6_addr[16 - _v6_zero_bytes], 0, _v6_zero_bytes);
+ }
+ if (_v6_mask != 0xff) {
+ ipv6.s6_addr[16 - _v6_zero_bytes] &= _v6_mask;
+ }
+ inet_ntop(AF_INET6, &ipv6, res, INET6_ADDRSTRLEN);
+ if (res[0]) {
+ s += res;
+ }
+ } break;
+ }
+}
+
+// Little helper function, to create the masks
+void
+ConditionCidr::_create_masks()
+{
+ _v4_mask.s_addr = htonl(UINT32_MAX << (32 - _v4_cidr));
+ _v6_zero_bytes = (128 - _v6_cidr) / 8;
+ _v6_mask = 0xff >> ((128 - _v6_cidr) % 8);
+}
+
+void
ConditionInbound::initialize(Parser &p)
{
Condition::initialize(p);
diff --git a/plugins/header_rewrite/conditions.h b/plugins/header_rewrite/conditions.h
index 2119b4b..a5c2db7 100644
--- a/plugins/header_rewrite/conditions.h
+++ b/plugins/header_rewrite/conditions.h
@@ -498,6 +498,38 @@ private:
IdQualifiers _id_qual;
};
+// cidr: A CIDR masked string representation of the Client's IP.
+class ConditionCidr : public Condition
+{
+ using MatcherType = Matchers<std::string>;
+ using self = ConditionCidr;
+
+public:
+ explicit ConditionCidr()
+ {
+ _create_masks(); // This must be called here, because we might not have parameters specified
+ TSDebug(PLUGIN_NAME_DBG, "Calling CTOR for ConditionCidr");
+ };
+
+ ConditionCidr(self &) = delete;
+ self &operator=(self &) = delete;
+
+ void initialize(Parser &p);
+ void set_qualifier(const std::string &q);
+ void append_value(std::string &s, const Resources &res);
+
+protected:
+ bool eval(const Resources &res);
+
+private:
+ void _create_masks();
+ int _v4_cidr = 24;
+ int _v6_cidr = 48;
+ struct in_addr _v4_mask; // We do a 32-bit & using this mask, for efficiency
+ unsigned char _v6_mask; // Only need one byte here, since we memset the rest (see next)
+ int _v6_zero_bytes; // How many initial bytes to memset to 0
+};
+
/// Information about the inbound (client) session.
class ConditionInbound : public Condition
{
diff --git a/plugins/header_rewrite/factory.cc b/plugins/header_rewrite/factory.cc
index 28defb7..2600471 100644
--- a/plugins/header_rewrite/factory.cc
+++ b/plugins/header_rewrite/factory.cc
@@ -141,6 +141,8 @@ condition_factory(const std::string &cond)
c = new ConditionGeo();
} else if (c_name == "ID") {
c = new ConditionId();
+ } else if (c_name == "CIDR") {
+ c = new ConditionCidr();
} else if (c_name == "INBOUND") {
c = new ConditionInbound();
} else {
--
To stop receiving notification emails like this one, please contact
zwoop@apache.org.