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
signature.asc
Description: PGP signature
_______________________________________________ Openvpn-devel mailing list Openvpn-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/openvpn-devel