Hi,

On Tue, Oct 11, 2022 at 09:11:25PM +0200, Gert Doering wrote:
> OTOH, in "not peer2peer mode", we only support topology subnet anyway,
> so maybe it should autoconfigure that, depending on the mode OpenVPN
> requests (p2p mode -> IFF_POINTOPOINT, p2mp mode -> IFF_BROADCAST),
> so we don't even need TUNSIFMODE.

It's not that easy - there are two factors coming into play here, which
are orthogonal.

Factor 1: single-peer (client or p2p) vs. multi-peer

 single-peer -> DCO has only 1 peer, all packets that go into the 
                tun/dco interface are sent out to the single peer
                ("dumb pipe mode") - exactly like tun(4) behaves

                If a subnet is configured on the interface, packets to
                ALL IPs (!= local) in that subnet are sent to the other
                side.  No next-hop lookup is done.

 multi-peer -> DCO has 0..N peers.  Packets that go into the tun/dco
               interface get mapped according to route next-hop <->
               peer[]->vpn_v4 (or v6) address and sent to that peer.

               If a subnet is configured on the interface (only supported
               mode :-) ), packets to IP addresses in that subnet that
               have no mapped-to peer are DROPPED.

 On Linux this is controlled by openvpn_dco_init() setting dco->ifmode
 to OVPN_MODE_MP/OVPN_MODE_P2P, and net_iface_new() passing this parameter
 to kernel DCO.

 On FreeBSD, OpenVPN does not signal the p2p/p2mp mode to kernel yet
 (if I am not misreading the code), and if I am reading ovpn_route_peer()
 in if_ovpn.c correctly, "single-peer mode" will drop packets where a
 corresponding peer can neither be found by ovpn_find_peer_by_ip, using
 target IP or Route->Gateway lookup.

 (*) ovpn_find_peer_by_ip() is using a sequential search, for every 
 single packet, which will perform poorly on servers with 1000s of
 clients... room for optimization.



Factor 2: IFF_POINTOPOINT vs. IFF_BROADCAST

 This seems to be a *BSD-specific thing, aka "there is nothing in the
 Linux specific code that seems to bother with this".

 An Interface can be put to point-to-point mode (by ioctl(TUNSIFMODE)
 with the IFF_POINTOPOINT flag set).  In that case, there is no "on-link"
 subnet, just "us" and "them", and ifconfig wants two IPv4 addresses
 as parameter

     ifconfig tun0 10.2.3.77 10.2.3.1

 ... that do not need to be adjacent.  It takes a "netmask" argument, but
 that does not have a real effect.  To simulate "subnet" mode, OpenVPN
 will add a 10.2.3.0/24 -> 10.2.3.1 route.

 In "dumb pipe mode", this works nicely - the /24 route shoves all packets
 towards the tun0 interface, and the tun(4) sends them over, without looking.

 In "openvpn non-dco p2mp server mode" this *also* works nicely, because
 the tun(4) interface is still in "dumb pipe mode" and OpenVPN will do
 an iroute lookup in the p2mp server forwarding path, sending to the proper
 client.

 In DCO mode with iroutes, this does not work at all anymore.  Say, there
 is a client on 10.2.3.50, using iroute 10.22.33.0/24, so OpenVPN tries
 to install a route via

    route add 10.22.33.0/24 10.2.3.50

 and FreeBSD *refuses* to install this route, because "10.2.3.50" is not
 adjacent.  In my initial tests I did not notice this, because the only
 client with iroute was assigned the .2 address,

 One option that sounds like it would work: always use "remote_addr" 
 (= second parameter to IFF_POINTOPOINT ifconfig) as next-hop for all 
 iroute-originated routes - this would make FreeBSD accept the route, and
 send packets towards the ovpn(4) interface.  Alas, the next-hop would
 be "remote_addr", not "the right p2mp peer", so the "what peer do I need
 to send this packet to?" search in ovpn(4) would find the peer on the
 "remote_addr" IP, not the correct one (= lookup happens in normal 
 routing table).  So, it wouldn't work [AND it would add more ugly bits
 to OpenVPN].


 Option #2: set the interface to IFF_BROADCAST, which means "true
 multi-IP interface, with subnet, and Kernel considers all IPs of that
 subnet to be adjacent, and acceptable route next-hops".

 This is what the patch I sent yesterday does to tun(4) interfaces, and 
 the result is amazingly well-behaved - "it just works" and gets *rid*
 of quite a bit of special-case hack-around code.  Want.

 Unfortunately, this breaks for two reasons with FreeBSD DCO as of
 today:

  - no TUNSIFMODE support in ovpn(4), so stuck to IFF_POINTOPOINT mode
    (I think I can add that, copy-pasting code from if_tuntap.c)

  - no single-peer mode in ovpn(4)
    -> this will break "I am on client .5 and want to send packets to
    client .6" because vpn_v4 peer lookup won't find ".6", and no route
    towards .1 (server) either, so packet drop.
    (I'm not sure I can make this happen, but I'll give it a try, 
     following the Linux DCO approach described above)


 (There is another option here that I think I could mention - we can,
 of course, do IFF_BROADCAST only on the openvpn p2mp server, and stick
 to IFF_POINTOPOINT on client/p2p instances.  BUT that implies we'd get
 yet another case for FreeBSD ifconfig - p2p, p2p-simulated subnet, subnet
 - so the OpenVPN code will get more complex, not simpler - and we still
 need IFF_BROADCAST support in ovpn(4) - so we can do it properly all
 the way, I'd say)


 Note that Aspect 2 is only about IPv4.  IPv6 always uses true subnet mode,
 and all these considerations are of no concern...


Phew, what a long mail :-) - hope it clarifies what we're missing today
and how to move forward.

gert
-- 
"If was one thing all people took for granted, was conviction that if you 
 feed honest figures into a computer, honest figures come out. Never doubted 
 it myself till I met a computer with a sense of humor."
                             Robert A. Heinlein, The Moon is a Harsh Mistress

Gert Doering - Munich, Germany                             g...@greenie.muc.de

Attachment: signature.asc
Description: PGP signature

_______________________________________________
Openvpn-devel mailing list
Openvpn-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel

Reply via email to