From patchwork Wed May 20 09:16:10 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ralf Lici X-Patchwork-Id: 4958 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:b695:b0:861:c897:cb9d with SMTP id dh21csp717175mab; Wed, 20 May 2026 02:17:06 -0700 (PDT) X-Forwarded-Encrypted: i=2; AFNElJ/oSxpIg6J+SomsK5+8ZBpW9uF0sRkZfKcjGv8JSD/s2U8VX1VHk+Tu1YF6qtRxTk7fqYBMM3tJYuY=@openvpn.net X-Received: by 2002:a05:6870:6e0e:b0:42c:6ea:3227 with SMTP id 586e51a60fabf-43a2defc15cmr15385208fac.19.1779268626759; Wed, 20 May 2026 02:17:06 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1779268626; cv=none; d=google.com; s=arc-20240605; b=YXP8XCyq90GAEtBuNLVC7V/QAlukksYXZ834BQZRvGKeg43cTT2b4HXO1wdB+9smuT zscuK08FwMz0POtdlGVhukZSj4bcvkJKQbRzi/sz2wQrxYr7W5ujpgpva6gSWHbDs8wM J3NYmSPimiVNuTFkkMZK2ESRTdOv4rLui3VGqU6fvgON4x1saTUyhhc+TraUWf0N930d PYIXsyqE17ShXIX4yB5T3DJsUFgv3WA2JLZjyJHnMZnKS5531XDZm32kQf5QvmoMeP/j 2h61LVZMk3TY6jiNU1sdX9VNuohYRgeoeYslEaSGR58do4D0OyrkSBNjtr6bVzyAQfMH uJmw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:content-transfer-encoding:list-subscribe:list-help :list-post:list-archive:list-unsubscribe:list-id:precedence:subject :mime-version:message-id:date:to:from:dkim-signature:dkim-signature :dkim-signature:dkim-signature; bh=SBUQ5el1fu8pVKn+3UMukbR+mInP3ao2fZILSdpq6eU=; fh=4NbAC/LsuMLI0S0hprUlLSLCiHwg6SCAifhH718Jh0Q=; b=OJAMpjwaMkobLGcUv1RZj+y+j0ib5AmHMtyfLzVqWTy+lvaDfqsY0Ah+xR2AS3Ij70 1D8iIKJz8H0IaWSYCQibXx2qLQSDiBp/R8Z4GEMoCTJkFMfZtUc2nsX7xFBjFDABFncu MMsMpCsg6J1pj3FHy8//nZnEFC/TJNqpIn8H6Pke1MgIDgzE0hfax99O7G/ECz2o10A8 9QBomSUgvB8qhxE/YlQsCo5k+525gw64GIYoLrX5DR/hDuEuhJTF2XgvYg/7cbRG5cTU VbUEC1qqAmiqH5HPHHn59LZjm+xdh/aNMB5grpbVEnnQSNGZREz6uNzBKoYxwSYCu5Z6 k2Yg==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=Chw+98Mp; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=IjZuBySK; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=TRMpCI3u; dkim=neutral (body hash did not verify) header.i=@mandelbit.com header.s=MBO0001 header.b=vG8fqOwj; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net Received: from lists.sourceforge.net (lists.sourceforge.net. [216.105.38.7]) by mx.google.com with ESMTPS id 586e51a60fabf-43a958999a9si8118074fac.330.2026.05.20.02.17.06 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 20 May 2026 02:17:06 -0700 (PDT) Received-SPF: pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) client-ip=216.105.38.7; Authentication-Results: mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=Chw+98Mp; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=IjZuBySK; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=TRMpCI3u; dkim=neutral (body hash did not verify) header.i=@mandelbit.com header.s=MBO0001 header.b=vG8fqOwj; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.sourceforge.net; s=beta; h=Content-Transfer-Encoding:Content-Type: List-Subscribe:List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id: Subject:MIME-Version:Message-ID:Date:To:From:Sender:Reply-To:Cc:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Owner; bh=SBUQ5el1fu8pVKn+3UMukbR+mInP3ao2fZILSdpq6eU=; b=Chw+98MpmyGnfR3i0Vclhvt2F+ OjlGERNcix7dcSuUs2DV3v2gBgHXF7RoMfWdIVyiDOcTY+d6Zqz5+KJW7ERfpIRE+L9bON/bVgFt3 NzCD9OIMxIRZs4HFPs0sKHku13JZWHnNY1qE94Dv9qmUF9ypcKYLYFRhlTKgDjX2KxyA=; Received: from [127.0.0.1] (helo=sfs-ml-2.v29.lw.sourceforge.com) by sfs-ml-2.v29.lw.sourceforge.com with esmtp (Exim 4.95) (envelope-from ) id 1wPd2y-00024D-Cn; Wed, 20 May 2026 09:17:01 +0000 Received: from [172.30.29.66] (helo=mx.sourceforge.net) by sfs-ml-2.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1wPd2f-00022C-N3 for openvpn-devel@lists.sourceforge.net; Wed, 20 May 2026 09:16:43 +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:Message-ID: Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=zO9EkoQ2m0Q7Pm1eR2ehLDemZUR2qATQKJ0PO/RwOgk=; b=IjZuBySKKwl7XSfclkMN2fWO7R tr2xsSfwDrgnN2U91MX83B5o0G2xYbpSTn+DK9EKpWhHh4bmauq3kstYtMUZ/XS+as+ZUjzMZZv69 WcGec/PdFmCmFikX4V/0JQk+0/HZAUnoCtDChWWnC68AKgQ+6p2H1D+4udEZh29+Pm5A=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Content-Transfer-Encoding:MIME-Version:Message-ID:Date:Subject:Cc:To:From :Sender:Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To: References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:List-Post: List-Owner:List-Archive; bh=zO9EkoQ2m0Q7Pm1eR2ehLDemZUR2qATQKJ0PO/RwOgk=; b=T RMpCI3uOS+/ZFzNWa0gVSoN6ZuCKf02tYzz2S/pVG1toje4vu0XCXxZvqLmiO2QkLklACCvVJk2ef rd9YEs39f3ZqOWbzk89WO5TuTrsKNnZVgUGdN81cUOhdJvdRi5LtGVJxZ/7bxoBkNXPoCYn0Ke97q lfCKwC7iNkBRRP5g=; Received: from mout-b-210.mailbox.org ([195.10.208.40]) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.95) id 1wPd2X-0003Ow-6T for openvpn-devel@lists.sourceforge.net; Wed, 20 May 2026 09:16:36 +0000 Received: from smtp202.mailbox.org (smtp202.mailbox.org [IPv6:2001:67c:2050:b231:465::202]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-b-210.mailbox.org (Postfix) with ESMTPS id 4gL5WY0qNrzDx4d; Wed, 20 May 2026 11:16:25 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mandelbit.com; s=MBO0001; t=1779268585; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=zO9EkoQ2m0Q7Pm1eR2ehLDemZUR2qATQKJ0PO/RwOgk=; b=vG8fqOwjuUXZieHO6J0eWo4PRAf9Uxia8H1s/963Jcs5sazk4C/iYeB6i1KDJOaGiDE7VX q2kpAXPihlne2U7UAzNukltGjw2vsCbtGvlPgeNZOdyCSuGMI8vsGQfx+f537hACjXG38P 2T8ssFF4gZY2ccU5sYaFNP+JGerAZchhAPCidnKc3tPwrsDEYBiepnL8skurQSHHgTR0T3 6DBKwDfjdQ92tXI3ZMf4HfH6gGvJGUMjf3+F4QvUCMdz/3PCVLLvxZlwaDaJEE0rsXaQ+o QNLi6yEBfizVY73gagooVrWktRipRCUvD8gya7l2Lyr8eqjlEjpLKK3NP2n3rg== Authentication-Results: outgoing_mbo_mout; dkim=none; spf=pass (outgoing_mbo_mout: domain of ralf@mandelbit.com designates 2001:67c:2050:b231:465::202 as permitted sender) smtp.mailfrom=ralf@mandelbit.com From: Ralf Lici To: openvpn-devel@lists.sourceforge.net Date: Wed, 20 May 2026 11:16:10 +0200 Message-ID: <20260520091613.158891-1-ralf@mandelbit.com> MIME-Version: 1.0 X-Rspamd-Queue-Id: 4gL5WY0qNrzDx4d X-Spam-Score: -0.2 (/) X-Spam-Report: Spam detection software, running on the system "sfi-spamd-2.hosts.colo.sdot.me", 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: xt_TCPMSS has local logic for scanning TCP options and lowering an existing MSS option without increasing it. Move that scan-and-clamp logic into a TCP helper so other networking code can reuse it without duplicating TCP option parsing. Keep xt_TCPMSS responsible for the policy-specific behavior of adding a m [...] Content analysis details: (-0.2 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature X-Headers-End: 1wPd2X-0003Ow-6T Subject: [Openvpn-devel] [PATCH ovpn net-next v4 1/3] tcp: factor out TCP MSS option clamping 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 X-GMAIL-THRID: =?utf-8?q?1865698379734139983?= X-GMAIL-MSGID: =?utf-8?q?1865698379734139983?= xt_TCPMSS has local logic for scanning TCP options and lowering an existing MSS option without increasing it. Move that scan-and-clamp logic into a TCP helper so other networking code can reuse it without duplicating TCP option parsing. Keep xt_TCPMSS responsible for the policy-specific behavior of adding a missing MSS option. Linux TCP option parsing keeps scanning after an MSS option, so a later duplicate can override an earlier value at the receiver. While factoring out the scan, keep walking the TCP option block after a valid MSS option and clamp later MSS options as well, while preserving the rule that MSS values are never increased. The helper returns 0 when at least one MSS option was handled, whether or not any value had to be lowered. It returns -ENOENT when no MSS option is present and -EINVAL when option parsing fails before any MSS option is found. If parsing fails after an MSS option was handled, the helper still returns 0 so callers do not treat the packet as missing an MSS option after the skb may already have been modified. Signed-off-by: Ralf Lici --- Changes since v3 https://lore.kernel.org/openvpn-devel/20260519080500.120724-1-ralf@mandelbit.com/ - keep scanning the TCP option block and clamp all MSS options No changes since v2 https://lore.kernel.org/openvpn-devel/20260518085908.135570-1-ralf@mandelbit.com/ No changes since v1 https://lore.kernel.org/openvpn-devel/20260515075941.102225-1-ralf@mandelbit.com/ include/net/tcp.h | 2 ++ net/ipv4/tcp.c | 70 +++++++++++++++++++++++++++++++++++++++ net/netfilter/xt_TCPMSS.c | 36 ++------------------ 3 files changed, 74 insertions(+), 34 deletions(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index 3c4e6adb0dbd..e722c7d936bf 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -538,6 +538,8 @@ void tcp_parse_options(const struct net *net, const struct sk_buff *skb, struct tcp_options_received *opt_rx, int estab, struct tcp_fastopen_cookie *foc); +int tcp_clamp_mss_option(struct sk_buff *skb, struct tcphdr *th, u16 maxmss); + /* * BPF SKB-less helpers */ diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 21ece4c71612..521aa63f5958 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -721,6 +721,76 @@ static inline void tcp_mark_urg(struct tcp_sock *tp, int flags) tp->snd_up = tp->write_seq; } +/** + * tcp_clamp_mss_option - clamp any existing TCP MSS option + * @skb: skb containing the TCP segment + * @th: TCP header in @skb + * @maxmss: upper bound for the TCP MSS option value + * + * Parse the TCP option block and lower any existing MSS option to @maxmss. + * The MSS value is never increased. If any MSS value is changed, the TCP + * checksum in @th is updated. + * + * The caller must ensure that @th and the complete TCP option block are + * present in the linear data area and writable. + * + * Return: 0 when at least one MSS option was handled, -ENOENT when no MSS + * option is present, or -EINVAL when the TCP option block is malformed before + * any MSS option is found. + */ +int tcp_clamp_mss_option(struct sk_buff *skb, struct tcphdr *th, u16 maxmss) +{ + int length = th->doff * 4 - sizeof(*th); + u8 *ptr = (u8 *)(th + 1); + bool found = false; + int ret = -ENOENT; + u16 oldmss; + + while (length > 0) { + int opcode = *ptr++; + int opsize; + + switch (opcode) { + case TCPOPT_EOL: + ret = -ENOENT; + goto out; + case TCPOPT_NOP: + length--; + continue; + default: + if (length < 2) { + ret = -EINVAL; + goto out; + } + + opsize = *ptr++; + if (opsize < 2 || opsize > length) { + ret = -EINVAL; + goto out; + } + + if (opcode == TCPOPT_MSS && opsize == TCPOLEN_MSS) { + found = true; + oldmss = get_unaligned_be16(ptr); + if (oldmss && oldmss > maxmss) { + put_unaligned_be16(maxmss, ptr); + inet_proto_csum_replace2(&th->check, + skb, + htons(oldmss), + htons(maxmss), + false); + } + } + + ptr += opsize - 2; + length -= opsize; + } + } +out: + return found ? 0 : ret; +} +EXPORT_SYMBOL_GPL(tcp_clamp_mss_option); + /* If a not yet filled skb is pushed, do not send it if * we have data packets in Qdisc or NIC queues : * Because TX completion will happen shortly, it gives a chance diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c index 80e1634bc51f..70983b757229 100644 --- a/net/netfilter/xt_TCPMSS.c +++ b/net/netfilter/xt_TCPMSS.c @@ -30,16 +30,6 @@ MODULE_DESCRIPTION("Xtables: TCP Maximum Segment Size (MSS) adjustment"); MODULE_ALIAS("ipt_TCPMSS"); MODULE_ALIAS("ip6t_TCPMSS"); -static inline unsigned int -optlen(const u_int8_t *opt, unsigned int offset) -{ - /* Beware zero-length options: make finite progress */ - if (opt[offset] <= TCPOPT_NOP || opt[offset+1] == 0) - return 1; - else - return opt[offset+1]; -} - static u_int32_t tcpmss_reverse_mtu(struct net *net, const struct sk_buff *skb, unsigned int family) @@ -77,7 +67,6 @@ tcpmss_mangle_packet(struct sk_buff *skb, const struct xt_tcpmss_info *info = par->targinfo; struct tcphdr *tcph; int len, tcp_hdrlen; - unsigned int i; __be16 oldval; u16 newmss; u8 *opt; @@ -113,29 +102,8 @@ tcpmss_mangle_packet(struct sk_buff *skb, } else newmss = info->mss; - opt = (u_int8_t *)tcph; - for (i = sizeof(struct tcphdr); i <= tcp_hdrlen - TCPOLEN_MSS; i += optlen(opt, i)) { - if (opt[i] == TCPOPT_MSS && opt[i+1] == TCPOLEN_MSS) { - u_int16_t oldmss; - - oldmss = (opt[i+2] << 8) | opt[i+3]; - - /* Never increase MSS, even when setting it, as - * doing so results in problems for hosts that rely - * on MSS being set correctly. - */ - if (oldmss <= newmss) - return 0; - - opt[i+2] = (newmss & 0xff00) >> 8; - opt[i+3] = newmss & 0x00ff; - - inet_proto_csum_replace2(&tcph->check, skb, - htons(oldmss), htons(newmss), - false); - return 0; - } - } + if (tcp_clamp_mss_option(skb, tcph, newmss) == 0) + return 0; /* There is data after the header so the option can't be added * without moving it, and doing so may make the SYN packet From patchwork Wed May 20 09:16:11 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ralf Lici X-Patchwork-Id: 4959 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:b695:b0:861:c897:cb9d with SMTP id dh21csp717191mab; Wed, 20 May 2026 02:17:08 -0700 (PDT) X-Forwarded-Encrypted: i=2; AFNElJ+hnejWYkopq70qhFYc1tcmhvEW1IoiWKHEgy1q1OieCmnLoEg/l8qPYj7LjvFW6GtNgeb8Kmpl5v0=@openvpn.net X-Received: by 2002:a54:4e99:0:b0:45e:f443:dc3d with SMTP id 5614622812f47-482e5609803mr10416013b6e.13.1779268628621; Wed, 20 May 2026 02:17:08 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1779268628; cv=none; d=google.com; s=arc-20240605; b=FUDzjf9EhJfHR+YQjU7MpkURJz0tH+ltCkTPdKlVYSd0ZRpCurjUELvcDgqaMPxjah X1iL01ZCI1bWqlqH7GYOUHZQVh0GH3KMAE9bwEb4/l902yHgOnbuhr7cHrMdwYnKmmXk yubBMya60yHOfi7xuR+XOSacyvCQp30IcNA3+0Nn9m3LKNDq9CMz76qU5wGzv6iDqacZ r+X/IrPFswk8fKsyxX6+xEhfkC5R/VDnbF41auGgp5Do6oVVdPNhwB9RQLikeCtnPuO2 GiPyoFUxbkgLIymBqyZxMZwGOuGkeeceeguGllpBiiHxDUEcnhjRw7KLV94lVYPAjcpG bncQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:content-transfer-encoding:list-subscribe:list-help :list-post:list-archive:list-unsubscribe:list-id:precedence:subject :mime-version:references:in-reply-to:message-id:date:to:from :dkim-signature:dkim-signature:dkim-signature:dkim-signature; bh=6NtzWeD5mgPRXoVbN6nKI9EirIXuQpx4qB8zZXHIvDk=; fh=4NbAC/LsuMLI0S0hprUlLSLCiHwg6SCAifhH718Jh0Q=; b=R5/9RIXsQqbVgzLXp66uV1rwqqCfz2DQtWA7ExKyB2VbFKGbajoCucSmb2yQE4ZAYG 3Z7MqFLWF6iVFfYVbwURt+DpEXloP4z8wNnHo25JfcKmSnz4qFUPNlqJzARgbDGE91hY N0WO5FC3eqnwBNR6XJz2D5UcNh89phF4tUGzuIG5OFw01jgZ3kuxWXsqHb6jq6K3JdiS JQ5N+hVoGuKKEmuqxFlYvezoAhILCIAt4hGeCntYRxSGaXv/kmo1HhVFC5T1Fc9la4xj HXZkQ1imUkU9YSmooUHe3N3c1eJcSutuU5iv10JVgylny89gIhKqBDzmvZNJtCOMmLa9 T+cA==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=LzM63Zy4; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=TClCRdDB; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b="FJvF/Nda"; dkim=neutral (body hash did not verify) header.i=@mandelbit.com header.s=MBO0001 header.b=U1yj7MLZ; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net Received: from lists.sourceforge.net (lists.sourceforge.net. [216.105.38.7]) by mx.google.com with ESMTPS id 5614622812f47-484fbee3675si2915838b6e.89.2026.05.20.02.17.08 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 20 May 2026 02:17:08 -0700 (PDT) Received-SPF: pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) client-ip=216.105.38.7; Authentication-Results: mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=LzM63Zy4; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=TClCRdDB; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b="FJvF/Nda"; dkim=neutral (body hash did not verify) header.i=@mandelbit.com header.s=MBO0001 header.b=U1yj7MLZ; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.sourceforge.net; s=beta; h=Content-Transfer-Encoding:Content-Type: List-Subscribe:List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id: Subject:MIME-Version:References:In-Reply-To:Message-ID:Date:To:From:Sender: Reply-To:Cc:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=6NtzWeD5mgPRXoVbN6nKI9EirIXuQpx4qB8zZXHIvDk=; b=LzM63Zy4vThXqGoOQenFH60L73 r3Q+JUVb4pjAjaecT+T082RUjSx5eBxRbZC4d8Jr45N8w2u2POjaIKf1dFw/KrVlqlxYQmNbi1CHO FwH3RpvUJkdcq1HWtbgDTvAVCIYf4L2Vi0lzxFE3vfCm+LnQOBV83vF3641ud49yPB00=; 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.95) (envelope-from ) id 1wPd2w-0005YT-Vq; Wed, 20 May 2026 09:16:59 +0000 Received: from [172.30.29.66] (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.95) (envelope-from ) id 1wPd2h-0005Y7-48 for openvpn-devel@lists.sourceforge.net; Wed, 20 May 2026 09:16:43 +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:Cc:To:From:Sender:Reply-To: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=XwHyaZwf8E2H75h1lcxPIb/LKWEja+E2u8Oc5I/YtrU=; b=TClCRdDBcgEj7Q6WtOwXCNQriC eydy297BhNJwVI383IJevKx2KZ8HzdN6roRPAN9KBMPw6f7bElbD53wjfyaYT0oPLIxcTnGmySgDx PP+5B3tRX4aeKt0DcCmtTXvXKREO7iGsTVqnbdlUT++juSsg9corEVu2CfNCGVlXAyag=; 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:Cc:To:From:Sender:Reply-To: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=XwHyaZwf8E2H75h1lcxPIb/LKWEja+E2u8Oc5I/YtrU=; b=FJvF/Nda1+ew0vAZN/mGHOR3Wc V2cLwklLkTaWqswHYZkUzZtuXWvRSzk2tVVGWGlIRBeOPXlHKIVKYgT4G+n82K5xgNM5Dzzvn+3Zz KzkXtwWNTdsPMfeAatKafoArCRBBKBCt584i+dftUvseUIHxq5A1j7QME6DOW4Uyqs8Q=; Received: from mout-b-206.mailbox.org ([195.10.208.51]) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.95) id 1wPd2f-0003PJ-AZ for openvpn-devel@lists.sourceforge.net; Wed, 20 May 2026 09:16:43 +0000 Received: from smtp202.mailbox.org (smtp202.mailbox.org [10.196.197.202]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-b-206.mailbox.org (Postfix) with ESMTPS id 4gL5Wc1D5mz9xFs; Wed, 20 May 2026 11:16:28 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mandelbit.com; s=MBO0001; t=1779268588; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=XwHyaZwf8E2H75h1lcxPIb/LKWEja+E2u8Oc5I/YtrU=; b=U1yj7MLZlwG6XbjrBPGceGvz38i8tf61eGbGobLswsbwIOXBwarcfkcvKAh6G3sKhZZiOS wMj6ffNEh0FS38WnXHv0lDqL3rzxNI1Rcj1YFw26Rdx8qHyG/iW36UaF8x9ADNDERQOqn9 bDqRRRCrkGUO6QWDs8NUSoTQaRZDHIx49gm2IvsL2RVAs/0vG53iKg1B8UXm76mW7eri+1 A+HBZ/yPQxY/3hNGpFWqmOvOwMRnfOxgwsot4SDsF2LUOUi09NQP3xdLCnAg7D9yY1Ew4B b8mnvxlo2eVFLSYGGhaQdzVeYUlTak4RjL2qJb3aZOW+QVPAGZ1rGVrmfRiGHQ== From: Ralf Lici To: openvpn-devel@lists.sourceforge.net Date: Wed, 20 May 2026 11:16:11 +0200 Message-ID: <20260520091613.158891-2-ralf@mandelbit.com> In-Reply-To: <20260520091613.158891-1-ralf@mandelbit.com> References: <20260520091613.158891-1-ralf@mandelbit.com> MIME-Version: 1.0 X-Spam-Score: -0.2 (/) X-Spam-Report: Spam detection software, running on the system "sfi-spamd-1.hosts.colo.sdot.me", 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: Add support for OpenVPN mssfix in ovpn. This clamps TCP MSS options in SYN and SYN-ACK packets crossing the ovpn device so TCP peers choose segment sizes that fit within the VPN path MTU after OpenVPN [...] Content analysis details: (-0.2 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain X-Headers-End: 1wPd2f-0003PJ-AZ Subject: [Openvpn-devel] [PATCH ovpn net-next v4 2/3] ovpn: implement TCP MSS clamping 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 X-GMAIL-THRID: =?utf-8?q?1865698381534621963?= X-GMAIL-MSGID: =?utf-8?q?1865698381534621963?= Add support for OpenVPN mssfix in ovpn. This clamps TCP MSS options in SYN and SYN-ACK packets crossing the ovpn device so TCP peers choose segment sizes that fit within the VPN path MTU after OpenVPN encapsulation. Store the computed IPv4 MSS clamp value per peer and apply it on both RX and TX paths. IPv6 packets use the same value minus 20 bytes, matching OpenVPN userspace behavior for the larger IPv6 header. Only non-fragmented TCP packets are considered, and the shared TCP MSS option helper is used to update existing MSS options without increasing them. Signed-off-by: Ralf Lici --- Changes since v3 https://lore.kernel.org/openvpn-devel/20260519080500.120724-2-ralf@mandelbit.com/ - use skb_network_offset when computing TCP header offsets - use ovpn_dev_dstats_{tx,rx}_dropped so drop-stat updates run with BH disabled Changes since v2 https://lore.kernel.org/openvpn-devel/20260518085908.135570-2-ralf@mandelbit.com/ - drop the skb when mssfix cannot make the TCP header/options writable - use READ_ONCE for peer->mssfix in ovpn_nl_send_peer and emit the cached value Changes since v1 https://lore.kernel.org/openvpn-devel/20260515075941.102225-2-ralf@mandelbit.com/ - reject IPv4 packet with ihl < 5 - use READ_ONCE and WRITE_ONCE when reading or updating peer->mssfix - validate the mssfix netlink attribute before saving it to avoid partial peer updates on an invalid attribute Documentation/netlink/specs/ovpn.yaml | 12 +++ drivers/net/ovpn/io.c | 104 ++++++++++++++++++++++++++ drivers/net/ovpn/netlink-gen.c | 9 ++- drivers/net/ovpn/netlink-gen.h | 6 +- drivers/net/ovpn/netlink.c | 19 +++++ drivers/net/ovpn/peer.h | 2 + include/uapi/linux/ovpn.h | 1 + 7 files changed, 147 insertions(+), 6 deletions(-) diff --git a/Documentation/netlink/specs/ovpn.yaml b/Documentation/netlink/specs/ovpn.yaml index b0c782e59a32..6755193a921e 100644 --- a/Documentation/netlink/specs/ovpn.yaml +++ b/Documentation/netlink/specs/ovpn.yaml @@ -171,6 +171,14 @@ attribute-sets: will advertise the tx-id to be used on the link. checks: max: 0xFFFFFF + - + name: mssfix + type: u16 + doc: >- + OpenVPN mssfix value for this peer. TCP MSS options in SYN and + SYN-ACK packets traveling through the ovpn device are clamped to + this value for IPv4. For IPv6, 20 bytes are subtracted before + clamping to account for the larger IPv6 header. - name: peer-new-input subset-of: peer @@ -201,6 +209,8 @@ attribute-sets: name: keepalive-timeout - name: tx-id + - + name: mssfix - name: peer-set-input subset-of: peer @@ -229,6 +239,8 @@ attribute-sets: name: keepalive-timeout - name: tx-id + - + name: mssfix - name: peer-del-input subset-of: peer diff --git a/drivers/net/ovpn/io.c b/drivers/net/ovpn/io.c index a6b777a9c2d9..6764bc703865 100644 --- a/drivers/net/ovpn/io.c +++ b/drivers/net/ovpn/io.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "ovpnpriv.h" #include "peer.h" @@ -54,12 +55,97 @@ static bool ovpn_is_keepalive(struct sk_buff *skb) return !memcmp(skb->data, ovpn_keepalive_message, OVPN_KEEPALIVE_SIZE); } +/** + * ovpn_apply_mssfix - clamp TCP MSS options on SYN packets + * @skb: skb to inspect and possibly modify + * @mssfix: maximum IPv4 MSS value to apply + * + * Verify that @skb carries a TCP SYN or SYN-ACK packet. If so, clamp any + * TCPOPT_MSS options to @mssfix for IPv4, or to @mssfix - 20 for IPv6 to + * account for the larger IPv6 header. MSS values are never increased. + * + * Notes: + * - the function assumes the IP header is fully linear; this is currently + * guaranteed because both TX and RX paths call it only after + * ovpn_ip_check_protocol, which linearizes the IP header; + * - MSS clamping is performed only when a valid TCPOPT_MSS option is present, + * matching the behavior of OpenVPN userspace. + * + * Return: 0 on success or when no update is needed, -ENOMEM if the TCP + * header/options cannot be made writable, or a negative parse error for + * malformed packets. + */ +static int ovpn_apply_mssfix(struct sk_buff *skb, u16 mssfix) +{ + const unsigned int nhoff = skb_network_offset(skb); + const struct ipv6hdr *ipv6h; + const struct iphdr *iph; + struct tcphdr *th; + int thoff, thlen; + __be16 frag_off; + u16 maxmss; + u8 nexthdr; + + switch (skb->protocol) { + case htons(ETH_P_IP): + iph = ip_hdr(skb); + if (unlikely(iph->ihl < 5)) + return -EINVAL; + if (iph->protocol != IPPROTO_TCP || + unlikely(ip_is_fragment(iph))) + return 0; + + thoff = nhoff + ip_hdrlen(skb); + maxmss = mssfix; + break; + case htons(ETH_P_IPV6): + ipv6h = ipv6_hdr(skb); + nexthdr = ipv6h->nexthdr; + thoff = ipv6_skip_exthdr(skb, nhoff + sizeof(struct ipv6hdr), + &nexthdr, &frag_off); + if (unlikely(thoff < 0)) + return thoff; + if (nexthdr != IPPROTO_TCP || unlikely(frag_off)) + return 0; + + maxmss = mssfix - 20; + break; + default: + return 0; + } + + if (unlikely(skb->len < thoff + sizeof(struct tcphdr))) + return -EINVAL; + + if (unlikely(skb_ensure_writable(skb, thoff + sizeof(struct tcphdr)))) + return -ENOMEM; + + th = (struct tcphdr *)(skb->data + thoff); + thlen = th->doff * 4; + + if (unlikely(thlen < sizeof(*th))) + return -EINVAL; + + if (likely(!th->syn)) + return 0; + + if (unlikely(skb->len < thoff + thlen)) + return -EINVAL; + + if (unlikely(skb_ensure_writable(skb, thoff + thlen))) + return -ENOMEM; + + th = (struct tcphdr *)(skb->data + thoff); + return tcp_clamp_mss_option(skb, th, maxmss); +} + /* Called after decrypt to write the IP packet to the device. * This method is expected to manage/free the skb. */ static void ovpn_netdev_write(struct ovpn_peer *peer, struct sk_buff *skb) { unsigned int pkt_len; + u16 mssfix; int ret; /* @@ -74,6 +160,16 @@ static void ovpn_netdev_write(struct ovpn_peer *peer, struct sk_buff *skb) */ skb->ip_summed = CHECKSUM_NONE; + /* apply the MSS fix after resetting the checksum state in order to + * avoid using stale metadata when updating the checksum + */ + mssfix = READ_ONCE(peer->mssfix); + if (mssfix && unlikely(ovpn_apply_mssfix(skb, mssfix) == -ENOMEM)) { + ovpn_dev_dstats_rx_dropped(peer->ovpn->dev); + kfree_skb(skb); + return; + } + /* skb hash for transport packet no longer valid after decapsulation */ skb_clear_hash(skb); @@ -336,12 +432,20 @@ static bool ovpn_encrypt_one(struct ovpn_peer *peer, struct sk_buff *skb) static void ovpn_send(struct ovpn_priv *ovpn, struct sk_buff *skb, struct ovpn_peer *peer) { + const u16 mssfix = READ_ONCE(peer->mssfix); struct sk_buff *curr, *next; /* this might be a GSO-segmented skb list: process each skb * independently */ skb_list_walk_safe(skb, curr, next) { + if (mssfix && + unlikely(ovpn_apply_mssfix(curr, mssfix) == -ENOMEM)) { + ovpn_dev_dstats_tx_dropped(ovpn->dev); + kfree_skb(curr); + continue; + } + if (unlikely(!ovpn_encrypt_one(peer, curr))) { ovpn_dev_dstats_tx_dropped(ovpn->dev); kfree_skb(curr); diff --git a/drivers/net/ovpn/netlink-gen.c b/drivers/net/ovpn/netlink-gen.c index 2147cec7c2c5..8fd24af5717a 100644 --- a/drivers/net/ovpn/netlink-gen.c +++ b/drivers/net/ovpn/netlink-gen.c @@ -55,7 +55,7 @@ const struct nla_policy ovpn_keydir_nl_policy[OVPN_A_KEYDIR_NONCE_TAIL + 1] = { [OVPN_A_KEYDIR_NONCE_TAIL] = NLA_POLICY_EXACT_LEN(OVPN_NONCE_TAIL_SIZE), }; -const struct nla_policy ovpn_peer_nl_policy[OVPN_A_PEER_TX_ID + 1] = { +const struct nla_policy ovpn_peer_nl_policy[OVPN_A_PEER_MSSFIX + 1] = { [OVPN_A_PEER_ID] = NLA_POLICY_FULL_RANGE(NLA_U32, &ovpn_a_peer_id_range), [OVPN_A_PEER_REMOTE_IPV4] = { .type = NLA_BE32, }, [OVPN_A_PEER_REMOTE_IPV6] = NLA_POLICY_EXACT_LEN(16), @@ -80,13 +80,14 @@ const struct nla_policy ovpn_peer_nl_policy[OVPN_A_PEER_TX_ID + 1] = { [OVPN_A_PEER_LINK_RX_PACKETS] = { .type = NLA_UINT, }, [OVPN_A_PEER_LINK_TX_PACKETS] = { .type = NLA_UINT, }, [OVPN_A_PEER_TX_ID] = NLA_POLICY_FULL_RANGE(NLA_U32, &ovpn_a_peer_tx_id_range), + [OVPN_A_PEER_MSSFIX] = { .type = NLA_U16, }, }; const struct nla_policy ovpn_peer_del_input_nl_policy[OVPN_A_PEER_ID + 1] = { [OVPN_A_PEER_ID] = NLA_POLICY_FULL_RANGE(NLA_U32, &ovpn_a_peer_id_range), }; -const struct nla_policy ovpn_peer_new_input_nl_policy[OVPN_A_PEER_TX_ID + 1] = { +const struct nla_policy ovpn_peer_new_input_nl_policy[OVPN_A_PEER_MSSFIX + 1] = { [OVPN_A_PEER_ID] = NLA_POLICY_FULL_RANGE(NLA_U32, &ovpn_a_peer_id_range), [OVPN_A_PEER_REMOTE_IPV4] = { .type = NLA_BE32, }, [OVPN_A_PEER_REMOTE_IPV6] = NLA_POLICY_EXACT_LEN(16), @@ -100,9 +101,10 @@ const struct nla_policy ovpn_peer_new_input_nl_policy[OVPN_A_PEER_TX_ID + 1] = { [OVPN_A_PEER_KEEPALIVE_INTERVAL] = { .type = NLA_U32, }, [OVPN_A_PEER_KEEPALIVE_TIMEOUT] = { .type = NLA_U32, }, [OVPN_A_PEER_TX_ID] = NLA_POLICY_FULL_RANGE(NLA_U32, &ovpn_a_peer_tx_id_range), + [OVPN_A_PEER_MSSFIX] = { .type = NLA_U16, }, }; -const struct nla_policy ovpn_peer_set_input_nl_policy[OVPN_A_PEER_TX_ID + 1] = { +const struct nla_policy ovpn_peer_set_input_nl_policy[OVPN_A_PEER_MSSFIX + 1] = { [OVPN_A_PEER_ID] = NLA_POLICY_FULL_RANGE(NLA_U32, &ovpn_a_peer_id_range), [OVPN_A_PEER_REMOTE_IPV4] = { .type = NLA_BE32, }, [OVPN_A_PEER_REMOTE_IPV6] = NLA_POLICY_EXACT_LEN(16), @@ -115,6 +117,7 @@ const struct nla_policy ovpn_peer_set_input_nl_policy[OVPN_A_PEER_TX_ID + 1] = { [OVPN_A_PEER_KEEPALIVE_INTERVAL] = { .type = NLA_U32, }, [OVPN_A_PEER_KEEPALIVE_TIMEOUT] = { .type = NLA_U32, }, [OVPN_A_PEER_TX_ID] = NLA_POLICY_FULL_RANGE(NLA_U32, &ovpn_a_peer_tx_id_range), + [OVPN_A_PEER_MSSFIX] = { .type = NLA_U16, }, }; /* OVPN_CMD_PEER_NEW - do */ diff --git a/drivers/net/ovpn/netlink-gen.h b/drivers/net/ovpn/netlink-gen.h index 67cd85f86173..dfca5d8f32ca 100644 --- a/drivers/net/ovpn/netlink-gen.h +++ b/drivers/net/ovpn/netlink-gen.h @@ -18,10 +18,10 @@ extern const struct nla_policy ovpn_keyconf_del_input_nl_policy[OVPN_A_KEYCONF_S extern const struct nla_policy ovpn_keyconf_get_nl_policy[OVPN_A_KEYCONF_CIPHER_ALG + 1]; extern const struct nla_policy ovpn_keyconf_swap_input_nl_policy[OVPN_A_KEYCONF_PEER_ID + 1]; extern const struct nla_policy ovpn_keydir_nl_policy[OVPN_A_KEYDIR_NONCE_TAIL + 1]; -extern const struct nla_policy ovpn_peer_nl_policy[OVPN_A_PEER_TX_ID + 1]; +extern const struct nla_policy ovpn_peer_nl_policy[OVPN_A_PEER_MSSFIX + 1]; extern const struct nla_policy ovpn_peer_del_input_nl_policy[OVPN_A_PEER_ID + 1]; -extern const struct nla_policy ovpn_peer_new_input_nl_policy[OVPN_A_PEER_TX_ID + 1]; -extern const struct nla_policy ovpn_peer_set_input_nl_policy[OVPN_A_PEER_TX_ID + 1]; +extern const struct nla_policy ovpn_peer_new_input_nl_policy[OVPN_A_PEER_MSSFIX + 1]; +extern const struct nla_policy ovpn_peer_set_input_nl_policy[OVPN_A_PEER_MSSFIX + 1]; int ovpn_nl_pre_doit(const struct genl_split_ops *ops, struct sk_buff *skb, struct genl_info *info); diff --git a/drivers/net/ovpn/netlink.c b/drivers/net/ovpn/netlink.c index 291e2e5bb450..2f1a88f6d4e0 100644 --- a/drivers/net/ovpn/netlink.c +++ b/drivers/net/ovpn/netlink.c @@ -184,6 +184,7 @@ static int ovpn_nl_peer_precheck(struct ovpn_priv *ovpn, struct nlattr **attrs) { sa_family_t local_fam, remote_fam; + u16 mssfix; if (NL_REQ_ATTR_CHECK(info->extack, info->attrs[OVPN_A_PEER], attrs, OVPN_A_PEER_ID)) @@ -263,6 +264,15 @@ static int ovpn_nl_peer_precheck(struct ovpn_priv *ovpn, return -EINVAL; } + if (attrs[OVPN_A_PEER_MSSFIX]) { + mssfix = nla_get_u16(attrs[OVPN_A_PEER_MSSFIX]); + if (mssfix > 0 && mssfix <= 20) { + NL_SET_ERR_MSG_FMT_MOD(info->extack, + "mssfix must be 0 (disable) or at least 21"); + return -EINVAL; + } + } + return 0; } @@ -311,6 +321,10 @@ static int ovpn_nl_peer_modify(struct ovpn_peer *peer, struct genl_info *info, if (attrs[OVPN_A_PEER_TX_ID]) peer->tx_id = nla_get_u32(attrs[OVPN_A_PEER_TX_ID]); + if (attrs[OVPN_A_PEER_MSSFIX]) + WRITE_ONCE(peer->mssfix, + nla_get_u16(attrs[OVPN_A_PEER_MSSFIX])); + if (attrs[OVPN_A_PEER_VPN_IPV4]) { rehash = true; peer->vpn_addrs.ipv4.s_addr = @@ -547,6 +561,7 @@ static int ovpn_nl_send_peer(struct sk_buff *skb, const struct genl_info *info, int ret = -EMSGSIZE; struct nlattr *attr; __be16 local_port; + u16 mssfix; void *hdr; int id; @@ -582,6 +597,10 @@ static int ovpn_nl_send_peer(struct sk_buff *skb, const struct genl_info *info, if (nla_put_u32(skb, OVPN_A_PEER_TX_ID, peer->tx_id)) goto err; + mssfix = READ_ONCE(peer->mssfix); + if (mssfix && nla_put_u16(skb, OVPN_A_PEER_MSSFIX, mssfix)) + goto err; + if (peer->vpn_addrs.ipv4.s_addr != htonl(INADDR_ANY)) if (nla_put_in_addr(skb, OVPN_A_PEER_VPN_IPV4, peer->vpn_addrs.ipv4.s_addr)) diff --git a/drivers/net/ovpn/peer.h b/drivers/net/ovpn/peer.h index 328401570cba..b4bae5259bdc 100644 --- a/drivers/net/ovpn/peer.h +++ b/drivers/net/ovpn/peer.h @@ -23,6 +23,7 @@ * @dev_tracker: reference tracker for associated dev * @id: unique identifier, used to match incoming packets * @tx_id: identifier to be used in TX packets + * @mssfix: maximum IPv4 TCP MSS to advertise on tunnelled SYN packets * @vpn_addrs: IP addresses assigned over the tunnel * @vpn_addrs.ipv4: IPv4 assigned to peer on the tunnel * @vpn_addrs.ipv6: IPv6 assigned to peer on the tunnel @@ -66,6 +67,7 @@ struct ovpn_peer { netdevice_tracker dev_tracker; u32 id; u32 tx_id; + u16 mssfix; struct { struct in_addr ipv4; struct in6_addr ipv6; diff --git a/include/uapi/linux/ovpn.h b/include/uapi/linux/ovpn.h index 06690090a1a9..d89168c6894e 100644 --- a/include/uapi/linux/ovpn.h +++ b/include/uapi/linux/ovpn.h @@ -56,6 +56,7 @@ enum { OVPN_A_PEER_LINK_RX_PACKETS, OVPN_A_PEER_LINK_TX_PACKETS, OVPN_A_PEER_TX_ID, + OVPN_A_PEER_MSSFIX, __OVPN_A_PEER_MAX, OVPN_A_PEER_MAX = (__OVPN_A_PEER_MAX - 1) From patchwork Wed May 20 09:16:12 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ralf Lici X-Patchwork-Id: 4957 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:b695:b0:861:c897:cb9d with SMTP id dh21csp717168mab; Wed, 20 May 2026 02:17:05 -0700 (PDT) X-Forwarded-Encrypted: i=2; AFNElJ+oZptKs7qCh0vis6LQLbL5G0bWgpOh0JWS8A+/WC6j90sVoeSJ6K+/naaCR/teAQlLQ68FktwjJWA=@openvpn.net X-Received: by 2002:a05:6870:2c41:b0:439:f46f:c3e6 with SMTP id 586e51a60fabf-43a2de0c518mr15280259fac.36.1779268625464; Wed, 20 May 2026 02:17:05 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1779268625; cv=none; d=google.com; s=arc-20240605; b=gWh7ZukYMnCnhpeV/3nspvucNbuPpcNBhzNJODFPrtWl+3c3vvn8isUFFsp8bX03UE MD//Pl1a45vVEGQgi2EkXGgrDxu5emr/V2WACBsArI8ElehAQJikr+1cl1a0hW4o++BR OGtL5fJslKL6o4lk4I82g/QHYPAlJb3Ih/9XqxgYGYgvnkSss/LlVDnCpFiLAcmmu8ew SZfM4QTA2LtjZntg7KLcWN865ABL7Vkjutz3BG+PkNzkaI8INiQn+tPGQm1DQMRX4l6r z3qG4eKKbdCYQY92n5Lx2gIsoObjQ5qcuVmc+gWV+yJeXE+dWtvR6Fva/B29vTHNM5nB hYog== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:content-transfer-encoding:list-subscribe:list-help :list-post:list-archive:list-unsubscribe:list-id:precedence:subject :mime-version:references:in-reply-to:message-id:date:to:from :dkim-signature:dkim-signature:dkim-signature:dkim-signature; bh=XR6qjNzIref6RcfZDilS4cwqbAXQniOSvjckCyF8AUs=; fh=4NbAC/LsuMLI0S0hprUlLSLCiHwg6SCAifhH718Jh0Q=; b=PaphNHOIzXcghwGcgDUzI56pFQsJKdLNn4jlX79WuLDhRkNoqetTG/2gDvzbyRepOa JXPBHSxS1nryjzyuVrDOuNEw4li1M6TzCCA1q1DRLILiMgRykyRtSoF8vAXIdrFBfF6w 8vuAsSMgDVt7CkqDC586YSTEI1NAyPyJ4/9wn+1Oy5xn03kZbCAyWwdeGEowe84sJOMG giCYlJKDsI1SaQ6dLEko83XgJTEDXhNo9meyy/06PEuVDvtuN5sE5KP7Gn2+lsRl6Y6O KVhtm1uN4toEBmHEKST/Rg5Ax9/fDyJv/vHJyMVfE8SCNoNXNc28iSAbrhbysgSBEvR8 jujg==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=fSgVfw0M; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=hXOubspT; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=MLtKIC34; dkim=neutral (body hash did not verify) header.i=@mandelbit.com header.s=MBO0001 header.b="a9yQax/k"; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net Received: from lists.sourceforge.net (lists.sourceforge.net. [216.105.38.7]) by mx.google.com with ESMTPS id 586e51a60fabf-43a9582f60esi8177638fac.257.2026.05.20.02.17.05 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 20 May 2026 02:17:05 -0700 (PDT) Received-SPF: pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) client-ip=216.105.38.7; Authentication-Results: mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=fSgVfw0M; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=hXOubspT; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=MLtKIC34; dkim=neutral (body hash did not verify) header.i=@mandelbit.com header.s=MBO0001 header.b="a9yQax/k"; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.sourceforge.net; s=beta; h=Content-Transfer-Encoding:Content-Type: List-Subscribe:List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id: Subject:MIME-Version:References:In-Reply-To:Message-ID:Date:To:From:Sender: Reply-To:Cc:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=XR6qjNzIref6RcfZDilS4cwqbAXQniOSvjckCyF8AUs=; b=fSgVfw0MekcnBYKZsRlBVC2FN6 vrq4rnNfcDY29pzerEEbTeKKFqwPzg70Vf5W+AM/gs0vWlc+Kg1idv3ocVlVBMefB+2McK4YLRFpt iDKK1XTRDnUO/Jf2tBGeJ1hnaLy8oL9q+vkmS3McL22GGRFXadqKM+qKxbjTOi7L8xLQ=; Received: from [127.0.0.1] (helo=sfs-ml-3.v29.lw.sourceforge.com) by sfs-ml-3.v29.lw.sourceforge.com with esmtp (Exim 4.95) (envelope-from ) id 1wPd2x-0002lj-ID; Wed, 20 May 2026 09:17:00 +0000 Received: from [172.30.29.66] (helo=mx.sourceforge.net) by sfs-ml-3.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1wPd2w-0002lL-1R for openvpn-devel@lists.sourceforge.net; Wed, 20 May 2026 09:16:58 +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:Cc:To:From:Sender:Reply-To: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=oy4OGVLnEfxAVYpMhNjAYCD4zJORiyoXP2wKb7ZA6pg=; b=hXOubspTzjXTQvZM4+L1YNGpX7 iIO+HDqBY0O9t/3WA0WZn1NSzT4cguCLzuATR0MhYc3goTuo+bijz3xDx5ZVX76uAYlWCsMGtC1Te qRABCy7XZwxPe1BYgzH0HC38kQOybz6JjIL52MWq3w46q1hunmZ9OksywYTd0Fss6X04=; 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:Cc:To:From:Sender:Reply-To: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=oy4OGVLnEfxAVYpMhNjAYCD4zJORiyoXP2wKb7ZA6pg=; b=MLtKIC34ptsG4n/398t5/iX/Rg w54nPwAXrJ2rQqd5qFOMaZa+kMlfin6yiMaZ6otBpU7P4EMjZ9ieLYg01gBtF7ezcq1Dxy4fQ/dbG nSarbmDThBLDyqZpCOVrzTnQGetVKIc6iVOl1mxnzWdbsBx+PSI7qM2voDNELDtlpP9A=; Received: from mout-b-210.mailbox.org ([195.10.208.40]) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.95) id 1wPd2g-0003PR-JZ for openvpn-devel@lists.sourceforge.net; Wed, 20 May 2026 09:16:45 +0000 Received: from smtp202.mailbox.org (smtp202.mailbox.org [IPv6:2001:67c:2050:b231:465::202]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-b-210.mailbox.org (Postfix) with ESMTPS id 4gL5Wd5N8rzDx9J; Wed, 20 May 2026 11:16:29 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mandelbit.com; s=MBO0001; t=1779268589; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=oy4OGVLnEfxAVYpMhNjAYCD4zJORiyoXP2wKb7ZA6pg=; b=a9yQax/k2t5FoLN2vJG4k3gi0kv+9rFpRi14Q2yLqyrg4+wHKwf13yayjMueLiJttv/XKT 5xUnerQC1PjC7h5dxO9GpzDnYm6GD1C/ParJiU1NGPcYatNr381raZpfDRfwrKzFW9zXXV STDLWVtgkO94x+Hz+3pFcMDbqUpDyiAh0h37rvLoe3PvyVDmMGmZQMdCtXqYwHCWjPgrZ3 lUQoro/rxFe+E4q9P0UcreCpa7tkmiECSJ1dqtNVuwScHRN8LkzA2AWb5IL2hz2UX9Tax8 g3+o/J+Z4bYKnpOAl9qzYQy10xD6pgjRLS1S8SKKQvReeNR/j4l6jEPI81kjhQ== Authentication-Results: outgoing_mbo_mout; dkim=none; spf=pass (outgoing_mbo_mout: domain of ralf@mandelbit.com designates 2001:67c:2050:b231:465::202 as permitted sender) smtp.mailfrom=ralf@mandelbit.com From: Ralf Lici To: openvpn-devel@lists.sourceforge.net Date: Wed, 20 May 2026 11:16:12 +0200 Message-ID: <20260520091613.158891-3-ralf@mandelbit.com> In-Reply-To: <20260520091613.158891-1-ralf@mandelbit.com> References: <20260520091613.158891-1-ralf@mandelbit.com> MIME-Version: 1.0 X-Rspamd-Queue-Id: 4gL5Wd5N8rzDx9J X-Spam-Score: -0.2 (/) X-Spam-Report: Spam detection software, running on the system "sfi-spamd-1.hosts.colo.sdot.me", 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: Extend ovpn-cli set_peer to pass the peer mssfix attribute. Use -1 as the selftest CLI sentinel for leaving mssfix unchanged, so existing timeout-only peer updates can keep omitting the netlink attrib [...] Content analysis details: (-0.2 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain X-Headers-End: 1wPd2g-0003PR-JZ Subject: [Openvpn-devel] [PATCH ovpn net-next v4 3/3] selftests: ovpn: add mssfix coverage 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 X-GMAIL-THRID: =?utf-8?q?1865698378604255008?= X-GMAIL-MSGID: =?utf-8?q?1865698378604255008?= Extend ovpn-cli set_peer to pass the peer mssfix attribute. Use -1 as the selftest CLI sentinel for leaving mssfix unchanged, so existing timeout-only peer updates can keep omitting the netlink attribute. Add an ovpn test stage that configures mssfix on each side of a peer pair and verifies the MSS advertised on TCP SYN packets seen on the tunnel device. This covers both TX-side and RX-side clamping, and also checks that an invalid non-zero MSS value is rejected. Signed-off-by: Ralf Lici --- No changes since v3 https://lore.kernel.org/openvpn-devel/20260519080500.120724-3-ralf@mandelbit.com/ No changes since v2 https://lore.kernel.org/openvpn-devel/20260518085908.135570-3-ralf@mandelbit.com/ Changes since v1 https://lore.kernel.org/openvpn-devel/20260515075941.102225-3-ralf@mandelbit.com/ - parse mssfix into long before narrowing in ovpn-cli tools/testing/selftests/net/ovpn/ovpn-cli.c | 20 ++++- .../selftests/net/ovpn/test-close-socket.sh | 4 +- tools/testing/selftests/net/ovpn/test-mark.sh | 4 +- tools/testing/selftests/net/ovpn/test.sh | 75 +++++++++++++++++-- 4 files changed, 90 insertions(+), 13 deletions(-) diff --git a/tools/testing/selftests/net/ovpn/ovpn-cli.c b/tools/testing/selftests/net/ovpn/ovpn-cli.c index d40953375c86..67351f33e7c8 100644 --- a/tools/testing/selftests/net/ovpn/ovpn-cli.c +++ b/tools/testing/selftests/net/ovpn/ovpn-cli.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -129,6 +130,7 @@ struct ovpn_ctx { __u32 keepalive_interval; __u32 keepalive_timeout; + int mssfix; enum ovpn_key_direction key_dir; enum ovpn_key_slot key_slot; @@ -732,6 +734,8 @@ static int ovpn_set_peer(struct ovpn_ctx *ovpn) ovpn->keepalive_interval); NLA_PUT_U32(ctx->nl_msg, OVPN_A_PEER_KEEPALIVE_TIMEOUT, ovpn->keepalive_timeout); + if (ovpn->mssfix >= 0) + NLA_PUT_U16(ctx->nl_msg, OVPN_A_PEER_MSSFIX, ovpn->mssfix); nla_nest_end(ctx->nl_msg, attr); ret = ovpn_nl_msg_send(ctx, NULL); @@ -1730,13 +1734,15 @@ static void usage(const char *cmd) fprintf(stderr, "\tmark: socket FW mark value\n"); fprintf(stderr, - "* set_peer : set peer attributes\n"); + "* set_peer : set peer attributes\n"); fprintf(stderr, "\tiface: ovpn interface name\n"); fprintf(stderr, "\tpeer_id: peer ID of the peer to modify\n"); fprintf(stderr, "\tkeepalive_interval: interval for sending ping messages\n"); fprintf(stderr, "\tkeepalive_timeout: time after which a peer is timed out\n"); + fprintf(stderr, + "\tmssfix: TCP MSS value to clamp SYN packets to (0 disables, -1 leaves unchanged)\n"); fprintf(stderr, "* del_peer : delete peer\n"); fprintf(stderr, "\tiface: ovpn interface name\n"); @@ -2166,6 +2172,7 @@ static int ovpn_run_cmd(struct ovpn_ctx *ovpn) static int ovpn_parse_cmd_args(struct ovpn_ctx *ovpn, int argc, char *argv[]) { + long mssfix; int ret; /* no args required for LISTEN_MCAST */ @@ -2307,7 +2314,7 @@ static int ovpn_parse_cmd_args(struct ovpn_ctx *ovpn, int argc, char *argv[]) } break; case CMD_SET_PEER: - if (argc < 6) + if (argc < 7) return -EINVAL; ovpn->peer_id = strtoul(argv[3], NULL, 10); @@ -2329,6 +2336,14 @@ static int ovpn_parse_cmd_args(struct ovpn_ctx *ovpn, int argc, char *argv[]) "keepalive interval value out of range\n"); return -1; } + + errno = 0; + mssfix = strtol(argv[6], NULL, 10); + if (errno == ERANGE || mssfix < -1 || mssfix > UINT16_MAX) { + fprintf(stderr, "mssfix value out of range\n"); + return -1; + } + ovpn->mssfix = mssfix; break; case CMD_DEL_PEER: if (argc < 4) @@ -2442,6 +2457,7 @@ int main(int argc, char *argv[]) memset(&ovpn, 0, sizeof(ovpn)); ovpn.sa_family = AF_UNSPEC; ovpn.cipher = OVPN_CIPHER_ALG_NONE; + ovpn.mssfix = -1; ovpn.cmd = ovpn_parse_cmd(argv[1]); if (ovpn.cmd == CMD_INVALID) { diff --git a/tools/testing/selftests/net/ovpn/test-close-socket.sh b/tools/testing/selftests/net/ovpn/test-close-socket.sh index af1532b4d2da..091c0103bdba 100755 --- a/tools/testing/selftests/net/ovpn/test-close-socket.sh +++ b/tools/testing/selftests/net/ovpn/test-close-socket.sh @@ -41,10 +41,10 @@ ovpn_prepare_network() { peer_ns="ovpn_peer${p}" ovpn_cmd_ok "set peer0 timeout for peer ${p}" \ ip netns exec ovpn_peer0 ${OVPN_CLI} set_peer tun0 \ - ${p} 60 120 + ${p} 60 120 -1 ovpn_cmd_ok "set peer${p} timeout for peer ${p}" \ ip netns exec "${peer_ns}" ${OVPN_CLI} set_peer \ - tun${p} $((p + OVPN_ID_OFFSET)) 60 120 + tun${p} $((p + OVPN_ID_OFFSET)) 60 120 -1 done } diff --git a/tools/testing/selftests/net/ovpn/test-mark.sh b/tools/testing/selftests/net/ovpn/test-mark.sh index 5a8f47554286..11af23beea2a 100755 --- a/tools/testing/selftests/net/ovpn/test-mark.sh +++ b/tools/testing/selftests/net/ovpn/test-mark.sh @@ -54,10 +54,10 @@ ovpn_mark_prepare_network() { peer_ns="ovpn_peer${p}" ovpn_cmd_ok "set peer0 timeout for peer ${p}" \ ip netns exec ovpn_peer0 "${OVPN_CLI}" set_peer tun0 \ - "${p}" 60 120 + "${p}" 60 120 -1 ovpn_cmd_ok "set peer${p} timeout for peer ${p}" \ ip netns exec "${peer_ns}" "${OVPN_CLI}" set_peer \ - tun"${p}" $((p + OVPN_ID_OFFSET)) 60 120 + tun"${p}" $((p + OVPN_ID_OFFSET)) 60 120 -1 done } diff --git a/tools/testing/selftests/net/ovpn/test.sh b/tools/testing/selftests/net/ovpn/test.sh index c06e3135fbef..a0630034351a 100755 --- a/tools/testing/selftests/net/ovpn/test.sh +++ b/tools/testing/selftests/net/ovpn/test.sh @@ -49,10 +49,10 @@ ovpn_prepare_network() { peer_ns="ovpn_peer${p}" ovpn_cmd_ok "set peer0 timeout for peer ${p}" \ ip netns exec ovpn_peer0 ${OVPN_CLI} set_peer tun0 \ - ${p} 60 120 + ${p} 60 120 -1 ovpn_cmd_ok "set peer${p} timeout for peer ${p}" \ ip netns exec "${peer_ns}" ${OVPN_CLI} set_peer \ - tun${p} $((p + OVPN_ID_OFFSET)) 60 120 + tun${p} $((p + OVPN_ID_OFFSET)) 60 120 -1 done } @@ -142,6 +142,66 @@ ovpn_run_iperf() { wait "${iperf_pid}" || return 1 } +ovpn_run_mssfix_flow() { + local filter + local iperf_pid + local direction="$1" + local mssfix="$2" + local tcpdump_pid + + filter="tcp and src host 5.5.5.1 and dst host 5.5.5.2" + filter="${filter} and tcp[tcpflags] & tcp-syn != 0" + + ovpn_run_bg iperf_pid ip netns exec ovpn_peer1 iperf3 -1 -s + sleep 1 + + timeout 3s ip netns exec ovpn_peer1 tcpdump --immediate-mode -l -p \ + -vv -nn -i tun1 -c 1 "${filter}" 2>&1 | + grep -iq "mss ${mssfix}" & + tcpdump_pid=$! + sleep 0.3 + + ovpn_cmd_ok "run ${direction} mssfix TCP flow" \ + ip netns exec ovpn_peer0 iperf3 -t 1 -c 5.5.5.2 + + ovpn_cmd_ok "capture ${direction} mssfix TCP SYN" wait "${tcpdump_pid}" + ovpn_cmd_ok "finish ${direction} mssfix TCP server" wait "${iperf_pid}" +} + +ovpn_run_mssfix() { + local peer0_id=$((1 + OVPN_ID_OFFSET)) + + # peer0 will clamp MSS for packets exchanged with peer1 + ovpn_cmd_ok "set peer0 mssfix for peer 1" \ + ip netns exec ovpn_peer0 ${OVPN_CLI} set_peer tun0 1 \ + 60 120 900 + + ovpn_cmd_fail "reject invalid peer0 mssfix for peer 1" \ + ip netns exec ovpn_peer0 ${OVPN_CLI} set_peer tun0 1 \ + 60 120 20 + + ovpn_cmd_ok "clear peer1 mssfix for peer ${peer0_id}" \ + ip netns exec ovpn_peer1 ${OVPN_CLI} set_peer tun1 \ + "${peer0_id}" 60 120 0 + + ovpn_run_mssfix_flow "TX" 900 + + ovpn_cmd_ok "clear peer0 mssfix for peer 1" \ + ip netns exec ovpn_peer0 ${OVPN_CLI} set_peer tun0 1 \ + 60 120 0 + + # peer1 will clamp MSS for packets exchanged with peer0 + ovpn_cmd_ok "set peer1 mssfix for peer ${peer0_id}" \ + ip netns exec ovpn_peer1 ${OVPN_CLI} set_peer tun1 \ + "${peer0_id}" 60 120 901 + + ovpn_run_mssfix_flow "RX" 901 + + ovpn_cmd_ok "clear peer1 mssfix for peer ${peer0_id}" \ + ip netns exec ovpn_peer1 ${OVPN_CLI} set_peer tun1 \ + "${peer0_id}" 60 120 0 +} + ovpn_run_key_rollover() { local p local peer_ns @@ -259,11 +319,11 @@ ovpn_run_timeouts() { # Non-fatal: this may fail in some protocol modes. ovpn_cmd_mayfail "set peer0 timeout for peer ${p} (non-fatal)" \ ip netns exec ovpn_peer0 ${OVPN_CLI} set_peer tun0 \ - ${p} 3 3 + ${p} 3 3 -1 peer_ns="ovpn_peer${p}" ovpn_cmd_ok "disable timeout on peer${p} while peer0 adjusts \ state" ip netns exec "${peer_ns}" ${OVPN_CLI} set_peer \ - tun${p} $((p + OVPN_ID_OFFSET)) 0 0 + tun${p} $((p + OVPN_ID_OFFSET)) 0 0 -1 done # wait for peers to timeout sleep 5 @@ -274,7 +334,7 @@ ovpn_run_timeouts() { peer_ns="ovpn_peer${p}" ovpn_cmd_ok "set peer${p} P2P timeout" \ ip netns exec "${peer_ns}" ${OVPN_CLI} set_peer \ - tun${p} $((p + OVPN_ID_OFFSET)) 3 3 + tun${p} $((p + OVPN_ID_OFFSET)) 3 3 -1 done sleep 5 } @@ -293,9 +353,9 @@ trap ovpn_stage_err ERR ktap_print_header if [ "${OVPN_FLOAT}" == "1" ]; then - ktap_set_plan 13 + ktap_set_plan 14 else - ktap_set_plan 12 + ktap_set_plan 13 fi ovpn_cleanup @@ -307,6 +367,7 @@ ovpn_run_stage "run LAN traffic behind peer1" ovpn_run_lan_traffic [ "${OVPN_FLOAT}" == "1" ] && ovpn_run_stage "run floating peer checks" \ ovpn_run_float_mode ovpn_run_stage "run iperf throughput" ovpn_run_iperf +ovpn_run_stage "run mssfix TCP SYN clamp" ovpn_run_mssfix ovpn_run_stage "run key rollout" ovpn_run_key_rollover ovpn_run_stage "query peers" ovpn_run_queries ovpn_run_stage "query missing peer fails" ovpn_query_peer_missing