在 Python 中打开 SSL 套接字连接

Posted

技术标签:

【中文标题】在 Python 中打开 SSL 套接字连接【英文标题】:Opening a SSL socket connection in Python 【发布时间】:2015-01-07 04:24:41 【问题描述】:

我正在尝试在 Python 中建立一个安全的套接字连接,但我很难使用它的 SSL 位。我找到了一些如何与 SSL 建立连接的代码示例,但它们都涉及密钥文件。我尝试连接的服务器不需要接收任何密钥或证书。我的问题是我如何基本上用 SSL 包装 python 套接字连接。我知道我想使用的密码是ADH-AES256-SHA,协议是TLSv1。这是我一直在尝试的:

import socket
import ssl

# SET VARIABLES
packet, reply = "<packet>SOME_DATA</packet>", ""
HOST, PORT = 'XX.XX.XX.XX', 4434

# CREATE SOCKET
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(10)

# WRAP SOCKET ???
ssl.wrap_socket(sock, ssl_version="TLSv1", ciphers="ADH-AES256-SHA")

# CONNECT AND PRINT REPLY
sock.connect((HOST, PORT))
sock.send(packet)
print sock.recv(1280)

# CLOSE SOCKET CONNECTION
sock.close()

当我运行此代码时,我没有收到任何错误,但我得到一个空白响应。当尝试在命令行中调试此代码时,通过在终端中键入python 并逐行粘贴代码,我得到我假设运行sock.send(packet) 时的状态代码。我得到的整数响应是26。如果有人知道这意味着什么,或者无论如何可以提供帮助,将不胜感激。提前致谢!

【问题讨论】:

【参考方案1】:

我正在寻找一个可以使用 https 包启动连接的良好工作 ssl 套接字。这对我帮助很大,但有点过时,所以这里是 python3 的代码:

import socket
import ssl

package = "GET /ws/LiveWebcastUpdate/22000557 HTTP/1.1\r\nHost: 
www.website_name.com\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; 
rv:80.0) Gecko/20100101 Firefox/80.0\r\nAccept: */*\r\nAccept-Language: nl,en- 
US;q=0.7,en;q=0.3\r\nSec-WebSocket-Version: 13\r\nOrigin: 
https://www.website_name.com\r\nSec-WebSocket-Key: 
NU/EsJMICjSociJ751l0Xw==\r\nConnection: keep-alive, Upgrade\r\nPragma: no- 
cache\r\nCache-Control: no-cache\r\nUpgrade: websocket\r\n\r\n"

hostname = 'www.website_name.com'
port = 443

context = ssl.create_default_context()

with socket.create_connection((hostname, port)) as sock:
    with context.wrap_socket(sock, server_hostname=hostname) as ssock:
        print(ssock.version())
        ssock.send(package.encode())
        while True:
            data = ssock.recv(2048)
            if ( len(data) < 1 ) :
                break
            print(data)

这是尽可能简单的,更多信息请访问 https://docs.python.org/3/library/ssl.html

【讨论】:

【参考方案2】:

您不应该设置PROTOCOL_TLSv1(或TLSv1)。这将连接限制为仅TLS v1.0。相反,您需要支持库支持的所有版本的 PROTOCOL_TLS(或已弃用的 PROTOCOL_SSLv23)。

您使用的是匿名密码,因为出于某种原因您认为不需要证书或密钥。这意味着没有服务器的身份验证,并且您很容易受到中间人攻击。除非你真的知道自己在做什么,否则我建议你不要使用匿名密码(如 ADH-AES256-SHA)。

【讨论】:

您认为您可以提供如何实现证书或密钥的示例,而不是仅仅说不使用匿名密码吗?【参考方案3】:

解决这些问题很有趣,但对我来说,我发现 python ssl 的底层基础设施是 openssl。尝试使用 openssl 验证您的证书并在尝试让 python 使用相同的堆栈之前执行此操作。

在验证叶证书之前,我需要将根证书导入 openssl。

这很有帮助。http://gagravarr.org/writing/openssl-certs/others.shtml#ca-openssl

另一个有趣的事情是,在不同主机上相同版本的 python 的两个不同构建有不同的方法。一个有ssl.get_default_verify_paths(),另一个根本没有。这里的教训是 python ssl 是建立在 openssl 之上的。不同的底层库给你不同的python。

Python SSL 是基于 openssl 构建的,因此请先解决 openssl 中的证书问题。

【讨论】:

【参考方案4】:

好的,我知道出了什么问题。我有点傻。我的代码有two 问题。我的第一个错误是在指定ssl_version 时我输入了TLSv1,而它应该是ssl.PROTOCOL_TLSv1。第二个错误是我没有引用包装的套接字,而是调用了我创建的原始套接字。下面的代码似乎对我有用。

import socket
import ssl

# SET VARIABLES
packet, reply = "<packet>SOME_DATA</packet>", ""
HOST, PORT = 'XX.XX.XX.XX', 4434

# CREATE SOCKET
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(10)

# WRAP SOCKET
wrappedSocket = ssl.wrap_socket(sock, ssl_version=ssl.PROTOCOL_TLSv1, ciphers="ADH-AES256-SHA")

# CONNECT AND PRINT REPLY
wrappedSocket.connect((HOST, PORT))
wrappedSocket.send(packet)
print wrappedSocket.recv(1280)

# CLOSE SOCKET CONNECTION
wrappedSocket.close()

希望这可以帮助别人!

【讨论】:

我收到了这个错误:ssl.SSLError: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure 有什么想法吗? 很难从输出中分辨出来。上面的代码sn-p你用了吗?如果没有,我会提出一个新问题并发布您正在使用的代码:) [SSL: WRONG_VERSION_NUMBER] 错误的版本号 (_ssl.c:590)。通过 GNU/Linux (Ubuntu 16.04) @Kostanos 您可以尝试使用不同的密码。 IE。将ADH-AES256-SHA 替换为AES256-SHA。如果这不起作用,请尝试将TLSv1.2AES256-SHA256 一起使用。服务器很可能不支持密码或协议。

以上是关于在 Python 中打开 SSL 套接字连接的主要内容,如果未能解决你的问题,请参考以下文章

如何在python中序列化httplib SSL连接对象?

Python中的套接字错误

实现 SSL 证书的 Python 套接字 [关闭]

ssl 套接字不支持错误

PHP Web套接字未在SSL中连接

SSL 套接字连接