I have an issue setting the SNI flag correctly using ssl.SSLContext in Python 2.7.10, the handshake fails every time and I can't figure out why.
Here is how I tried to do it:
import ssl
import socket
if ssl.HAS_SNI:
print "SNI is available"
print(ssl.OPENSSL_VERSION)
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
context.load_cert_chain('cacrt.pem', 'cakey.pem', 'password')
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock = context.wrap_socket(sock, server_hostname='virtServer')
sock.connect(('ip.to.the.server', 443))
http_client = tornado.httpclient.HTTPClient()
http_client.fetch('https://ip.to.the.server/some_url', method='GET', ssl_options=context)
And here is the output I get:
SNI is available
OpenSSL 0.9.8zd 8 Jan 2015
Traceback (most recent call last):
File "test/steps/test.py", line 37, in <module>
sock.connect(('10.59.71.242', 443))
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ssl.py", line 844, in connect
self._real_connect(addr, False)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ssl.py", line 835, in _real_connect
self.do_handshake()
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ssl.py", line 808, in do_handshake
self._sslobj.do_handshake()
ssl.SSLError: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:590)
What am I doing wrong that is causing this error? How can I change my code to solve this issue ?
Any ideas/help on this would be much appreciated.
Thanks, Regards, Yaro
It is very hard to tell without having ore information about the server, but I'll try:
You are restricting the protocol to TLS 1.0. It might be that the server expects TLS 1.2 or TLS 1.1 or SSL 3.0. Note that TLS 1.1+ are not support with the version of OpenSSL you are using. It might also be that the server has no shared ciphers.
Try to connect with a browser and see which TLS version is spoken and which ciphers are used. If this works but requires TLS 1.1+ try to create a connection with curl or wget. If this is a public URL use SSLLabs to check the supported protocols and ciphers.
If you really use an IP address here it might also be a problem that the server does not accept the IP address as the SNI name. Some servers cause a handshake failure if the given name does not match the configuration while others simply return a default certificate. Apart from that the hostname in the URL must match the name in the certificate so that the certificate validation can succeed.