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:
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: