From patchwork Fri Jun 24 01:13:18 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arne Schwabe X-Patchwork-Id: 2548 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director14.mail.ord1d.rsapps.net ([172.31.255.6]) by backend30.mail.ord1d.rsapps.net with LMTP id yAGkKJGctWJ8WQAAIUCqbw (envelope-from ) for ; Fri, 24 Jun 2022 07:14:25 -0400 Received: from proxy4.mail.iad3b.rsapps.net ([172.31.255.6]) by director14.mail.ord1d.rsapps.net with LMTP id 0HtKKJGctWKGdQAAeJ7fFg (envelope-from ) for ; Fri, 24 Jun 2022 07:14:25 -0400 Received: from smtp5.gate.iad3b ([172.31.255.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy4.mail.iad3b.rsapps.net with LMTPS id SNEYI5GctWLIEAAA9crAow (envelope-from ) for ; Fri, 24 Jun 2022 07:14:25 -0400 X-Spam-Threshold: 95 X-Spam-Score: 0 X-Spam-Flag: NO X-Virus-Scanned: OK X-Orig-To: openvpnslackdevel@openvpn.net X-Originating-Ip: [216.105.38.7] Authentication-Results: smtp5.gate.iad3b.rsapps.net; iprev=pass policy.iprev="216.105.38.7"; spf=pass smtp.mailfrom="openvpn-devel-bounces@lists.sourceforge.net" smtp.helo="lists.sourceforge.net"; dkim=fail (signature verification failed) header.d=sourceforge.net; dkim=fail (signature verification failed) header.d=sf.net; dmarc=none (p=nil; dis=none) header.from=rfc2549.org X-Suspicious-Flag: YES X-Classification-ID: cdd95036-f3ae-11ec-b09d-525400155d63-1-1 Received: from [216.105.38.7] ([216.105.38.7:37810] helo=lists.sourceforge.net) by smtp5.gate.iad3b.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id AC/67-11634-19C95B26; Fri, 24 Jun 2022 07:14:25 -0400 Received: from [127.0.0.1] (helo=sfs-ml-4.v29.lw.sourceforge.com) by sfs-ml-4.v29.lw.sourceforge.com with esmtp (Exim 4.94.2) (envelope-from ) id 1o4hFi-0004xU-5b; Fri, 24 Jun 2022 11:13:29 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-4.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1o4hFh-0004xH-16 for openvpn-devel@lists.sourceforge.net; Fri, 24 Jun 2022 11:13:27 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=Content-Transfer-Encoding:MIME-Version:References: In-Reply-To:Message-Id:Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=xO6pcy2iPKc6W+heueqtoN9lORigkF+U7LDuzbda0ww=; b=S91tVDUyFwu+oedvyzOwDDvY9V 7RzxIkdMx3qlXFxlx7stvEnU27vs2Ty45M9j5L+9ZMLI/UwGccGW5bjXRGAbKvbvW3/TAg7vMcPPc 2TAobfN2VCqwM41v9yYZb29xGkvk8Cgc/gD5d+R9yVsIIbNxEL4N5U9Frdzjo9WIl6ho=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-Id: Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=xO6pcy2iPKc6W+heueqtoN9lORigkF+U7LDuzbda0ww=; b=NLqX/dCtxCdhyee7dNCAd8kJE0 3ssSypomnVmtr53cmcVbSEIAmFNwtYJBZVaV3o0aiOEYQfuJeten/TYWg9fHbi4himv97EUSpyXXT qghPDX5tek9dzzfgCgsotJ0G18Of61ElzwpR2szG07Awp7o4J0d8sZWcWSjLrAiCrYnQ=; Received: from mail.blinkt.de ([192.26.174.232]) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.94.2) id 1o4hFd-00C8IX-He for openvpn-devel@lists.sourceforge.net; Fri, 24 Jun 2022 11:13:27 +0000 Received: from kamera.blinkt.de ([2001:638:502:390:20c:29ff:fec8:535c]) by mail.blinkt.de with smtp (Exim 4.95 (FreeBSD)) (envelope-from ) id 1o4hFX-0007mA-78 for openvpn-devel@lists.sourceforge.net; Fri, 24 Jun 2022 13:13:19 +0200 Received: (nullmailer pid 3220037 invoked by uid 10006); Fri, 24 Jun 2022 11:13:19 -0000 From: Arne Schwabe To: openvpn-devel@lists.sourceforge.net Date: Fri, 24 Jun 2022 13:13:18 +0200 Message-Id: <20220624111318.3219982-4-arne@rfc2549.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220624111318.3219982-1-arne@rfc2549.org> References: <20220624111318.3219982-1-arne@rfc2549.org> MIME-Version: 1.0 X-Spam-Report: Spam detection software, running on the system "util-spamd-2.v13.lw.sourceforge.com", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: This allows tun-mtu to pushed but only up to the size of the preallocated buffers. This is not a perfect solution but should allow most of the use cases where the mtu is close enough to 1500. Signed-off-by: Arne Schwabe --- Changes.rst | 8 ++++ doc/man-sections/client-options.rst | 4 ++ doc/man-sections/vpn-network-options.rst | 5 +++ src/openvpn/init.c | 50 ++++++++++++ [...] Content analysis details: (0.2 points, 6.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 SPF_NONE SPF: sender does not publish an SPF Record 0.2 HEADER_FROM_DIFFERENT_DOMAINS From and EnvelopeFrom 2nd level mail domains are different -0.0 T_SCC_BODY_TEXT_LINE No description available. X-Headers-End: 1o4hFd-00C8IX-He Subject: [Openvpn-devel] [PATCH v2 4/4] Allow tun-mtu to be pushed X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox This allows tun-mtu to pushed but only up to the size of the preallocated buffers. This is not a perfect solution but should allow most of the use cases where the mtu is close enough to 1500. Signed-off-by: Arne Schwabe --- Changes.rst | 8 ++++ doc/man-sections/client-options.rst | 4 ++ doc/man-sections/vpn-network-options.rst | 5 +++ src/openvpn/init.c | 50 ++++++++++++++++++++---- src/openvpn/mtu.c | 1 + src/openvpn/mtu.h | 3 ++ src/openvpn/options.c | 15 ++++++- src/openvpn/options.h | 2 + src/openvpn/ssl.c | 3 ++ 9 files changed, 83 insertions(+), 8 deletions(-) diff --git a/Changes.rst b/Changes.rst index 98d6df60d..616a977ed 100644 --- a/Changes.rst +++ b/Changes.rst @@ -79,6 +79,14 @@ Cookie based handshake for UDP server shake. The tls-crypt-v2 option allows controlling if older clients are accepted. + +Tun MTU can be pushed + As part of changing the ``--tun-mtu`` default to 1420 (see below), the + client can now also dynamically configure its MTU and the server will + try to push the client MTU when the client supports it. The directive + ``--tun-mtu-max`` has been introduced to specify the maximum pushable + MTU size. + Deprecated features ------------------- ``inetd`` has been removed diff --git a/doc/man-sections/client-options.rst b/doc/man-sections/client-options.rst index 8e0e4f18a..940175eaf 100644 --- a/doc/man-sections/client-options.rst +++ b/doc/man-sections/client-options.rst @@ -358,6 +358,10 @@ configuration. The client announces the list of supported ciphers configured with the ``--data-ciphers`` option to the server. + :code:`IV_MTU=` + The client announces the support of pushable MTU and the maximum MTU + it is willing to accept. + :code:`IV_GUI_VER= ` The UI version of a UI if one is running, for example :code:`de.blinkt.openvpn 0.5.47` for the Android app. diff --git a/doc/man-sections/vpn-network-options.rst b/doc/man-sections/vpn-network-options.rst index 26b37dc36..1dda4912d 100644 --- a/doc/man-sections/vpn-network-options.rst +++ b/doc/man-sections/vpn-network-options.rst @@ -542,6 +542,11 @@ routing. packets larger than ``tun-mtu`` (e.g. Linux and FreeBSD) but other platforms (like macOS) limit received packets to the same size as the MTU. +--tun-max-mtu maxmtu + This configures the maximum MTU size that a server can push to ``maxmtu``. + The default for ``maxmtu`` is 1600. This will increase internal buffers + allocation for larger packet sizes. + --tun-mtu-extra n Assume that the TUN/TAP device might return as many as ``n`` bytes more than the ``--tun-mtu`` size on read. This parameter defaults to 0, which diff --git a/src/openvpn/init.c b/src/openvpn/init.c index 638fd10c8..246dbae9e 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -2126,7 +2126,8 @@ pull_permission_mask(const struct context *c) | OPT_P_ECHO | OPT_P_PULL_MODE | OPT_P_PEER_ID - | OPT_P_NCP; + | OPT_P_NCP + | OPT_P_PUSH_MTU; if (!c->options.route_nopull) { @@ -2285,6 +2286,31 @@ do_deferred_options(struct context *c, const unsigned int found) #endif struct tls_session *session = &c->c2.tls_multi->session[TM_ACTIVE]; + if (!update_session_cipher(session, &c->options)) + { + /* The update_session_cipher method will already print an error */ + return false; + } + + /* Cipher is considered safe, so we can use it to calculate the max + * MTU size */ + if (found & OPT_P_PUSH_MTU) + { + /* MTU has changed, check that the pushed MTU is small enough to + * be able to change it */ + msg(D_PUSH, "OPTIONS IMPORT: tun-mtu set to %d", c->options.ce.tun_mtu); + + struct frame *frame = &c->c2.frame; + + if (c->options.ce.tun_mtu > frame->tun_max_mtu) + { + msg(D_PUSH_ERRORS, "Server pushed a large mtu, please add " + "tun-mtu-max %d in the client configuration", + c->options.ce.tun_mtu); + } + frame->tun_mtu = min_int(frame->tun_max_mtu, c->options.ce.tun_mtu); + } + if (!tls_session_update_crypto_params(session, &c->options, &c->c2.frame, frame_fragment, get_link_socket_info(c))) { @@ -2448,10 +2474,16 @@ frame_finalize_options(struct context *c, const struct options *o) struct frame *frame = &c->c2.frame; frame->tun_mtu = get_frame_mtu(c, o); + frame->tun_max_mtu = o->ce.tun_mtu_max; - /* We always allow at least 1500 MTU packets to be received in our buffer - * space */ - size_t payload_size = max_int(1500, frame->tun_mtu); + /* max mtu needs to be at least as large as the tun mtu */ + frame->tun_max_mtu = max_int(frame->tun_mtu, frame->tun_max_mtu); + + /* We always allow at least 1600 MTU packets to be received in our buffer + * space to allow server to push "baby giant" MTU sizes */ + frame->tun_max_mtu = max_int(1600, frame->tun_max_mtu); + + size_t payload_size = frame->tun_max_mtu; /* The extra tun needs to be added to the payload size */ if (o->ce.tun_mtu_defined) @@ -2459,9 +2491,9 @@ frame_finalize_options(struct context *c, const struct options *o) payload_size += o->ce.tun_mtu_extra; } - /* Add 100 byte of extra space in the buffer to account for slightly - * mismatched MUTs between peers */ - payload_size += 100; + /* Add 32 byte of extra space in the buffer to account for small errors + * in the calculation */ + payload_size += 32; /* the space that is reserved before the payload to add extra headers to it @@ -2994,6 +3026,10 @@ do_init_frame_tls(struct context *c) c->c2.frame.buf.payload_size); frame_print(&c->c2.tls_multi->opt.frame, D_MTU_INFO, "Control Channel MTU parms"); + + /* Keep the max mtu also in the frame of tls multi so it can access + * it in push_peer_info */ + c->c2.tls_multi->opt.frame.tun_max_mtu = c->c2.frame.tun_max_mtu; } if (c->c2.tls_auth_standalone) { diff --git a/src/openvpn/mtu.c b/src/openvpn/mtu.c index 0cad9b1c9..e4d4a9cd5 100644 --- a/src/openvpn/mtu.c +++ b/src/openvpn/mtu.c @@ -244,6 +244,7 @@ frame_print(const struct frame *frame, buf_printf(&out, " max_frag:%d", frame->max_fragment_size); #endif buf_printf(&out, " tun_mtu:%d", frame->tun_mtu); + buf_printf(&out, " tun_max_mtu:%d", frame->tun_max_mtu); buf_printf(&out, " headroom:%d", frame->buf.headroom); buf_printf(&out, " payload:%d", frame->buf.payload_size); buf_printf(&out, " tailroom:%d", frame->buf.tailroom); diff --git a/src/openvpn/mtu.h b/src/openvpn/mtu.h index d643027d3..e80d8bd01 100644 --- a/src/openvpn/mtu.h +++ b/src/openvpn/mtu.h @@ -137,6 +137,9 @@ struct frame { * control frame payload (although most of * code ignores it) */ + int tun_max_mtu; /**< the maximum tun-mtu size the buffers are + * are sized for. This is the upper bound that + * a server can push as MTU */ int extra_tun; /**< Maximum number of bytes in excess of * the tun/tap MTU that might be read diff --git a/src/openvpn/options.c b/src/openvpn/options.c index b30c05eba..d87c6595c 100644 --- a/src/openvpn/options.c +++ b/src/openvpn/options.c @@ -6283,7 +6283,7 @@ add_option(struct options *options, } else if (streq(p[0], "tun-mtu") && p[1] && !p[3]) { - VERIFY_PERMISSION(OPT_P_MTU|OPT_P_CONNECTION); + VERIFY_PERMISSION(OPT_P_PUSH_MTU|OPT_P_CONNECTION); options->ce.tun_mtu = positive_atoi(p[1]); options->ce.tun_mtu_defined = true; if (p[2]) @@ -6295,6 +6295,19 @@ add_option(struct options *options, options->ce.occ_mtu = 0; } } + else if (streq(p[0], "tun-mtu-max") && p[1] && !p[3]) + { + VERIFY_PERMISSION(OPT_P_MTU|OPT_P_CONNECTION); + int max_mtu = positive_atoi(p[1]); + if (max_mtu < 68 || max_mtu > 65536) + { + msg(msglevel, "--tun-mtu-max value '%s' is invalid", p[1]); + } + else + { + options->ce.tun_mtu_max = max_mtu; + } + } else if (streq(p[0], "tun-mtu-extra") && p[1] && !p[2]) { VERIFY_PERMISSION(OPT_P_MTU|OPT_P_CONNECTION); diff --git a/src/openvpn/options.h b/src/openvpn/options.h index 1085a462a..5a1720ca9 100644 --- a/src/openvpn/options.h +++ b/src/openvpn/options.h @@ -119,6 +119,7 @@ struct connection_entry int tun_mtu; /* MTU of tun device */ int occ_mtu; /* if non-null, this is the MTU we announce to peers in OCC */ + int tun_mtu_max; /* maximum MTU that can be pushed */ bool tun_mtu_defined; /* true if user overriding parm with command line option */ int tun_mtu_extra; bool tun_mtu_extra_defined; @@ -720,6 +721,7 @@ struct options #define OPT_P_CONNECTION (1<<27) #define OPT_P_PEER_ID (1<<28) #define OPT_P_INLINE (1<<29) +#define OPT_P_PUSH_MTU (1<<30) #define OPT_P_DEFAULT (~(OPT_P_INSTANCE|OPT_P_PULL_MODE)) diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c index ddd90080b..a6071e3c1 100644 --- a/src/openvpn/ssl.c +++ b/src/openvpn/ssl.c @@ -1939,6 +1939,9 @@ push_peer_info(struct buffer *buf, struct tls_session *session) { iv_proto |= IV_PROTO_REQUEST_PUSH; iv_proto |= IV_PROTO_AUTH_PENDING_KW; + + /* support for tun-mtu as part of the push message */ + buf_printf(&out, "IV_MTU=%d\n", session->opt->frame.tun_max_mtu); } /* support for Negotiable Crypto Parameters */