From db8abff7f4bc7822ea010e86d79c21aa644732be Mon Sep 17 00:00:00 2001 From: "Matthieu Baerts (NGI0)" Date: Tue, 9 Dec 2025 11:20:54 +0100 Subject: [PATCH 1/4] man: sshd: clarify MPTCP option On the listener side, an MPTCP socket will accept both "plain" TCP and MPTCP requests, not MPTCP requests only. It is also important to note that when the client didn't request to use MPTCP, a "plain" TCP socket is returned to the application. Link: https://www.mptcp.dev/faq.html#why--when-should-mptcp-be-enabled-by-default Signed-off-by: Matthieu Baerts (NGI0) --- hpnsshd_config.5 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hpnsshd_config.5 b/hpnsshd_config.5 index e1ff05b4653..08d936b11a3 100644 --- a/hpnsshd_config.5 +++ b/hpnsshd_config.5 @@ -2067,7 +2067,8 @@ directives. .It Cm UseMPTCP If set to .Cm yes , -this will enable Multipath TCP (MPTCP) instead of TCP (this only works on Linux). +this will enable Multipath TCP (MPTCP) support. This only works on Linux. MPTCP +will be used if requested by clients. If not, TCP will be used as before. The default is .Cm no . .It Cm UsePAM From 11bfd4d91ee8341adb5d851b354c5fec86574de1 Mon Sep 17 00:00:00 2001 From: "Matthieu Baerts (NGI0)" Date: Tue, 9 Dec 2025 11:42:13 +0100 Subject: [PATCH 2/4] configure: remove MPTCP check It is not used, and not recommended: when packages are distributed, a different kernel will be used at build time and at run time. These kernels can have different versions, different parameters, etc. Also, on Linux, it is common to use containers at build time to reproduce a specific environments, except that it doesn't include the right kernel. Instead, IPPROTO_MPTCP can be checked to see if the OS supports it or not. Signed-off-by: Matthieu Baerts (NGI0) --- configure.ac | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/configure.ac b/configure.ac index 8d696b7e7e6..c5d94840fef 100644 --- a/configure.ac +++ b/configure.ac @@ -2644,38 +2644,6 @@ if test ! -z "$check_for_openpty_ctty_bug"; then fi -# Testing MPTCP Support -# Does the OS support MPTCP? -# We don't use this at the moment -# but I am holding it in resrve -cjr 04/04/2025 - AC_MSG_CHECKING([whether the OS supports MPTCP]) - AC_RUN_IFELSE( - [AC_LANG_PROGRAM([[ - #include - #include - #include - #include - #include - #include - #include - - ]], [[ - int sock = -1; - sock = socket(AF_INET, SOCK_STREAM, IPPROTO_MPTCP); - if (sock < 0) { - exit(1); - } - ]])], - [ - AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_MPTCP], [1], - [OS Supports MPTCP]) - ], - [ - AC_MSG_RESULT([no]) - ] - ) - if test "x$ac_cv_func_getaddrinfo" = "xyes" && \ test "x$check_for_hpux_broken_getaddrinfo" = "x1"; then AC_MSG_CHECKING([if getaddrinfo seems to work]) From 4d3f62e8762d88651ce0689a25482412f44dd4a6 Mon Sep 17 00:00:00 2001 From: "Matthieu Baerts (NGI0)" Date: Tue, 9 Dec 2025 11:13:42 +0100 Subject: [PATCH 3/4] mptcp: do not always define IPPROTO_MPTCP IPPROTO_MPTCP has been introduced in the Linux kernel v5.6, more than 5 years ago. It has been added in netinet the same year. In other words, it should be available on systems having a kernel supporting MPTCP. In this case, IPPROTO_MPTCP can be used to identify OS where MPTCP is supported directly where it is used. This will simplify the next patch. Signed-off-by: Matthieu Baerts (NGI0) --- defines.h | 4 ---- sshconnect.c | 4 ++++ sshd.c | 4 ++++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/defines.h b/defines.h index 488adafb48a..15ccc903314 100644 --- a/defines.h +++ b/defines.h @@ -941,10 +941,6 @@ struct winsize { # define SSH_IOBUFSZ (32*1024) #endif -#ifndef IPPROTO_MPTCP -#define IPPROTO_MPTCP 262 -#endif - /* * We want functions in openbsd-compat, if enabled, to override system ones. * We no-op out the weak symbol definition rather than remove it to reduce diff --git a/sshconnect.c b/sshconnect.c index dc9de9fb8e5..07bf6b49d28 100644 --- a/sshconnect.c +++ b/sshconnect.c @@ -355,7 +355,11 @@ ssh_create_socket(struct addrinfo *ai) /* user request for Multipath TCP */ if (options.use_mptcp) +#ifdef IPPROTO_MPTCP sock = socket(ai->ai_family, ai->ai_socktype, IPPROTO_MPTCP); +#else + sock = -1; +#endif else sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); diff --git a/sshd.c b/sshd.c index cd01cc51c84..9a732d9f92d 100644 --- a/sshd.c +++ b/sshd.c @@ -828,8 +828,12 @@ listen_on_addrs(struct listenaddr *la) } /* Create socket for listening. */ if (options.use_mptcp) +#ifdef IPPROTO_MPTCP listen_sock = socket(ai->ai_family, ai->ai_socktype, IPPROTO_MPTCP); +#else + listen_sock = -1; +#endif else listen_sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); From 591a73ab5fd80dcb5cbdf31fc022f1c921fdf82a Mon Sep 17 00:00:00 2001 From: "Matthieu Baerts (NGI0)" Date: Tue, 9 Dec 2025 11:26:17 +0100 Subject: [PATCH 4/4] sshd: use MPTCP by default if supported If not, a "plain" TCP socket is used like before. It is interesting to do so to let only the clients deciding if MPTCP is going to be used or not: clients are probably the ones who know if they can benefit from using MPTCP or not, not the server side. Like that, it is easier to do experimentations with MPTCP without having to explicitly ask sysadmin to enable this option with a long explanation. On the server side, it is safe to enable MPTCP by default because MPTCP will only be used if requested by clients. If not, a "plain" TCP socket is returned to the application, not impacting the performances and then not introducing any regressions. Note that GO server applications are using MPTCP by default since v1.24 [1]. Link: https://go.dev/doc/go1.24#netpkgnet [1] Signed-off-by: Matthieu Baerts (NGI0) --- hpnsshd_config.5 | 2 +- servconf.c | 2 +- sshd.c | 9 +++++---- sshd_config | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/hpnsshd_config.5 b/hpnsshd_config.5 index 08d936b11a3..667d3187886 100644 --- a/hpnsshd_config.5 +++ b/hpnsshd_config.5 @@ -2070,7 +2070,7 @@ If set to this will enable Multipath TCP (MPTCP) support. This only works on Linux. MPTCP will be used if requested by clients. If not, TCP will be used as before. The default is -.Cm no . +.Cm yes . .It Cm UsePAM Enables the Pluggable Authentication Module interface. If set to diff --git a/servconf.c b/servconf.c index 2b5ca03eaee..ca3369b4f55 100644 --- a/servconf.c +++ b/servconf.c @@ -487,7 +487,7 @@ fill_default_server_options(ServerOptions *options) if (options->hpn_disabled == -1) options->hpn_disabled = 0; if (options->use_mptcp == -1) - options->use_mptcp = 0; + options->use_mptcp = 1; if (options->ip_qos_interactive == -1) options->ip_qos_interactive = IPTOS_DSCP_EF; if (options->ip_qos_bulk == -1) diff --git a/sshd.c b/sshd.c index 9a732d9f92d..869638a2620 100644 --- a/sshd.c +++ b/sshd.c @@ -827,14 +827,15 @@ listen_on_addrs(struct listenaddr *la) continue; } /* Create socket for listening. */ - if (options.use_mptcp) + listen_sock = -1; #ifdef IPPROTO_MPTCP + if (options.use_mptcp) listen_sock = socket(ai->ai_family, ai->ai_socktype, IPPROTO_MPTCP); -#else - listen_sock = -1; #endif - else + + /* Fallback to "plain" TCP if MPTCP is not available */ + if (listen_sock == -1) listen_sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); diff --git a/sshd_config b/sshd_config index 1ceafad10e4..ae50e6c693c 100644 --- a/sshd_config +++ b/sshd_config @@ -103,7 +103,7 @@ AuthorizedKeysFile .ssh/authorized_keys #PermitTunnel no #ChrootDirectory none #VersionAddendum none -#UseMPTCP no +#UseMPTCP yes # no default banner path #Banner none