From c6124549cd1e5bf402f7122f2f8fe6c5289c8e93 Mon Sep 17 00:00:00 2001 From: SomberNight Date: Mon, 2 Jul 2018 00:59:28 +0200 Subject: [PATCH] don't dns resolve raw IP addresses --- lib/network.py | 49 +++++++++++++++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/lib/network.py b/lib/network.py index f2f2aab76..cf02535d5 100644 --- a/lib/network.py +++ b/lib/network.py @@ -32,12 +32,14 @@ import threading import socket import json import sys +import ipaddress import dns import dns.resolver import socks from . import util +from .util import print_error from . import bitcoin from .bitcoin import COIN from . import constants @@ -452,27 +454,38 @@ class Network(util.DaemonThread): # On Windows, socket.getaddrinfo takes a mutex, and might hold it for up to 10 seconds # when dns-resolving. To speed it up drastically, we resolve dns ourselves, outside that lock. # see #4421 - def fast_getaddrinfo(host, *args, **kwargs): - try: - if str(host) not in ('localhost', 'localhost.',): - answers = dns.resolver.query(host) - addr = str(answers[0]) - else: - addr = host - except dns.exception.DNSException: - # dns failed for some reason, e.g. dns.resolver.NXDOMAIN - # this is normal. Simply report back failure: - raise socket.gaierror(11001, 'getaddrinfo failed') - except BaseException as e: - # Possibly internal error in dnspython :( see #4483 - # Fall back to original socket.getaddrinfo to resolve dns. - self.print_error('dnspython failed to resolve dns with error:', e) - addr = host - return socket._getaddrinfo(addr, *args, **kwargs) - socket.getaddrinfo = fast_getaddrinfo + socket.getaddrinfo = self._fast_getaddrinfo else: socket.getaddrinfo = socket._getaddrinfo + @staticmethod + def _fast_getaddrinfo(host, *args, **kwargs): + def needs_dns_resolving(host2): + try: + ipaddress.ip_address(host2) + return False # already valid IP + except ValueError: + pass # not an IP + if str(host) in ('localhost', 'localhost.',): + return False + return True + try: + if needs_dns_resolving(host): + answers = dns.resolver.query(host) + addr = str(answers[0]) + else: + addr = host + except dns.exception.DNSException: + # dns failed for some reason, e.g. dns.resolver.NXDOMAIN + # this is normal. Simply report back failure: + raise socket.gaierror(11001, 'getaddrinfo failed') + except BaseException as e: + # Possibly internal error in dnspython :( see #4483 + # Fall back to original socket.getaddrinfo to resolve dns. + print_error('dnspython failed to resolve dns with error:', e) + addr = host + return socket._getaddrinfo(addr, *args, **kwargs) + @with_interface_lock def start_network(self, protocol, proxy): assert not self.interface and not self.interfaces