paulc / dnslib Goto Github PK
View Code? Open in Web Editor NEWA Python library to encode/decode DNS wire-format packets
Home Page: https://github.com/paulc/dnslib
License: BSD 2-Clause "Simplified" License
A Python library to encode/decode DNS wire-format packets
Home Page: https://github.com/paulc/dnslib
License: BSD 2-Clause "Simplified" License
Exceptions thrown from the socket class in dns.py leave the socket open. Eventually your process will have too many open file descriptors:
OSError: [Errno 24] Too many open files
Is there any reason not to rename README to README.md so it would get rendered nicely by the Github page renderer?
The dnslib/server.py implements isAlive but checks for self.thread.isAlive which should be self.thread.is_alive. The isAlive method on DNSserver class can remain for backwards compatibility reasons.
dnslib/shellresolver.py
114: while udp_server.isAlive():
dnslib/server.py
358: def isAlive(self):
359: return self.thread.isAlive()
dnslib/fixedresolver.py
96: while udp_server.isAlive():
dnslib/zoneresolver.py
116: while udp_server.isAlive():
dnslib/proxy.py
156: while udp_server.isAlive():
dnslib/intercept.py
161: while udp_server.isAlive():
Hi, thanks for dnslib, it's great.
It would be great if dnslib could upload wheels to pypi to speedup install and also make the library available on more platforms.
Is this something you'd be interested in supporting?
I'm not sure if there's a reason behind this, but the __eq__
method of DNSLabel allows for case-insensitive comparison, whereas __hash__
, matchSuffix
and stripSuffix
are case sensitive.
My use case is storing some records in a dict keyed by name and to get it to work properly now requires manually converting everything to lowercase before searching.
Hi Paul and thanks for a great library!
It seems like the change in dns.py ce07017 breaks the error reporting on parse errors on HTTPS records. hexlify
return bytes and hex()
that was used earlier returns a string.
Here is some code to reproduce, possibly there are some issues with the HTTPS parsing in general since this packet is parsed okay in Wireshark.
Anything I can do to help? Not that familiar with the HTTPS record type thou..
Python 3.10.6 (main, Aug 3 2022, 17:39:45) [GCC 12.1.1 20220730] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import dnslib
>>> import binascii
>>> dnslib.DNSRecord.parse(binascii.unhexlify("93088410000100020000000107646973636f726403636f6d0000410001c00c004100010000012c002b0001000001000c0268330568332d323902683200040014a29f80e9a29f87e8a29f88e8a29f89e8a29f8ae8c00c002e00010000012c005f00410d020000012c632834e5632575c586c907646973636f726403636f6d0044d488ce4a5b9085289c671f0296b2b06cffaca28880c57643befd43d6de433d84ae078b282fc2cdd744f3bea2f201042a7a0d6f3e17ebd887b082bbe30dfda100002904d0000080000000"))
Traceback (most recent call last):
File "/home/lanrob1702/.cache/pypoetry/virtualenvs/nmsg-processor-l4-TU0Er-py3.10/lib/python3.10/site-packages/dnslib/dns.py", line 1837, in parse
v = bytearray(buffer.get(n))
File "/home/lanrob1702/.cache/pypoetry/virtualenvs/nmsg-processor-l4-TU0Er-py3.10/lib/python3.10/site-packages/dnslib/buffer.py", line 63, in get
raise BufferError("Not enough bytes [offset=%d,remaining=%d,requested=%d]" %
dnslib.buffer.BufferError: Not enough bytes [offset=138,remaining=64,requested=40039]
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/lanrob1702/.cache/pypoetry/virtualenvs/nmsg-processor-l4-TU0Er-py3.10/lib/python3.10/site-packages/dnslib/dns.py", line 109, in parse
rr.append(RR.parse(buffer))
File "/home/lanrob1702/.cache/pypoetry/virtualenvs/nmsg-processor-l4-TU0Er-py3.10/lib/python3.10/site-packages/dnslib/dns.py", line 814, in parse
rdata = RDMAP.get(QTYPE.get(rtype),RD).parse(
File "/home/lanrob1702/.cache/pypoetry/virtualenvs/nmsg-processor-l4-TU0Er-py3.10/lib/python3.10/site-packages/dnslib/dns.py", line 1841, in parse
raise DNSError("Error unpacking HTTPS: " + str(e) + binascii.hexlify(buffer.data[buffer.offset:]))
TypeError: can only concatenate str (not "bytes") to str
It would be good if dnslib
added and exposed typing information so that calling libraries can check they are passing the correct types.
To support inline type hints would require dropping support for python<3.5
, however given the security support schedule it may be desirable to drop support up to 3.7
. Checking PyPI Stats, versions <=3.6
make up less than 1% of daily downloads.
I'd be willing to help out with this.
If I want to add a DKIM signature as a RR for a domain, it raises the following stack trace. In BIND/ NSD, one can separate the TXT record in quotes to accommodate this case. But what's the workaround for this in dnslib?
Traceback (most recent call last):
File "ddns.py", line 56, in <module>
D._domainkey.mail: [TXT(DKIM)],
File "python3.8/site-packages/dnslib/dns.py", line 1114, in __init__
raise DNSError("TXT record too long: %s" % self.data)
You can see from the following test log that there are now syntax warning with Python 3.12:
=== digparser.py
Testing: Python 3.12.1
/<<PKGBUILDDIR>>/dnslib/digparser.py:144: SyntaxWarning: invalid escape sequence '\d'
m = re.search('version: (\d+),',edns)
/<<PKGBUILDDIR>>/dnslib/digparser.py:147: SyntaxWarning: invalid escape sequence '\s'
m = re.search('flags:\s*(.*?);',edns)
/<<PKGBUILDDIR>>/dnslib/digparser.py:150: SyntaxWarning: invalid escape sequence '\d'
m = re.search('udp: (\d+)',edns)
Testing: Python 3.11.7
=== ranges.py
Testing: Python 3.12.1
Testing: Python 3.11.7
=== test_decode.py
Testing: Python 3.12.1
/<<PKGBUILDDIR>>/dnslib/digparser.py:144: SyntaxWarning: invalid escape sequence '\d'
m = re.search('version: (\d+),',edns)
/<<PKGBUILDDIR>>/dnslib/digparser.py:147: SyntaxWarning: invalid escape sequence '\s'
m = re.search('flags:\s*(.*?);',edns)
/<<PKGBUILDDIR>>/dnslib/digparser.py:150: SyntaxWarning: invalid escape sequence '\d'
m = re.search('udp: (\d+)',edns)
..................................................................
----------------------------------------------------------------------
Ran 66 tests in 0.134s
Looking at what's new for 3.12, in the 'Other Language Changes' section, this seems to be relevant:
A backslash-character pair that is not a valid escape sequence now generates a [SyntaxWarning](https://docs.python.org/dev/library/exceptions.html#SyntaxWarning), instead of [DeprecationWarning](https://docs.python.org/dev/library/exceptions.html#DeprecationWarning). For example, re.compile("\d+\.\d+") now emits a [SyntaxWarning](https://docs.python.org/dev/library/exceptions.html#SyntaxWarning) ("\d" is an invalid escape sequence, use raw strings for regular expression: re.compile(r"\d+\.\d+")). In a future Python version, [SyntaxError](https://docs.python.org/dev/library/exceptions.html#SyntaxError) will eventually be raised, instead of [SyntaxWarning](https://docs.python.org/dev/library/exceptions.html#SyntaxWarning). (Contributed by Victor Stinner in [gh-98401](https://github.com/python/cpython/issues/98401).)
Hello,
Can you provide an example of how to send a DNAME Record? I have seen that DNAME is listed in QTYPE, but there's no RD sub-class for DNAME.
Thank you!
Not an issue as such, but
Needed to attach a custom logger to DNSLogger
, format was fine, but needed to overload every method as print was used...
It would have been so much better if there was a log_print
or _print
or _output
method in the DNSLogger class instead.
Then using a customer logger w/o format change would be much simpler.
If you could implement this would be great. :) Great code, btw!
Lines 178 to 302 in 729a655
In #22 case-insensitive hashing was mentioned and resolved.
matchSuffix should (at least most of the time) be case insensitive https://datatracker.ietf.org/doc/html/rfc4343
>>> from dnslib.dns import DNSLabel
>>> l = DNSLabel("test.example.Com")
>>> l
<DNSLabel: 'test.example.Com.'>
>>> l.matchSuffix("example.Com")
True
>>> l.matchSuffix("example.com")
False
>>>
The last command is False, expected True
It is seen in the wild that requests are coming in especially as .ip6.arpa.
and .IP6.ARPA.
Originally posted by @NiKiZe in #22 (comment)
Possible Fix:
@@ -113,14 +115,14 @@ class DNSLabel(object):
Return True if label suffix matches
"""
suffix = DNSLabel(suffix)
- return self.label[-len(suffix.label):] == suffix.label
+ return DNSLabel(self.label[-len(suffix.label):]) == suffix
Would you mind adding the null record (experimental)?
in dnslib.QTYPE, add 10:'NULL'
I need it in one of my Python tools. I added it on my machine, but it would be easier for maintenance if it was in the master code.
Thanks,
Didier
Is automated testing feasable?
That would verifying if the library works in various python versions simpler i guess.
It is one of the hurdles to keep it in gentoo.
Ref: https://bugs.gentoo.org/show_bug.cgi?id=718762
When dns payload is sent over TCP (possibly DNS over HTTPS or it could be DNS over TCP when response is large), the data payload extracted from TCP protocol and passed to DNSRecord.parse()
throws error related to parsing of data where data is not available when offset is set.
Hi,
Thank you for this great project!
When running an instance of DNSServer
, the output is quite verbose. I've looked through the documentation and did not find a way to mute the logs completely with one single option.
It would be nice to have this option.
Regards
From https://en.wikipedia.org/wiki/SRV_record
The priority field determines the precedence of use of the record's data. Clients should use the SRV records with the lowest-numbered priority value first, and fall back to records of higher value if the connection fails. If a service has multiple SRV records with the same priority value, clients should load balance them in proportion to the values of their weight fields. In the following example, both the priority and weight fields are used to provide a combination of load balancing and backup service.
# _service._proto.name. TTL class SRV priority weight port target.
_sip._tcp.example.com. 86400 IN SRV 10 60 5060 bigbox.example.com.
_sip._tcp.example.com. 86400 IN SRV 10 20 5060 smallbox1.example.com.
_sip._tcp.example.com. 86400 IN SRV 10 20 5060 smallbox2.example.com.
_sip._tcp.example.com. 86400 IN SRV 20 0 5060 backupbox.example.com.
Is this supported in dnslib?
I'm getting exceptions like this:
Exception happened during processing of request from ('xxxxxxxxxxx', 48736)
Traceback (most recent call last):
File "/usr/lib/python3.6/socketserver.py", line 654, in process_request_thread
self.finish_request(request, client_address)
File "/usr/lib/python3.6/socketserver.py", line 364, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "/usr/lib/python3.6/socketserver.py", line 724, in __init__
self.handle()
File "/usr/local/lib/python3.6/dist-packages/dnslib/server.py", line 135, in handle
new_data = self.request.recv(8192)
ConnectionResetError: [Errno 104] Connection reset by peer
I suggest a try/except on the first part of https://github.com/paulc/dnslib/blob/master/dnslib/server.py#L126 to handle this.
Might be related to #16.
In your example usage, you parse a 'packet' using 'dnslib.DNSRecord.parse'. What is a 'packet'? I.e. what layer of the communication stack? Also, what data-type is 'packet'?
What I'm trying to do is read DNS traffic from pcaps (I know how to filter out things that aren't DNS traffic), with a library like dpkt. dpkt can give me any layer of the stack I want, but neither the full packet nor solely the application layer seem to work as input to 'dnslib.DNSRecord.parse'.
I used to update dns manually with using nsupdate
command with bind9
as DNS Server
Now I'm succeed using DNS Server/Client with this library, thank you so much.
I'm wonder should I make my own algorithm or own program,
or there is already feature in this library?
In nsupdate
command, there was update section
instead of addition section nor answer section. So there's special section to update like that, but that readme.me didn't mention it. Instead, it mention DNSSec which it's one component for updating?
Hello, I was wondering if you would be open to using Enum instead of Bimap? I will happily make a PR if you are open to the change.
I get a bunch of these errors after running the server for a while:
Traceback (most recent call last):
File "/usr/lib/python3.6/socketserver.py", line 654, in process_request_thread
self.finish_request(request, client_address)
File "/usr/lib/python3.6/socketserver.py", line 364, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "/usr/lib/python3.6/socketserver.py", line 724, in __init__
self.handle()
File "/usr/local/lib/python3.6/dist-packages/dnslib/server.py", line 130, in handle length = struct.unpack("!H",bytes(data[:2]))[0] struct.error: unpack requires a buffer of 2 bytes
Apparently they are harmless, but I wonder if dnslib is handling something in the DNS protocol wrongly. If not it'd be nice to have a try/catch to avoid logging these. Any ideas of what is causing them?
I also get a few like these:
Error unpacking DNSQuestion [offset=344]: Not enough bytes [offset=344,remaining=59,requested=79]
File "/home/matt/Programming/Python/nsfilter/venv/lib/python3.7/site-packages/dnslib/bimap.py", line 68, in __getitem__
raise self.error("%s: Invalid forward lookup: [%s]" % (self.name,k))
File "/home/matt/Programming/Python/nsfilter/rules.py", line 525, in __call__
qtype = dnslib.dns.QTYPE[nsquery.q.qtype]
dnslib.dns.DNSError: QTYPE: Invalid forward lookup: [65]
File "/home/matt/Programming/Python/nsfilter/venv/lib/python3.7/site-packages/dnslib/bimap.py", line 68, in __getitem__
raise self.error("%s: Invalid forward lookup: [%s]" % (self.name,k))
----------------------------------------
dnslib.dns.DNSError: QTYPE: Invalid forward lookup: [65]
Is there any expectation that this will get added?
A DNSRecord instance such as
<DNS Header: id=0x9d1a type=QUERY opcode=UPDATE flags= rcode='NOERROR' zo=1 pr=1 up=3 ad=0>
<DNS Question: 'xxx.net.' qtype=SOA qclass=IN>
<DNS RR: 'yyy.xxx.net.' rtype=CNAME rclass=None ttl=0 rdata=''>
<DNS RR: 'yyy.xxx.net.' rtype=AAAA rclass=* ttl=0 rdata=''>
<DNS RR: 'yyy.xxx.net.' rtype=A rclass=* ttl=0 rdata=''>
<DNS RR: 'yyy.xxx.net.' rtype=A rclass=IN ttl=1200 rdata='192.168.1.2'>
will fail to pack() with the following error:
>>> r.pack()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/peter/.local/lib/python3.12/site-packages/dnslib/dns.py", line 335, in pack
rr.pack(buffer)
File "/home/peter/.local/lib/python3.12/site-packages/dnslib/dns.py", line 888, in pack
self.rdata.pack(buffer)
^^^^^^^^^^^^^^^
AttributeError: 'str' object has no attribute 'pack'
I believe the source of the error is
Line 831 in 724f94e
Hello, can you please add into README a note that RDATA format like this "\# 15 0761617263683634067562756E7475" is byte's hexdump format, and way to bring it back is unhex it via: binascii.unhexlify(data)?
Hi,
dnslib client does not validate DNS transaction id (TXID) as specified in the RFC.
This considered as implementation bug. Attackers can use this to redirect users to their malicious name servers.
I know the client created for testing but other projects using dnslib as a dependency might be affected as well.
I suggest to add a simple validate:
#... request code
a_pkt = q.send(address,port,tcp=args.tcp)
a = DNSRecord.parse(a_pkt)
if q.header.id != a.header.id:
raise DNSError('Response transaction id does not match query transaction id')
I parsed a bunch of DNS traffic with dnslib and noticed that some NSEC response records contains a TYPE65534 record that causes dnslib to fail.
Example:
;; Sending:
;; QUERY: 822601000001000000000000066f696c70726f02636800002f0001
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 33318
;; flags: rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;oilpro.ch. IN NSEC
;; Got answer:
;; RESPONSE: 822681800001000100000000066f696c70726f02636800002f0001c00c002f000100000e100036066f696c70726f02636800000722000000000380ff200000000000000000000000000000000000000000000000000000000000000002
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 33318
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;oilpro.ch. IN NSEC
;; ANSWER SECTION:
oilpro.ch. 3600 IN NSEC oilpro.ch. NS SOA RRSIG NSEC DNSKEY TYPE65534
TYPE65534 is an internal type used by BIND to keep track of signing, not sure why it shows up in the NSEC data, but it does.
https://www.dns.cam.ac.uk/news/2020-04-27-nsdiff.html
https://ftp.iij.ad.jp/pub/network/isc/bind9/9.14.6/doc/arm/Bv9ARM.ch04.html
Also possible to query for the TYPE65534 record on the domain
$ dig oilpro.ch TYPE65534
; <<>> DiG 9.18.6 <<>> oilpro.ch TYPE65534
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 16416
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; MBZ: 0x0005, udp: 512
;; QUESTION SECTION:
;oilpro.ch. IN TYPE65534
;; ANSWER SECTION:
oilpro.ch. 5 IN TYPE65534 \# 5 0D2A680001
oilpro.ch. 5 IN TYPE65534 \# 5 0DD5C60001
;; Query time: 63 msec
;; SERVER: 192.168.42.2#53(192.168.42.2) (UDP)
;; WHEN: Mon Oct 24 13:50:23 CEST 2022
;; MSG SIZE rcvd: 72
Quick and dirty fix for my needs for decoding the NSEC part
--- dnslib/dns.py
+++ dnslib/dns.py
@@ -1634,7 +1636,7 @@ def decode_type_bitmap(type_bitmap):
for i in range(8):
if (value << i) & 0x80:
bitpos = (256*winnum) + (8*pos) + i
- rrlist.append(QTYPE[bitpos])
+ rrlist.append(QTYPE.get(bitpos, "TYPE" + str(bitpos)))
This only helps for unknown types in the type bitmap thou, and only for decoding. Dnslib still fails to parse unknown RR types in general
$ ./test_decode.py --new oilpro.ch TYPE65534
Traceback (most recent call last):
File "/home/lanrob1702/development/dnslib/dnslib/bimap.py", line 75, in __getattr__
return self.reverse[k]
KeyError: 'TYPE65534'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/lanrob1702/development/dnslib/dnslib/./test_decode.py", line 264, in <module>
new_test(*args.new,nodig=args.nodig,dnssec=args.dnssec)
File "/home/lanrob1702/development/dnslib/dnslib/./test_decode.py", line 72, in new_test
q = DNSRecord.question(domain,qtype)
File "/home/lanrob1702/development/dnslib/dnslib/dns.py", line 140, in question
return DNSRecord(q=DNSQuestion(qname,getattr(QTYPE,qtype),
File "/home/lanrob1702/development/dnslib/dnslib/bimap.py", line 77, in __getattr__
raise self.error("%s: Invalid reverse lookup: [%s]" % (self.name,k))
dnslib.dns.DNSError: QTYPE: Invalid reverse lookup: [TYPE65534]
A better solution would probably be to implement support for RFC3597: Handling of Unknown DNS Resource Record (RR) Types
[5](https://datatracker.ietf.org/doc/html/rfc3597#section-5). Text Representation
In the "type" field of a master file line, an unknown RR type is
represented by the word "TYPE" immediately followed by the decimal RR
type number, with no intervening whitespace. In the "class" field,
an unknown class is similarly represented as the word "CLASS"
immediately followed by the decimal class number.
This convention allows types and classes to be distinguished from
each other and from TTL values, allowing the "[<TTL>] [<class>]
<type> <RDATA>" and "[<class>] [<TTL>] <type> <RDATA>" forms of
[[RFC1035](https://datatracker.ietf.org/doc/html/rfc1035)] to both be unambiguously parsed.
The RDATA section of an RR of unknown type is represented as a
sequence of white space separated words as follows:
The special token \# (a backslash immediately followed by a hash
sign), which identifies the RDATA as having the generic encoding
defined herein rather than a traditional type-specific encoding.
An unsigned decimal integer specifying the RDATA length in octets.
Zero or more words of hexadecimal data encoding the actual RDATA
field, each containing an even number of hexadecimal digits.
If the RDATA is of zero length, the text representation contains only
the \# token and the single zero representing the length.
Most of the parts needed seems to already be available in the RR and RD base classes.
@paulc Would a PR with necessary updates to RR, RD and the Bimap be interesting if I decide to take a look at it?
I've been working on a change to add a DS record RD subclass over in rmbolger/dnslib@801edf7. It has a very similar structure to the DNSKEY record. The main difference is that the DNSKEY has the public key encoded as Base64 whereas the DS has the digest value encoded as Hex.
At a basic level, it seems to be working. But when I attempt to test it in a way that adds multiple answers to a DNSRecord
something is happening where all of the instances of the record get overwritten with a copy of first one seen. The easiest demonstration is comparing an actual dig query to the dnslib.client output. For example:
>dig example.org. DS
; <<>> DiG 9.17.15 <<>> example.org. DS
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 60
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;example.org. IN DS
;; ANSWER SECTION:
example.org. 2121 IN DS 3397 8 1 DEE10345942C98711EB058B25A749EE342FCE1DC
example.org. 2121 IN DS 3397 8 2 ED1168604BC6A14068B9905401E62698BB3663B6EC2073EBD3599B88 2A785BF6
example.org. 2121 IN DS 31589 8 1 7B8370002875DDA781390A8E586C31493847D9BC
example.org. 2121 IN DS 31589 8 2 3FDC4C11FA3AD3535EA8C1CE3EAF7BFA5CA9AE8A834D98FEE10085CF AEB625AA
example.org. 2121 IN DS 37780 8 1 B4A5CCE8D82DC585E327E5896EAE82E0B9A76DC6
example.org. 2121 IN DS 37780 8 2 D96AFA9022000D368B5F497877DF289A1E9A13A1AB1F97BC1BF4D5DE 16879134
Six unique results where the digest values may have whitespace within the hex text (allowed but not mandated by the RFC).
>python -m dnslib.client --query --hex --dig example.org. DS
;; Sending:
;; QUERY: ef2b01000001000000000000076578616d706c65036f726700002b0001
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 61227
;; flags: rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;example.org. IN DS
;; Got answer:
;; RESPONSE: ef2b81800001000600000000076578616d706c65036f726700002b0001c00c002b000100000e1000187b6508017b8370002875dda781390a8e586c31493847d9bcc00c002b000100000e10002493940802d96afa9022000d368b5f497877df289a1e9a13a1ab1f97bc1bf4d5de16879134c00c002b000100000e10001893940801b4a5cce8d82dc585e327e5896eae82e0b9a76dc6c00c002b000100000e1000240d450802ed1168604bc6a14068b9905401e62698bb3663b6ec2073ebd3599b882a785bf6c00c002b000100000e1000180d450801dee10345942c98711eb058b25a749ee342fce1dcc00c002b000100000e1000247b6508023fdc4c11fa3ad3535ea8c1ce3eaf7bfa5ca9ae8a834d98fee10085cfaeb625aa
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 61227
;; flags: qr rd ra; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;example.org. IN DS
;; ANSWER SECTION:
example.org. 3600 IN DS 3397 8 1 DEE10345942C98711EB058B25A749EE342FCE1DC
example.org. 3600 IN DS 3397 8 1 DEE10345942C98711EB058B25A749EE342FCE1DC
example.org. 3600 IN DS 3397 8 1 DEE10345942C98711EB058B25A749EE342FCE1DC
example.org. 3600 IN DS 3397 8 1 DEE10345942C98711EB058B25A749EE342FCE1DC
example.org. 3600 IN DS 3397 8 1 DEE10345942C98711EB058B25A749EE342FCE1DC
example.org. 3600 IN DS 3397 8 1 DEE10345942C98711EB058B25A749EE342FCE1DC
The first result matches the first result in the dig output. But the next 5 results are just clones of the first instead of their individual rdata. I've tried adding some debug logging in the DS.parse
method but it seems to be parsing the unique packets normally.
I feel like I must be doing something wrong here, but I can't figure out what it is.
Is it possible to get the request IP in resolve()
? The use case is that I'm running a small DNS server for a domain, and I noticed it's being used as a full DNS server by somebody. I want to resolve any requests to *.mydomain.com for any IP except for a whitelist.
I'm trying to use dnslib
for a DNS cache server. The minimal environment is as:
import socket
from dns_resolve import *
IP = '127.0.0.1'
PORT = 8123
def main():
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((IP, PORT))
print('DNS is listening on {0}:{1} ...'.format(IP, PORT))
while True:
data, addr = sock.recvfrom(1024)
q = DNSRecord.parse(data)
sock.sendto(str(q).encode('utf-8'), addr)
if __name__ == '__main__':
main()
And when I do dig in shell as:
dig @127.0.0.1 -p 8123 google.com
The reply is:
;; Warning: ID mismatch: expected ID 39351, got 15163
;; Warning: query response not set
I print q
, and the ID is actually the expected ID 39351. I've tried to manually set the ID, new a DNSRecord with specific values, new a DNSHeader, restart the Python server, but I still got the warning which says expected ID xxx, got 15163
. I have no idea where 15163
comes from.
PS. I also tried to change the while
part to:
while True:
data, addr = sock.recvfrom(1024)
sock.sendto(data, addr)
In this case, dig can get the reply with the correct ID number.
I'm not sure if it's a problem or not, but I've been recently comparing some dig
output to dnslib output for TXT records and I'm not sure what to think about TXT records with bytes in them that translate to unicode chars - for example:
$ dig -t TXT @8.8.8.8 smartjailmail.com
....
smartjailmail.com. 3600 IN TXT "google-site-verification=7Avm2jKuluvrgko_FgTUqYqlYpvYu6hMf\005\000\000\000\000\000\000\000DQ"
....
And via dnslib.client
$ python -m dnslib.client --server 8.8.8.8:53 smartjailmail.com TXT
...
smartjailmail.com. 3600 IN TXT "google-site-verification=7Avm2jKuluvrgko_FgTUqYqlYpvYu6hMfDQ"
...
and via repr
on the RD.data
property:
b'google-site-verification=7Avm2jKuluvrgko_FgTUqYqlYpvYu6hMf\x05\x00\x00\x00\x00\x00\x00\x00DQ'
As I read the code dnslib took the bytes and tried to parse it as utf-8 and discards any non-utf8 chars - and dig
escapes anything outside of ascii perhaps?
When I read the RFC \DDD
indeed is allowed:
\DDD where each D is a digit is the octet corresponding to
the decimal number described by DDD. The resulting
octet is assumed to be text and is not checked for
special meaning.
but I'm not quite sure what to expect of it with regards to dnslib - As I read the RFC encoding of TXT records is not prescribed ๐คท I would worry that a TXT record with some kind of esoteric encoding would break the dnslib way of turning the TXT records into text again
According to pypi, the newest release is 0.9.12 but the newest tag on GitHub is 0.9.7. Could you please push the missing tags? Monitoring new releases via GitHub is much more convenient since it provides ATOM feeds.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.