Python ssl 无法使用 TLS1.2 客户端连接到 TLS1.2 服务器

标签 python python-3.x sockets ssl tls1.2

我正在开发一个 python3 套接字 + ssl 服务器,用于服务器和客户端之间的数据交换。我制作了一个可与 Google.com、python.org 和我自己的 apache2 网络服务器配合使用的客户端。

当我启动服务器并尝试通过 open ssl 连接时 openssl s_client -connect myserver.com:8443 它返回:

    CONNECTED(00000003)
    140035580617152:error:1408F10B:SSL routines:ssl3_get_record:wrong version number:../ssl/record/ssl3_record.c:252:
    ---
    no peer certificate available
    ---
    No client certificate CA names sent
    ---
    SSL handshake has read 5 bytes and written 176 bytes
    Verification: OK
    ---
    New, (NONE), Cipher is (NONE)
    Secure Renegotiation IS NOT supported
    Compression: NONE
    Expansion: NONE
    No ALPN negotiated
    SSL-Session:
        Protocol  : TLSv1.2
        Cipher    : 0000
        Session-ID: 
        Session-ID-ctx: 
        Master-Key: 
        PSK identity: None
        PSK identity hint: None
        SRP username: None
        Start Time: 1547929149
        Timeout   : 7200 (sec)
        Verify return code: 0 (ok)
        Extended master secret: no
    ---

我对此不确定,但看起来支持 TLSv1.2。 当我尝试与我的客户端连接时出现以下错误

    Traceback (most recent call last):
      File "client-1.py", line 38, in <module>
        sock.connect((HOST, PORT))
      File "/usr/lib/python3.6/ssl.py", line 1109, in connect
        self._real_connect(addr, False)
      File "/usr/lib/python3.6/ssl.py", line 1100, in _real_connect
        self.do_handshake()
      File "/usr/lib/python3.6/ssl.py", line 1077, in do_handshake
        self._sslobj.do_handshake()
      File "/usr/lib/python3.6/ssl.py", line 689, in do_handshake
        self._sslobj.do_handshake()
    ssl.SSLError: [SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:847)

奇怪的是,当我使用我的客户端连接到例如我自己的 apache2 服务器(使用 ssl)时,它返回 TLSv1.2 这真的让我想知道问题是否出在我的客户端或我的服务器

我已经尝试在服务器和客户端上使用不同的 TLS/SSL 版本,但到目前为止都没有用。 我尝试的另一件事是更新 OpenSSL,截至 2019 年 1 月 19 日,它是 Ubuntu 18.04 上可用的最新版本

我的服务器如下所示

import socket
import sys
from _thread import *
import ssl

context = ssl.SSLContext()
ssl.PROTOCOL_TLS_SERVER
#context.load_cert_chain(certfile="ssl/localhost/localhost.crt", keyfile="ssl/localhost/localhost.key")
context.load_cert_chain(certfile="ssl/certificate.crt", keyfile="ssl/private.key")


host = ''
port = 8443
print(port)

buffer = 134217700 #128 MiB

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)




def log_client_to_file(ip, port, data, file):
    #context manager
    with open(file, 'a') as f:
        f.write("User sent data from:\n\tIP: %s\n\tPort: %s\nData:\n%s\n\n" % (ip, port, data))

    #close file
    f.close()

def conn_process(buffer):
    data_tmp = conn.recv(buffer)
    data = str.encode('')
    while len(data_tmp) > 2:
        data += data_tmp
        data_tmp = conn.recv(buffer
        if len(data_tmp) < 2:
            data += data_tmp
            break
    return data

try:
    s.bind((host,port))
except socket.error as e:
    print(str(e))


s.listen(4)


print('Server is up and waiting for connection')
def client_threaded(conn, ip, port, file):
    conn.send(str.encode('Connected'))

    while True:

        data = conn_process(buffer)

        reply = 'Server output: %s' % data.decode('utf-8')
        if not data:
            break
        conn.sendall(str.encode(reply))
        log_client_to_file(ip, port, data, file)

while True:
    conn, addr = s.accept()
    print('connected to: %s:%s' % (addr[0], str(addr[1])))


    start_new_thread(client_threaded, (conn, addr[0], str(addr[1]), 'connections.log'))

s.close()


s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

现在,我的客户端是这样构建的,

import socket
import ssl

HOST = 'myserver.com'
PORT = 8443


args = ssl.SSLContext()
ssl.PROTOCOL_TLS_CLIENT
args.verify_mode = ssl.CERT_NONE
args.check_hostname = False
#ssl.ca_certs="ssl/ca_bundle.crt",

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock = args.wrap_socket(s, server_hostname=HOST)

sock.connect((HOST, PORT))

print(sock.version())

注意:因为我正在使用自签名证书进行测试,所以我还没有验证它们

由于客户端和服务器都使用 TLS,我希望连接不会成为问题,但我不断收到上述错误, ssl.SSLError: [SSL: WRONG_VERSION_NUMBER] 错误的版本号 (_ssl.c:847) 这让我很惊讶,因为我找不到任何错误。 也许你们知道我做错了什么以及我该如何解决

请注意,我正在使用 python 3.6 和 OpenSSL 1.1.0g 2017 年 11 月 2 日

最佳答案

I'm not sure about this but it looks like TLSv1.2 is supported.

不,它没有。

... ssl3_get_record:wrong version number:../ssl/record/ssl3_record.c:252:
...
SSL handshake has read 5 bytes and written 176 bytes
...
   Protocol  : TLSv1.2
   Cipher    : 0000

这表明客户端使用 ClientHello(176 字节)开始 TLS 握手,并且仅从服务器返回 5 个字节,这对于 TLS 握手中的预期响应来说太短了。这 5 个字节不包含 TLS 版本号,这就是为什么它会发出错误的版本号。这也由无通用密码表示:Cipher : 0000

看看你的服务器代码,在我看来你在开始时设置了一些 SSL 上下文(并且显示的代码似乎也被破坏了)但从未真正使用它,即你的服务器只是纯 TCP。难怪客户会提示。

关于Python ssl 无法使用 TLS1.2 客户端连接到 TLS1.2 服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54271387/

相关文章:

python - 带有变量的python子进程check_output中的错误

python - Dask - 如何连接到正在运行的集群调度程序并访问 'total_occupancy' ?

python - 外部 Pinax(入门)项目在哪里?

python - 反转 Python 字符串中的单词(包括标点符号)

c - IP 片段的 UDP 校验和如何变化?

python - 在 python 中使用带有条件的服务器端游标读取大量数据

python-3.x - 散列与 python 中的期望值不匹配的元组

python-3.x - 从 pathlib 的 Path 对象获取顶级

c - 如何为 connect() 设置超时以及如何测量它?

java - 使用 JAXB 从套接字解码 xml 后客户端被阻止