DNS bootstrap over Tor
If proxy type is SOCKS5, it will try to perform DNS bootstrap using the Tor RESOLVE extension.
This commit is contained in:
parent
1e89616c0f
commit
d75533c6b6
|
@ -5,6 +5,7 @@ import pickle
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from debug import logger
|
from debug import logger
|
||||||
|
import socks
|
||||||
|
|
||||||
def knownNodes():
|
def knownNodes():
|
||||||
try:
|
try:
|
||||||
|
@ -37,20 +38,51 @@ def dns():
|
||||||
# defaultKnownNodes.py. Hopefully either they are up to date or the user
|
# defaultKnownNodes.py. Hopefully either they are up to date or the user
|
||||||
# has run Bitmessage recently without SOCKS turned on and received good
|
# has run Bitmessage recently without SOCKS turned on and received good
|
||||||
# bootstrap nodes using that method.
|
# bootstrap nodes using that method.
|
||||||
with shared.printLock:
|
if shared.config.get('bitmessagesettings', 'socksproxytype') == 'none':
|
||||||
if shared.config.get('bitmessagesettings', 'socksproxytype') == 'none':
|
try:
|
||||||
|
for item in socket.getaddrinfo('bootstrap8080.bitmessage.org', 80):
|
||||||
|
logger.info('Adding ' + item[4][0] + ' to knownNodes based on DNS bootstrap method')
|
||||||
|
shared.knownNodes[1][shared.Peer(item[4][0], 8080)] = int(time.time())
|
||||||
|
except:
|
||||||
|
logger.error('bootstrap8080.bitmessage.org DNS bootstrapping failed.')
|
||||||
|
try:
|
||||||
|
for item in socket.getaddrinfo('bootstrap8444.bitmessage.org', 80):
|
||||||
|
logger.info ('Adding ' + item[4][0] + ' to knownNodes based on DNS bootstrap method')
|
||||||
|
shared.knownNodes[1][shared.Peer(item[4][0], 8444)] = int(time.time())
|
||||||
|
except:
|
||||||
|
logger.error('bootstrap8444.bitmessage.org DNS bootstrapping failed.')
|
||||||
|
elif shared.config.get('bitmessagesettings', 'socksproxytype') == 'SOCKS5':
|
||||||
|
for port in [8080, 8444]:
|
||||||
|
logger.debug("Resolving %i through SOCKS...", port)
|
||||||
|
address_family = socket.AF_INET
|
||||||
|
sock = socks.socksocket(address_family, socket.SOCK_STREAM)
|
||||||
|
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
|
sock.settimeout(20)
|
||||||
|
proxytype = socks.PROXY_TYPE_SOCKS5
|
||||||
|
sockshostname = shared.config.get(
|
||||||
|
'bitmessagesettings', 'sockshostname')
|
||||||
|
socksport = shared.config.getint(
|
||||||
|
'bitmessagesettings', 'socksport')
|
||||||
|
rdns = True # Do domain name lookups through the proxy; though this setting doesn't really matter since we won't be doing any domain name lookups anyway.
|
||||||
|
if shared.config.getboolean('bitmessagesettings', 'socksauthentication'):
|
||||||
|
socksusername = shared.config.get(
|
||||||
|
'bitmessagesettings', 'socksusername')
|
||||||
|
sockspassword = shared.config.get(
|
||||||
|
'bitmessagesettings', 'sockspassword')
|
||||||
|
sock.setproxy(
|
||||||
|
proxytype, sockshostname, socksport, rdns, socksusername, sockspassword)
|
||||||
|
else:
|
||||||
|
sock.setproxy(
|
||||||
|
proxytype, sockshostname, socksport, rdns)
|
||||||
try:
|
try:
|
||||||
for item in socket.getaddrinfo('bootstrap8080.bitmessage.org', 80):
|
ip = sock.resolve("bootstrap" + str(port) + ".bitmessage.org")
|
||||||
logger.info('Adding ' + item[4][0] + ' to knownNodes based on DNS bootstrap method')
|
sock.shutdown(socket.SHUT_RDWR)
|
||||||
shared.knownNodes[1][shared.Peer(item[4][0], 8080)] = int(time.time())
|
sock.close()
|
||||||
except:
|
except:
|
||||||
logger.error('bootstrap8080.bitmessage.org DNS bootstrapping failed.')
|
logger.error("SOCKS DNS resolving failed", exc_info=True)
|
||||||
try:
|
if ip is not None:
|
||||||
for item in socket.getaddrinfo('bootstrap8444.bitmessage.org', 80):
|
logger.info ('Adding ' + ip + ' to knownNodes based on SOCKS DNS bootstrap method')
|
||||||
logger.info ('Adding ' + item[4][0] + ' to knownNodes based on DNS bootstrap method')
|
shared.knownNodes[1][shared.Peer(ip, port)] = time.time()
|
||||||
shared.knownNodes[1][shared.Peer(item[4][0], 8444)] = int(time.time())
|
else:
|
||||||
except:
|
logger.info('DNS bootstrap skipped because the proxy type does not support DNS resolution.')
|
||||||
logger.error('bootstrap8444.bitmessage.org DNS bootstrapping failed.')
|
|
||||||
else:
|
|
||||||
logger.info('DNS bootstrap skipped because SOCKS is used.')
|
|
||||||
|
|
||||||
|
|
|
@ -155,7 +155,7 @@ class socksocket(socket.socket):
|
||||||
"""
|
"""
|
||||||
self.__proxy = (proxytype, addr, port, rdns, username, password)
|
self.__proxy = (proxytype, addr, port, rdns, username, password)
|
||||||
|
|
||||||
def __negotiatesocks5(self, destaddr, destport):
|
def __negotiatesocks5(self):
|
||||||
"""__negotiatesocks5(self,destaddr,destport)
|
"""__negotiatesocks5(self,destaddr,destport)
|
||||||
Negotiates a connection through a SOCKS5 server.
|
Negotiates a connection through a SOCKS5 server.
|
||||||
"""
|
"""
|
||||||
|
@ -200,6 +200,8 @@ class socksocket(socket.socket):
|
||||||
raise Socks5AuthError((2, _socks5autherrors[2]))
|
raise Socks5AuthError((2, _socks5autherrors[2]))
|
||||||
else:
|
else:
|
||||||
raise GeneralProxyError((1, _generalerrors[1]))
|
raise GeneralProxyError((1, _generalerrors[1]))
|
||||||
|
|
||||||
|
def __connectsocks5(self, destaddr, destport):
|
||||||
# Now we can request the actual connection
|
# Now we can request the actual connection
|
||||||
req = struct.pack('BBB', 0x05, 0x01, 0x00)
|
req = struct.pack('BBB', 0x05, 0x01, 0x00)
|
||||||
# If the given destination address is an IP address, we'll
|
# If the given destination address is an IP address, we'll
|
||||||
|
@ -247,6 +249,37 @@ class socksocket(socket.socket):
|
||||||
else:
|
else:
|
||||||
self.__proxypeername = (destaddr, destport)
|
self.__proxypeername = (destaddr, destport)
|
||||||
|
|
||||||
|
def __resolvesocks5(self, host):
|
||||||
|
# Now we can request the actual connection
|
||||||
|
req = struct.pack('BBB', 0x05, 0xF0, 0x00)
|
||||||
|
req += chr(0x03).encode() + chr(len(host)).encode() + host
|
||||||
|
req = req + struct.pack(">H", 8444)
|
||||||
|
self.sendall(req)
|
||||||
|
# Get the response
|
||||||
|
ip = ""
|
||||||
|
resp = self.__recvall(4)
|
||||||
|
if resp[0:1] != chr(0x05).encode():
|
||||||
|
self.close()
|
||||||
|
raise GeneralProxyError((1, _generalerrors[1]))
|
||||||
|
elif resp[1:2] != chr(0x00).encode():
|
||||||
|
# Connection failed
|
||||||
|
self.close()
|
||||||
|
if ord(resp[1:2])<=8:
|
||||||
|
raise Socks5Error((ord(resp[1:2]), _socks5errors[ord(resp[1:2])]))
|
||||||
|
else:
|
||||||
|
raise Socks5Error((9, _socks5errors[9]))
|
||||||
|
# Get the bound address/port
|
||||||
|
elif resp[3:4] == chr(0x01).encode():
|
||||||
|
ip = socket.inet_ntoa(self.__recvall(4))
|
||||||
|
elif resp[3:4] == chr(0x03).encode():
|
||||||
|
resp = resp + self.recv(1)
|
||||||
|
ip = self.__recvall(ord(resp[4:5]))
|
||||||
|
else:
|
||||||
|
self.close()
|
||||||
|
raise GeneralProxyError((1,_generalerrors[1]))
|
||||||
|
boundport = struct.unpack(">H", self.__recvall(2))[0]
|
||||||
|
return ip
|
||||||
|
|
||||||
def getproxysockname(self):
|
def getproxysockname(self):
|
||||||
"""getsockname() -> address info
|
"""getsockname() -> address info
|
||||||
Returns the bound IP address and port number at the proxy.
|
Returns the bound IP address and port number at the proxy.
|
||||||
|
@ -361,7 +394,8 @@ class socksocket(socket.socket):
|
||||||
else:
|
else:
|
||||||
portnum = 1080
|
portnum = 1080
|
||||||
_orgsocket.connect(self, (self.__proxy[1], portnum))
|
_orgsocket.connect(self, (self.__proxy[1], portnum))
|
||||||
self.__negotiatesocks5(destpair[0], destpair[1])
|
self.__negotiatesocks5()
|
||||||
|
self.__connectsocks5(destpair[0], destpair[1])
|
||||||
elif self.__proxy[0] == PROXY_TYPE_SOCKS4:
|
elif self.__proxy[0] == PROXY_TYPE_SOCKS4:
|
||||||
if self.__proxy[2] != None:
|
if self.__proxy[2] != None:
|
||||||
portnum = self.__proxy[2]
|
portnum = self.__proxy[2]
|
||||||
|
@ -380,3 +414,15 @@ class socksocket(socket.socket):
|
||||||
_orgsocket.connect(self, (destpair[0], destpair[1]))
|
_orgsocket.connect(self, (destpair[0], destpair[1]))
|
||||||
else:
|
else:
|
||||||
raise GeneralProxyError((4, _generalerrors[4]))
|
raise GeneralProxyError((4, _generalerrors[4]))
|
||||||
|
|
||||||
|
def resolve(self, host):
|
||||||
|
if self.__proxy[0] == PROXY_TYPE_SOCKS5:
|
||||||
|
if self.__proxy[2] != None:
|
||||||
|
portnum = self.__proxy[2]
|
||||||
|
else:
|
||||||
|
portnum = 1080
|
||||||
|
_orgsocket.connect(self, (self.__proxy[1], portnum))
|
||||||
|
self.__negotiatesocks5()
|
||||||
|
return self.__resolvesocks5(host)
|
||||||
|
else:
|
||||||
|
return None
|
Reference in New Issue
Block a user