2

次のコードを使用して、Python を使用して HTTP 接続を設定しようとしています。hosts問題のマシンのやresolv.confファイルなどを変更できないため、自分で DNS 解決を行います。

class resolver(object):
    def __init__(self, server):
        self.server = server
    def __call__(self, host):
        res = check_output('host %s %s' % (host, self.server), shell = True)
        ips = findall('has address (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})', res)
        return choice(ips)

class http_connection(httplib.HTTPConnection):
    dns_server = '8.8.8.8'
    def connect(self):
        resolv = resolver(http_connection.dns_server)
        self.sock = socket.create_connection((resolv(self.host), self.port), self.timeout)
...
x = http_connection('%s:%d' % (args.host, args.port))
x.request('GET','/start/')
rep = x.getresponse()
print rep.read()

すべてが機能し、DNS から IP を取得し、ソケットが作成され (ホスト名ではなく、IP ポートのペアで)、応答が得られます。唯一のことは、最大5〜6秒という長い時間がかかることです。デバッグ後、何らかの理由で、解決された IP のリバース DNS ルックアップが発生し、タイムアウトになることがわかりました。/etc/hosts にエントリを追加した後、別のマシンで再現してこれが問題であることを確認しました。また、価値があるのは、curlまたはwgetを使用してもRDNSが発生したことです。

これを回避するための 2 つのオプションが表示されますが、実際にそれらを実装する方法がわかりません。

  1. 理想的には、逆ルックアップをデフォルトの動作にできるだけ一致させたいので、このルックアップを自分で提供する dns_server (resolv.conf にはありません) に強制的に移動させる方法はありますか?
  2. それが不可能な場合、この RDNS をどこかで無効にすることはできますか? setsockopt レベルまで上げることができます。
4

1 に答える 1

1

私はついにこれを自分で回避する方法を見つけました。どうやらこれは、送信元アドレスを自分で明示的に指定せず、システムに選択させた場合に発生するようです。Linux は、どのインターフェイスを使用するのが最適かを判断するためにいくつかのトリックを行っていると思いますが、RDNS はその 1 つです。

次のように source_address を指定すると、すべてが正常に機能します。

class http_connection(httplib.HTTPConnection):
    def __init__(self, dns_server, *args, **kwargs):
        httplib.HTTPConnection.__init__(self, *args, **kwargs)
        self.resolv = resolver(dns_server, self.source_address)
    def connect(self):
        self.sock = socket.create_connection((self.resolv(self.host), self.port), self.timeout, self.source_address)
...
x = http_connection(args.dns_server, '%s:%d' % (args.host, args.port), source_address = (args.source_address, 0))
于 2012-11-08T09:53:45.293 に答える