Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for identifying devices by id such as mac address #5646

Merged
merged 5 commits into from Aug 29, 2017
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
24 changes: 14 additions & 10 deletions contrib/ProtobufLogger.py
Expand Up @@ -144,16 +144,20 @@ def printSummary(self, msg, typestr):
if requestor:
requestorstr = ' (' + requestor + ')'

print('[%s] %s of size %d: %s%s -> %s (%s), id: %d, uuid: %s%s' % (datestr,
typestr,
msg.inBytes,
ipfromstr,
requestorstr,
iptostr,
protostr,
msg.id,
messageidstr,
initialrequestidstr))
deviceId = binascii.hexlify(bytearray(msg.deviceId))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if msg.deviceId is empty?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

python protobuf returns empty python string

requestorId = msg.requestorId

print('[%s] %s of size %d: %s%s -> %s (%s), id: %d, uuid: %s%s '
'requestorid: %s deviceid: %s' % (datestr,
typestr,
msg.inBytes,
ipfromstr,
requestorstr,
iptostr,
protostr,
msg.id,
messageidstr,
initialrequestidstr))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

requestorid and deviceid are missing in this parameter list

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[2017-08-28 16:46:49.461187] Response of size 50: 127.0.0.1 -> 127.0.0.1 (UDP), id: 47036, uuid: f2b4bcba0b144a09b9a49b234770f142 requestorid: pietje deviceid: 414243444546

With:

-                                                    initialrequestidstr))
+                                                    initialrequestidstr, requestorId, deviceId))


def getRequestorSubnet(self, msg):
requestorstr = None
Expand Down
1 change: 1 addition & 0 deletions pdns/dnsmessage.proto
Expand Up @@ -75,4 +75,5 @@ message PBDNSMessage {
optional bytes originalRequestorSubnet = 14; // EDNS Client Subnet value
optional string requestorId = 15; // Username of the requestor
optional bytes initialRequestId = 16; // UUID of the incoming query that initiated this outgoing query or incoming response
optional bytes deviceId = 17; // Device ID of the requestor (could be mac address IP address or e.g. IMEI)
}
6 changes: 5 additions & 1 deletion pdns/lua-recursor4.cc
Expand Up @@ -597,7 +597,7 @@ bool RecursorLua4::ipfilter(const ComboAddress& remote, const ComboAddress& loca
return false; // don't block
}

unsigned int RecursorLua4::gettag(const ComboAddress& remote, const Netmask& ednssubnet, const ComboAddress& local, const DNSName& qname, uint16_t qtype, std::vector<std::string>* policyTags, LuaContext::LuaObject& data, const std::map<uint16_t, EDNSOptionView>& ednsOptions, bool tcp, std::string& requestorId)
unsigned int RecursorLua4::gettag(const ComboAddress& remote, const Netmask& ednssubnet, const ComboAddress& local, const DNSName& qname, uint16_t qtype, std::vector<std::string>* policyTags, LuaContext::LuaObject& data, const std::map<uint16_t, EDNSOptionView>& ednsOptions, bool tcp, std::string& requestorId, std::string& deviceId)
{
if(d_gettag) {
auto ret = d_gettag(remote, ednssubnet, local, qname, qtype, ednsOptions, tcp);
Expand All @@ -618,6 +618,10 @@ unsigned int RecursorLua4::gettag(const ComboAddress& remote, const Netmask& edn
if (reqIdret) {
requestorId = *reqIdret;
}
const auto deviceIdret = std::get<4>(ret);
if (deviceIdret) {
deviceId = *deviceIdret;
}
return std::get<0>(ret);
}
return 0;
Expand Down
5 changes: 3 additions & 2 deletions pdns/lua-recursor4.hh
Expand Up @@ -71,6 +71,7 @@ public:
std::vector<std::string>* policyTags{nullptr};
std::unordered_map<std::string,bool>* discardedPolicies{nullptr};
std::string requestorId;
std::string deviceId;
bool& variable;
bool& wantsRPZ;
unsigned int tag{0};
Expand Down Expand Up @@ -102,7 +103,7 @@ public:
DNSName followupName;
};

unsigned int gettag(const ComboAddress& remote, const Netmask& ednssubnet, const ComboAddress& local, const DNSName& qname, uint16_t qtype, std::vector<std::string>* policyTags, LuaContext::LuaObject& data, const std::map<uint16_t, EDNSOptionView>&, bool tcp, std::string& requestorId);
unsigned int gettag(const ComboAddress& remote, const Netmask& ednssubnet, const ComboAddress& local, const DNSName& qname, uint16_t qtype, std::vector<std::string>* policyTags, LuaContext::LuaObject& data, const std::map<uint16_t, EDNSOptionView>&, bool tcp, std::string& requestorId, std::string& deviceId);

bool prerpz(DNSQuestion& dq, int& ret);
bool preresolve(DNSQuestion& dq, int& ret);
Expand All @@ -122,7 +123,7 @@ public:
d_postresolve);
}

typedef std::function<std::tuple<unsigned int,boost::optional<std::unordered_map<int,string> >,boost::optional<LuaContext::LuaObject>,boost::optional<std::string> >(ComboAddress, Netmask, ComboAddress, DNSName, uint16_t, const std::map<uint16_t, EDNSOptionView>&, bool)> gettag_t;
typedef std::function<std::tuple<unsigned int,boost::optional<std::unordered_map<int,string> >,boost::optional<LuaContext::LuaObject>,boost::optional<std::string>,boost::optional<std::string> >(ComboAddress, Netmask, ComboAddress, DNSName, uint16_t, const std::map<uint16_t, EDNSOptionView>&, bool)> gettag_t;
gettag_t d_gettag; // public so you can query if we have this hooked

private:
Expand Down
19 changes: 14 additions & 5 deletions pdns/pdns_recursor.cc
Expand Up @@ -206,6 +206,7 @@ struct DNSComboWriter {
#ifdef HAVE_PROTOBUF
boost::uuids::uuid d_uuid;
string d_requestorId;
string d_deviceId;
#endif
EDNSSubnetOpts d_ednssubnet;
bool d_ecsFound{false};
Expand Down Expand Up @@ -647,13 +648,14 @@ catch(...)
}

#ifdef HAVE_PROTOBUF
static void protobufLogQuery(const std::shared_ptr<RemoteLogger>& logger, uint8_t maskV4, uint8_t maskV6, const boost::uuids::uuid& uniqueId, const ComboAddress& remote, const ComboAddress& local, const Netmask& ednssubnet, bool tcp, uint16_t id, size_t len, const DNSName& qname, uint16_t qtype, uint16_t qclass, const std::vector<std::string>& policyTags, const std::string& requestorId)
static void protobufLogQuery(const std::shared_ptr<RemoteLogger>& logger, uint8_t maskV4, uint8_t maskV6, const boost::uuids::uuid& uniqueId, const ComboAddress& remote, const ComboAddress& local, const Netmask& ednssubnet, bool tcp, uint16_t id, size_t len, const DNSName& qname, uint16_t qtype, uint16_t qclass, const std::vector<std::string>& policyTags, const std::string& requestorId, const std::string& deviceId)
{
Netmask requestorNM(remote, remote.sin4.sin_family == AF_INET ? maskV4 : maskV6);
const ComboAddress& requestor = requestorNM.getMaskedNetwork();
RecProtoBufMessage message(DNSProtoBufMessage::Query, uniqueId, &requestor, &local, qname, qtype, qclass, id, tcp, len);
message.setEDNSSubnet(ednssubnet, ednssubnet.isIpv4() ? maskV4 : maskV6);
message.setRequestorId(requestorId);
message.setDeviceId(deviceId);

if (!policyTags.empty()) {
message.setPolicyTags(policyTags);
Expand Down Expand Up @@ -816,6 +818,7 @@ static void startDoResolve(void *p)
dq.data = dc->d_data;
#ifdef HAVE_PROTOBUF
dq.requestorId = dc->d_requestorId;
dq.deviceId = dc->d_deviceId;
#endif

if(dc->d_mdp.d_qtype==QType::ANY && !dc->d_tcp && g_anyToTcp) {
Expand Down Expand Up @@ -1150,6 +1153,7 @@ static void startDoResolve(void *p)
pbMessage.setPolicyTags(dc->d_policyTags);
pbMessage.setQueryTime(dc->d_now.tv_sec, dc->d_now.tv_usec);
pbMessage.setRequestorId(dq.requestorId);
pbMessage.setDeviceId(dq.deviceId);
protobufLogResponse(luaconfsLocal->protobufServer, pbMessage);
}
#endif
Expand Down Expand Up @@ -1416,6 +1420,7 @@ static void handleRunningTCPQuestion(int fd, FDMultiplexer::funcparam_t& var)
uint16_t qclass=0;
bool needECS = false;
string requestorId;
string deviceId;
#ifdef HAVE_PROTOBUF
auto luaconfsLocal = g_luaconfs.getLocal();
if (luaconfsLocal->protobufServer) {
Expand All @@ -1432,7 +1437,7 @@ static void handleRunningTCPQuestion(int fd, FDMultiplexer::funcparam_t& var)

if(t_pdl && t_pdl->d_gettag) {
try {
dc->d_tag = t_pdl->gettag(conn->d_remote, dc->d_ednssubnet.source, dest, qname, qtype, &dc->d_policyTags, dc->d_data, ednsOptions, true, requestorId);
dc->d_tag = t_pdl->gettag(conn->d_remote, dc->d_ednssubnet.source, dest, qname, qtype, &dc->d_policyTags, dc->d_data, ednsOptions, true, requestorId, deviceId);
}
catch(std::exception& e) {
if(g_logCommonErrors)
Expand All @@ -1449,6 +1454,7 @@ static void handleRunningTCPQuestion(int fd, FDMultiplexer::funcparam_t& var)
#ifdef HAVE_PROTOBUF
if(luaconfsLocal->protobufServer || luaconfsLocal->outgoingProtobufServer) {
dc->d_requestorId = requestorId;
dc->d_deviceId = deviceId;
dc->d_uuid = (*t_uuidGenerator)();
}

Expand All @@ -1457,7 +1463,7 @@ static void handleRunningTCPQuestion(int fd, FDMultiplexer::funcparam_t& var)
const struct dnsheader* dh = (const struct dnsheader*) conn->data;

if (!luaconfsLocal->protobufTaggedOnly) {
protobufLogQuery(luaconfsLocal->protobufServer, luaconfsLocal->protobufMaskV4, luaconfsLocal->protobufMaskV6, dc->d_uuid, conn->d_remote, dest, dc->d_ednssubnet.source, true, dh->id, conn->qlen, qname, qtype, qclass, dc->d_policyTags, dc->d_requestorId);
protobufLogQuery(luaconfsLocal->protobufServer, luaconfsLocal->protobufMaskV4, luaconfsLocal->protobufMaskV6, dc->d_uuid, conn->d_remote, dest, dc->d_ednssubnet.source, true, dh->id, conn->qlen, qname, qtype, qclass, dc->d_policyTags, dc->d_requestorId, dc->d_deviceId);
}
}
catch(std::exception& e) {
Expand Down Expand Up @@ -1567,6 +1573,7 @@ static string* doProcessUDPQuestion(const std::string& question, const ComboAddr
std::vector<std::string> policyTags;
LuaContext::LuaObject data;
string requestorId;
string deviceId;
#ifdef HAVE_PROTOBUF
boost::uuids::uuid uniqueId;
auto luaconfsLocal = g_luaconfs.getLocal();
Expand Down Expand Up @@ -1607,7 +1614,7 @@ static string* doProcessUDPQuestion(const std::string& question, const ComboAddr

if(t_pdl && t_pdl->d_gettag) {
try {
ctag=t_pdl->gettag(fromaddr, ednssubnet.source, destaddr, qname, qtype, &policyTags, data, ednsOptions, false, requestorId);
ctag=t_pdl->gettag(fromaddr, ednssubnet.source, destaddr, qname, qtype, &policyTags, data, ednsOptions, false, requestorId, deviceId);
}
catch(std::exception& e) {
if(g_logCommonErrors)
Expand All @@ -1627,7 +1634,7 @@ static string* doProcessUDPQuestion(const std::string& question, const ComboAddr
#ifdef HAVE_PROTOBUF
if(luaconfsLocal->protobufServer) {
if (!luaconfsLocal->protobufTaggedOnly || !policyTags.empty()) {
protobufLogQuery(luaconfsLocal->protobufServer, luaconfsLocal->protobufMaskV4, luaconfsLocal->protobufMaskV6, uniqueId, fromaddr, destaddr, ednssubnet.source, false, dh->id, question.size(), qname, qtype, qclass, policyTags, requestorId);
protobufLogQuery(luaconfsLocal->protobufServer, luaconfsLocal->protobufMaskV4, luaconfsLocal->protobufMaskV6, uniqueId, fromaddr, destaddr, ednssubnet.source, false, dh->id, question.size(), qname, qtype, qclass, policyTags, requestorId, deviceId);
}
}
#endif /* HAVE_PROTOBUF */
Expand All @@ -1648,6 +1655,7 @@ static string* doProcessUDPQuestion(const std::string& question, const ComboAddr
pbMessage.setEDNSSubnet(ednssubnet.source, ednssubnet.source.isIpv4() ? luaconfsLocal->protobufMaskV4 : luaconfsLocal->protobufMaskV6);
pbMessage.setQueryTime(g_now.tv_sec, g_now.tv_usec);
pbMessage.setRequestorId(requestorId);
pbMessage.setDeviceId(deviceId);
protobufLogResponse(luaconfsLocal->protobufServer, pbMessage);
}
#endif /* HAVE_PROTOBUF */
Expand Down Expand Up @@ -1718,6 +1726,7 @@ static string* doProcessUDPQuestion(const std::string& question, const ComboAddr
dc->d_uuid = uniqueId;
}
dc->d_requestorId = requestorId;
dc->d_deviceId = deviceId;
#endif

MT->makeThread(startDoResolve, (void*) dc); // deletes dc
Expand Down
7 changes: 7 additions & 0 deletions pdns/protobuf.cc
Expand Up @@ -236,6 +236,13 @@ void DNSProtoBufMessage::setRequestorId(const std::string& requestorId)
#endif /* HAVE_PROTOBUF */
}

void DNSProtoBufMessage::setDeviceId(const std::string& deviceId)
{
#ifdef HAVE_PROTOBUF
d_message.set_deviceid(deviceId);
#endif /* HAVE_PROTOBUF */
}

void DNSProtoBufMessage::setResponder(const std::string& responder)
{
#ifdef HAVE_PROTOBUF
Expand Down
1 change: 1 addition & 0 deletions pdns/protobuf.hh
Expand Up @@ -69,6 +69,7 @@ public:
void setResponder(const std::string& responder);
void setResponder(const ComboAddress& responder);
void setRequestorId(const std::string& requestorId);
void setDeviceId(const std::string& deviceId);
std::string toDebugString() const;
void addTag(const std::string& strValue);
void addRR(const DNSName& qame, uint16_t utype, uint16_t uClass, uint32_t uTTl, const std::string& strBlob);
Expand Down
6 changes: 6 additions & 0 deletions pdns/recursordist/docs/lua-scripting/dq.rst
Expand Up @@ -101,6 +101,12 @@ The DNSQuestion object contains at least the following fields:

A string that will be used to set the ``requestorId`` field in :doc:`protobuf <../lua-config/protobuf>` messages.

.. attribute:: DNSQuestion.deviceId str

.. versionadded:: 4.1.0

A string that will be used to set the ``deviceId`` field in :doc:`protobuf <../lua-config/protobuf>` messages.

.. attribute:: DNSQuestion.udpAnswer -> str

Answer to the :attr:`udpQuery <DNSQuestion.udpQuery>` when when using the ``udpQueryResponse`` :attr:`followupFunction <DNSQuestion.followupFunction>`.
Expand Down
2 changes: 1 addition & 1 deletion pdns/recursordist/docs/lua-scripting/hooks.rst
Expand Up @@ -68,7 +68,7 @@ Interception Functions

.. versionadded:: 4.1.0

It can also return a table whose keys and values are strings to fill the :attr:`DNSQuestion.data` table, as well as a ``requestorId`` value to fill the :attr:`DNSQuestion.requestorId` field.
It can also return a table whose keys and values are strings to fill the :attr:`DNSQuestion.data` table, as well as a ``requestorId`` value to fill the :attr:`DNSQuestion.requestorId` field and a ``deviceId`` value to fill the :attr:`DNSQuestion.deviceId` field.

The tagged packetcache can e.g. be used to answer queries from cache that have e.g. been filtered for certain IPs (this logic should be implemented in :func:`gettag`).
This ensure that queries are answered quickly compared to setting :attr:`dq.variable <DNSQuestion.variable>` to true.
Expand Down