Я немного покопался, почему явный client.createResolver(servers)
не работал на наших корпоративных машинах с Windows.В кишках Twisted's createResolver
является зависимой от ОС веткой:
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
не используется, поэтому custom-DNSсерверы игнорируются.Далее следует, что _ThreadedResolverImpl (), который использует код, специфичный для платформы, перед добавлением в цепочку преобразователя заключен в root.bootstrap()
.
Цель root.bootstrap - использовать средство поиска платформы для поиска.root-servers.net, b.root-servers.net и т. д. с использованием синхронного распознавателя платформы Windows (который работает - и возвращает IP-адреса), а затем выполняет прямые DNS-запросы к корневым серверам.UDP-пакеты, запущенные на корневых серверах, затем блокируются нашим корпоративным брандмауэром - я вижу их в Wireshark.
Стандартный вызов getResolver (), используемый names.client.getHostByName (), вызывает createResolver()
напрямую, чтоможет снова привести к этой неправильной настройке, загруженной рабочей настройкой DNS.В большинстве сред я думаю, что добавление Resolver (с корневыми или явными серверами) в ResolverChain вместе с _ThreadedResolverImpl
будет работать как запасной вариант - за исключением того, что преобразователь платформы представляет собой другой интерфейс.
Вот пример обнаружениялокальные 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