dns - TXT records in dnsPython -
i have implemented simple dns server. responds txt record. hosting script ns server example.com. ns server x.y.z.k. works fine when issue like:
$ dig demo.example.com @x.y.z.k
; <<>> dig 9.3.6-p1-redhat-9.3.6-4.p1.el5_4.1 <<>> demo.example.com @x.y.z.k ;; global options: printcmd ;; got answer: ;; ->>header<<- opcode: query, status: noerror, id: 10028 ;; flags: qr rd ra; query: 1, answer: 1, authority: 2, additional: 2 ;; question section: ;demo.example.com. in ;; answer section: demo.example.com. 1000 in txt "test message"
but not work when ask same question 1 of public name servers (for example sun's dns @ 4.2.2.1):
$ dig demo.example.com @4.2.2.1
(i same thing when issue $ dig demo.example.com @4.2.2.1 txt
)
; <<>> dig 9.3.6-p1-redhat-9.3.6-4.p1.el5_4.1 <<>> demo.example.com ;; global options: printcmd ;; got answer: ;; ->>header<<- opcode: query, status: servfail, id: 10905 ;; flags: qr rd ra; query: 1, answer: 0, authority: 0, additional: 0 ;; question section: ;demo.example.com. in ;; query time: 5837 msec ;; server: 172.16.1.1#53(172.16.1.1) ;; when: tue jul 20 04:01:27 2010 ;; msg size rcvd: 75
do guys have idea wrong? interestingly if change response type cname, instead of txt, works fine.
def dns_respond(resp, q, data_type): rrset = dns.rrset.from_text(q.name, 1000, dns.rdataclass.in, dns.rdatatype.txt, 'test message') resp.answer.append(rrset) return resp def dns_ok(resp, q, data = none, msg = ''): return dns_respond(resp = resp, q = q, data_type = 'ok') def dns_error(resp, q): return dns_respond(resp = resp, q = q, data_type = 'error') def requesthandler(address, message): resp = none message_id = ord(message[0]) * 256 + ord(message[1]) logging.debug('msg id = ' + str(message_id)) if message_id in serving_ids: # request taken, drop message logging.debug('i serving request.') return serving_ids.append(message_id) msg = dns.message.from_wire(message) op = msg.opcode() if op == 0: # standard , inverse query qs = msg.question if len(qs) > 0: q = qs[0] logging.debug('request ' + str(q)) if q.rdtype == dns.rdatatype.a: resp = std_qry(msg) else: # not implemented #resp = std_qry(msg) resp = make_response(qry=msg, rcode=4) else: # not implemented resp = make_response(qry=msg, rcode=4) if resp: s.sendto(resp.to_wire(), address) def std_qry(msg): qs = msg.question logging.debug(str(len(qs)) + ' questions.') answers = [] nxdomain = false q in qs: resp = make_response(qry=msg) logging.critical('sending...') return dns_ok(resp, q) def make_response(qry=none, id=none, rcode=0): if qry none , id none: raise exception, 'bad use of make_response' if qry none: resp = dns.message.message(id) # qr = 1 resp.flags |= dns.flags.qr if rcode != 1: raise exception, 'bad use of make_response' else: resp = dns.message.make_response(qry) #resp.flags |= dns.flags.aa resp.flags |= dns.flags.ra resp.set_rcode(rcode) return resp s = socket.socket(socket.af_inet, socket.sock_dgram) s.setsockopt(socket.sol_socket, socket.so_reuseaddr, 1) s.bind(('', 53)) logging.debug('binded udp port 53.') serving_ids = [] while true: logging.debug('waiting requests.') message, address = s.recvfrom(1024) logging.debug('serving request.') requesthandler(address, message)
i can see few real bugs that'll stop working:
- you're returning
txt
recorda
record query - show stopper. - you should returning
aa
flag (authoritative answer) instead ofra
- your headers there 2 answers in authority , additional sections, there aren't
- you're not removing served ids list once they've been served
in addition there few protocol-related issues need fixing:
- you need able return
ns
records ,soa
records when asked, or delegation may not work reliably - query matching should use whole (source ip, source port, queryid) tuple account, not (queryid)
- if question name in right domain, not right subdomain should return
nxdomain
(rcode = 3) - if question name matches right subdomain wrong record type should return
noerror
(rcode = 0) instead ofnotimpl
- if question name isn't part of right domain @ should return
refused
(rcode = 5)
Comments
Post a Comment