Unbound DNS Server, Python module: inspect response message elements -
goal
i leverage unbound python module examine response before it's dispatched client. primarily, i'm interested in ;; answer section:
, i.e. ip address query got resolved to.
problem
what had looked trivial modification of logdnsmsg function turned out dounting task of browsing reply_info
, rrset_ref
, ub_packed_rrset_key
structures in pursuit of desired ;; answer section:
bytes.
the reason logdnsmsg function not work expected a
queries ;; answer section:
, while suprisingly operates expected ;; authority section:
on aaaa
queries.
lemme demonstrate comparison between python implemented logdnsmsg function , native log_dns_msg function; former displaying gibberish , latter performing expected. both functions called within python module context follows:
+++ def operate(id, event, qstate, qdata): log_info("pythonmod: operate called, id: %d, event:%s" % (id, strmodulevent(event))) if (qstate.return_msg): logdnsmsg(qstate) log_dns_msg("blackpie karmmmmmm xxxxxxx", qstate.return_msg.qinfo, qstate.return_msg.rep) +++
note altered original logdnsmsg uses logging framework in favour of print
. output same print
being scattered across logfile @ buffer's discretion.
dig
output:
karm@localhost:~$ dig seznam.cz @127.0.0.1 -p53535 ; <<>> dig 9.9.4-p2-redhat-9.9.4-18.p2.fc20 <<>> seznam.cz @127.0.0.1 -p53535 ;; global options: +cmd ;; got answer: ;; ->>header<<- opcode: query, status: noerror, id: 38630 ;; flags: qr rd ra; query: 1, answer: 1, authority: 0, additional: 1 ;; opt pseudosection: ; edns: version: 0, flags:; udp: 4096 ;; question section: ;seznam.cz. in ;; answer section: seznam.cz. 300 in 77.75.76.3 ;; query time: 656 msec ;; server: 127.0.0.1#53535(127.0.0.1) ;; when: sat apr 25 16:04:32 cest 2015 ;; msg size rcvd: 54
output aaaa
query, ;; authority section:
looks decent enough both logdnsmsg , log_dns_msg:
[1429970672] unbound[14053:0] info: pythonmod: operate called, id: 1, event:module_event_moddone [1429970672] unbound[14053:0] info: ------------------------------------------------------------------------------------------ [1429970672] unbound[14053:0] info: query: e.root-servers.net., type: aaaa (28), class: in (1) [1429970672] unbound[14053:0] info: ------------------------------------------------------------------------------------------ [1429970672] unbound[14053:0] info: return reply :: flags: 8080, qdcount: 1, security:0, ttl=86400 [1429970672] unbound[14053:0] info: qinfo :: qname: ['e', 'root-servers', 'net', ''] e.root-servers.net., qtype: aaaa, qclass: in [1429970672] unbound[14053:0] info: reply: [1429970672] unbound[14053:0] info: 0:['root-servers', 'net', ''] root-servers.net. flags: 0004 [1429970672] unbound[14053:0] info: type:soa (6) class:in (1) [1429970672] unbound[14053:0] info: 0:ttl=3600000 [1429970672] unbound[14053:0] info: [1429970672] unbound[14053:0] info: 0x00 | 00 40 01 61 0c 72 6f 6f 74 2d 73 65 72 76 65 72 73 | . @ . . r o o t - s e r v e r s 0x10 | 73 03 6e 65 74 00 05 6e 73 74 6c 64 0c 76 65 72 69 | s . n e t . . n s t l d . v e r 0x20 | 69 73 69 67 6e 2d 67 72 73 03 63 6f 6d 00 78 0c e3 | s g n - g r s . c o m . x . . 0x30 | e3 24 00 00 38 40 00 00 1c 20 00 12 75 00 00 36 ee | . $ . . 8 @ . . . . . u . . 6 . 0x40 | ee 80 | . . [1429970672] unbound[14053:0] info: ------------------------------------------------------------------------------------------ [1429970672] unbound[14053:0] info: blackpie karmmmmmm xxxxxxx ;; ->>header<<- opcode: query, rcode: noerror, id: 0 ;; flags: qr ra ; query: 1, answer: 0, authority: 1, additional: 0 ;; question section: e.root-servers.net. in aaaa ;; answer section: ;; authority section: root-servers.net. 3600000 in soa a.root-servers.net. nstld.verisign-grs.com. 2014110500 14400 7200 1209600 3600000 ;; additional section: ;; msg size rcvd: 96 [1429970672] unbound[14053:0] debug: mesh_run: python module exit state module_finished
on contrary, a
query, ;; answer section:
useless far logdnsmsg goes:
[1429970672] unbound[14053:0] info: pythonmod: operate called, id: 1, event:module_event_moddone [1429970672] unbound[14053:0] info: ------------------------------------------------------------------------------------------ [1429970672] unbound[14053:0] info: query: seznam.cz., type: (1), class: in (1) [1429970672] unbound[14053:0] info: ------------------------------------------------------------------------------------------ [1429970672] unbound[14053:0] info: return reply :: flags: 8080, qdcount: 1, security:0, ttl=300 [1429970672] unbound[14053:0] info: qinfo :: qname: ['seznam', 'cz', ''] seznam.cz., qtype: a, qclass: in [1429970672] unbound[14053:0] info: reply: [1429970672] unbound[14053:0] info: 0:['seznam', 'cz', ''] seznam.cz. flags: 0000 [1429970672] unbound[14053:0] info: type:a (1) class:in (1) [1429970672] unbound[14053:0] info: 0:ttl=300 [1429970672] unbound[14053:0] info: [1429970672] unbound[14053:0] info: 0x00 | 00 04 4d 4b 4c 03 | . . m k l . [1429970672] unbound[14053:0] info: ------------------------------------------------------------------------------------------ [1429970672] unbound[14053:0] info: blackpie karmmmmmm xxxxxxx ;; ->>header<<- opcode: query, rcode: noerror, id: 0 ;; flags: qr ra ; query: 1, answer: 1, authority: 0, additional: 0 ;; question section: seznam.cz. in ;; answer section: seznam.cz. 300 in 77.75.76.3 ;; authority section: ;; additional section: ;; msg size rcvd: 43 [1429970672] unbound[14053:0] debug: mesh_run: python module exit state module_finished
note 00 04 4d 4b 4c 03
bytes erroneously interpreted ascii.
question
where in struct ub_packed_rrset_key** rrsets;
1 finds desired ;; answer section:
data? (if indeed right place look.)
i've been fiddling quite time without luck. examined sldns_wire2str_pkt_scan
function used internally unpacking wire
binary data, none wiser.
logdnsmsg()
logging hex dump of contents of each dns resource record. outputs bytes alongside ascii interpretation (with .
s non-printable bytes). means if data contains ascii strings these visible in output, while other types of data (like ip addresses) not translate meaningful text.
the first 2 bytes of data rdlength
field, indicating length of record data. remaining bytes rdata
field proper. interpretation of these bytes depends on record type. a
records consist of single 32-bit ip address, easy parse.
the following example code prints contents of a
record:
def print_a_record(data): rdlength, rdata = data[:2], data[2:] assert rdlength == '\x00\x04' assert len(rdata) == 4 addr_bytes = [ord(c) c in rdata] print('{}.{}.{}.{}'.format(*addr_bytes))
further information:
Comments
Post a Comment