2015-06-17 5 views
1

У меня проблема с правильной установкой флага SNI с использованием ssl.SSLContext в Python 2.7.10, рукопожатие терпит неудачу каждый раз, и я не могу понять, почему.SSLV3_ALERT_HANDSHAKE_FAILURE с SNI с использованием Tornado 4.2 в Python 2.9.10

Вот как я пытался сделать это:

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) 

А вот выход я получаю:

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) 

Что я делаю неправильно, что вызывает эту ошибку? Как я могу изменить свой код для решения этой проблемы?

Любые идеи/помощь по этому вопросу будут высоко оценены.

Спасибо, С уважением, Яро

ответ

1

Это очень трудно сказать, без руды информацию о сервере, но я попытаюсь:

OpenSSL 0.9.8zd 8 янв 2015

контекст = ssl.SSLContext (ssl.PROTOCOL_TLSv1)

Вы ограничиваете протокол к TLS 1.0. Возможно, сервер ожидает TLS 1.2 или TLS 1.1 или SSL 3.0. Обратите внимание, что TLS 1.1+ не поддерживает версию OpenSSL, которую вы используете. Возможно также, что на сервере нет общих шифров.

Попробуйте подключиться к браузеру и посмотреть, какая версия TLS используется и какие шифры используются. Если это работает, но требует TLS 1.1+, попробуйте создать соединение с curl или wget. Если это общедоступный URL-адрес, используйте SSLLabs, чтобы проверить поддерживаемые протоколы и шифры.

http_client.fetch('https://ip.to.the.server/some_url', method='GET', ssl_options=context) 

Если вы действительно использовать IP-адрес здесь также может быть проблемой, что сервер не принимает IP-адрес в качестве имени SNI. Некоторые серверы вызывают сбои при рукопожатии, если данное имя не соответствует конфигурации, а другие просто возвращают сертификат по умолчанию. Кроме того, имя хоста в URL-адресе должно совпадать с именем в сертификате, чтобы проверка сертификата могла быть успешной.

1

Спасибо Steffen, ваши предложения в конечном итоге привели меня к решению. Проблема не в версии TLS или OpenSSL, а в том, что я не указывал шифры и необходимый шифр (RC4-SHA) не был в списке по умолчанию в Python 2.7.10.

context.set_ciphers('RC4-SHA') 

Кроме того, я не мог использовать созданный контекст с Tornado, так как мне нужно, чтобы обеспечить определенную server_hostname, которые образуют то, что я видел, может быть сделано только на патрубках объекта:

sock = context.wrap_socket(sock, server_hostname='virtServer') 

Вместо этого я использовали sock.write ('...') и sock.recv(), чтобы сделать запрос, и все отлично работало.