在 python http.client.HTTPSConnection 中设置更新的 ssl 版本

Posted

技术标签:

【中文标题】在 python http.client.HTTPSConnection 中设置更新的 ssl 版本【英文标题】:Setting newer ssl version in python http.client.HTTPSConnection 【发布时间】:2021-09-08 00:28:14 【问题描述】:

我有以下 https 客户端,它尝试将简单的 POST 请求发送到删除服务器。

!/usr/bin/python3

import http.client
import json
import ssl

context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)

connection = http.client.HTTPSConnection('192.168.11.1', 444, context = context)

headers = 'Content-type': 'application/json',
           'Accept': 'application/json',
           'Content-Length': '0'

foo = 'ver': '111'
json_foo = json.dumps(foo)

connection.request('POST', '/post', json_foo, headers)

response = connection.getresponse()

print(response.read().decode())

但是,这样做时我得到[SSL: WRONG_VERSION_NUMBER] wrong version number 所以我尝试手动将 ssl 协议设置为较新的版本(通过在创建连接时使用 ssl.SSLContext)。

这是调用堆栈:

  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/http/client.py", line 1245, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/http/client.py", line 1291, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/http/client.py", line 1240, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/http/client.py", line 1008, in _send_output
    self.send(msg)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/http/client.py", line 948, in send
    self.connect()
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/http/client.py", line 1414, in connect
    self.sock = self._context.wrap_socket(self.sock,
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/ssl.py", line 500, in wrap_socket
    return self.sslsocket_class._create(
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/ssl.py", line 1040, in _create
    self.do_handshake()
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/ssl.py", line 1309, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLError: [SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:1108)

但是,在 python3 中,这是我拥有的选项。不幸的是,协议 2 和 3 不在列表中。

PROTOCOL_SSLv23     
PROTOCOL_TLS_SERVER 
PROTOCOL_TLSv1_2
PROTOCOL_TLS        
PROTOCOL_TLSv1
PROTOCOL_TLS_CLIENT 
PROTOCOL_TLSv1_1

知道如何在 http 连接中升级 ssl 版本的套接字吗? 我需要升级 ssl 包吗?我认为它在python3(3.8.2)中相对更新

谢谢!

【问题讨论】:

"... 协议 2 和 3 ..." - SSLv2 和 SSLv3 旧且损坏,因此今天已禁用。最新的实际上是 TLS 1.3,您的堆栈似乎还不支持。但是 TLS 1.2 很好,使用它。此外,您不需要显式设置上下文,当没有给出任何内容时它将使用默认上下文,并且此默认上下文通常是您想要的。 “我有这个以下 https 客户端 ...” - 最好使用更现代的资源进行学习。 @SteffenUllrich,感谢您的有用评论。该服务器基于aiohttp.web,看起来它不支持上面列出的任何协议。我愿意采用更好的http客户端包(最好内置在python3中,但不是强制性的)也许你可以推荐任何http.client的替代品并支持更多的ssl协议? 您拥有的协议支持可能很好。我的猜测是您的服务器端是问题所在。如果服务器根本不使用 TLS,也会发生这种恼人的错误消息。不幸的是,对服务器一无所知,所以我只能猜测。 @SteffenUllrich,我的第一个怀疑是在客户端,因为当我使用以下curl 命令行时它起作用了:curl -X POST -H "Content-type: application/json" -H "Accept: application/json" -d '"param":"value"' "http://192.168.11.1:444/post" ... 使用 client.http 时,ssl 版本错误来自协议握手(用完整的调用堆栈更新了问题) 【参考方案1】:

...当我使用... curl ...“http://192.168.11.1:444/post”时它起作用了

您使用 curl 成功完成的是一个普通的 HTTP 请求(http://... 不是 https://...)。您正在尝试(和失败)的代码是 HTTPS 请求,即 HTTP over TLS。错误消息是因为尝试对不支持 TLS 的服务器使用 TLS。

【讨论】:

以上是关于在 python http.client.HTTPSConnection 中设置更新的 ssl 版本的主要内容,如果未能解决你的问题,请参考以下文章

以奇怪的格式获取PHP IP

python交互窗口在哪

在CentOS 8上安装Python

在树莓派上的python3

如何在命令行里运行python脚本

如何在windows cmd下运行python