sl2tps, MRU, MTU, and MSS

Brian Candler B.Candler at pobox.com
Fri Jan 27 05:00:53 PST 2006


On Thu, Jan 05, 2006 at 11:04:04AM +0000, Brian Candler wrote:
> I've done a bit more debugging on the MSS problem I'm having with sl2tps
> running with IPSEC transport layer security. The client is Windows XP
> out-of-the-box.
> 
> Here's what happens:
> 
> 1. PPP negotiates an MRU of 1400
> 2. However, ifconfig ng0 shows an MTU of 1376 (where does that come from?)
> 3. When the client opens a TCP connection, it offers an MSS of 1360

...and then fragmentation problems occur, because the remote server sends IP
datagrams which are 1400 bytes with DF bit set, the ng0 interface with MTU
1376 rejects them, the generated ICMP messages are discarded by an
intervening NAT gateway, and the TCP connection fails.

> root at candlerb ~# ifconfig ng0
> ng0: flags=88d1<UP,POINTOPOINT,RUNNING,NOARP,SIMPLEX,MULTICAST> mtu 1376
>         inet 172.17.0.216 --> 192.168.100.100 netmask 0xffffffff

I've done some digging, and I've found the sources of this problem, but I
don't know what the right fixes are.

After PPP has negotiated an MRU of 1400, why does the ng0 interface get an
MTU of 1376? There appear to be two reasons for this.

(1) In libpdel, file ppp/ppp_link.c, the interface MRU is explicitly set to
20 less than the requested MRU:

#define WINXP_PPTP_HACK(x)    ((x) - 20)      /* winxp pptp stupidity hack */
...
                        lconf->mru = MIN(
                            WINXP_PPTP_HACK(link->lcp_req.mru[PPP_PEER]),
                            ppp_channel_get_mtu(link->device));

My test client for L2TP over IPSEC does happen to be WINXP, but as far as I
can see this hack is done unconditionally.

(2a) In libpdel, file ppp/ppp_bundle.c, the interface MTU is taken from the
PPP MRU, and then additionally 4 is subtracted if conf.mppe_40,
conf.mppe_56 or conf.mppe_128 is set.

                        if (bundle->conf.mppe_40
                            || bundle->conf.mppe_56
                            || bundle->conf.mppe_128)
                                mtu -= 4;       /* allow for mppe header */

Note that this happens even if MPPE has not been negotiated.

(2b) in sl2tps, file sls_manager.c, conf->mppe_128 is set to 1

        conf->mppe_128 = 1;
        conf->mppe_stateless = 1;

Now, if I modify sl2tps to set conf->mppe_128 to 0, and I change the
WINXP_PPTP_HACK macro to make it a no-op, my L2TP/IPSEC client connects, ng0
gets the correct MTU of 1400, and TCP traffic flows happily through the
tunnel.

So what's the correct fix?

Well in case (2), I'd have thought that the MTU should not be reduced by 4
unless MPPE has actually been negotiated in CCP (option 18, see RFC 3078).

For case (1), I don't know, because I don't know where the WINXP_PPTP_HACK
macro comes from or under what circumstances it is required. All I can say
is that WINXP using L2TP over IPSEC does *not* need this hack (and indeed,
the hack breaks things). Perhaps it should only be used if PPTP is the
underlying transport. I don't know if there's a straightforward way to
detect when that's the case.

Is there anyone here who knows the libpdel ppp code better and can suggest
the right fixes?

Thanks,

Brian.


More information about the freebsd-net mailing list