Unbound DNS Server, Python module: checking response message elements

goal

I would like to use the Unbound Python module to verify the response immediately before sending it to the client. First of all, I'm interested ;; ANSWER SECTION: ;; ANSWER SECTION: that is, to the IP address to which the request was resolved.

Problem

What looked like a trivial modification of the logDnsMsg function turned out to be the task of viewing reply_info , rrset_ref and ub_packed_rrset_key to look for the desired bytes ;; ANSWER SECTION: ;; ANSWER SECTION:

The reason is that the logDnsMsg function does not work as expected for A requests ;; ANSWER SECTION: ;; ANSWER SECTION: while it suprisingly works as expected for ;; AUTHORITY SECTION: ;; AUTHORITY SECTION: on AAAA requests.

Lemme demonstrates a comparison between the logDnsMsg function implemented by Python and the log_dns_msg built-in function; moreover, the former shows gibberish, and the latter performs exactly as expected. Both functions are called from the context of the Python module as 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 that I changed the original logDnsMsg as it uses a logging structure in favor of print . The result was the same for print , but for scatter in the log file at the discretion of the buffer.

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 A ;; ANSWER SECTION: seznam.cz. 300 IN A 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 

The output for the AAAA request, ;; AUTHORITY SECTION: ;; AUTHORITY SECTION: looks decent enough from logDnsMsg and 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 | . @ . a . root - servers 0x10 | 73 03 6E 65 74 00 05 6E 73 74 6C 64 0C 76 65 72 69 | s . net . . nstld . veri 0x20 | 69 73 69 67 6E 2D 67 72 73 03 63 6F 6D 00 78 0C E3 | isign - grs . com . 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 is module_finished 

In contrast, for query A ;; ANSWER SECTION: ;; ANSWER SECTION: completely useless as 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: A (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 | . . MKL . [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 A ;; ANSWER SECTION: seznam.cz. 300 IN A 77.75.76.3 ;; AUTHORITY SECTION: ;; ADDITIONAL SECTION: ;; MSG SIZE rcvd: 43 [1429970672] unbound[14053:0] debug: mesh_run: python module exit state is module_finished 

Note the bytes 00 04 4D 4B 4C 03 , which are mistakenly interpreted as ASCII.

Question

Where in struct ub_packed_rrset_key** rrsets; You can find the data you need ;; ANSWER SECTION: ;; ANSWER SECTION: :? (If this is really a good place to look.)

I have been doing this for quite some time. I looked at the sldns_wire2str_pkt_scan function, which is used to unpack wire binary data, but I'm not wiser.

+6
source share
1 answer

logDnsMsg() logs a hex dump of the contents of each DNS resource record. It outputs bytes along with their interpretation of ASCII (p . For non-printable bytes). This means that if the data contains ASCII strings, they will be visible on the output, while other data types (for example, IP addresses) will not be translated into meaningful text.

The first two bytes of data are an RDLENGTH field indicating the length of the record data. The remaining bytes are the RDATA field. The interpretation of these bytes depends on the type of record. A records consist of a single 32-bit IP address, so they are easy to parse.

The following code example prints the contents of record A :

 def print_a_record(data): rdlength, rdata = data[:2], data[2:] assert rdlength == '\x00\x04' assert len(rdata) == 4 addr_bytes = [ord(c) for c in rdata] print('{}.{}.{}.{}'.format(*addr_bytes)) 

Additional Information:

+1
source

Source: https://habr.com/ru/post/985948/


All Articles