Crashes when connecting to IPv6 services
Closed this issue · 2 comments
pde commented
Trying one of the use cases described in the docs (in this case socksifying through tor)
In [1]: import socks
In [2]: import socket
In [3]: import urllib2
In [4]: socks.set_default_proxy(socks.SOCKS5, "localhost", 9050)
In [5]: socket.socket = socks.socksocket
In [6]: urllib2.urlopen("https://google.com")
Produces the following error:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-6-728442f30dba> in <module>()
----> 1 urllib2.urlopen("https://google.com")
/usr/lib/python2.7/urllib2.pyc in urlopen(url, data, timeout, cafile, capath, cadefault, context)
152 else:
153 opener = _opener
--> 154 return opener.open(url, data, timeout)
155
156 def install_opener(opener):
/usr/lib/python2.7/urllib2.pyc in open(self, fullurl, data, timeout)
429 req = meth(req)
430
--> 431 response = self._open(req, data)
432
433 # post-process response
/usr/lib/python2.7/urllib2.pyc in _open(self, req, data)
447 protocol = req.get_type()
448 result = self._call_chain(self.handle_open, protocol, protocol +
--> 449 '_open', req)
450 if result:
451 return result
/usr/lib/python2.7/urllib2.pyc in _call_chain(self, chain, kind, meth_name, *args)
407 func = getattr(handler, meth_name)
408
--> 409 result = func(*args)
410 if result is not None:
411 return result
/usr/lib/python2.7/urllib2.pyc in https_open(self, req)
1238 def https_open(self, req):
1239 return self.do_open(httplib.HTTPSConnection, req,
-> 1240 context=self._context)
1241
1242 https_request = AbstractHTTPHandler.do_request_
/usr/lib/python2.7/urllib2.pyc in do_open(self, http_class, req, **http_conn_args)
1192
1193 try:
-> 1194 h.request(req.get_method(), req.get_selector(), req.data, headers)
1195 except socket.error, err: # XXX what error?
1196 h.close()
/usr/lib/python2.7/httplib.pyc in request(self, method, url, body, headers)
999 def request(self, method, url, body=None, headers={}):
1000 """Send a complete request to the server."""
-> 1001 self._send_request(method, url, body, headers)
1002
1003 def _set_content_length(self, body):
/usr/lib/python2.7/httplib.pyc in _send_request(self, method, url, body, headers)
1033 for hdr, value in headers.iteritems():
1034 self.putheader(hdr, value)
-> 1035 self.endheaders(body)
1036
1037 def getresponse(self, buffering=False):
/usr/lib/python2.7/httplib.pyc in endheaders(self, message_body)
995 else:
996 raise CannotSendHeader()
--> 997 self._send_output(message_body)
998
999 def request(self, method, url, body=None, headers={}):
/usr/lib/python2.7/httplib.pyc in _send_output(self, message_body)
848 msg += message_body
849 message_body = None
--> 850 self.send(msg)
851 if message_body is not None:
852 #message_body was not a string (i.e. it is a file) and
/usr/lib/python2.7/httplib.pyc in send(self, data)
810 if self.sock is None:
811 if self.auto_open:
--> 812 self.connect()
813 else:
814 raise NotConnected()
/usr/lib/python2.7/httplib.pyc in connect(self)
1202 "Connect to a host on a given (SSL) port."
1203
-> 1204 HTTPConnection.connect(self)
1205
1206 if self._tunnel_host:
/usr/lib/python2.7/httplib.pyc in connect(self)
791 """Connect to the host and port specified in __init__."""
792 self.sock = self._create_connection((self.host,self.port),
--> 793 self.timeout, self.source_address)
794
795 if self._tunnel_host:
/usr/lib/python2.7/socket.pyc in create_connection(address, timeout, source_address)
561 sock.bind(source_address)
562 print "SA is", sa
--> 563 sock.connect(sa)
564 return sock
565
/usr/local/lib/python2.7/dist-packages/socks.pyc in connect(self, dest_pair)
626 dest_pair - 2-tuple of (IP/hostname, port).
627 """
--> 628 dest_addr, dest_port = dest_pair
629
630 if self.type == socket.SOCK_DGRAM:
ValueError: too many values to unpack
It seems that socks's connect() method is being called with a 4-tuple, ('2607:f8b0:4005:802::1000', 443, 0, 0) in this case.
pde commented
That's expected; the sa argument that's passed in is a sockaddr from getaddrinfo, which is different in IPv4 and IPv6. The call site is here.
lvh commented
Maybe this should synchronously raise a socket.error
so that socket.create_connection
will succeed the second time it tries to connect (using IPv4).