electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

commit 27cc09e8e229e4e55ebf5ae010803bd4730da841
parent 89a9ce2ab4520c39148a83d66f1fc553612f64d3
Author: ThomasV <thomasv@gitorious>
Date:   Tue,  1 Oct 2013 11:24:55 +0200

prevent dns leaks when using proxy. fixes issue #147

Diffstat:
Mlib/interface.py | 41++++++++++++++++++++++++++---------------
Mlib/network.py | 4++++
2 files changed, 30 insertions(+), 15 deletions(-)

diff --git a/lib/interface.py b/lib/interface.py @@ -17,9 +17,11 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. -import random, socket, ast, re, ssl, errno, os +import random, ast, re, errno, os import threading, traceback, sys, time, json, Queue import socks +import socket +import ssl from version import ELECTRUM_VERSION, PROTOCOL_VERSION from util import print_error, print_msg @@ -60,6 +62,7 @@ class Interface(threading.Thread): s = config.get('server') host, port, protocol = s.split(':') port = int(port) + if protocol not in 'ghst': raise BaseException('Unknown protocol: %s'%protocol) @@ -68,6 +71,8 @@ class Interface(threading.Thread): self.protocol = protocol self.use_ssl = ( protocol in 'sg' ) self.proxy = self.parse_proxy_options(config.get('proxy')) + if self.proxy: + self.proxy_mode = proxy_modes.index(self.proxy["mode"]) + 1 self.server = host + ':%d:%s'%(port, protocol) @@ -174,7 +179,7 @@ class Interface(threading.Thread): print_error( "send_http", messages ) if self.proxy: - socks.setdefaultproxy(proxy_modes.index(self.proxy["mode"]) + 1, self.proxy["host"], int(self.proxy["port"]) ) + socks.setdefaultproxy(self.proxy_mode, self.proxy["host"], int(self.proxy["port"]) ) socks.wrapmodule(urllib2) cj = cookielib.CookieJar() @@ -237,31 +242,37 @@ class Interface(threading.Thread): def start_tcp(self): + if self.proxy is not None: + + socks.setdefaultproxy(self.proxy_mode, self.proxy["host"], int(self.proxy["port"])) + socket.socket = socks.socksocket + # prevent dns leaks, see http://stackoverflow.com/questions/13184205/dns-over-proxy + def getaddrinfo(*args): + return [(socket.AF_INET, socket.SOCK_STREAM, 6, '', (args[0], args[1]))] + socket.getaddrinfo = getaddrinfo + if self.use_ssl: cert_path = os.path.join( self.config.get('path'), 'certs', self.host) if not os.path.exists(cert_path): - dir_path = os.path.join( self.config.get('path'), 'certs') - if not os.path.exists(dir_path): - os.mkdir(dir_path) + # get server certificate. + # Do not use ssl.get_server_certificate because it does not work with proxy + s = socket.socket( socket.AF_INET, socket.SOCK_STREAM ) try: - cert = ssl.get_server_certificate((self.host, self.port)) + s.connect((self.host, self.port)) except: print_error("failed to connect", self.host, self.port) return + + s = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_SSLv3, cert_reqs=ssl.CERT_NONE, ca_certs=None) + dercert = s.getpeercert(True) + s.close() + cert = ssl.DER_cert_to_PEM_cert(dercert) with open(cert_path,"w") as f: f.write(cert) - self.connection_msg = "%s:%d"%(self.host, self.port) - - - if self.proxy is None: - s = socket.socket( socket.AF_INET, socket.SOCK_STREAM ) - else: - self.connection_msg += " using proxy %s:%s:%s"%(self.proxy.get('mode'), self.proxy.get('host'), self.proxy.get('port')) - s = socks.socksocket() - s.setproxy(proxy_modes.index(self.proxy["mode"]) + 1, self.proxy["host"], int(self.proxy["port"]) ) + s = socket.socket( socket.AF_INET, socket.SOCK_STREAM ) s.settimeout(2) s.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) diff --git a/lib/network.py b/lib/network.py @@ -56,6 +56,10 @@ class Network(threading.Thread): self.proxy = self.config.get('proxy') self.heights = {} + dir_path = os.path.join( self.config.path, 'certs') + if not os.path.exists(dir_path): + os.mkdir(dir_path) + def register_callback(self, event, callback): with self.lock: