Opened 4 years ago

Closed 4 years ago

#1247 closed Bug / Defect (fixed)

"remote_host" route moniker not working when v6 connection was established

Reported by: madduck Owned by: Gert Döring
Priority: major Milestone: release 2.5
Component: Generic / unclassified Version: OpenVPN 2.4.7 (Community Ed)
Severity: Not set (select this one, unless your'e a OpenVPN developer) Keywords:
Cc: Antonio Quartulli

Description

Given a line

route remote_host default net_gateway

results in a route to 255.255.255.255 being added to the kernel routing table, which is bad. This only happens, if the connection to the OpenVPN server was made using IPv6, and can thus be avoided by using udp4.

Ideally, the line should yield a v6 route to be added in much the same way it would add a v4 route, depending on the address family used.

Change History (8)

comment:1 Changed 4 years ago by madduck

I forgot to include that I get a log message

RESOLVE: Cannot parse IP address: net_gateway: (Name or service not known)

which is a bit weird. There is a v4 net_gateway, but there is no v4 remote_host.

comment:2 Changed 4 years ago by tct

Just in case this goes somewhere .. CC

There is also a chance this is related to #1161

Version 1, edited 4 years ago by tct (previous) (next) (diff)

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

Cc: Antonio Quartulli added
Milestone: release 2.5
Owner: set to Gert Döring
Status: newassigned

Yeah, stupid indeed. We should see that this gets fixed for 2.5 and maybe even backported to 2.4.

Haven't looked into the code yet, but it looks like "some lookup function is returning -1 to signal 'I don't know' while the routing code just sees this as -1 = 255.255.255.255 and tries to install such a route".

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

Yeah, easy to reproduce.

Config: test server, pushing two routes, plus the line from above in the config.

With proto udp4, I get

2020-09-11 10:07:55 us=664190 UDPv4 link remote: [AF_INET]199.102.77.82:51194
...
2020-09-11 10:07:57 us=559325 net_route_v4_add: 199.102.77.82/32 via 193.149.48.190 dev [NULL] table 0 metric -1
2020-09-11 10:07:57 us=559359 net_route_v4_add: 10.194.0.0/16 via 10.194.2.53 dev [NULL] table 0 metric -1
2020-09-11 10:07:57 us=559385 net_route_v4_add: 10.194.2.1/32 via 10.194.2.53 dev [NULL] table 0 metric -1

and if I use proto udp6, I get

2020-09-11 10:08:35 us=54073 UDPv6 link remote: [AF_INET6]2607:fc50:1001:5200::4:51194
...
2020-09-11 10:08:36 us=980990 net_route_v4_add: 255.255.255.255/32 via 193.149.48.190 dev [NULL] table 0 metric -1
2020-09-11 10:08:36 us=981305 net_route_v4_add: 10.194.0.0/16 via 10.194.2.53 dev [NULL] table 0 metric -1
2020-09-11 10:08:36 us=981474 net_route_v4_add: 10.194.2.1/32 via 10.194.2.53 dev [NULL] table 0 metric -1

this does not seem to have adverse effects (and I do not get this "RESOLVE" error) but it's obviously not a useful thing to do...

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

Bah, this code... if I do the simple fix in route.c:get_special_addr()

    else if (!strcmp(string, "remote_host"))
    {
        if (rl)
        {
            if (rl->spec.flags & RTSA_REMOTE_HOST &&
                (int) rl->spec.remote_host != 0xffffffff)
...
            else
            {
                msg(M_INFO, PACKAGE_NAME " ROUTE: remote_host undefined");

I do see this in the log - but it now installs a route for 0.0.0.91. Wut...

2020-09-11 10:26:19 us=88549 OpenVPN ROUTE: remote_host undefined
...
2020-09-11 10:26:19 us=89235 net_route_v4_add: 0.0.0.91/32 via 193.149.48.190 dev [NULL] table 0 metric -1

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

So, there's actually a couple of things coming to gether to wreck this.

init.c::do_init_route_list() calls

        init_route_list(route_list,
                        options->routes,
                        gw,
                        metric,
                        link_socket_current_remote(link_socket_info),
                        es,
                        ctx))

which does the right thing

    if (lsa->actual.dest.addr.sa.sa_family != AF_INET)
    {
        return IPV4_INVALID_ADDR;
    }

but since this is just a 32 bit integer (-1 = 255.255.255.255) it's passed onwards.

route.c::init_route_list() does

    if (remote_host)
    {
        rl->spec.remote_host = remote_host;
        rl->spec.flags |= RTSA_REMOTE_HOST;
    }

which is true for "everything that is not 0", and INVALID_ADDR is not 0 - so it is set.

get_special_addr() will then, correctly, determine "oh, I have a remote_host address!" and return it.

Now, if I fix init_route_list(), init_route() will still fail to handle "status = false" correctly... so, two fixes needed.

With those, I end up at

2020-09-11 10:53:15 us=578045 OpenVPN ROUTE: remote_host undefined
2020-09-11 10:53:15 us=578050 OpenVPN ROUTE: failed to parse/resolve route for host/network: remote_host

which is correct for "I want a v4 route to something I only know the v6 address for".

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

Resolution: fixed
Status: assignedclosed

commit aa34684972eb01bfa5c355d1c8a8a9d384bf0175 (master)
commit 78c50eba82fe9bf9a899cb8587e11dcc227c0cdd (release/2.5)
commit 09e46c3ca7ead4e7b817fa527302dfb1a2f225d0 (release/2.4)
Author: Gert Doering
Date: Fri Sep 11 10:59:07 2020 +0200

Fix handling of 'route remote_host' for IPv6 transport case.

(this will show up in 2.4.10, and 2.5.0)

Note: See TracTickets for help on using tickets.