Browse code

Push server mtu to client when supported and support occ mtu

To maximise compatibility allow to lie our MTU in the default OCC
message.

Patch v2: improve documentation
Patch v3: split changing default MTU into its own patch
Patch v5: remove leftover mentions to default MTU

Signed-off-by: Arne Schwabe <arne@rfc2549.org>
Acked-by: Gert Doering <gert@greenie.muc.de>
Message-Id: <20221109154810.1268403-2-arne@rfc2549.org>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg25499.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>

Arne Schwabe authored on 2022/11/10 00:48:10
Showing 4 changed files
... ...
@@ -524,10 +524,23 @@ routing.
524 524
   arguments of ``--ifconfig`` to mean "address netmask", no longer "local
525 525
   remote".
526 526
 
527
-  Take the TUN device MTU to be **n** and derive the link MTU from it
528
-  (default :code:`1500`). In most cases, you will probably want to leave
529
-  this parameter set to its default value.
527
+--tun-mtu args
528
+
529
+  Valid syntaxes:
530
+  ::
531
+
532
+      tun-mtu tun-mtu
533
+      tun-mtu tun-mtu occ-mtu
534
+
535
+  Take the TUN device MTU to be ``tun-mtu`` and derive the link MTU from it.
536
+  In most cases, you will probably want to leave this parameter set to
537
+  its default value.
538
+
539
+  The default for :code:`tun-mtu` is 1500.
540
+
541
+  The OCC MTU can be used to avoid warnings about mismatched MTU from
542
+  clients. If :code:`occ-mtu` is not specified, it will to default to the
543
+  tun-mtu.
530 544
 
531 545
   The MTU (Maximum Transmission Units) is the maximum datagram size in
532 546
   bytes that can be sent unfragmented over a particular network path.
... ...
@@ -540,6 +553,10 @@ routing.
540 540
   It's best to use the ``--fragment`` and/or ``--mssfix`` options to deal
541 541
   with MTU sizing issues.
542 542
 
543
+  Note: Depending on the platform, the operating system allows to receive
544
+  packets larger than ``tun-mtu`` (e.g. Linux and FreeBSD) but other platforms
545
+  (like macOS) limit received packets to the same size as the MTU.
546
+
543 547
 --tun-max-mtu maxmtu
544 548
   This configures the maximum MTU size that a server can push to ``maxmtu``,
545 549
   by configuring the internal buffers to allow at least this packet size.
... ...
@@ -825,6 +825,7 @@ init_options(struct options *o, const bool init_gc)
825 825
     o->status_file_version = 1;
826 826
     o->ce.bind_local = true;
827 827
     o->ce.tun_mtu = TUN_MTU_DEFAULT;
828
+    o->ce.occ_mtu = 0;
828 829
     o->ce.link_mtu = LINK_MTU_DEFAULT;
829 830
     o->ce.tls_mtu = TLS_MTU_DEFAULT;
830 831
     o->ce.mtu_discover_type = -1;
... ...
@@ -4193,7 +4194,15 @@ options_string(const struct options *o,
4193 4193
     buf_printf(&out, ",link-mtu %u",
4194 4194
                (unsigned int) calc_options_string_link_mtu(o, frame));
4195 4195
 
4196
-    buf_printf(&out, ",tun-mtu %d", frame->tun_mtu);
4196
+    if (o->ce.occ_mtu != 0)
4197
+    {
4198
+        buf_printf(&out, ",tun-mtu %d", o->ce.occ_mtu);
4199
+    }
4200
+    else
4201
+    {
4202
+        buf_printf(&out, ",tun-mtu %d", frame->tun_mtu);
4203
+    }
4204
+
4197 4205
     buf_printf(&out, ",proto %s",  proto_remote(o->ce.proto, remote));
4198 4206
 
4199 4207
     bool p2p_nopull = o->mode == MODE_POINT_TO_POINT && !PULL_DEFINED(o);
... ...
@@ -6447,11 +6456,19 @@ add_option(struct options *options,
6447 6447
         options->ce.link_mtu = positive_atoi(p[1]);
6448 6448
         options->ce.link_mtu_defined = true;
6449 6449
     }
6450
-    else if (streq(p[0], "tun-mtu") && p[1] && !p[2])
6450
+    else if (streq(p[0], "tun-mtu") && p[1] && !p[3])
6451 6451
     {
6452 6452
         VERIFY_PERMISSION(OPT_P_PUSH_MTU|OPT_P_CONNECTION);
6453 6453
         options->ce.tun_mtu = positive_atoi(p[1]);
6454 6454
         options->ce.tun_mtu_defined = true;
6455
+        if (p[2])
6456
+        {
6457
+            options->ce.occ_mtu = positive_atoi(p[2]);
6458
+        }
6459
+        else
6460
+        {
6461
+            options->ce.occ_mtu = 0;
6462
+        }
6455 6463
     }
6456 6464
     else if (streq(p[0], "tun-mtu-max") && p[1] && !p[3])
6457 6465
     {
... ...
@@ -118,6 +118,7 @@ struct connection_entry
118 118
     const char *socks_proxy_authfile;
119 119
 
120 120
     int tun_mtu;         /* MTU of tun device */
121
+    int occ_mtu;         /* if non-null, this is the MTU we announce to peers in OCC */
121 122
     int tun_mtu_max;     /* maximum MTU that can be pushed */
122 123
 
123 124
     bool tun_mtu_defined; /* true if user overriding parm with command line option */
... ...
@@ -673,6 +673,22 @@ prepare_push_reply(struct context *c, struct gc_arena *gc,
673 673
         push_option_fmt(gc, push_list, M_USAGE, "protocol-flags%s", buf_str(&proto_flags));
674 674
     }
675 675
 
676
+    /* Push our mtu to the peer if it supports pushable MTUs */
677
+    int client_max_mtu = 0;
678
+    const char *iv_mtu = extract_var_peer_info(tls_multi->peer_info, "IV_MTU=", gc);
679
+
680
+    if (iv_mtu && sscanf(iv_mtu, "%d", &client_max_mtu) == 1)
681
+    {
682
+        push_option_fmt(gc, push_list, M_USAGE, "tun-mtu %d", o->ce.tun_mtu);
683
+        if (client_max_mtu < o->ce.tun_mtu)
684
+        {
685
+            msg(M_WARN, "Warning: reported maximum MTU from client (%d) is lower "
686
+                "than MTU used on the server (%d). Add tun-max-mtu %d "
687
+                "to client configuration.", client_max_mtu,
688
+                o->ce.tun_mtu, o->ce.tun_mtu);
689
+        }
690
+    }
691
+
676 692
     return true;
677 693
 }
678 694