【问题标题】:Python Twisted Custom DNSPython Twisted 自定义 DNS
【发布时间】:2014-10-01 10:44:03
【问题描述】:

我是 python 的 Twisted 框架的新手。我正在玩客户 DNS 服务器,我想知道如何定位 DNS 请求的 SRC_IP。

我正在使用以下脚本:http://twisted.readthedocs.org/en/latest/names/howto/custom-server.html

特别是动态解析并想知道我如何定位请求的源 IP 的那个。 谢谢

【问题讨论】:

    标签: python dns twisted


    【解决方案1】:

    对twisted不太熟悉,我不知道这是否是最好的方式。我怀疑我在下面提出的不是因为直接在套接字上操作感觉不对,而是这样。

    子类server.DNSServerFactory并覆盖handleQuery()方法,例如:

    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')]
    )
    

    需要担心的事情:

    1. IPV6 地址
    2. 直接使用socket 似乎很卑鄙。
    3. socket.SOCK_STREAM 是否总是暗示 TCP 连接?

    还有其他方法可以做到这一点,例如子类dns.DNSDatagramProtocol 并覆盖datagramReceived(self, data, addr) 以获取客户端UDP 地址。 TCP 客户端地址将通过子类化和覆盖server.DNSServerFactory.connectionMade(self, protocol) 并使用protocol.transport.getPeer() 获取对等方的地址来获得。


    更新答案以在 DynamicResolver 中提供对等地址

    修改MyDNSServerFactory.handleQuery() 为具有peer_address 属性的解析器设置peer_address

    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)
    

    将以下peer_address 属性添加到类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
    

    现在您可以在DynamicResolver.query() 中访问peer_address,例如

        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())
    

    【讨论】:

    • 如果可以的话,还有一个简短的问题;如何让 self.peer_address 的内容在我的 DynamicResolver() 类中可用?
    • 是的...触摸socket让每个人都超级伤心。
    • @Jean-PaulCalderone :好的,那么其他方式(子类化 DNSDatagramProtocol 和 DNSServerFactory)更好吗?这两种方法在我看来都不优雅。
    • @pjf - hhhmmm DynamicResolver 可以从self.resolver.resolvers 列表中的MyDNSServerFactory 实例访问。这会很难看,但您可以为 peer_address 添加一个属性到 DynamicResolver,并通过迭代 self.resolver.resolvers 并为具有 peer_address 属性的解析器设置 peer_addresshandleQuery 设置它。跨度>
    • @pjf - 已更新答案以使对等地址可用于 DynamicResolver。
    猜你喜欢
    • 2012-08-26
    • 2017-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-20
    • 2012-08-30
    • 2014-11-27
    • 2011-10-31
    相关资源
    最近更新 更多