I'm trying to use Python to test a web server. I have nearly no experience with Python, but encouraged to use it because its easy to learn and simple to do things with (someone else's opinion, not mine at the moment). The script I am using is:
s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s2 = ssl.wrap_socket(s1,
ca_certs="./pki/signing-dss-cert.pem",
cert_reqs=ssl.CERT_REQUIRED,
ssl_version=ssl.PROTOCOL_TLSv1,
server_hostname="localhost")
s2.connect( ("localhost", 8443) )
s2.send("GET / ")
time.sleep(1)
s2.send("HTTP/1.1")
The error is:
Traceback (most recent call last):
File "./fetch.sh", line 10, in <module>
server_hostname="localhost")
TypeError: wrap_socket() got an unexpected keyword argument 'server_hostname'
I've also tried using servername
, name
, hostname
and sni
with no joy.
The Python docs don't mention SNI (TLS/SSL wrapper for socket objects and SSL wiki page). But I know the patch for SNI and server_hostname
was incorporated 4 years ago in 2010 (Add a *server_hostname* argument to SSLContext.wrap_socket
, changeset 65593:846c0e1342d0).
The equivalent OpenSSL call I need access to is SSL_set_tlsext_host_name
.
How do I specify the SNI hostname? (Eventually, I'll need to set it to an arbitrary name because I am testing a proxy).
First connect, then wrap the socket.
In case of python2 I also use the following hack sometimes (because the
httplib.HTTPSConnection
documentation says that it doesn't perform any kind of checking on the https server cert):Note that if you want to communicate with the server then using a http client is often much easier than playing around with raw sockets.
The patch you're mentioning is for Python 3.2, and you're using Python 2.7. Issue 5639 also seems to indicate there is no plan to back-port SNI support for Python 2.7.
You could wrap the socket with pyOpenSSL instead (its
Connection
class has aset_tlsext_host_name
since version 0.13. (I'm not sure which version comes with Debian 7.3, you might want to set up a virtualenv and upgrade to a newer version locally, if needed.)There is an SNI example is the pyOpenSSL repository.
If you want your usage of
wrap_socket
to be more compatible with the trick were you replace the value ofsock
in anhttplib
connection, you could have a look at how urllib3 does this with pyOpenSSL. Essentially, it creates anOpenSSL.SSL.Connection
from an existing socket, but since that connection isn't compatible with a socket, it wraps it into a class that implements the required method.(By the way, in Python 2.7,
urllib
,urllib2
andhttpconnection
don't do any certificate verification at all, unless you implement it yourself by wrapping their sockets.)EDIT:
Here is a version of your code that should work with Python 3.2. Unfortunately, the
server_name
parameter isn't in the plainssl.wrap_socket
, only inSSLContext.wrap_socket
, but you can useSSLSocket
directly.My env is:requests==2.7.0, python-2.7.5-34.el7.x86_64, gevent==1.0.2
Change python version to python-2.7.5-18.el7_1.1.x86_64, problem is solved.
on CentOS:
pakages can search on google.