Как аккуратно закрыть сокет Python TLS 1.3 (отправить close_notify) без unwrap()?Python

Программы на Python
Anonymous
Как аккуратно закрыть сокет Python TLS 1.3 (отправить close_notify) без unwrap()?

Сообщение Anonymous »

Я начинаю работать с Python и пытаюсь создать простой сокет TLS 1.3, но у меня возникла проблема.
Когда сеанс закрывается, я получаю ошибку TLS:

Код: Выделить всё

Alert (Level: Fatal, Description: Decode Error)
Это вызывает TCP RST со стороны моего клиента:

Код: Выделить всё

CLient -> Server TCP: [FIN, ACK]
Server -> Client TCP: [ACK]
Server -> Client TLS1.3: Alert (Level: Fatal, Description: Decode Error)
Client -> Server TCP: [RST, ACK]
Изображение
Код моего сервера:

Код: Выделить всё

import socket, ssl

host, port = "127.0.0.1", 8086

# SSL context
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
context.load_cert_chain("./Certificates/cert-server.pem", "./Certificates/cert-key.pem")

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
with context.wrap_socket(sock, server_side=True) as ssock:
ssock.bind((host, port))
ssock.listen(5)

while True:
conn, ip = ssock.accept()
from_client = ''

while True:
data = str(conn.recv(4096), encoding='utf8')
if not data:
break
print(data)
conn.send(bytes("I'm Server", encoding='utf8'))

conn.close()
break
Мой клиентский код:

Код: Выделить всё

import socket, ssl

host, port = "127.0.0.1", 8086

# SSL context
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
context.load_default_certs()

# For Wireshark TLS Decryption
context.keylog_filename = "./keys.txt"

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
with context.wrap_socket(sock, server_hostname=host) as ssock:
ssock.connect((host, port))
ssock.send(bytes("I'm Client", encoding='utf8'))
from_server = str(ssock.recv(4096), encoding='utf8')
print(from_server)
Проведя небольшое исследование в Интернете, я обнаружил, что для правильного закрытия сеанса TLS требуется предупреждение close_notify.
Поэтому я добавил

Код: Выделить всё

 ssock.unwrap()
в мой клиентский код:

Код: Выделить всё

import socket, ssl

host, port = "127.0.0.1", 8086

# SSL context
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
context.load_default_certs()

# For Wireshark TLS Decryption
context.keylog_filename = "./keys.txt"

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
with context.wrap_socket(sock, server_hostname=host) as ssock:
ssock.connect((host, port))
ssock.send(bytes("I'm Client", encoding='utf8'))
from_server = str(ssock.recv(4096), encoding='utf8')
print(from_server)
# Need add this to send TLS close_notify
ssock.unwrap()
Когда я добавляю это, проблема решается, и мой сеанс закрывается правильно:

Код: Выделить всё

Client -> Server TLS: Alert(Level: Warning, Description: Close Notify)
Server -> Client TCP: [ACK]
Server -> Client TCP: [FIN, ACK]
CLient -> Server TCP: [ACK]
Client -> Server TCP: [FIN, ACK]
Server -> Client TCP: [ACK]
Изображение
Почему оператор with не отправляет автоматически close_notify при закрытии сокета TLS?
Есть ли способ правильно закрыть сеанс TLS в Python без явного вызова unwrap()?
Я пробовал ssock.shutdown(), но это не дало никакого эффекта.

Вернуться в «Python»