Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

net: tcp: Send RST reply for unexpected TCP packets #64029

Conversation

rlubos
Copy link
Contributor

@rlubos rlubos commented Oct 17, 2023

This PR improves the handling of unexpected packets within Zephyr's TCP stack. The TCP stack will now send RST packet in a response to unexpected TCP packets, to address issues mostly related to ungraceful TCP connection shutdown (for example due to reboot):

  1. Invalid ACK value received during handshake (connection still open
    on the peer side),
  2. Unexpected data packet on a listening port (accepted connection
    closed),
  3. SYN received on a closed port.

For this, a new helper function was introduced which allows to send an RST packet to any destination (current functions allow only to send TCP packets to destinations associated with a TCP connection context, which is not always the case in this scenario).

Finally, add a few new tests to cover this functionality.

Fixes #63966

Add a helper function which allows to send a RST packet in response to
an unexpected TCP packet, w/o associated connection or net context.

Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
@rlubos rlubos force-pushed the net/tcp-fix-missing-rst-on-unexpected-packets branch from 7d8cd44 to a4128c1 Compare October 17, 2023 14:56
if (IS_ENABLED(CONFIG_NET_TCP) && proto == IPPROTO_TCP) {
net_tcp_reply_rst(pkt);
Copy link
Member

@jukkar jukkar Oct 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In Linux one can use netfilter to prevent RST to be sent out if there is no socket bind to the port, and in Zephyr that might be possible at some point using net_pkt_filter (currently not possible). So I was thinking that should we have a Kconfig option to allow earlier behavior, so that RST would not be sent if option is set, by default the option could be off so RST would be sent out. WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I can add such an option.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jukkar I've added a Kconfig option to configure whether to send RST packet on closed port. If disabled, ICMP is sent instead as it used to.

Send RST as a reply for unexpected TCP packets in the following
scenarios:
1) Unexpected ACK value received during handshake (connection still open
   on the peer side),
2) Unexpected data packet on a listening port (accepted connection
   closed),
3) SYN received on a closed port.

This allows the other end to detect that the connection is no longer
valid (for example due to reboot) and release the resources.

Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
Add tests which verify that Zephyr's TCP stack replies with RST packet
as expected.

Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
Add Kconfig option to control TCP RST behavior on connection attempts on
unbound ports. If enabled, TCP stack will reply with RST packet (enabled
by default).

Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
The test delegates putting the server socket into listening (i. e.
calling listen() on the socket) to a separate thread, which did have a
chance to run before client attempted to establish TCP connection.

This was not visible before, as we did not reply with RST to a
connection attempt on a closed port, so the connection was eventually
establish after SYN retransmission. But as we do reject such a
connection now with RST, the connection attempt failed. Therefore, a
small delay was added after spawning the server thread, to give it a
chance to configure the server socket.

Additionally, lower the CONFIG_NET_TCP_TIME_WAIT_DELAY value so that TCP
contexts are released earlier, and add a respective delay in the test
teardown function. Not doing so also triggered unneeded SYN
retransmissions, as there were no enough TCP context to accept the
incoming connection, before freeing the resources allocated for the
previous one.

Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
@rlubos rlubos force-pushed the net/tcp-fix-missing-rst-on-unexpected-packets branch from a4128c1 to 177984f Compare October 18, 2023 11:35
@rlubos rlubos requested a review from nashif as a code owner October 18, 2023 11:35
@rlubos
Copy link
Contributor Author

rlubos commented Oct 18, 2023

@cfriedt Thrift tests needed small adjustments due to timing issues, please check the commit message for details.

@fabiobaltieri fabiobaltieri added this to the v3.6.0 milestone Oct 19, 2023
@carlescufi carlescufi merged commit 822a82d into zephyrproject-rtos:main Oct 20, 2023
23 checks passed
@jukkar jukkar added the Backport Backport PR and backport failure issues label Oct 24, 2023
@fabiobaltieri fabiobaltieri added backport v3.5-branch Backport to the v3.5-branch and removed Backport Backport PR and backport failure issues labels Oct 24, 2023
@rlubos rlubos deleted the net/tcp-fix-missing-rst-on-unexpected-packets branch October 25, 2023 10:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

net: ip: Does not reset expired TCP session
6 participants