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 (or smaller).
Signed-off-by: Arne Schwabe <arne@rfc2549.org>
Patch v4: rebase for check_session_cipher name change
Patch v5: remove mention of change of default mtu, remove leftover code
from an earlier approach.
Signed-off-by: Arne Schwabe <arne@rfc2549.org>
Acked-by: Gert Doering <gert@greenie.muc.de>
Message-Id: <20221109154810.1268403-1-arne@rfc2549.org>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg25498.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
| ... | ... |
@@ -99,6 +99,11 @@ Inline auth username and password |
| 99 | 99 |
missing OpenVPN will prompt for input via stdin. This applies to inline'd |
| 100 | 100 |
http-proxy-user-pass too. |
| 101 | 101 |
|
| 102 |
+Tun MTU can be pushed |
|
| 103 |
+ The client can now also dynamically configure its MTU and the server |
|
| 104 |
+ will try to push the client MTU when the client supports it. The |
|
| 105 |
+ directive ``--tun-mtu-max`` has been introduced to increase the maximum |
|
| 106 |
+ pushable MTU size (defaults to 1600). |
|
| 102 | 107 |
|
| 103 | 108 |
Improved control channel packet size control (``max-packet-size``) |
| 104 | 109 |
The size of control channel is no longer tied to |
| ... | ... |
@@ -363,6 +363,10 @@ configuration. |
| 363 | 363 |
The client announces the list of supported ciphers configured with the |
| 364 | 364 |
``--data-ciphers`` option to the server. |
| 365 | 365 |
|
| 366 |
+ :code:`IV_MTU=<max_mtu>` |
|
| 367 |
+ The client announces the support of pushable MTU and the maximum MTU |
|
| 368 |
+ it is willing to accept. |
|
| 369 |
+ |
|
| 366 | 370 |
:code:`IV_GUI_VER=<gui_id> <version>` |
| 367 | 371 |
The UI version of a UI if one is running, for example |
| 368 | 372 |
:code:`de.blinkt.openvpn 0.5.47` for the Android app. |
| ... | ... |
@@ -540,6 +540,12 @@ 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 |
+--tun-max-mtu maxmtu |
|
| 544 |
+ This configures the maximum MTU size that a server can push to ``maxmtu``, |
|
| 545 |
+ by configuring the internal buffers to allow at least this packet size. |
|
| 546 |
+ The default for ``maxmtu`` is 1600. Currently, only increasing beyond 1600 |
|
| 547 |
+ is possible, and attempting to reduce max-mtu below 1600 will be ignored. |
|
| 548 |
+ |
|
| 543 | 549 |
--tun-mtu-extra n |
| 544 | 550 |
Assume that the TUN/TAP device might return as many as ``n`` bytes more |
| 545 | 551 |
than the ``--tun-mtu`` size on read. This parameter defaults to 0, which |
| ... | ... |
@@ -2312,7 +2312,8 @@ pull_permission_mask(const struct context *c) |
| 2312 | 2312 |
| OPT_P_ECHO |
| 2313 | 2313 |
| OPT_P_PULL_MODE |
| 2314 | 2314 |
| OPT_P_PEER_ID |
| 2315 |
- | OPT_P_NCP; |
|
| 2315 |
+ | OPT_P_NCP |
|
| 2316 |
+ | OPT_P_PUSH_MTU; |
|
| 2316 | 2317 |
|
| 2317 | 2318 |
if (!c->options.route_nopull) |
| 2318 | 2319 |
{
|
| ... | ... |
@@ -2475,6 +2476,23 @@ do_deferred_options(struct context *c, const unsigned int found) |
| 2475 | 2475 |
} |
| 2476 | 2476 |
} |
| 2477 | 2477 |
|
| 2478 |
+ if (found & OPT_P_PUSH_MTU) |
|
| 2479 |
+ {
|
|
| 2480 |
+ /* MTU has changed, check that the pushed MTU is small enough to |
|
| 2481 |
+ * be able to change it */ |
|
| 2482 |
+ msg(D_PUSH, "OPTIONS IMPORT: tun-mtu set to %d", c->options.ce.tun_mtu); |
|
| 2483 |
+ |
|
| 2484 |
+ struct frame *frame = &c->c2.frame; |
|
| 2485 |
+ |
|
| 2486 |
+ if (c->options.ce.tun_mtu > frame->tun_max_mtu) |
|
| 2487 |
+ {
|
|
| 2488 |
+ msg(D_PUSH_ERRORS, "Server-pushed tun-mtu is too large, please add " |
|
| 2489 |
+ "tun-mtu-max %d in the client configuration", |
|
| 2490 |
+ c->options.ce.tun_mtu); |
|
| 2491 |
+ } |
|
| 2492 |
+ frame->tun_mtu = min_int(frame->tun_max_mtu, c->options.ce.tun_mtu); |
|
| 2493 |
+ } |
|
| 2494 |
+ |
|
| 2478 | 2495 |
return true; |
| 2479 | 2496 |
} |
| 2480 | 2497 |
|
| ... | ... |
@@ -2635,10 +2653,16 @@ frame_finalize_options(struct context *c, const struct options *o) |
| 2635 | 2635 |
struct frame *frame = &c->c2.frame; |
| 2636 | 2636 |
|
| 2637 | 2637 |
frame->tun_mtu = get_frame_mtu(c, o); |
| 2638 |
+ frame->tun_max_mtu = o->ce.tun_mtu_max; |
|
| 2639 |
+ |
|
| 2640 |
+ /* max mtu needs to be at least as large as the tun mtu */ |
|
| 2641 |
+ frame->tun_max_mtu = max_int(frame->tun_mtu, frame->tun_max_mtu); |
|
| 2638 | 2642 |
|
| 2639 |
- /* We always allow at least 1500 MTU packets to be received in our buffer |
|
| 2640 |
- * space */ |
|
| 2641 |
- size_t payload_size = max_int(1500, frame->tun_mtu); |
|
| 2643 |
+ /* We always allow at least 1600 MTU packets to be received in our buffer |
|
| 2644 |
+ * space to allow server to push "baby giant" MTU sizes */ |
|
| 2645 |
+ frame->tun_max_mtu = max_int(1600, frame->tun_max_mtu); |
|
| 2646 |
+ |
|
| 2647 |
+ size_t payload_size = frame->tun_max_mtu; |
|
| 2642 | 2648 |
|
| 2643 | 2649 |
/* we need to be also large enough to hold larger control channel packets |
| 2644 | 2650 |
* if configured */ |
| ... | ... |
@@ -2650,9 +2674,9 @@ frame_finalize_options(struct context *c, const struct options *o) |
| 2650 | 2650 |
payload_size += o->ce.tun_mtu_extra; |
| 2651 | 2651 |
} |
| 2652 | 2652 |
|
| 2653 |
- /* Add 100 byte of extra space in the buffer to account for slightly |
|
| 2654 |
- * mismatched MUTs between peers */ |
|
| 2655 |
- payload_size += 100; |
|
| 2653 |
+ /* Add 32 byte of extra space in the buffer to account for small errors |
|
| 2654 |
+ * in the calculation */ |
|
| 2655 |
+ payload_size += 32; |
|
| 2656 | 2656 |
|
| 2657 | 2657 |
|
| 2658 | 2658 |
/* the space that is reserved before the payload to add extra headers to it |
| ... | ... |
@@ -3211,6 +3235,10 @@ do_init_frame_tls(struct context *c) |
| 3211 | 3211 |
c->c2.frame.buf.payload_size); |
| 3212 | 3212 |
frame_print(&c->c2.tls_multi->opt.frame, D_MTU_INFO, |
| 3213 | 3213 |
"Control Channel MTU parms"); |
| 3214 |
+ |
|
| 3215 |
+ /* Keep the max mtu also in the frame of tls multi so it can access |
|
| 3216 |
+ * it in push_peer_info */ |
|
| 3217 |
+ c->c2.tls_multi->opt.frame.tun_max_mtu = c->c2.frame.tun_max_mtu; |
|
| 3214 | 3218 |
} |
| 3215 | 3219 |
if (c->c2.tls_auth_standalone) |
| 3216 | 3220 |
{
|
| ... | ... |
@@ -222,6 +222,7 @@ frame_print(const struct frame *frame, |
| 222 | 222 |
buf_printf(&out, " max_frag:%d", frame->max_fragment_size); |
| 223 | 223 |
#endif |
| 224 | 224 |
buf_printf(&out, " tun_mtu:%d", frame->tun_mtu); |
| 225 |
+ buf_printf(&out, " tun_max_mtu:%d", frame->tun_max_mtu); |
|
| 225 | 226 |
buf_printf(&out, " headroom:%d", frame->buf.headroom); |
| 226 | 227 |
buf_printf(&out, " payload:%d", frame->buf.payload_size); |
| 227 | 228 |
buf_printf(&out, " tailroom:%d", frame->buf.tailroom); |
| ... | ... |
@@ -138,6 +138,9 @@ struct frame {
|
| 138 | 138 |
* control frame payload (although most of |
| 139 | 139 |
* code ignores it) |
| 140 | 140 |
*/ |
| 141 |
+ int tun_max_mtu; /**< the maximum tun-mtu size the buffers are |
|
| 142 |
+ * are sized for. This is the upper bound that |
|
| 143 |
+ * a server can push as MTU */ |
|
| 141 | 144 |
|
| 142 | 145 |
int extra_tun; /**< Maximum number of bytes in excess of |
| 143 | 146 |
* the tun/tap MTU that might be read |
| ... | ... |
@@ -6449,10 +6449,23 @@ add_option(struct options *options, |
| 6449 | 6449 |
} |
| 6450 | 6450 |
else if (streq(p[0], "tun-mtu") && p[1] && !p[2]) |
| 6451 | 6451 |
{
|
| 6452 |
- VERIFY_PERMISSION(OPT_P_MTU|OPT_P_CONNECTION); |
|
| 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 | 6455 |
} |
| 6456 |
+ else if (streq(p[0], "tun-mtu-max") && p[1] && !p[3]) |
|
| 6457 |
+ {
|
|
| 6458 |
+ VERIFY_PERMISSION(OPT_P_MTU|OPT_P_CONNECTION); |
|
| 6459 |
+ int max_mtu = positive_atoi(p[1]); |
|
| 6460 |
+ if (max_mtu < 68 || max_mtu > 65536) |
|
| 6461 |
+ {
|
|
| 6462 |
+ msg(msglevel, "--tun-mtu-max value '%s' is invalid", p[1]); |
|
| 6463 |
+ } |
|
| 6464 |
+ else |
|
| 6465 |
+ {
|
|
| 6466 |
+ options->ce.tun_mtu_max = max_mtu; |
|
| 6467 |
+ } |
|
| 6468 |
+ } |
|
| 6456 | 6469 |
else if (streq(p[0], "tun-mtu-extra") && p[1] && !p[2]) |
| 6457 | 6470 |
{
|
| 6458 | 6471 |
VERIFY_PERMISSION(OPT_P_MTU|OPT_P_CONNECTION); |
| ... | ... |
@@ -118,6 +118,8 @@ struct connection_entry |
| 118 | 118 |
const char *socks_proxy_authfile; |
| 119 | 119 |
|
| 120 | 120 |
int tun_mtu; /* MTU of tun device */ |
| 121 |
+ int tun_mtu_max; /* maximum MTU that can be pushed */ |
|
| 122 |
+ |
|
| 121 | 123 |
bool tun_mtu_defined; /* true if user overriding parm with command line option */ |
| 122 | 124 |
int tun_mtu_extra; |
| 123 | 125 |
bool tun_mtu_extra_defined; |
| ... | ... |
@@ -730,6 +732,7 @@ struct options |
| 730 | 730 |
#define OPT_P_CONNECTION (1<<27) |
| 731 | 731 |
#define OPT_P_PEER_ID (1<<28) |
| 732 | 732 |
#define OPT_P_INLINE (1<<29) |
| 733 |
+#define OPT_P_PUSH_MTU (1<<30) |
|
| 733 | 734 |
|
| 734 | 735 |
#define OPT_P_DEFAULT (~(OPT_P_INSTANCE|OPT_P_PULL_MODE)) |
| 735 | 736 |
|
| ... | ... |
@@ -2048,6 +2048,9 @@ push_peer_info(struct buffer *buf, struct tls_session *session) |
| 2048 | 2048 |
|
| 2049 | 2049 |
/* support for AUTH_FAIL,TEMP control message */ |
| 2050 | 2050 |
iv_proto |= IV_PROTO_AUTH_FAIL_TEMP; |
| 2051 |
+ |
|
| 2052 |
+ /* support for tun-mtu as part of the push message */ |
|
| 2053 |
+ buf_printf(&out, "IV_MTU=%d\n", session->opt->frame.tun_max_mtu); |
|
| 2051 | 2054 |
} |
| 2052 | 2055 |
|
| 2053 | 2056 |
/* support for Negotiable Crypto Parameters */ |