[Python] How to close a Python TLS 1.3 socket cleanly (send close_notify) without unwrap()?

Discussão em 'Python' iniciado por Stack, Agosto 10, 2025.

  1. Stack

    Stack Membro Participativo

    I’m starting with Python and I’m trying to make a simple TLS 1.3 socket, but I’m having an issue. When the session is closed, I get a TLS error :

    Alert (Level: Fatal, Description: Decode Error)


    Which causes a TCP RST from my client side:

    CLient -> Server TCP: [FIN, ACK]
    Server -> Client TCP: [ACK]
    Server -> Client TLS1.3: Alert (Level: Fatal, Description: Decode Error)
    Client -> Server TCP: [RST, ACK]


    RST-error

    My server code :

    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


    My client code:

    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)


    After doing some research on the Internet, I found that a TLS session needs a close_notify alert to be closed properly. So I added

    ssock.unwrap()


    to my client code:

    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()


    When I add this, the problem is solved and my session closes properly:

    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]


    close_notify

    Why doesn’t the with statement automatically send close_notify when the TLS socket is closed? Is there a way to properly close a TLS session in Python without explicitly calling unwrap()?

    Thanks !

    I tried ssock.shutdown(), but it had no effect.

    Continue reading...

Compartilhe esta Página