I am new to the Twisted framework for python. I am playing around with a customer DNS server and I want to know how to located the SRC_IP of the DNS Request.
I am using the following script: http://twisted.readthedocs.org/en/latest/names/howto/custom-server.html
Specifically the one that dynamically resolves and want to know how I can located the source IP of the Request. Thanks
Not being overly familiar with twisted, I don't know if this is the best way. I suspect that what I propose below is not because operating directly on the sockets doesn't feel right, but here it goes.
Subclass server.DNSServerFactory
and override the handleQuery()
method, for example:
import socket
from twisted.internet.address import IPv4Address
class MyDNSServerFactory(server.DNSServerFactory):
def handleQuery(self, message, protocol, address):
if protocol.transport.socket.type == socket.SOCK_STREAM:
self.peer_address = protocol.transport.getPeer()
elif protocol.transport.socket.type == socket.SOCK_DGRAM:
self.peer_address = IPv4Address('UDP', *address)
else:
print "Unexpected socket type %r" % protocol.transport.socket.type
print "Got message from : %r" % self.peer_address
return server.DNSServerFactory.handleQuery(self, message, protocol, address)
.
.
.
factory = MyDNSServerFactory(
clients=[DynamicResolver(), client.Resolver(resolv='/etc/resolv.conf')]
)
Things to worry about:
socket
seems underhanded.There are other ways to do it, e.g. subclass dns.DNSDatagramProtocol
and override datagramReceived(self, data, addr)
to get the client UDP address. TCP client addresses would be gotten by subclassing and overriding server.DNSServerFactory.connectionMade(self, protocol)
and getting the peer's address with protocol.transport.getPeer()
.
Updated answer to make peer address available in DynamicResolver
Modify MyDNSServerFactory.handleQuery()
to set peer_address
for resolvers that have a peer_address
attribute:
class MyDNSServerFactory(server.DNSServerFactory):
def handleQuery(self, message, protocol, address):
if protocol.transport.socket.type == socket.SOCK_STREAM:
self.peer_address = protocol.transport.getPeer()
elif protocol.transport.socket.type == socket.SOCK_DGRAM:
self.peer_address = IPv4Address('UDP', *address)
else:
print "Unexpected socket type %r" % protocol.transport.socket.type
print "Got message from : %r" % self.peer_address
# Make peer_address available to resolvers that support that attribute
for resolver in self.resolver.resolvers:
if hasattr(resolver, 'peer_address'):
resolver.peer_address = self.peer_address
return server.DNSServerFactory.handleQuery(self, message, protocol, address)
Add the following peer_address
property to class DynamicResolver
:
def __init__(self):
self._peer_address = None
@property
def peer_address(self):
return self._peer_address
@peer_address.setter
def peer_address(self, value):
self._peer_address = value
Now you can access peer_address
in DynamicResolver.query()
, e.g.
def query(self, query, timeout=None):
print "In DynamicResolver.query(): self.peer_address = %r" % self.peer_address
if self._dynamicResponseRequired(query):
return defer.succeed(self._doDynamicResponse(query))
else:
return defer.fail(error.DomainError())