ОБНОВЛЕНО: фиксированный/рабочий код внизу вопроса. Реализован для использования wrap_socket()
вместо SSL.Context()
. Согласованный шифр кажется незатронутым ssl.PROTOCOL_
Почему этот код Python не подключается через SSL?
У меня есть служба XML, которая слушает порт 8388. У службы есть свой собственный встроенный CA и выдает файл P12 для любого клиента, настроенного на его интерфейсе администратора (мне нужно включить сертификат CA в моих подключениях).
Я настроил клиента и загрузил файл P12; также экспортировал файлы PEM (для более легкой отладки) из P12 и экспортировал файл PEM для CA сервера (который был хранилищем ключей Java).
Если я использую openssl s_client
и подаю ему сертификат/ключ на стороне клиента и файл CA, все работает правильно; т.е.: проверить возврат: 1 в усеченном выходе ниже. Процесс openssl не создает никаких ошибок сертификата на сервере (как и мой скрипт Python). Из того, что я читал, это означает, что сертификаты все в порядке и действительны.
# openssl s_client -connect srv.domain.net:8388 -CAfile server_ca.pem -cert client_cert.pem -key client_key.pem
CONNECTED(00000003)
depth=1 ... emailAddress = [email protected]
verify return:1
depth=0 ...CN = srv.domain.net
verify return:1
---
Certificate chain
0 s:/[email protected]=srv.domain.net
i:/C=US/[email protected]
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIJRDCCByygAwIBAgIGAVGIopaoMA0GCSqGSIb3DQEBDQUAMIG...rV
-----END CERTIFICATE-----
subject=/[email protected]=srv.domain.net
issuer=/C=US/[email protected]
---
Acceptable client certificate CA names
/C=US/[email protected]
/.../CN=srv.domain.net
---
SSL handshake has read 3369 bytes and written 5705 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES256-GCM-SHA384
Session-ID: ...DF6572FA00D62D83CF0B1A82F
Session-ID-ctx:
Master-Key: ...7F685C0B163A7739C271E9722FC0554108175C4
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
Start Time: 1461337153
Timeout : 300 (sec)
Verify return code: 0 (ok)
---
Я сейчас пытается подключить Python (2.7.9) скрипт для службы XML с использованием того же CERT, ключ и CA файл, но я не могу заставить его работать. Python жалуется на ошибки SSLv3, и сервер говорит, что он не может проверить клиента. Таким образом, соединение работает, но рукопожатие, сертификаты или шифры или что-то не так.
Я искал множество примеров и реализаций, и этот, казалось, был самым простым, поэтому я начал с него для шаблона. SSL3 - это не протокол, который я бы придерживался (POODLE), но он должен был быть из рабочего примера, поэтому я хотел сделать как можно меньше изменений, чтобы заставить все работать, а затем откорректировать их. Кто-нибудь знает, что я здесь не так? ouput/errors/logs отправляются на крайнем дне. Выход
#!/usr/bin/python
# -*- coding: utf-8 -*-
import socket
import OpenSSL
from OpenSSL import *
import sys
serverName = sys.argv[1]
print "Using server : " + serverName
ctx = SSL.Context(SSL.SSLv3_METHOD)
ctx.use_privatekey_file('client_key.pem')
ctx.use_certificate_file('client_cert.pem')
ctx.load_verify_locations(cafile='server_ca.pem')
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((serverName, 8388))
sslSocket = socket.ssl(s)
print repr(sslSocket.server())
print repr(sslSocket.issuer())
print ("writing socket..")
sslSocket.write('<transaction><data>14</data></transaction>\n')
s.close()
Python:
Using server : localhost
Traceback (most recent call last):
File "./test3.py", line 29, in <module>
sslSocket = socket.ssl(s)
File "/usr/lib/python2.7/socket.py", line 64, in ssl
return _realssl.sslwrap_simple(sock, keyfile, certfile)
File "/usr/lib/python2.7/ssl.py", line 993, in sslwrap_simple
ssl_sock.do_handshake()
ssl.SSLError: [SSL: SSLV3_ALERT_BAD_CERTIFICATE] sslv3 alert bad certificate (_ssl.c:581)
Журналы сервера после подключения выше:
Apr 22 10:39:56 srv.domain.net ERROR server.auth [Thread-183,run:233] Couldn't validate the client certificate. Verify the validity and dates of the client cert.
Apr 22 10:39:56 srv.domain.net javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
Apr 22 10:39:56 srv.domain.net at sun.security.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:431)
Apr 22 10:39:56 srv.domain.net at com.xml.server.auth.run(auth.java:226)
Apr 22 10:39:56 srv.domain.net at java.lang.Thread.run(Thread.java:745)
Рабочий код:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import socket
import ssl
import sys
import os
serverName = sys.argv[1]
print "Using server : " + serverName
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# ssl.PROTOCOL_xxx does not seem to affect negotiated cipher??
wrapper = ssl.wrap_socket(s,
ca_certs = "server_ca.pem",
certfile = "client_cert.pem",
keyfile = "client_key.pem",
cert_reqs=ssl.CERT_REQUIRED,
ssl_version=ssl.PROTOCOL_TLSv1)
wrapper.connect((serverName, 8388))
# some info on the connnection/cipher in use
print repr(wrapper.getpeername())
print repr(wrapper.cipher())
print repr(wrapper.getpeercert())
# send server command
print ("writing socket..")
wrapper.send ("<transaction><data>14</data></transaction>\n")
# read server reply
print "server reply: " + wrapper.recv(4096)
wrapper.close()
s.close()
Возможно, это не является причиной проблемы, но вы ограничиваете нерабочий код python SSL 3.0, тогда как openssl успешно использует TLS 1.2. Повторите попытку с удалением этого ограничения. –
Вы имеете в виду 'ctx = SSL.Context (SSL.SSLv3_METHOD)'? Независимо от того, какой протокол я тоже установил (SSL.SSLv23_METHOD, TLSv1_METHOD, TLSv1_2_METHOD), я все равно получаю ту же ошибку «sslv3 alert bad certificate». Я озадачен .. это диктует сервер? – Koko
Насколько я понимаю, сервер не хочет принимать ваш сертификат клиента. По крайней мере, вы знаете, что эта ошибка не относится к версии SSL/TLS. –