]>
git.ipfire.org Git - thirdparty/pdns.git/blob - contrib/ProtobufLogger.py
10 # run: protoc -I=../pdns/ --python_out=. ../pdns/dnsmessage.proto
11 # to generate dnsmessage_pb2
14 class PDNSPBConnHandler(object):
16 def __init__(self
, conn
):
21 data
= self
._conn
.recv(2)
24 (datalen
,) = struct
.unpack("!H", data
)
25 data
= self
._conn
.recv(datalen
)
27 msg
= dnsmessage_pb2
.PBDNSMessage()
28 msg
.ParseFromString(data
)
29 if msg
.type == dnsmessage_pb2
.PBDNSMessage
.DNSQueryType
:
30 self
.printQueryMessage(msg
)
31 elif msg
.type == dnsmessage_pb2
.PBDNSMessage
.DNSResponseType
:
32 self
.printResponseMessage(msg
)
33 elif msg
.type == dnsmessage_pb2
.PBDNSMessage
.DNSOutgoingQueryType
:
34 self
.printOutgoingQueryMessage(msg
)
35 elif msg
.type == dnsmessage_pb2
.PBDNSMessage
.DNSIncomingResponseType
:
36 self
.printIncomingResponseMessage(msg
)
38 print('Discarding unsupported message type %d' % (msg
.type))
42 def printQueryMessage(self
, message
):
43 self
.printSummary(message
, 'Query')
44 self
.printQuery(message
)
46 def printOutgoingQueryMessage(self
, message
):
47 self
.printSummary(message
, 'Query (O)')
48 self
.printQuery(message
)
50 def printResponseMessage(self
, message
):
51 self
.printSummary(message
, 'Response')
52 self
.printQuery(message
)
53 self
.printResponse(message
)
55 def printIncomingResponseMessage(self
, message
):
56 self
.printSummary(message
, 'Response (I)')
57 self
.printQuery(message
)
58 self
.printResponse(message
)
60 def printQuery(self
, message
):
61 if message
.HasField('question'):
63 if message
.question
.HasField('qClass'):
64 qclass
= message
.question
.qClass
65 print("- Question: %d, %d, %s" % (qclass
,
66 message
.question
.qType
,
67 message
.question
.qName
))
70 def getAppliedPolicyTypeAsString(polType
):
71 if polType
== dnsmessage_pb2
.PBDNSMessage
.UNKNOWN
:
73 elif polType
== dnsmessage_pb2
.PBDNSMessage
.QNAME
:
75 elif polType
== dnsmessage_pb2
.PBDNSMessage
.CLIENTIP
:
77 elif polType
== dnsmessage_pb2
.PBDNSMessage
.RESPONSEIP
:
79 elif polType
== dnsmessage_pb2
.PBDNSMessage
.NSDNAME
:
81 elif polType
== dnsmessage_pb2
.PBDNSMessage
.NSIP
:
84 def printResponse(self
, message
):
85 if message
.HasField('response'):
86 response
= message
.response
88 if response
.HasField('queryTimeSec'):
89 datestr
= datetime
.datetime
.fromtimestamp(response
.queryTimeSec
).strftime('%Y-%m-%d %H:%M:%S')
90 if response
.HasField('queryTimeUsec'):
91 datestr
= datestr
+ '.' + str(response
.queryTimeUsec
)
92 print("- Query time: %s" % (datestr
))
95 if response
.HasField('appliedPolicy') and response
.appliedPolicy
:
96 policystr
= ', Applied policy: ' + response
.appliedPolicy
97 if response
.HasField('appliedPolicyType'):
98 policystr
= policystr
+ ' (' + self
.getAppliedPolicyTypeAsString(response
.appliedPolicyType
) + ')'
102 tagsstr
= ', Tags: ' + ','.join(response
.tags
)
104 rrscount
= len(response
.rrs
)
106 print("- Response Code: %d, RRs: %d%s%s" % (response
.rcode
,
111 for rr
in response
.rrs
:
115 if rr
.HasField('class'):
116 rrclass
= getattr(rr
, 'class')
118 if rr
.HasField('udr'):
120 if (rrclass
== 1 or rrclass
== 255) and rr
.HasField('rdata'):
122 rdatastr
= socket
.inet_ntop(socket
.AF_INET
, rr
.rdata
)
126 rdatastr
= socket
.inet_ntop(socket
.AF_INET6
, rr
.rdata
)
128 print("\t - %d, %d, %s, %d, %s, %d" % (rrclass
,
135 def printSummary(self
, msg
, typestr
):
136 datestr
= datetime
.datetime
.fromtimestamp(msg
.timeSec
).strftime('%Y-%m-%d %H:%M:%S')
137 if msg
.HasField('timeUsec'):
138 datestr
= datestr
+ '.' + str(msg
.timeUsec
)
141 fromvalue
= getattr(msg
, 'from')
142 if msg
.socketFamily
== dnsmessage_pb2
.PBDNSMessage
.INET
:
143 if msg
.HasField('from'):
144 ipfromstr
= socket
.inet_ntop(socket
.AF_INET
, fromvalue
)
145 if msg
.HasField('to'):
146 iptostr
= socket
.inet_ntop(socket
.AF_INET
, msg
.to
)
148 if msg
.HasField('from'):
149 ipfromstr
= socket
.inet_ntop(socket
.AF_INET6
, fromvalue
)
150 if msg
.HasField('to'):
151 iptostr
= socket
.inet_ntop(socket
.AF_INET6
, msg
.to
)
153 if msg
.socketProtocol
== dnsmessage_pb2
.PBDNSMessage
.UDP
:
158 messageidstr
= binascii
.hexlify(bytearray(msg
.messageId
))
161 if msg
.HasField('serverIdentity'):
162 serveridstr
= msg
.serverIdentity
164 initialrequestidstr
= ''
165 if msg
.HasField('initialRequestId'):
166 initialrequestidstr
= ', initial uuid: %s ' % (binascii
.hexlify(bytearray(msg
.initialRequestId
)))
169 requestor
= self
.getRequestorSubnet(msg
)
171 requestorstr
= ' (' + requestor
+ ')'
173 deviceId
= binascii
.hexlify(bytearray(msg
.deviceId
))
174 requestorId
= msg
.requestorId
176 if (msg
.HasField('newlyObservedDomain')):
177 nod
= msg
.newlyObservedDomain
179 print('[%s] %s of size %d: %s%s -> %s (%s), id: %d, uuid: %s%s '
180 'requestorid: %s deviceid: %s serverid: %s nod: %d' % (datestr
,
195 def getRequestorSubnet(self
, msg
):
197 if msg
.HasField('originalRequestorSubnet'):
198 if len(msg
.originalRequestorSubnet
) == 4:
199 requestorstr
= socket
.inet_ntop(socket
.AF_INET
,
200 msg
.originalRequestorSubnet
)
201 elif len(msg
.originalRequestorSubnet
) == 16:
202 requestorstr
= socket
.inet_ntop(socket
.AF_INET6
,
203 msg
.originalRequestorSubnet
)
206 class PDNSPBListener(object):
208 def __init__(self
, addr
, port
):
209 res
= socket
.getaddrinfo(addr
, port
, socket
.AF_UNSPEC
,
210 socket
.SOCK_STREAM
, 0,
213 print("Error parsing the supplied address")
215 family
, socktype
, _
, _
, sockaddr
= res
[0]
216 self
._sock
= socket
.socket(family
, socktype
)
217 self
._sock
.setsockopt(socket
.SOL_SOCKET
, socket
.SO_REUSEPORT
, 1)
219 self
._sock
.bind(sockaddr
)
220 except socket
.error
as exp
:
221 print("Error while binding: %s" % str(exp
))
224 self
._sock
.listen(100)
228 (conn
, _
) = self
._sock
.accept()
230 handler
= PDNSPBConnHandler(conn
)
231 thread
= threading
.Thread(name
='Connection Handler',
232 target
=PDNSPBConnHandler
.run
,
234 thread
.setDaemon(True)
240 if __name__
== "__main__":
241 if len(sys
.argv
) != 3:
242 sys
.exit('Usage: %s <address> <port>' % (sys
.argv
[0]))
244 PDNSPBListener(sys
.argv
[1], sys
.argv
[2]).run()