Opened 3 years ago
Last modified 19 months ago
#1425 assigned Bug / Defect
netlink routes does not work with "push route"
Reported by: | dpalumbo | Owned by: | Antonio Quartulli |
---|---|---|---|
Priority: | major | Milestone: | release 2.5.5 |
Component: | Generic / unclassified | Version: | OpenVPN 2.5.0 (Community Ed) |
Severity: | Not set (select this one, unless your'e a OpenVPN developer) | Keywords: | netlink route ifconfig Network is unreachable |
Cc: |
Description
Moving to openvpn 2.5, netlink is now used in place of ifconfig/route commands
https://github.com/OpenVPN/openvpn/blob/release/2.5/Changes.rst
On Linux, if configured without --enable-iproute2, configuring IP >addresses and adding/removing routes is now done via the netlink(3) kernel interface. This is much faster than calling ifconfig or route and also enables OpenVPN to run with less privileges.
What is happening, is that when the interface / routing is created with netlink, this is the routing entry that we see:
172.17.14.0/24 via 172.17.14.1 dev tun-su
while with the old route we have:
172.17.14.0/24 dev tun-su proto kernel scope link src 172.17.14.127
Because of that (subnet not "known" by the kernel) any further command to add a route via push, eg
push "route 172.17.16.0 255.255.255.0 vpn_gateway 100"
Fail with
2021-08-27 10:49:45 us=890376 net_route_v4_add: 172.17.16.0/24 via 172.18.14.1 dev [NULL] table 0 metric 100 2021-08-27 10:49:45 us=890389 sitnl_send: rtnl: generic error (-101): Network is unreachable
This is not necessarily an error in push, because also trying to add the route manually gives this error:
# route add -net 172.17.16.0/24 gw 172.17.14.1 metric 100 SIOCADDRT: Network is unreachable #
To me, seems that the whole "push" mechanism has been compromised, but i've not performed extensive test.
This bug is also described in
https://bbs.archlinux.org/viewtopic.php?id=260625
But the workaround is not working for me.
I've replicated the bug in Debian 11.
openvpn server config
[...] push "topology subnet" ifconfig 172.17.14.1 255.255.255.0 ifconfig-pool 172.17.14.126 172.17.14.252 route 172.17.14.0 255.255.255.0 push "route 172.17.14.0 255.255.255.0" push "route-gateway 172.17.14.1" push "route 172.17.16.0 255.255.255.0 vpn_gateway 100" mode server topology subnet tls-server [...]
Recompiling the package with --with-iproute2 fix the issue.
Change History (12)
comment:1 Changed 3 years ago by
comment:2 follow-up: 5 Changed 3 years ago by
Tackling this issue with gdb, the issue happens after a sitnl_route_add
.
The line that was breaking up the configuration was:
push "route 172.18.14.0 255.255.255.0"
This config entry is unneeded (probably needed in an old version, or just my mistake).
Without that line, the proper routing table is populated.
That's anyway IMHO an improvement in the code, as either this should be ignored, or should not modify the existing routing table (which has been just created by openvpn itself).
And/or ignore a push route with the vpn_gateway set in the pushed route.
Finally as netlink report the changed route (it should at least) also that logs could be useful.
This is the log entry when openvpn start with "wrong" push:
2021-08-30 12:05:32 us=646249 net_addr_v4_add: 172.18.14.127/24 dev tun-su 2021-08-30 12:05:32 us=646285 net_route_v4_add: 172.18.14.0/24 via 172.18.14.1 dev [NULL] table 0 metric -1 2021-08-30 12:05:32 us=646303 net_route_v4_add: 172.17.16.0/24 via 172.18.14.1 dev [NULL] table 0 metric 100 [...]
This is the log entry when openvpn start with "correct" push:
2021-08-30 12:13:09 us=353535 net_addr_v4_add: 172.18.14.127/24 dev tun-su 2021-08-30 12:13:09 us=353571 net_route_v4_add: 172.17.16.0/24 via 172.18.14.1 dev [NULL] table 0 metric 100 [...]
See the line:
https://github.com/OpenVPN/openvpn/blob/5a5d11a0dea51e709b44dfabc1ec97b5f3c5b222/src/openvpn/networking_sitnl.c#L1147
according to this, the gateway is not specified in the caller (but specified afterward via push "route-gateway 172.18.14.1"
), which have the route modified by netlink.
likely, this was not happening on the previous version because route
command was not smart enough to modify the existing entry.
HTH
comment:3 Changed 3 years ago by
Can you try changing this in your server config:
push "topology subnet" ifconfig 172.17.14.1 255.255.255.0 ifconfig-pool 172.17.14.126 172.17.14.252
To:
push "topology subnet" server 172.17.14.0 255.255.255.0 nopool ifconfig-pool 172.17.14.126 172.17.14.252
comment:4 Changed 3 years ago by
Hi @tgt,
I'm not sure why you asked that, but i believe that --server would do much more.
According to the manual, this is expanded as:
mode server tls-server push "topology [topology]" if dev tun AND (topology == net30 OR topology == p2p): ifconfig 10.8.0.1 10.8.0.2 if !nopool: ifconfig-pool 10.8.0.4 10.8.0.251 route 10.8.0.0 255.255.255.0 if client-to-client: push "route 10.8.0.0 255.255.255.0" else if topology == net30: push "route 10.8.0.1" if dev tap OR (dev tun AND topology == subnet): ifconfig 10.8.0.1 255.255.255.0 if !nopool: ifconfig-pool 10.8.0.2 10.8.0.253 255.255.255.0 push "route-gateway 10.8.0.1" if route-gateway unset: route-gateway 10.8.0.2
Which is not what i'm looking for, and make no sense to me.
Anyhow, as reported, the fix is to remove
push "route 172.18.14.0 255.255.255.0"
Because, with netlink, this causes the route to be re-written.
This route is already pushed by openvpn as default, as this is the subnet pushed by ifconfig.
comment:5 Changed 3 years ago by
Replying to dpalumbo:
Tackling this issue with gdb, the issue happens after a
sitnl_route_add
.
The line that was breaking up the configuration was:
push "route 172.18.14.0 255.255.255.0"This config entry is unneeded (probably needed in an old version, or just my mistake).
Without that line, the proper routing table is populated.
Replying to dpalumbo:
as reported, the fix is to remove
push "route 172.18.14.0 255.255.255.0"
Can we close this now ?
comment:6 Changed 3 years ago by
I believe that the correct answer is that OpenVPN should intercept the wrong route and ignore it.
Do you need a dedicated ticket?
This one seems to me that contains the proper information.
comment:7 Changed 3 years ago by
Milestone: | → release 2.5.5 |
---|---|
Owner: | set to Antonio Quartulli |
Status: | new → assigned |
@ordex, I have only skimmed this - but this is your field. Can we fix this? (As in: do what iproute2 does, which might be "ignore exact match routes for on-link ifconfig networks")
This IPv4 stuff...
comment:8 Changed 3 years ago by
Replying to dpalumbo:
What is happening, is that when the interface / routing is created with netlink, this is the routing entry that we see:
172.17.14.0/24 via 172.17.14.1 dev tun-su
while with the old route we have:
172.17.14.0/24 dev tun-su proto kernel scope link src 172.17.14.127
Because of that (subnet not "known" by the kernel) any further command to add a route via push, eg
push "route 172.17.16.0 255.255.255.0 vpn_gateway 100"
Fail with
2021-08-27 10:49:45 us=890376 net_route_v4_add: 172.17.16.0/24 via 172.18.14.1 dev [NULL] table 0 metric 100 2021-08-27 10:49:45 us=890389 sitnl_send: rtnl: generic error (-101): Network is unreachableThis is not necessarily an error in push, because also trying to add the route manually gives this error:
# route add -net 172.17.16.0/24 gw 172.17.14.1 metric 100 SIOCADDRT: Network is unreachable #
Note:
net_route_v4_add: 172.17.16.0/24 via 172.18.14.1
Where is 172.18.14.1 ?
comment:9 Changed 3 years ago by
Where is 172.18.14.1 ?
172.18.14.1 is the same server as 172.17.14.1, but running TCP (172.18) in place of UDP (172.17).
I was using it for several tests, so please consider this IP to be as 172.17.14.1.
In short,
- when ifconfig is 172.17.14.1, the error is on the "push route 172.17.14.0 [...]"
- when ifconfig is 172.18.14.1, the error is on the "push route 172.18.14.0 [...]"
do what iproute2 does, which might be "ignore exact match routes for on-link ifconfig networks
Catch exactly the point.
Please note, iproute2 is not ignoring it, it does have an error when the relative command is executed (as already reported):
2021-08-27 10:49:45 us=890376 net_route_v4_add: 172.17.16.0/24 via 172.18.14.1 dev [NULL] table 0 metric 100 2021-08-27 10:49:45 us=890389 sitnl_send: rtnl: generic error (-101): Network is unreachable
It could be intercepted by OpenVPN even before the netlink code, eventually.
HTH
comment:10 Changed 3 years ago by
Thanks for the report. I think this is the same issue reported in #1378 (add a route to the same subnet already configured via ifconfig).
This is obviously a configuration error, but we want sitnl to detect the problematic route and just ignore it.
comment:11 Changed 3 years ago by
If I'm not wrong, #1378 declare that the route is not added.
Which is the opposite of this issue.
The sitnl code refuses to add routes for targets that are already there as connected route, and I think that this is the correct thing to do (actually, the kernel code refuses this) - but we need a proper error message. Antonio was already volunteered to fix this.
In this case sitnl is not refusing to do it.
Anyhow, the final goal (ignore a wrongly pushed route) is definitely going to fix the issue.
comment:12 Changed 19 months ago by
For this specific issue, we would need to check if the route that we want to add is overlapping with the subnet configured by ifconfig. if so, we should just skip the route and move on.
I've tracked down with strace the route added by netlink
And the failing following push route
From
http://manpages.ubuntu.com/manpages/bionic/man7/rtnetlink.7.html
That should be the difference (to be further analyzed):
RT_SCOPE_UNIVERSE global route
RT_SCOPE_LINK route on this link
RTPROT_KERNEL by the kernel
RTPROT_BOOT during boot