From af7afecf7cd499c11173745da904f1de7db2bd34 Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Wed, 30 Jan 2019 16:58:04 +0100 Subject: [PATCH] dnsdist: Add IP 'encryption' options to RemoteLog{,Response}Action --- pdns/dnsdist-lua-actions.cc | 40 +++++++++++++++++++++---- pdns/dnsdistdist/docs/rules-actions.rst | 8 +++++ 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/pdns/dnsdist-lua-actions.cc b/pdns/dnsdist-lua-actions.cc index 55c7251e0..25d2dbbf0 100644 --- a/pdns/dnsdist-lua-actions.cc +++ b/pdns/dnsdist-lua-actions.cc @@ -19,6 +19,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "config.h" #include "threadname.hh" #include "dnsdist.hh" #include "dnsdist-ecs.hh" @@ -30,7 +31,12 @@ #include "ednsoptions.hh" #include "fstrm_logger.hh" #include "remote_logger.hh" -#include "boost/optional/optional_io.hpp" + +#include + +#ifdef HAVE_LIBCRYPTO +#include "ipcipher.hh" +#endif /* HAVE_LIBCRYPTO */ class DropAction : public DNSAction { @@ -771,7 +777,7 @@ private: class RemoteLogAction : public DNSAction, public boost::noncopyable { public: - RemoteLogAction(std::shared_ptr& logger, boost::optional > alterFunc, const std::string& serverID): d_logger(logger), d_alterFunc(alterFunc), d_serverID(serverID) + RemoteLogAction(std::shared_ptr& logger, boost::optional > alterFunc, const std::string& serverID, const std::string& ipEncryptKey): d_logger(logger), d_alterFunc(alterFunc), d_serverID(serverID), d_ipEncryptKey(ipEncryptKey) { } DNSAction::Action operator()(DNSQuestion* dq, string* ruleresult) const override @@ -786,6 +792,13 @@ public: message.setServerIdentity(d_serverID); } +#if HAVE_LIBCRYPTO + if (!d_ipEncryptKey.empty()) + { + message.setRequestor(encryptCA(*dq->remote, d_ipEncryptKey)); + } +#endif /* HAVE_LIBCRYPTO */ + if (d_alterFunc) { std::lock_guard lock(g_luamutex); (*d_alterFunc)(*dq, &message); @@ -805,6 +818,7 @@ private: std::shared_ptr d_logger; boost::optional > d_alterFunc; std::string d_serverID; + std::string d_ipEncryptKey; }; class SNMPTrapAction : public DNSAction @@ -891,7 +905,7 @@ private: class RemoteLogResponseAction : public DNSResponseAction, public boost::noncopyable { public: - RemoteLogResponseAction(std::shared_ptr& logger, boost::optional > alterFunc, const std::string& serverID, bool includeCNAME): d_logger(logger), d_alterFunc(alterFunc), d_serverID(serverID), d_includeCNAME(includeCNAME) + RemoteLogResponseAction(std::shared_ptr& logger, boost::optional > alterFunc, const std::string& serverID, const std::string& ipEncryptKey, bool includeCNAME): d_logger(logger), d_alterFunc(alterFunc), d_serverID(serverID), d_ipEncryptKey(ipEncryptKey), d_includeCNAME(includeCNAME) { } DNSResponseAction::Action operator()(DNSResponse* dr, string* ruleresult) const override @@ -906,6 +920,13 @@ public: message.setServerIdentity(d_serverID); } +#if HAVE_LIBCRYPTO + if (!d_ipEncryptKey.empty()) + { + message.setRequestor(encryptCA(*dr->remote, d_ipEncryptKey)); + } +#endif /* HAVE_LIBCRYPTO */ + if (d_alterFunc) { std::lock_guard lock(g_luamutex); (*d_alterFunc)(*dr, &message); @@ -925,6 +946,7 @@ private: std::shared_ptr d_logger; boost::optional > d_alterFunc; std::string d_serverID; + std::string d_ipEncryptKey; bool d_includeCNAME; }; @@ -1221,14 +1243,18 @@ void setupLuaActions() } std::string serverID; + std::string ipEncryptKey; if (vars) { if (vars->count("serverID")) { serverID = boost::get((*vars)["serverID"]); } + if (vars->count("ipEncryptKey")) { + ipEncryptKey = boost::get((*vars)["ipEncryptKey"]); + } } #ifdef HAVE_PROTOBUF - return std::shared_ptr(new RemoteLogAction(logger, alterFunc, serverID)); + return std::shared_ptr(new RemoteLogAction(logger, alterFunc, serverID, ipEncryptKey)); #else throw std::runtime_error("Protobuf support is required to use RemoteLogAction"); #endif @@ -1243,14 +1269,18 @@ void setupLuaActions() } std::string serverID; + std::string ipEncryptKey; if (vars) { if (vars->count("serverID")) { serverID = boost::get((*vars)["serverID"]); } + if (vars->count("ipEncryptKey")) { + ipEncryptKey = boost::get((*vars)["ipEncryptKey"]); + } } #ifdef HAVE_PROTOBUF - return std::shared_ptr(new RemoteLogResponseAction(logger, alterFunc, serverID, includeCNAME ? *includeCNAME : false)); + return std::shared_ptr(new RemoteLogResponseAction(logger, alterFunc, serverID, ipEncryptKey, includeCNAME ? *includeCNAME : false)); #else throw std::runtime_error("Protobuf support is required to use RemoteLogResponseAction"); #endif diff --git a/pdns/dnsdistdist/docs/rules-actions.rst b/pdns/dnsdistdist/docs/rules-actions.rst index 36d8b3a55..b23b03f75 100644 --- a/pdns/dnsdistdist/docs/rules-actions.rst +++ b/pdns/dnsdistdist/docs/rules-actions.rst @@ -963,6 +963,9 @@ The following actions exist. .. versionchanged:: 1.3.0 ``options`` optional parameter added. + .. versionchanged:: 1.3.4 + ``ipEncryptKey`` optional key added to the options table. + Send the content of this query to a remote logger via Protocol Buffer. ``alterFunction`` is a callback, receiving a :class:`DNSQuestion` and a :class:`DNSDistProtoBufMessage`, that can be used to modify the Protocol Buffer content, for example for anonymization purposes @@ -973,12 +976,16 @@ The following actions exist. Options: * ``serverID=""``: str - Set the Server Identity field. + * ``ipEncryptKey=""``: str - A key, that can be generated via the :ref:`makeIPCipherKey` function, to encrypt the IP address of the requestor for anonymization purposes. The encryption is done using ipcrypt for IPv4 and a 128-bit AES ECB operation for IPv6. .. function:: RemoteLogResponseAction(remoteLogger[, alterFunction[, includeCNAME [, options]]]) .. versionchanged:: 1.3.0 ``options`` optional parameter added. + .. versionchanged:: 1.3.4 + ``ipEncryptKey`` optional key added to the options table. + Send the content of this response to a remote logger via Protocol Buffer. ``alterFunction`` is the same callback that receiving a :class:`DNSQuestion` and a :class:`DNSDistProtoBufMessage`, that can be used to modify the Protocol Buffer content, for example for anonymization purposes ``includeCNAME`` indicates whether CNAME records inside the response should be parsed and exported. @@ -992,6 +999,7 @@ The following actions exist. Options: * ``serverID=""``: str - Set the Server Identity field. + * ``ipEncryptKey=""``: str - A key, that can be generated via the :ref:`makeIPCipherKey` function, to encrypt the IP address of the requestor for anonymization purposes. The encryption is done using ipcrypt for IPv4 and a 128-bit AES ECB operation for IPv6. .. function:: SetECSAction(v4 [, v6]) -- 2.40.0