Opened 6 years ago

Last modified 16 months ago

#1085 accepted Bug / Defect

--topology subnet is not ignore --dev tap mode

Reported by: Bytor Owned by: Gert Döring
Priority: critical Milestone: release 2.7
Component: Generic / unclassified Version: OpenVPN git master branch (Community Ed)
Severity: Not set (select this one, unless your'e a OpenVPN developer) Keywords: freebsd, netbsd, openbsd, tap, topology subnet
Cc: Antonio Quartulli

Description

On FreeBSD 11.2 with OpenVPN 2.4.6, contrary to the lines in the man page:

       --topology mode
              Configure virtual addressing topology when running in --dev tun mode.  This directive has no meaning in --dev tap mode, which always uses a subnet topology.

using the line "topology subnet" in a config file with "dev tap" results in subnet mode being turned off and point-to-point mode seemingly being turned on.

On the server side, one sees the following:

root@opensecrets:/usr/local/etc/openvpn# ifconfig tap0
tap0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
	options=80000<LINKSTATE>
	ether 00:bd:55:98:05:00
	inet6 fe80::2bd:55ff:fe98:500%tap0 prefixlen 64 tentative scopeid 0x5 
	inet6 2001:470:b09d:17::1 prefixlen 64 tentative 
	inet 10.128.64.1 netmask 0xfffff000 broadcast 10.128.64.2 
	nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
	media: Ethernet autoselect
	status: active
	groups: tap 
	Opened by PID 88373

With the supposed point-to-point peer IP address as the broadcast address.

On the client side with both those lines in the config file, you see this:

root@authns1:/var/log/openvpn # ifconfig tap0
tap0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
	options=80000<LINKSTATE>
	ether 00:bd:18:b9:1d:00
	hwaddr 00:bd:18:b9:1d:00
	inet6 fe80::2bd:18ff:feb9:1d00%tap0 prefixlen 64 scopeid 0x4 
	inet6 2001:470:b09d:17::10 prefixlen 64 
	inet 10.128.64.16 netmask 0xfffff000 broadcast 10.128.64.1 
	nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>
	media: Ethernet autoselect
	status: active
	groups: tap 
	Opened by PID 7148

Again with the supposed point-to-point peer address as the broadcast.

Commenting out "topology subnet" line results in the expected values.

Server:

root@opensecrets:/usr/local/etc/openvpn# ifconfig tap0
tap0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
	options=80000<LINKSTATE>
	ether 00:bd:56:a5:14:00
	inet6 fe80::2bd:56ff:fea5:1400%tap0 prefixlen 64 tentative scopeid 0x5 
	inet6 2001:470:b09d:17::1 prefixlen 64 tentative 
	inet 10.128.64.1 netmask 0xfffff000 broadcast 10.128.79.255 
	nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
	media: Ethernet autoselect
	status: active
	groups: tap 
	Opened by PID 88524

Client:

root@authns1:/var/log/openvpn # ifconfig tap0
tap0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
	options=80000<LINKSTATE>
	ether 00:bd:68:3c:1f:00
	hwaddr 00:bd:68:3c:1f:00
	inet6 fe80::2bd:68ff:fe3c:1f00%tap0 prefixlen 64 tentative scopeid 0x4 
	inet6 2001:470:b09d:17::10 prefixlen 64 
	inet 10.128.64.16 netmask 0xfffff000 broadcast 10.128.79.255 
	nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>
	media: Ethernet autoselect
	status: active
	groups: tap 
	Opened by PID 7425

Since the man page says that --topology has no meaning in --dev tap mode, one would expect that it would have no effect at all.

Change History (16)

comment:1 Changed 6 years ago by Gert Döring

Cc: Antonio Quartulli added

Having the openvpn logs would be good (to see what the server is pushing and what the client is calling ifconfig with, based on this).

But ndeed, --topology should have no effect in tap mode. But that code has been rewritten so many times that I won't claim it hasn't been broken and needs to be fixed...

Does this also happen with master? (FreeBSD port "openvpn-devel")?

I'm asking because ordex just reworked large parts of tun.c, which is responsible for interpreting options and calling ifconfig accordingly...

(And I wonder what happens on a linux client, given that the logic for "which branch do I need to use?" is fairly similar)

comment:2 Changed 6 years ago by Bytor

I don't know, I haven't tried openvpn-devel. However, the log lines are:

With topology subnet:

root@authns1:/var/log/openvpn # cat openvpn.log 
Sat Aug 18 19:03:56 2018 OpenVPN 2.4.6 amd64-portbld-freebsd11.2 [SSL (OpenSSL)] [LZO] [LZ4] [PKCS11] [MH/RECVDA] [AEAD] built on Aug 18 2018
Sat Aug 18 19:03:56 2018 library versions: OpenSSL 1.0.2o-freebsd  27 Mar 2018, LZO 2.10
Sat Aug 18 19:03:56 2018 WARNING: No server certificate verification method has been enabled.  See http://openvpn.net/howto.html#mitm for more info.
Sat Aug 18 19:03:56 2018 TCP/UDP: Preserving recently used remote address: [AF_INET]104.234.237.35:1194
Sat Aug 18 19:03:56 2018 UDP link local (bound): [AF_INET][undef]:1194
Sat Aug 18 19:03:56 2018 UDP link remote: [AF_INET]104.234.237.35:1194
Sat Aug 18 19:03:57 2018 [opensecrets.vpn.cory.albrecht.name] Peer Connection Initiated with [AF_INET]104.234.237.35:1194
Sat Aug 18 19:03:59 2018 TUN/TAP device /dev/tap0 opened
Sat Aug 18 19:03:59 2018 /sbin/ifconfig tap0 ether fe:ef:17:00:00:01
Sat Aug 18 19:03:59 2018 TUN/TAP link layer address set to fe:ef:17:00:00:01
Sat Aug 18 19:03:59 2018 do_ifconfig, tt->did_ifconfig_ipv6_setup=1
Sat Aug 18 19:03:59 2018 /sbin/ifconfig tap0 10.128.64.16 10.128.64.1 mtu 1500 netmask 255.255.240.0 up
add net 10.128.64.0: gateway 10.128.64.1 fib 0: route already in table
Sat Aug 18 19:03:59 2018 ERROR: FreeBSD route add command failed: external program exited with error status: 1
Sat Aug 18 19:03:59 2018 /sbin/ifconfig tap0 inet6 2001:470:b09d:17::10/64
add net 10.128.0.0: gateway 10.128.64.1
add net 10.128.16.0: gateway 10.128.64.1
add net 10.128.32.0: gateway 10.128.64.1
add net 10.128.48.0: gateway 10.128.64.1
add net 172.31.0.0: gateway 10.128.64.1
Sat Aug 18 19:03:59 2018 add_route_ipv6(2001:470:b09d::/64 -> 2001:470:b09d:17::1 metric -1) dev tap0
add net 2001:470:b09d::/64: gateway 2001:470:b09d:17::1
Sat Aug 18 19:03:59 2018 WARNING: this configuration may cache passwords in memory -- use the auth-nocache option to prevent this
Sat Aug 18 19:03:59 2018 Initialization Sequence Completed

Without topology subnet:

Sat Aug 18 19:05:11 2018 OpenVPN 2.4.6 amd64-portbld-freebsd11.2 [SSL (OpenSSL)] [LZO] [LZ4] [PKCS11] [MH/RECVDA] [AEAD] built on Aug 18 2018
Sat Aug 18 19:05:11 2018 library versions: OpenSSL 1.0.2o-freebsd  27 Mar 2018, LZO 2.10
Sat Aug 18 19:05:11 2018 WARNING: No server certificate verification method has been enabled.  See http://openvpn.net/howto.html#mitm for more info.
Sat Aug 18 19:05:11 2018 TCP/UDP: Preserving recently used remote address: [AF_INET]104.234.237.35:1194
Sat Aug 18 19:05:11 2018 UDP link local (bound): [AF_INET][undef]:1194
Sat Aug 18 19:05:11 2018 UDP link remote: [AF_INET]104.234.237.35:1194
Sat Aug 18 19:05:12 2018 [opensecrets.vpn.cory.albrecht.name] Peer Connection Initiated with [AF_INET]104.234.237.35:1194
Sat Aug 18 19:05:13 2018 TUN/TAP device /dev/tap0 opened
Sat Aug 18 19:05:13 2018 /sbin/ifconfig tap0 ether fe:ef:17:00:00:01
Sat Aug 18 19:05:13 2018 TUN/TAP link layer address set to fe:ef:17:00:00:01
Sat Aug 18 19:05:13 2018 do_ifconfig, tt->did_ifconfig_ipv6_setup=1
Sat Aug 18 19:05:13 2018 /sbin/ifconfig tap0 10.128.64.16 netmask 255.255.240.0 mtu 1500 up
Sat Aug 18 19:05:13 2018 /sbin/ifconfig tap0 inet6 2001:470:b09d:17::10/64
add net 10.128.0.0: gateway 10.128.64.1
add net 10.128.16.0: gateway 10.128.64.1
add net 10.128.32.0: gateway 10.128.64.1
add net 10.128.48.0: gateway 10.128.64.1
add net 172.31.0.0: gateway 10.128.64.1
Sat Aug 18 19:05:13 2018 add_route_ipv6(2001:470:b09d::/64 -> 2001:470:b09d:17::1 metric -1) dev tap0
add net 2001:470:b09d::/64: gateway 2001:470:b09d:17::1
Sat Aug 18 19:05:13 2018 WARNING: this configuration may cache passwords in memory -- use the auth-nocache option to prevent this
Sat Aug 18 19:05:13 2018 Initialization Sequence Completed

As you can see, the problem is when FreeBSD's ifconfig is called with "/sbin/ifconfig tap0 10.128.64.16 10.128.64.1 mtu 1500 netmask 255.255.240.0 up" with at 10.128.64.1 inserted in there as if it were trying to use "ifconfig tun" between two peers, but for a "ifconfig tap", that parameter position would be the broadcast address.

comment:3 Changed 6 years ago by tct

CC

comment:4 Changed 6 years ago by Gert Döring

I can reproduce this on FreeBSD 11.2 and master - actually, just adding "--topology subnet" to our t_client test 4a exhibits this nicely.

Sun Aug 19 14:51:37 2018 TUN/TAP device /dev/tap3 opened
Sun Aug 19 14:51:37 2018 /sbin/ifconfig tap3 10.194.4.9 10.194.4.1 mtu 1500 netmask 255.255.255.0 up

... which is, quite obviously, not what it should do here. So thanks for your report, we need to fix this (... most likely across all non-linux platforms, since the logic seems to be very similar everywhere).

Linux is fine, though:

Sun Aug 19 14:56:08 2018 /bin/ifconfig tap3 10.194.4.9 netmask 255.255.255.0 mtu 1500 broadcast 10.194.4.255

Sun Aug 19 14:59:25 2018 /bin/ip addr add dev tap3 10.194.4.9/24 broadcast 10.194.4.255

@ordex: I wonder if we should this in master to get rid of the 3-tier if() in all the platforms, and set an enum in the generic code to "tun, p2p", "tun, subnet", "tap" and then just have a switch/case per plattform... for 2.4 this is too radical, there we just fix the bug. I'll look into it soonish (tonight, maybe).

comment:5 Changed 6 years ago by Gert Döring

ok, broken in release/2.4 on FreeBSD 11.2 as well. So unrelated to the recent tun.c work (as expected)

comment:6 Changed 6 years ago by Gert Döring

Linux does not do anything special for TOP_SUBNET, it just checks "is this a tun device, with point-to-point mode?" and both tap and top subnet fall into the same clause which just works.

The BSDs need the extra dance for tun+TOP_SUBNET because their tun interface cannot do "real subnet mode" without interfering with IPv6 - so we run in "simulate subnet on p2p" mode. Which of course should never trigger for tap mode.

comment:7 Changed 6 years ago by Gert Döring

This patch makes FreeBSD work:

diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c
index db7c25ff..00aaca91 100644
--- a/src/openvpn/tun.c
+++ b/src/openvpn/tun.c
@@ -1445,7 +1445,7 @@ do_ifconfig(struct tuntap *tt,
                         tun_mtu
                         );
         }
-        else if (tt->topology == TOP_SUBNET)
+        else if (tt->type == DEV_TYPE_TUN && tt->topology == TOP_SUBNET)
         {
             remote_end = create_arbitrary_remote( tt );
             argv_printf(&argv,
@@ -1475,7 +1475,7 @@ do_ifconfig(struct tuntap *tt,
         tt->did_ifconfig = true;
 
         /* Add a network route for the local tun interface */
-        if (!tun && tt->topology == TOP_SUBNET)
+        if (!tun && tt->type == DEV_TYPE_TUN && tt->topology == TOP_SUBNET)
         {
             struct route_ipv4 r;
             CLEAR(r);

... very obvious, after the fact, but still quite a bit to test across the platforms... (I'll only do 2.4, because the code has changed too much to make "git cherrypick" work here)

(Funky tidbit: NetBSD ifconfig seems to just happily take the "wrong" syntax and the test still works...)

Last edited 6 years ago by Gert Döring (previous) (diff)

comment:9 Changed 6 years ago by Gert Döring

Patch has been applied to the release/2.4 branch.

For reference: this is still broken in master, but warrants a proper
cleanup/refactor approach there.

commit 6c13e24e5709f404231632f14758ea8f6bd9ec83
Author: Gert Doering
Date: Sun Aug 19 22:07:03 2018 +0200

Fix combination of --dev tap and --topology subnet across multiple platforms.

Signed-off-by: Gert Doering <gert@…>
Acked-by: Antonio Quartulli <antonio@…>
Message-Id: <20180819200703.20362-1-gert@…>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg17414.html
Signed-off-by: Gert Doering <gert@…>

comment:10 Changed 4 years ago by Gert Döring

Owner: set to Gert Döring
Status: newaccepted

comment:11 Changed 4 years ago by Gert Döring

so master is still broken, but I still intend to fix it "nicely"

comment:12 Changed 4 years ago by Gert Döring

Milestone: release 2.5
Version: OpenVPN git master branch (Community Ed)

comment:13 Changed 4 years ago by Gert Döring

Priority: majorcritical

It is still broken in master & release/2.5 - and the 2.4 patch won't apply due to "tun.c looks much nicer now".

The "real" solution I had in mind (make this an enum, and a switch/case) is a bit too heavy for "in beta3/beta4", so it will be a few extra if() clauses... and then "defer to 2.6"

comment:15 Changed 4 years ago by Gert Döring

Keywords: freebsd netbsd openbsd tap topology subnet added
Milestone: release 2.5release 2.6

Patch has been applied to the master and release/2.5 branch.

(I leave the ticket open with "milestone 2.6" to prod me into
the long-planned refactoring of these if() variants into something
with an enum and "speaking" identifiers)

commit 860a7bc77ef515f1d042a2860f7e2bd9980e19be (master)
commit a5964e34057bd3a2c0cb232f1abc6feeefdf146e (release/2.5)
Author: Gert Doering
Date: Mon Sep 14 09:08:43 2020 +0200

Fix combination of --dev tap and --topology subnet across multiple platforms.

comment:16 Changed 16 months ago by Gert Döring

Milestone: release 2.6release 2.7

The FreeBSD code happened to get fixed by introducing true subnet mode into 2.6

commit 22bc63c78439ed23b974b8f822330d75ec79c7fc
Author: Gert Doering <gert@…>
Date: Wed Oct 12 16:59:15 2022 +0200

FreeBSD DCO: introduce real subnet mode

so the corresponding code is now really nice

    /* example: ifconfig tun2 10.2.0.2 10.2.0.1 mtu 1450 netmask 255.255.255.255
 up */
    if (tun)       /* point-to-point tun */
    {   
        argv_printf(&argv, "%s %s %s %s mtu %d netmask 255.255.255.255 up",
                    IFCONFIG_PATH, ifname, ifconfig_local,
                    ifconfig_remote_netmask, tun_mtu);
    }
    else            /* tun with topology subnet and tap mode (always subnet) */
    {
        int netbits = netmask_to_netbits2(tt->remote_netmask);
        argv_printf(&argv, "%s %s %s/%d mtu %d up", IFCONFIG_PATH,
                    ifname, ifconfig_local, netbits, tun_mtu );
    }

... but for all the other OSes, we still have this very unorderly code - bumping the milestone to 2.7 to go on a big rewrite of tun.c for these.

Note: See TracTickets for help on using tickets.