尝试使用Python 3编写TLS客户端。不知道什么是正确的方法来检测和处理连接拒绝服务器。
如果TLS服务器需要客户端证书,但客户端没有调用SSLContext.load_cert_chain()
或分配了错误的证书,则服务器将终止连接。问题是,客户端在下一次调用SSLSocket.recv()
之前不会检测到它。
例如,下面的代码将创建一个客户端TLS套接字并连接到服务器,并保持服务器的轮询数据:
import ssl
import socket
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
context.verify_mode = ssl.CERT_REQUIRED
context.check_hostname = False
# context.load_cert_chain(certfile='client.crt', keyfile='client.key')
context.load_verify_locations(cafile='ca.crt')
with socket.create_connection(('127.0.0.1', 12345)) as client:
with context.wrap_socket(client, server_hostname='example.com') as ssock:
ssock.sendall(b'Hello, world\n')
while 1:
data = ssock.recv(1024)
if not data:
ssock.close()
exit()
do_something(data)
假设服务器端在OpenSSL中运行-Verify=1
:
openssl s_server -port 12345 -CAfile ca.crt -cert server.crt -key server.key -Verify 1
在客户端中注解了context.load_cert_chain()
后,此连接将被服务器拒绝并丢弃:
ERROR
00A77D53F87F0000:error:0A0000C7:SSL routines:tls_process_client_certificate:peer did not return a certificate:ssl/statem/statem_srvr.c:3511:
shutting down SSL
CONNECTION CLOSED
但是客户端直到在while 1
循环中第一次调用ssock.recv()才知道这一点:
Traceback (most recent call last):
File "client.py", line 13, in <module>
data = ssock.recv(1024)
^^^^^^^^^^^^^^^^
File "***/python3.11/ssl.py", line 1263, in recv
return self.read(buflen)
^^^^^^^^^^^^^^^^^
File "***/python3.11/ssl.py", line 1136, in read
return self._sslobj.read(len)
^^^^^^^^^^^^^^^^^^^^^^
ssl.SSLError: [SSL: TLSV13_ALERT_CERTIFICATE_REQUIRED] tlsv13 alert certificate required (_ssl.c:2576)
在进入while 1
循环之前,是否有方法检测服务器关闭的连接?
1条答案
按热度按时间wkyowqbh1#
尝试此更改,它必须正常工作:
我使用ssock.settimeout(1)在recv()调用上设置了1秒的超时。这意味着,如果在指定的超时时间内没有数据可供读取,recv()将返回None。您可以捕获ssl.SSLWantReadError异常来处理这种情况,并继续检查数据,而不会陷入recv()调用。