我在python中有一个简单的TLS客户端,可以连接到TLS服务器。我无法控制服务器。即使最近访问过,我也需要与每台服务器进行新的TLS握手。
1)默认情况下,非浏览器TLS客户端(例如以下python客户端)是否执行会话恢复?
2)我怎么知道他们是否这样做?如果在后台执行会话恢复,如何禁用它?
请注意,我为我连接到的每个新域创建了一个新套接字。
import socket, ssl
context = ssl.SSLContext()
context.verify_mode = ssl.CERT_NONE
context.check_hostname = False
mycipher = "DHE-RSA-AES128-SHA"
context.set_ciphers(mycipher)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
domain = "google.com"
mySocket = context.wrap_socket(sock, server_hostname = domain)
mySocket.connect((domain, 443))
mySocket.close()
答案 0 :(得分:1)
这是一个困难但有趣的问题。而且您确实使用了适当的术语 TLS ,这给我带来了快乐;-)
首先,请注意,TLS1.3中的会话恢复已发生更改,因此这可能会对您将来产生影响(至少在命名(TLS1.3之前的版本中),此功能更多地介绍了会话和票证,而TLS1.3更喜欢谈论预共享密钥):https://timtaubert.de/blog/2017/02/the-future-of-session-resumption/
现在关于您的问题:
ticket_lifetime_hint
和has_ticket
;这应该与恢复有关。现在看看https://docs.python.org/3.7/library/ssl.html#ssl.SSLContext.options,如果浏览所有可能的值,则会得到:
ssl.OP_NO_TICKET
阻止客户端请求会话票证。
所以我在1)中的假设可能是错误的,并且默认情况下您已恢复会话。您应该使用上面的选项将其禁用
(相反)似乎存在于PyOpenSSL
中(相对于股票ssl
),因为这里甚至还有一个问题,关于如何为该库禁用此功能:{{ 3}}
ClientHello
/ ServerHello
开始,其中恢复从相同的消息开始但以{{1 }} 延期。它的存在将显示TLS恢复。在TLS 1.2中,客户端将在恢复握手期间发送pre_shared_key
扩展名。SessionTicket
。否则默认情况下,它是ssl.OP_NO_TICKET
,其中包含旨在最大化互操作性的各种选项,但内容可能会有所不同,具体取决于您的Python版本和所使用的基础OpenSSL库。OP_ALL
属性,我猜它使用TLS恢复或已设置为使用它。答案 1 :(得分:0)
1)默认情况下,非浏览器TLS客户端(例如以下python客户端)是否会执行会话恢复?
默认情况下,python tls / ssl库不执行会话恢复。
2)我怎么知道他们是否这样做?如果在后台执行会话恢复,如何禁用它?
您可以使用以下代码来验证是否未恢复会话:
import socket
import ssl
hostname = 'www.stackoverflow.com'
context = ssl.create_default_context()
# Create a new socket, then create a secure socket
sock = socket.create_connection((hostname, 443))
ssock = context.wrap_socket(sock, server_hostname=hostname)
# Was the TLS Session re-used?
print(ssock.session_reused) # False
答案 2 :(得分:0)
TLS 会话恢复可以通过使用最后一个 ssl 会话来启用。
hostname = 'google.com'
port = 443
resource = '/'
context = ssl.SSLContext(ssl.PROTOCOL_TLS)
sock = socket.create_connection((hostname, port))
ssock = context.wrap_socket(sock, server_hostname=hostname)
#send - receive
ssr = ssock.session
print(ssock.session_reused) # False
ssock.close()
sock = socket.create_connection((hostname, port))
ssock = context.wrap_socket(sock, server_hostname=hostname, session=ssr)
#send - receive
print(ssock.session_reused) # True , if server support it
ssock.close()