[PATCH v2 1/2] netfilter: conntrack: introduce no_random_port proc entry

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Sriram Yagnaraman <sriram.yagnaraman@xxxxxxxx>

This patch introduces a new proc entry to disable source port
randomization for SCTP connections.

As specified in RFC9260 all transport addresses used by an SCTP endpoint
MUST use the same port number but can use multiple IP addresses. That
means that all paths taken within an SCTP association should have the
same port even if they pass through different NAT/middleboxes in the
network.

Disabling source port randomization provides a deterministic source port
for the remote SCTP endpoint for all paths used in the SCTP association.
On NAT/middlebox restarts we will always end up with the same port after
the restart, and the SCTP endpoints involved in the SCTP association can
remain transparent to restarts.

Of course, there is a downside as this makes it impossible to have
multiple SCTP endpoints behind NAT that use the same source port.
But, this is a lesser of a problem than losing an existing association
altogether.

Reported-by: kernel test robot <lkp@xxxxxxxxx>
Signed-off-by: Sriram Yagnaraman <sriram.yagnaraman@xxxxxxxx>
---
 include/net/netns/conntrack.h           |  1 +
 net/netfilter/nf_conntrack_proto_sctp.c |  3 +++
 net/netfilter/nf_conntrack_standalone.c | 13 +++++++++++++
 net/netfilter/nf_nat_core.c             | 10 +++++++++-
 4 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/include/net/netns/conntrack.h b/include/net/netns/conntrack.h
index e1290c159184..097bed663805 100644
--- a/include/net/netns/conntrack.h
+++ b/include/net/netns/conntrack.h
@@ -60,6 +60,7 @@ struct nf_dccp_net {
 #ifdef CONFIG_NF_CT_PROTO_SCTP
 struct nf_sctp_net {
 	unsigned int timeouts[SCTP_CONNTRACK_MAX];
+	u8 sctp_no_random_port;
 };
 #endif
 
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
index 5a936334b517..5e4d3215dcf6 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -699,6 +699,9 @@ void nf_conntrack_sctp_init_net(struct net *net)
 	 * 'new' timeout, like udp or icmp.
 	 */
 	sn->timeouts[0] = sctp_timeouts[SCTP_CONNTRACK_CLOSED];
+
+	/* leave source port randomization as true by default */
+	sn->sctp_no_random_port = 0;
 }
 
 const struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp = {
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 4ffe84c5a82c..e35876ce418d 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -602,6 +602,7 @@ enum nf_ct_sysctl_index {
 	NF_SYSCTL_CT_PROTO_TIMEOUT_SCTP_SHUTDOWN_ACK_SENT,
 	NF_SYSCTL_CT_PROTO_TIMEOUT_SCTP_HEARTBEAT_SENT,
 	NF_SYSCTL_CT_PROTO_TIMEOUT_SCTP_HEARTBEAT_ACKED,
+	NF_SYSCTL_CT_PROTO_SCTP_NO_RANDOM_PORT,
 #endif
 #ifdef CONFIG_NF_CT_PROTO_DCCP
 	NF_SYSCTL_CT_PROTO_TIMEOUT_DCCP_REQUEST,
@@ -892,6 +893,14 @@ static struct ctl_table nf_ct_sysctl_table[] = {
 		.mode           = 0644,
 		.proc_handler   = proc_dointvec_jiffies,
 	},
+	[NF_SYSCTL_CT_PROTO_SCTP_NO_RANDOM_PORT] = {
+		.procname	= "nf_conntrack_sctp_no_random_port",
+		.maxlen		= sizeof(u8),
+		.mode		= 0644,
+		.proc_handler	= proc_dou8vec_minmax,
+		.extra1		= SYSCTL_ZERO,
+		.extra2		= SYSCTL_ONE,
+	},
 #endif
 #ifdef CONFIG_NF_CT_PROTO_DCCP
 	[NF_SYSCTL_CT_PROTO_TIMEOUT_DCCP_REQUEST] = {
@@ -1037,6 +1046,10 @@ static void nf_conntrack_standalone_init_sctp_sysctl(struct net *net,
 	XASSIGN(HEARTBEAT_SENT, sn);
 	XASSIGN(HEARTBEAT_ACKED, sn);
 #undef XASSIGN
+#define XASSIGN(XNAME, rval) \
+	table[NF_SYSCTL_CT_PROTO_SCTP_ ## XNAME].data = (rval)
+	XASSIGN(NO_RANDOM_PORT, &sn->sctp_no_random_port);
+#undef XASSIGN
 #endif
 }
 
diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c
index 18319a6e6806..cdcff0ed094c 100644
--- a/net/netfilter/nf_nat_core.c
+++ b/net/netfilter/nf_nat_core.c
@@ -19,6 +19,7 @@
 #include <net/netfilter/nf_conntrack_bpf.h>
 #include <net/netfilter/nf_conntrack_core.h>
 #include <net/netfilter/nf_conntrack_helper.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
 #include <net/netfilter/nf_conntrack_seqadj.h>
 #include <net/netfilter/nf_conntrack_zones.h>
 #include <net/netfilter/nf_nat.h>
@@ -422,10 +423,17 @@ static void nf_nat_l4proto_unique_tuple(struct nf_conntrack_tuple *tuple,
 		}
 		goto find_free_id;
 #endif
+	case IPPROTO_SCTP:
+		/* SCTP port randomization disabled, try to use the same source port
+		 * as in the original packet. Drop packets if another endpoint tries
+		 * to use same source port behind NAT.
+		 */
+		if (nf_sctp_pernet(nf_ct_net(ct))->sctp_no_random_port)
+			return;
+		fallthrough;
 	case IPPROTO_UDP:
 	case IPPROTO_UDPLITE:
 	case IPPROTO_TCP:
-	case IPPROTO_SCTP:
 	case IPPROTO_DCCP:
 		if (maniptype == NF_NAT_MANIP_SRC)
 			keyptr = &tuple->src.u.all;
-- 
2.34.1




[Index of Archives]     [Netfitler Users]     [Berkeley Packet Filter]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux