[Twisted-Python] twisted names - how to add answers to a message and send replies
I have a small script which answers dns queries by returning the original message. I have spent a couple of hours RTFMing, but I still cannot find out how to correctly add answers to the message, before returning it. I want to add an answer, either a Record_CNAME or Record_A, so as to produce a trivial authoritative-only DNS server. Adding a Record_XXX object to message.answers using the Array's 'append' method produces a MalformedPacket (according to wireshark), though the server does not throw any exceptions. (In this situation, the answer count, as shown by dig, does rise to 1, even though no answer is displayed [due to malformed packet?].) Perhaps there is a completely different way to do this? Could I craft a message with answers from scratch? Any help appreciated, Chris. #!/usr/bin/python from twisted.internet.protocol import Protocol, Factory from twisted.internet import reactor from twisted.names.server import DNSServerFactory from twisted.names.dns import Query, DNSDatagramProtocol, RRHeader, Record_CNAME, Record_A, Message from twisted.names import dns from twisted.internet.interfaces import IAddress class Controller(object): def messageReceived(self, m, protocol, addr): print m, dir(m), m.queries, m.answers # tried all sorts of things here protocol.transport.write(m.toStr(), addr) controller = Controller() if __name__ == "__main__": reactor.listenUDP(53, DNSDatagramProtocol(controller)) reactor.run()
On Wed, 12 Mar 2008 08:04:21 +0000, Chris Dew <chris@sidwells.com> wrote:
I have a small script which answers dns queries by returning the original message. I have spent a couple of hours RTFMing, but I still cannot find out how to correctly add answers to the message, before returning it.
I want to add an answer, either a Record_CNAME or Record_A, so as to produce a trivial authoritative-only DNS server.
Adding a Record_XXX object to message.answers using the Array's 'append' method produces a MalformedPacket (according to wireshark), though the server does not throw any exceptions. (In this situation, the answer count, as shown by dig, does rise to 1, even though no answer is displayed [due to malformed packet?].)
Perhaps there is a completely different way to do this? Could I craft a message with answers from scratch?
Did you set `m.answer´ to 1? Jean-Paul
Thanks for your reply. I have tried setting answer to 1. I have included an amended version of my programme at the end of this email. When I run this, the server reports no error. When I 'dig @localhost foo.bar' I get the response: """ ;; Warning: Message parser reports malformed message packet. ; <<>> DiG 9.4.1 <<>> @localhost foo.bar ; (1 server found) ;; global options: printcmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 18948 ;; flags: qr rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 ;; WARNING: recursion requested but not available ;; WARNING: Messages has 4 extra bytes at end ;; QUESTION SECTION: ;foo.bar. IN A ;; Query time: 1 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Thu Mar 13 07:37:50 2008 ;; MSG SIZE rcvd: 29 """ Wireshark also shows the reply packet to be malformed: 0000 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 ........ ......E. 0010 00 39 00 00 40 00 40 11 3c b2 7f 00 00 01 7f 00 .9..@.@. <....... 0020 00 01 00 35 82 43 00 25 fe 38 51 cf 81 00 00 01 ...5.C.% .8Q..... 0030 00 01 00 00 00 00 03 66 6f 6f 03 62 61 72 00 00 .......f oo.bar.. 0040 01 00 01 0a 0b 0c 0d You can see the 10.11.12.13 at the end (hex), but something about the packet is wrong. Could you point out my mistake? If it's a bug in twisted.names, I'm happy to look at fixing it (I've worked with the dns protocol at packet level before), but I first want to make sure that I am using the API correctly. Thanks, Chris. #!/usr/bin/python from twisted.internet.protocol import Protocol, Factory from twisted.internet import reactor from twisted.names.server import DNSServerFactory from twisted.names.dns import Query, DNSDatagramProtocol, RRHeader, Record_CNAME, Record_A, Message from twisted.names import dns from twisted.internet.interfaces import IAddress class Controller(object): def messageReceived(self, m, protocol, addr): print m, dir(m), m.queries, m.answers # this should always answer 10.11.12.13, regardless of the query m.answer = 1 m.answers.append(Record_A(address="10.11.12.13")) protocol.transport.write(m.toStr(), addr) controller = Controller() if __name__ == "__main__": reactor.listenUDP(53, DNSDatagramProtocol(controller)) reactor.run() On 12/03/2008, Jean-Paul Calderone <exarkun@divmod.com> wrote:
I have a small script which answers dns queries by returning the original message. I have spent a couple of hours RTFMing, but I still cannot find out how to correctly add answers to the message, before returning it.
I want to add an answer, either a Record_CNAME or Record_A, so as to
On Wed, 12 Mar 2008 08:04:21 +0000, Chris Dew <chris@sidwells.com> wrote: produce
a trivial authoritative-only DNS server.
Adding a Record_XXX object to message.answers using the Array's 'append' method produces a MalformedPacket (according to wireshark), though the server does not throw any exceptions. (In this situation, the answer count, as shown by dig, does rise to 1, even though no answer is displayed [due to malformed packet?].)
Perhaps there is a completely different way to do this? Could I craft a message with answers from scratch?
Did you set `m.answer´ to 1?
Jean-Paul
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
On Thu, 13 Mar 2008 07:52:24 +0000, Chris Dew <chris@sidwells.com> wrote:
Thanks for your reply. I have tried setting answer to 1. I have included an amended version of my programme at the end of this email.
When I run this, the server reports no error. When I 'dig @localhost foo.bar' I get the response:
[snip]
Could you point out my mistake? If it's a bug in twisted.names, I'm happy to look at fixing it (I've worked with the dns protocol at packet level before), but I first want to make sure that I am using the API correctly.
See below. I think it's a documentation deficiency, but probably not a bug in the code.
[snip]
#!/usr/bin/python
from twisted.internet.protocol import Protocol, Factory from twisted.internet import reactor from twisted.names.server import DNSServerFactory from twisted.names.dns import Query, DNSDatagramProtocol, RRHeader, Record_CNAME, Record_A, Message from twisted.names import dns from twisted.internet.interfaces import IAddress
class Controller(object): def messageReceived(self, m, protocol, addr): print m, dir(m), m.queries, m.answers # this should always answer 10.11.12.13, regardless of the query m.answer = 1 m.answers.append(Record_A(address="10.11.12.13")) protocol.transport.write(m.toStr(), addr)
Answers should be a list of RRHeaders, not bare Record_As.
controller = Controller()
if __name__ == "__main__": reactor.listenUDP(53, DNSDatagramProtocol(controller)) reactor.run()
Jean-Paul
I have it working now. I have attached a working programme below. (Note: the RRHeader's name should be gathered from one of the queries, rather than being hard-coded, as in my example below. I did it this way, as it more obviously illustrates RRHeader's constructor.) Thanks for your help, Chris. #!/usr/bin/python from twisted.internet.protocol import Protocol, Factory from twisted.internet import reactor from twisted.names.server import DNSServerFactory from twisted.names.dns import Query, DNSDatagramProtocol, RRHeader, Record_CNAME, Record_A, Message from twisted.names import dns from twisted.internet.interfaces import IAddress class Controller(object): def messageReceived(self, m, protocol, addr): print m, dir(m), m.queries, m.answers # this should always answer 10.11.12.13, regardless of the query m.answer = 1 m.answers.append(RRHeader(name="foo.bar", payload=Record_A(address=" 10.11.12.13"))) protocol.transport.write(m.toStr(), addr) controller = Controller() if __name__ == "__main__": reactor.listenUDP(53, DNSDatagramProtocol(controller)) reactor.run() On 13/03/2008, Jean-Paul Calderone <exarkun@divmod.com> wrote:
On Thu, 13 Mar 2008 07:52:24 +0000, Chris Dew <chris@sidwells.com> wrote:
Thanks for your reply. I have tried setting answer to 1. I have included an amended version of my programme at the end of this email.
When I run this, the server reports no error. When I 'dig @localhost foo.bar' I get the response:
[snip]
Could you point out my mistake? If it's a bug in twisted.names, I'm
happy
to look at fixing it (I've worked with the dns protocol at packet level before), but I first want to make sure that I am using the API correctly.
See below. I think it's a documentation deficiency, but probably not a bug in the code.
[snip]
#!/usr/bin/python
from twisted.internet.protocol import Protocol, Factory from twisted.internet import reactor from twisted.names.server import DNSServerFactory from twisted.names.dns import Query, DNSDatagramProtocol, RRHeader, Record_CNAME, Record_A, Message from twisted.names import dns from twisted.internet.interfaces import IAddress
class Controller(object): def messageReceived(self, m, protocol, addr): print m, dir(m), m.queries, m.answers # this should always answer 10.11.12.13, regardless of the query m.answer = 1 m.answers.append(Record_A(address="10.11.12.13")) protocol.transport.write(m.toStr(), addr)
Answers should be a list of RRHeaders, not bare Record_As.
controller = Controller()
if __name__ == "__main__": reactor.listenUDP(53, DNSDatagramProtocol(controller)) reactor.run()
Jean-Paul
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
participants (2)
-
Chris Dew -
Jean-Paul Calderone