uTP: Handle cases of unexpected packets #714
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR implements solutions for cases where Ultralight receives a
uTP
packet for a closed or non-existent connection.Previously Ultralight would ignore these packets on the
uTP
level. The packet arrives viatalkReq
, UL responds withtalkResp
, and sends the packet to theuTP
packet queue to process. DuringhandleCurrentPacket
,uTP
would find no open request for the packet, and simply throw it away and move on to the next packet in the queue.There are generally 3 scenarios where this may occur:
uTP
stream, sending a FIN-ACK packet to close the stream, but our peer failed to receive this packet. Since the peer still believes the connection to be open, they resend the FIN packet one or more times, attempting to complete the transfer.uTP
stream, sending a RESET packet to close the stream, but our peer failed to receive the RESET. Unaware that we have closed our end, they continue to send packets, awaiting a reply that will never come.uTP
packets as a DoS attack.In the first 2 scenarios, we are dealing with a well-meaning peer who is behaving as expected, unaware that packet-loss has corrupted the connection. The proper response in these cases should be to send this peer a RESET packet, so that they know to close the connection on their side.
In the attack scenario, we waste resources by processing the malicious packets and responding with our own RESET packets. For each malicious packet, we would be responding with 2 of our own packets (talkResp, and RESET). With no safeguards, a bad actor could send infinite malicious packets as a DoS attack.
PR: #712 enabled Ultralight to BLACKLIST peers on the UDP level. UDP packets from a blacklisted peer will never be processed by the client.
This PR modifies
uTP
to respond with BLACKLIST when an unexpected packet can't be traced to a closed connection, and to respond with RESET when a packet arrives for a previously closed stream. An exception to this is when receiving a RESET packet for an already closed connection. In that case we do not send a RESET, as this could result in an infinite RESET loop between peers.This should improve network health by closing connections that linger open, and improve client health by safeguarding against this DoS attack vector.