在 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 版本的主要内容,如果未能解决你的问题,请参考以下文章