Subsequent ssl:transport_accept() for the same IP stuck in dtls_packet_demux.erl call with infinity
Starting with Erlang 24.3.3 we observe issues with DTLS ssl transport_accept for clients that have been connected before.
To Reproduce
We are using the following options to create a new listen socket and wait for clients:
ssl_opts = [
active: false,
reuseaddr: true,
protocol: :dtls,
versions: [:"dtlsv1.2"],
ciphers: [
%{key_exchange: :psk, cipher: :aes_256_cbc, mac: :sha, prf: :default_prf},
%{key_exchange: :psk, cipher: :aes_128_cbc, mac: :sha256, prf: :default_prf},
%{key_exchange: :psk, cipher: :aes_128_cbc, mac: :sha, prf: :default_prf}
],
user_lookup_fun: {fn(:psk, psk_identity, _user_state) -> {:ok, Base.decode16!(psk_identity)} end, '3014F7B6E400090000001234'},
log_level: :debug,
# log_alert: true,
ip: {0, 0, 0, 0, 0, 0, 0, 1}
]
:ssl.start()
{:ok, listen_socket} = :ssl.listen(20_127, ssl_opts)
{:ok, session_socket_1} = :ssl.transport_accept(listen_socket)
{:ok, session_socket_1} = :ssl.handshake(session_socket_1, [], 5_000)
Using OpenSSL s_client we can now connect to the socket and see a successful handshake:
openssl s_client -bind [::1]:10127 -connect [::1]:20127 -dtls1_2 -psk_identity 3014F7B6E400090000001234 -psk 3014F7B6E400090000001234 -6 -cipher PSK-AES256-CBC-SHA
After closing the client we want to accept the next client by doing:
{:ok, session_socket_2} = :ssl.transport_accept(listen_socket)
{:ok, session_socket_2} = :ssl.handshake(session_socket_2, [], 5_000)
If we repeat the openssl command we can see the client requesting another handshake but the application is stuck in transport_accept.
Expected behavior Subsequent ssl:transport_accept() calls do not block and return a new session socket.
Affected versions Erlang 24.3.3 and higher
Hmm ... Did you upgrade from OTP 24.3.1 or was the jump to 24.3.3 larger? Just to make sure as the only change between those versions seems unlikely to affect this.
The jump was from 24.1.2. to 24.3.3
Then I would say the bug was most likely introduced in OTP.24.2. We will look into it further.
Hmm this works for me in OTP-25.0, when closing the socket with ^D in openssl, how do you close it?
Also for dlts you should probably set {recbuf, 32768} or more to ensure the packets is not discarded by the OS.
I closed openssl (Version 1.1.1k 25 Mar 2021) using ^C. Thanks for the hint with the recbuf.
Yes it seems I broke this when I tried to fix it and misunderstood how this should work :-/ It will take some time until I have time to prioritize this and get it correct.
See #4393 so it didn't seem to work for everybody previously either, and it could be attacked by a forged "clienthello" as in Also see RFC