Re: [RFC PATCH 0/4] Introduce per-peer MTU setting

2022-01-07 Thread Leon Schuermann


Toke Høiland-Jørgensen  writes:
> I'm not sure I understand the use case? Either PMTUD works through the
> tunnel and you can just let that do its job, or it doesn't and you
> have to do out-of-band discovery anyway in which case you can just use
> the FIB route MTU?

For traffic _through_ the WireGuard tunnel, that is correct. As
WireGuard in general does not do any funny business with the traffic it
forwards, path MTU discovery through the tunnel works just fine. I'll
call that end-to-end PMTUD. If this does not work for any reason, one
has to fall back onto specifying the MTU in FIB, or some other
mechanism.

I am however concerned about the link(s) _underneath_ the WireGuard
tunnel (where the encrypted + authenticated packets are forwarded), so
the endpoint-to-endpoint link. Regular path MTU discovery does not work
here. As far as I understand, the reasoning behind this is that even if
the WireGuard endpoint does receive ICMP Fragmentation Needed / Packet
Too Big messages from a host on the path the tunnel traverses, these
messages are not and cannot be authenticated. This means that this
information cannot be forwarded to the sender of the original packet,
outside of the tunnel.

This is a real-word issue I am experiencing in WireGuard setups. For
instance, I administer the WireGuard instance of a small student ISP.
Clients connect from a variety of networks to this endpoint, such as DSL
links (PPPoE) which commonly have 1492 bytes MTU, or connections using
Dual-Stack Lite, having 1460 bytes MTU due to the encapsulation
overhead. Essentially no residential providers fragment packets, and
some do not even send ICMP responses. Sometimes people use a tunnel
inside another tunnel, further decreasing MTU.

While reducing the server and client MTUs to the maximum MTU supported
by all supported link types technically works, it increases IP, tunnel
and transport header overhead. It is thus desirable to be able to
specify an individual MTU per WireGuard peer, to use the available MTU
on the respective routes. This is also on the WireGuard project's todo
[1] and has been discussed before [2].

> what do you mean by "usable on the rest of the route"?

Actually, I think I might be wrong here. Initial tests have suggested me
that if the route MTU is specified in the FIB, Linux would not take any
ICMP Fragmentation Needed / Packet Too Big responses into account. I've
tested this again, and it seems to indeed perform proper path MTU
discovery even if the route MTU is specified. This is important as a
route to the destination host might first go through a WireGuard tunnel
to a peer, and then forwarded over paths which might have an even lower
MTU.

Thus the FIB entry MTU is a viable solution for setting individual
peer's route limits, but it might be rather inelegant to modify the
route's MTU values in the FIB from within kernel space, which might be
needed for an in-band PMTUD mechanism.

>> Furthermore, with the goal of eventually introducing an in-band
>> per-peer PMTUD mechanism, keeping an internal per-peer MTU value does
>> not require modifying the FIB and thus potentially interfere with
>> userspace.
>
> What "in-band per-peer PMTUD mechanism"? And why does it need this?

As outlined above, WireGuard cannot utilize the regular ICMP-based PMTUD
mechanism over the endpoint-to-endpoint path. It is however not great to
default to a low MTU to accomodate for low-MTU links on this path, and
very inconvenient to manually adjust the tunnel MTUs.

A solution to this issue could be a PMTUD mechanism through the tunnel
link itself. It would circumvent the security considerations with
ICMP-based PMTUD by relying exclusively on an encrypted + authenticated
message exchange. For instance, a naive approach could be to send ICMP
echo messages with increasing/decreasing payload size to the peer and
discover the usable tunnel MTU based on the (lost) responses. While this
can be implemented outside of the WireGuard kernel module, it makes
certain assumptions about the tunnel and endpoint configuration, such as
the endpoints having an IP assigned, this IP being in the AllowedIPs
(not a given), responding to ICMP echo packets, etc. If such a mechanism
were to be (optionally) integrated into WireGuard directly, it could
have the potential to reduce these kinds of headaches significantly.

#+BEGIN_EXAMPLE
Here is an illustration of these issues using a hacky Mininet test
setup[3], which has the following topology (all traffic from h5 being
routed over the tunnel between h1 and h4), with fragmentation disabled:

  /--- wireguard ---\
 /   \
/  ethetheth  \
h1 <-> h2 <-> h3 <-> h4 <-> h5

The route from h1 to h4 has an MTU of 1500 bytes:

mininet> h1 ping -c1 -Mdo -s1472 h4
1480 bytes from 10.0.2.2: icmp_seq=1 ttl=62 time=0.508 ms

The route from h1 to h5 (through the WireGuard tunnel, via h4) has an
MTU of 1420 bytes:

mininet> h1 ping -c1 -Mdo -s1392 h5
1400 bytes from 

Re: [RFC PATCH 0/4] Introduce per-peer MTU setting

2022-01-04 Thread Toke Høiland-Jørgensen
leon@is.currently.online writes:

> From: Leon Schuermann 
>
> This patch series is an attempt to integrate a per-peer MTU setting
> into WireGuard. With matching changes to the wireguard-tools,
> individual MTU values can be set and retrieved for each registered
> peer.
>
> While Linux supports setting an MTU metric for specific FIB route
> entries [which I've only found out after implementing this :)], and
> thus allows to lower the MTU for individual peers, this appears to
> disable regular path MTU discovery (PMTUD) entirely on the
> route. While regular PMTUD does not work over the tunnel link, it
> should still be usable on the rest of the route.

I'm not sure I understand the use case? Either PMTUD works through the
tunnel and you can just let that do its job, or it doesn't and you have
to do out-of-band discovery anyway in which case you can just use the
FIB route MTU? Or what do you mean by "usable on the rest of the route"?

> Furthermore, with the goal of eventually introducing an in-band
> per-peer PMTUD mechanism, keeping an internal per-peer MTU value does
> not require modifying the FIB and thus potentially interfere with
> userspace.

What "in-band per-peer PMTUD mechanism"? And why does it need this?

-Toke


[RFC PATCH 0/4] Introduce per-peer MTU setting

2022-01-04 Thread leon
From: Leon Schuermann 

This patch series is an attempt to integrate a per-peer MTU setting
into WireGuard. With matching changes to the wireguard-tools,
individual MTU values can be set and retrieved for each registered
peer.

While Linux supports setting an MTU metric for specific FIB route
entries [which I've only found out after implementing this :)], and
thus allows to lower the MTU for individual peers, this appears to
disable regular path MTU discovery (PMTUD) entirely on the
route. While regular PMTUD does not work over the tunnel link, it
should still be usable on the rest of the route.

Furthermore, with the goal of eventually introducing an in-band
per-peer PMTUD mechanism, keeping an internal per-peer MTU value does
not require modifying the FIB and thus potentially interfere with
userspace.

In an effort to solve this issues, this patch series introduces a
rather generic framework for implementing these kinds of dynamic MTU
policies. By providing a hook in the netdevice implementation to
decide on the applicable MTU, very flexible designs can be built. I
suppose that these changes are rather controversial, or at least
require some more discussion. I'm sending this patchset to the
WireGuard development list in hopes to get some initial feedback on
the idea and implementation and would like to eventually submit the
non-WireGuard changes directly to the netdev ML.

The patches are currently based on v5.10, as that happens to be
what I was developing on. I'll gladly rebase to the latest
revision / wireguard-devel if requested.

Thanks!

Leon

Leon Schuermann (4):
  netdevice: add ndo_lookup_mtu for dynamically determining MTU
  net/ipv4: respect MTU determined by `ndo_lookup_mtu`
  net/ipv6: respect MTU determined by `ndo_lookup_mtu`
  net/wireguard: add per-peer MTU setting

 drivers/net/wireguard/allowedips.c |  2 +-
 drivers/net/wireguard/allowedips.h |  2 +-
 drivers/net/wireguard/device.c | 20 --
 drivers/net/wireguard/netlink.c|  8 +++
 drivers/net/wireguard/peer.c   |  1 +
 drivers/net/wireguard/peer.h   |  1 +
 drivers/net/wireguard/queueing.h   |  2 +-
 include/linux/netdevice.h  | 12 +++
 include/net/ip.h   | 34 ++
 include/net/ip6_route.h| 14 ++--
 include/uapi/linux/wireguard.h |  5 +
 net/ipv4/ip_forward.c  |  2 +-
 net/netfilter/nf_flow_table_core.c |  2 +-
 13 files changed, 87 insertions(+), 18 deletions(-)


base-commit: 2c85ebc57b3e1817b6ce1a6b703928e113a90442
-- 
2.33.1