扭曲的dns不起作用

时间:2010-10-31 22:46:01

标签: python twisted

我想知道为什么以下不起作用。

from twisted internet import defer, reactor
from twisted.python.failure import Failure
import twisted.names.client

def do_lookup(do_lookup):
    d = twisted.names.client.getHostByName(domain)
    d.addBoth(lookup_done)

def lookup_done(result):
    print 'result:', result
    reactor.stop()

domain = 'twistedmatrix.com'    
reactor.callLater(0, do_lookup, domain) 
reactor.run()

结果:

result: [Failure instance: Traceback
(failure with no frames): <class
'twisted.names.error.ResolverError'>:
Stuck at response without answers or
delegation ]

3 个答案:

答案 0 :(得分:5)

在撰写本文时,这在Windows上失败,因为它使用了无效的路径来存放Windows主机文件(在twisted.names.client.createResolver中。它使用'c:\ windows \ hosts'。这对Windows版本98来说很好和我(参考here),但失败的版本与XP一样“现代”。

今天,应该使用类似的东西:

hosts = os.path.join(
                     os.environ.get('systemroot','C:\\Windows'),
                     r'system32\drivers\etc\hosts'
                    )

认为这只能部分地解决问题(或者这可能是一个红色的鲱鱼)。

这仅适用于此hosts文件中实际指定的名称。它可能需要做的是DNS服务器的某种注册表查询,然后查询实际的DNS名称查找。

This 配方看起来很有希望获得实际的DNS服务器。

答案 1 :(得分:3)

将您的示例更正为以下内容,以使其在语法上有效:

from twisted.internet import reactor
import twisted.names.client

def do_lookup(domain):
    d = twisted.names.client.getHostByName(domain)
    d.addBoth(lookup_done)

def lookup_done(result):
    print 'result:', result
    reactor.stop()

domain = 'twistedmatrix.com'
reactor.callLater(0, do_lookup, domain)
reactor.run()

我明白了:

$ python so-example.py 
result: 66.35.39.65

所以,回答你的问题:你的本地DNS环境坏了,而不是twisted.names。或者也许有一个错误。你需要进一步追踪它。

答案 2 :(得分:1)

我做了一些挖掘,为什么显式client.createResolver(servers)无法在我们的企业Windows机器上运行。在guts of Twisted的createResolver是一个依赖于os的分支:

def createResolver(servers=None, resolvconf=None, hosts=None):
    ...
    from twisted.names import resolve, cache, root, hosts as hostsModule
    if platform.getType() == 'posix':
        if resolvconf is None:
            resolvconf = '/etc/resolv.conf'
        if hosts is None:
            hosts = '/etc/hosts'
        theResolver = Resolver(resolvconf, servers)
        hostResolver = hostsModule.Resolver(hosts)
    else:
        if hosts is None:
            hosts = r'c:\windows\hosts'
        from twisted.internet import reactor
        bootstrap = _ThreadedResolverImpl(reactor)
        hostResolver = hostsModule.Resolver(hosts)
        theResolver = root.bootstrap(bootstrap)

    L = [hostResolver, cache.CacheResolver(), theResolver]
    return resolve.ResolverChain(L)

Windows的第一个警告标志是未使用参数servers,因此将忽略自定义DNS服务器。接下来是_ThreadedResolverImpl(),它使用特定于平台的代码,在被添加到解析器链之前被包装在root.bootstrap()中。

root.bootstrap的目的是使用平台解析器使用同步Windows平台解析器(工作 - 并返回IP)查找a.root-servers.net,b.root-servers.net等,然后对 root 服务器进行直接DNS查询。然后,我们的公司防火墙会阻止向根服务器发出的UDP数据包 - 我在Wireshark中看到它们。

names.client.getHostByName()使用的默认getResolver()调用直接调用createResolver(),这可能会再次导致由正在运行的DNS设置引导的这个损坏的设置。对于大多数环境,我认为将Resolver(带有根服务器或显式服务器)与_ThreadedResolverImpl一起添加到ResolverChain中作为后备工作 - 除了平台解析器是一个不同的接口。

以下是异步检测本地DNS服务器的示例(通过解析ipconfig的输出),然后安装自定义解析程序以使用它们。

import sys

from twisted.python import log
from twisted.names import root, hosts, resolve, cache, client
from twisted.python.runtime import platform

from twisted.internet import reactor
from twisted.internet import utils
import re

def parseIpconfigDNSServers(output):
    servers = []
    found = False
    for line in output.split('\n'):
        if 'DNS Servers . . . . . . . . . . . :' in line or (found and not '. . . .' in line):
            servers.append(line[38:].strip())
            found = True
        else:
            found = False
    log.msg( 'Windows: Detected DNS servers %s' % (str(servers)))
    return servers

if platform.getType() != 'posix':
    d = utils.getProcessOutput(os.path.join(os.environ['WINDIR'], 'system32', 'ipconfig.exe'), ["/all"])
    d.addCallback(parseIpconfigDNSServers)
    d.addCallback(lambda r: client.Resolver(servers=[(h, 53) for h in r]))
    d.addErrback(log.msg)
    theResolver = root.DeferredResolver(d)
    client.theResolver = resolve.ResolverChain([cache.CacheResolver(), theResolver])

if __name__ == '__main__':
    log.startLogging(sys.stdout)
    def do_lookup(domain):
        d = client.getHostByName(domain)
        d.addBoth(log.msg)

    from twisted.internet import reactor
    reactor.callLater(0, do_lookup, 'example.com')
    reactor.run()

我已将其整理并在此处发布https://gist.github.com/shuckc/af7490e1c4a2652ca740