AW: OpenConnect does not take over MTU
Daniel Lenski
dlenski at gmail.com
Thu Jun 9 13:33:12 PDT 2022
On Wed, Jun 8, 2022 at 5:29 PM David Woodhouse <dwmw2 at infradead.org> wrote:
>
> On Wed, 2022-06-08 at 19:35 +0000, Schütz Dominik wrote:
> > Hi,
> >
> > sorry that the reply to the mail with the subject "Pulse with ESP has
> > problems with Kerberos Tickets" and "OpenConnect does not take over
> > MTU" took so long.
> >
> > We have found out the following about MTU with OpenConnect and
> > "protocol=pulse" (ESP):
> >
> > With OpenConnect, the MTU of the virtual adapter (tun0) is always
> > 1400, regardless of whether the MTU of the physical adapter is larger
> > or smaller.
> >
> > root at host1:~# ifconfig -a
> > tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST> mtu 1400
> > wlp110s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1300
> >
> > root at host1:~# ifconfig -a
> > tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST> mtu 1400
> > wlp110s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1400
> >
> > root at host1:~# ifconfig -a
> > tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST> mtu 1400
> > wlp110s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
> >
> >
> > The PulseUI (9.1.R14) dynamically adjusts the MTU of the tun0.
Very similar finding in a recent GitLab issue:
https://gitlab.com/openconnect/openconnect/-/issues/447#note_981440366
It appears that when OpenConnect talks to a Pulse server, it *always*
receives an MTU of 1400. Here is the code where OpenConnect receives
the Pulse server's (alleged) MTU value:
https://gitlab.com/openconnect/openconnect/blob/master/pulse.c#L361-373
Does anyone have a counter-example, a case where OpenConnect receives
an MTU *other than* 1400 from a Pulse server?
> This is amazingly useful; thank you.
>
> One thing is missing; we don't know how (or 'if') the client *tells*
> the far end what the MTU should be.
>
> If you could get a MITM capture and look for unknown attributes in what
> their client sends to the server (or indeed in what the server sends
> back), especially looking for those MTU values, it would be very much
> appreciated.
>
> Setting the MTU on *our* side is only half the equation.
>
> We certainly *can* do that, of course, and we have the logic to fetch
> the TCP MSS and subtract from it already for other protocols; we can
> extend that to Pulse.
In my opinion, we should *never* just accept/trust an MTU value sent
by a server—at least not for a UDP based tunnel.
Too many of them are broken in their calculation method. Pulse seems
to always send 1400; GlobalProtect seems to always send ZERO.
The robust course of action:
(1) Try to estimate our MTU to the server ("outer MTU"), based on the
Internet-facing interface's MTU.
(2) Try to estimate the MTU of the tunnel ("inner MTU"), given the
overhead of the specific protocol stack. This is what the
calculate_mtu() function already does.
https://gitlab.com/openconnect/openconnect/blob/master/mtucalc.c
(3) Try to get the server to accept our value(s):
- With CSTP we have a way to tell the server what we think MTU is
between client and server over the Internet (that's what
"X-CSTP-Base-MTU" is)
- With PPP, we have a way to tell the server what we think the MTU
of the tunnel is
(https://gitlab.com/openconnect/openconnect/blob/master/ppp.c#L400-415)
- With Juniper, Pulse, GlobalProtect, Array(?) we have no known
way to tell the server what we think the MTU should
(4) Once the tunnel is up, VERIFY the "inner MTU" by doing a binary
search to find the biggest packet size that we can actually get
through.
- For Cisco DTLS, we already do this:
https://gitlab.com/openconnect/openconnect/blob/master/dtls.c#L473
- For GP ESP, we COULD do this using the probe packets, since
they're just pings (ICMP Echo-Request), which we can fill up with
arbitrarily-large payloads:
https://gitlab.com/openconnect/openconnect/blob/master/gpst.c#L1332
- For PPP DTLS *or* TCP, we COULD do this using LCP Echo-Request,
since it's legal to add an arbitrarily-large payload there too:
https://datatracker.ietf.org/doc/html/rfc1661#section-5.8
- For Juniper/Pulse ESP, I'm not sure. The (pre-encapsulation)
probe packet is just a single zero byte. If we send, let's say, 500
zero bytes, will the server echo that back as needed?
- Array: ??
(5) Hope/pray that the tunnel isn't asymmetrical, or that the server
hasn't ended up with its own wrong idea of the MTU, and that it's not
trying to send back overly-large packets to us, which are getting
dropped.
-Dan
More information about the openconnect-devel
mailing list