prevent dns leaks when using proxy. fixes issue #147

This commit is contained in:
ThomasV 2013-10-01 11:24:55 +02:00
parent 89a9ce2ab4
commit 27cc09e8e2
2 changed files with 30 additions and 15 deletions

View File

@ -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)

View File

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