1

私が直面している問題は、イーサネット インターフェイスで IPv6 が有効になっているためです。そのため、ホスト名の解決によって、必要のないときに IPv6 の結果が得られることがあります。

オペレーティング システム/名前解決/イーサネット構成を変更せずに、twisted.names.client がipv4 アドレスのみを返すようにすることは可能ですか?

コード例:

#!/usr/bin/python

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

def got_arg(*args):
    print 'got_arg',args

def get_arg(arg):
    d = client.getHostByName('www.google.com').addCallback(got_arg)

if __name__ == '__main__':
    get_arg('www.google.com')
    reactor.run()

このコードは、Linux ボックスで常にipv6 アドレスを提供します。

got_arg ('2001:4860:4001:800::1010',)

何も変更せずに ipv4 ルックアップを強制できるようにしたいと考えています。何か案は?強制がないため、少なくとも結果が ipv4/ipv6 で分割された dict または tuple があると便利です。

4

1 に答える 1

3

私はこれを理解しました.. client.lookupAllRecords を使用してから、返されるレコードのタイプをテストする必要があります..

#!/usr/bin/python

from twisted.internet import defer, reactor
from twisted.names import client, dns

def got_arg(*args):
    for a in args[0][0]:
        if a.payload.TYPE == dns.A:
            print 'A    - ipv4',a.payload
        elif a.payload.TYPE == dns.AAAA:
            print 'AAAA - ipv6',a.payload


def get_arg(arg):
    d = client.lookupAllRecords('www.google.com').addCallback(got_arg)

if __name__ == '__main__':
    get_arg('www.google.com')
    reactor.run()

編集

私は、この解決策が不十分であることを認識しています。特に、レコードの最初のバッチに別のアドレスを指す単一の CNAME しか含まれていない場合..

これは、 twisted.names.common.extractRecord() が最初に ipv6 アドレスを探し、すぐにそれらを返すためです。この動作をオーバーライドする明白なメカニズムはありません。

そこで、醜いモンキー パッチを作成して ipv6 アドレスのチェーンを解決しようとさえしないように、これに対するハックなソリューションをまとめました。

#!/usr/bin/python

import socket
from twisted.names import dns
from twisted.names import common

def myExtractRecord(resolver, name, answers, level=10):
    if not level:
        return None
    for r in answers:
        if r.name == name and r.type == dns.A:
            return socket.inet_ntop(socket.AF_INET, r.payload.address)
    for r in answers:
        if r.name == name and r.type == dns.CNAME:
            result = myExtractRecord(
                resolver, r.payload.name, answers, level - 1)
            if not result:
                return resolver.getHostByName(
                    str(r.payload.name), effort=level - 1)
            return result
    # No answers, but maybe there's a hint at who we should be asking about
    # this
    for r in answers:
        if r.type == dns.NS:
            from twisted.names import client
            r = client.Resolver(servers=[(str(r.payload.name), dns.PORT)])
            return r.lookupAddress(str(name)
                ).addCallback(
                    lambda (ans, auth, add):
                        myExtractRecord(r, name, ans + auth + add, level - 1))

common.extractRecord = myExtractRecord

私はそれを dnsclient.py に入れて、メインのプログラムで次のように使用します。

from twisted.names import client
import dnsclient

これに対するよりエレガントな解決策があれば、私はすべて耳にします。getHostByName が dns.A,dns.AAAA,dns.A && dns.AAAA のマスクを受け入れて、どのレコードのツリーをたどるかを判断する場合、これはより友好的だと思います。

于 2012-12-11T13:11:18.547 に答える