[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20200902195656.7538-1-mmilev_ml@icloud.com>
Date: Wed, 2 Sep 2020 21:56:56 +0200
From: Mihail Milev <mmilev_ml@...oud.com>
To: davem@...emloft.net, kuba@...nel.org, edumazet@...gle.com
Cc: netdev@...r.kernel.org
Subject: [PATCH net-next] Sysctl parameter to disable TCP RST packet to unknown socket
What?
Create a new sysctl parameter called tcp_disable_rst_unkn_socket,
which by default is set to 0 - "disabled". When this parameter is
set to 1 - "enabled", it suppresses sending a TCP RST packet as a
response to received TCP packets destined for a socket, which is
unknown to the kernel.
Important!
By enabling this sysctl parameter, the TCP stack becomes non-
conformal to RFC 793, which clearly states (as of revision
September 1981) in the listing on page 36, point 1:
"1. If the connection does not exist (CLOSED) then a reset is sent
in response to any incoming segment except another reset. ..."
Why?
This modification is targeted to network protocol developers,
testers and problem investigators. When new protocols on top of
the TCP stack are developed using raw sockets, the incoming
packets nevertheless go through the kernel TCP stack, if the
PROTOCOL field in the IP packet is set to 0x06 = TCP. Since in
such situations there is no socket, which has been opened in the
normal way - using connect or bind, the kernel does not know
where to send these incoming packets and discards them and also
sends the aforementioned RST packet. This packet interferes with
the protocol development and it is meaningful to have the option
to disable its generation.
In another scenario, software and/or security testers often need
to validate the correctness of software implementation. They can
create an unusual situation by disabling the TCP RST packet and
observe how the software under test performs in such situations.
How?
1. Define a new element inside include/uapi/linux/sysctl.h for
the /proc/sys/net/ipv4 enum.
2. Define a new variable to hold the value of the sysctl
parameter inside include/net/netns/ipv4.h for the netns_ipv4
struct.
3. Modify the control table named ipv4_table inside net/ipv4/
sysctl_net_ipv4.c, by adding the procname
tcp_disable_rst_unkn_socket. Point it to the variable defined
in point 2 above and limit its values to either 0 or 1 by
using proc_douintvec_minmax with SYSCTL_ZERO and SYSCTL_ONE as
extra1 and extra2.
4. Create a definition for the default value of 0 inside include/
net/tcp.h
5. In the tcp_sk_init function in net/ipv4/tcp_ipv4.c assign the
default value to the variable defined in point 2.
6. In the same file place the call to tcp_v4_send_reset inside
the function tcp_v4_rcv inside an if, which checks the value
of the variable defined in point 2.
Signed-off-by: Mihail Milev <mmilev_ml@...oud.com>
---
include/net/netns/ipv4.h | 1 +
include/net/tcp.h | 5 +++++
include/uapi/linux/sysctl.h | 1 +
net/ipv4/sysctl_net_ipv4.c | 9 +++++++++
net/ipv4/tcp_ipv4.c | 6 +++++-
5 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
index 9e36738c1fe1..1d74959ff6fe 100644
--- a/include/net/netns/ipv4.h
+++ b/include/net/netns/ipv4.h
@@ -177,6 +177,7 @@ struct netns_ipv4 {
struct inet_timewait_death_row tcp_death_row;
int sysctl_max_syn_backlog;
int sysctl_tcp_fastopen;
+ unsigned int sysctl_tcp_disable_rst_unkn_socket;
const struct tcp_congestion_ops __rcu *tcp_congestion_control;
struct tcp_fastopen_context __rcu *tcp_fastopen_ctx;
spinlock_t tcp_fastopen_ctx_lock;
diff --git a/include/net/tcp.h b/include/net/tcp.h
index eab6c7510b5b..cdd46be2cc94 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -241,6 +241,11 @@ void tcp_time_wait(struct sock *sk, int state, int timeo);
*/
#define TFO_SERVER_WO_SOCKOPT1 0x400
+/* The default value is 0 = do not disable the RST packet, when a packet
+ * for an unknown socket comes in.
+ */
+#define TCP_DISABLE_RST_UNKN_SOCKET 0
+
/* sysctl variables for tcp */
extern int sysctl_tcp_max_orphans;
diff --git a/include/uapi/linux/sysctl.h b/include/uapi/linux/sysctl.h
index 27c1ed2822e6..79fa12dd2110 100644
--- a/include/uapi/linux/sysctl.h
+++ b/include/uapi/linux/sysctl.h
@@ -426,6 +426,7 @@ enum
NET_TCP_ALLOWED_CONG_CONTROL=123,
NET_TCP_MAX_SSTHRESH=124,
NET_TCP_FRTO_RESPONSE=125,
+ NET_IPV4_TCP_DISABLE_RST_UNKN_SOCKET=126,
};
enum {
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 54023a46db04..304bbaaac94f 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -588,6 +588,15 @@ static struct ctl_table ipv4_table[] = {
.mode = 0644,
.proc_handler = proc_do_static_key,
},
+ {
+ .procname = "tcp_disable_rst_unkn_socket",
+ .data = &init_net.ipv4.sysctl_tcp_disable_rst_unkn_socket,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_douintvec_minmax,
+ .extra1 = SYSCTL_ZERO,
+ .extra2 = SYSCTL_ONE,
+ },
{ }
};
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 80b42d5c76fe..1a5a9ad84dd1 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -2049,7 +2049,9 @@ int tcp_v4_rcv(struct sk_buff *skb)
bad_packet:
__TCP_INC_STATS(net, TCP_MIB_INERRS);
} else {
- tcp_v4_send_reset(NULL, skb);
+ if(!net->ipv4.sysctl_tcp_disable_rst_unkn_socket) {
+ tcp_v4_send_reset(NULL, skb);
+ }
}
discard_it:
@@ -2894,6 +2896,8 @@ static int __net_init tcp_sk_init(struct net *net)
else
net->ipv4.tcp_congestion_control = &tcp_reno;
+ net->ipv4.sysctl_tcp_disable_rst_unkn_socket = TCP_DISABLE_RST_UNKN_SOCKET;
+
return 0;
fail:
tcp_sk_exit(net);
--
2.25.1
Powered by blists - more mailing lists