After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 682620 - IPv6 support (openvpn)
IPv6 support (openvpn)
Status: RESOLVED FIXED
Product: NetworkManager
Classification: Platform
Component: VPN: openvpn
git master
Other Linux
: Normal normal
: ---
Assigned To: Dan Williams
NetworkManager maintainer(s)
Depends on:
Blocks:
 
 
Reported: 2012-08-24 16:38 UTC by Dan Winship
Modified: 2014-01-10 21:37 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
0001-service-pass-IPv6-related-information-to-NM.patch (16.40 KB, patch)
2013-11-14 15:10 UTC, Dan Williams
none Details | Review
0002-properties-expose-IPv6-capability-to-the-UI.patch (910 bytes, patch)
2013-11-14 15:11 UTC, Dan Williams
none Details | Review
ABRT-grabbed backtrace (25.27 KB, text/plain)
2013-12-18 09:14 UTC, Tore Anderson
  Details
more compact version of the abort backtrace (2.98 KB, text/plain)
2013-12-23 19:11 UTC, Nicolas Iooss
  Details
New patch for network-manager-openvpn without IPv6 Point-to-Point configuration (16.20 KB, patch)
2013-12-23 19:45 UTC, Nicolas Iooss
none Details | Review

Description Dan Winship 2012-08-24 16:38:39 UTC
The openvpn VPN plugin should support IPv6, when available. This means both
connecting to a VPN endpoint at an IPv6 address, and tunneling IPv6 over the
VPN when the server supports it.

Porting examples from the openconnect plugin:
  http://git.gnome.org/browse/network-manager-openconnect/commit/?id=da9b5ab
  http://git.gnome.org/browse/network-manager-openconnect/commit/?id=1aecd60
  http://git.gnome.org/browse/network-manager-openconnect/commit/?id=cd70a97
Comment 1 Tore Anderson 2012-12-16 12:07:54 UTC
Starting with version 2.3, OpenVPN gains support for IPv6. So this should be implementable now, I think.

If there server supports IPv6 payload, i.e., routing IPv6 packets through the tunnel is supported (the OpenVPN client<->server traffic could still be IPv4, and IPv4 payload may be simultaneously present), nm-openvpn-service-openvpn-helper gets called with the following environment variables set:

ifconfig_ipv6_remote=2001:db8::1
ifconfig_ipv6_local=2001:db8::1000
ifconfig_ipv6_netbits=64
route_ipv6_network_1=2001:db8:1::/64
route_ipv6_gateway_1=2001:db8::1

Currently, NM ignores these, logging "<info> No IPv6 configuration". However, IPv4 payload continues to work as long as the client<->server traffic is done over IPv4.

The server in question had the following configuration set:

server-ipv6 2001:db8::/64
push "route-ipv6 2001:db8:1::/64"



When it comes to IPv6 transport support, it is a bit clunky as of OpenVPN 2.3rc1, as "--proto <udp6|tcp6>" forces AF_INET6 (without AI_V4MAPPED) for both getaddrinfo() and socket calls, while "--proto <udp|tcp>" forces AF_INET. So if you use e.g. "proto udp6" with an IPv4-only hostname/address, or vice versa, it'll fail. However, a fix for this is also in the works:

http://thread.gmane.org/gmane.network.openvpn.devel/7160/focus=7165

This will make "--proto <udp|tcp>" work dual-stacked, i.e. it will do a regular AF_UNSPEC getaddrinfo() for the hostname given with "--remote", and attempt to use the results in the order returned. When testing F17 NetworkManager/OpenVPN plugin using an OpenVPN 2.3rc1 binary with the above dual-stack patch to the same OpenVPN server, I additionally get the following IPv6-related environment variables:

untrusted_ip6=2a02:c0:1001:100:216:3eff:feaf:f94f
trusted_ip6=2a02:c0:1001:100:216:3eff:feaf:f94f

Curiously enough, NM logs "<info> VPN Gateway: 87.238.35.20", and a static host route to this address via eth0's default gateway is installed. While the VPN gateway name used ("greed.fud.no") does resolve to this IPv4 address, it isn't used for any server<->client communication, which uses IPv6 instead. So I'm guessing that the NM OpenVPN plugin resolves the hostname on its own, and blindly and incorrectly assumes that the host name's IPv4 address will be used for server<->client communication.

If I replace the dual-stacked gateway hostname for a single-stacked IPv6-only one ("v6.fud.no"), the connection eventually fails:

NetworkManager[799]: <warn> VPN plugin failed: 2
nm-openvpn[31246]: WARNING: Failed running command (--up/--down): external program exited with error status: 1
nm-openvpn[31246]: Exiting due to fatal error
NetworkManager[799]: <warn> VPN plugin failed: 1
NetworkManager[799]: <info> VPN plugin state changed: stopped (6)
NetworkManager[799]: <info> VPN plugin state change reason: 0

However, before it fails, the OpenVPN binary gets started, and is able to successfully establish a VPN tunnel to the server, and nm-openvpn-service-openvpn-helper with all the IPv6-related environment variables described above. It is only afterwards that nm-openvpn bombs out - presumably it doesn't understand what to do with the remote IPv6 gateway address.

BTW, I'll be happy to provide access to the dual-stacked OpenVPN server for testing purposes if need be, just let me know on IRC.
Comment 2 Dan Williams 2013-10-01 20:05:54 UTC
Summary: there are two parts to this:

1) enable IPv6 *inside* the tunnel by parsing the server-provided parameters "ifconfig_ipv6_*" and "route_ipv6*" and assigning those addresses to the tunnel interface

2) enable IPv6 *outside* the tunnel by accepting IPv6 gateway addresses and doing the right routing magic

The first is easy and should certainly be done.

The second would be a lot easier, and less confusing for users, if you didn't have to specify --proto specifically.  We can autodetect this for static IP addresses, but if the user gives a hostname as the gateway, then nm-openvpn-service would  need to do a hostname lookup to find out if the returned address was IPv4 or IPv6, and pass the appropriate --proto option.
Comment 3 Tore Anderson 2013-10-01 20:28:06 UTC
(In reply to comment #2)

> 1) enable IPv6 *inside* the tunnel by parsing the server-provided parameters
> "ifconfig_ipv6_*" and "route_ipv6*" and assigning those addresses to the tunnel
> interface
> 
> [...]
> 
> The first is easy and should certainly be done.

Yep. And FWIW, these patches work just fine for me:

https://mail.gnome.org/archives/networkmanager-list/2013-August/msg00054.html

(We can punt on the second issue as there might be potentially helpful changes coming from upstream by making --proto [tcp|udp] dual-stack capable.)

Tore
Comment 4 Dan Williams 2013-11-14 15:10:34 UTC
Created attachment 259811 [details] [review]
0001-service-pass-IPv6-related-information-to-NM.patch

Nicolas Iooss' patch #1 for tunnel IPv6 support
Comment 5 Dan Williams 2013-11-14 15:11:21 UTC
Created attachment 259812 [details] [review]
0002-properties-expose-IPv6-capability-to-the-UI.patch

Nicolas Iooss' second openvpn ipv6 patch.
Comment 6 Tore Anderson 2013-12-15 22:42:41 UTC
Hi, OpenVPN upstream has now added the aforementioned dual-stack patches. This means that when openvpn is started with "--proto udp" or "--proto tcp", it will look up the VPN gateway name with getaddrinfo() and loop through the results, trying them in the order returned. This results in a preference for IPv6. These changes will go into OpenVPN 2.4, due out this spring. I've made RPMs available here in case anyone would like to test: http://fud.no/nm-openvpn-ipv6/.

I've tested stock F20 NetworkManager-openvpn with this new OpenVPN upstream, entering an IPv6 address for the VPN gateway. This fails. Even though the log messages indicate that OpenVPN itself connects successfully, NetworkManager aborts the connection with the following error messages:

NetworkManager[661]: ** (process:1881): WARNING **: trusted_remote_to_gvalue: failed to look up VPN gateway address '2001:db8::1' (-9)
NetworkManager[661]: ** (process:1881): WARNING **: nm-openvpn-service-openvpn-helper did not receive a valid VPN Gateway from openvpn
NetworkManager[661]: <warn> VPN plugin failed: 2

The bug is obvious - NetworkManager-openvpn just doesn't grok the IPv6 VPN gateway address.

If I try the same with NetworkManager-openvpn with Nicolas Iooss' patches applied (RPMs also available at the URL mentioned above), it gets much further, I do get the output showing all the VPN details and routing (so nm-openvpn-service-openvpn-helper does its job well), but eventually it fails too. This time NetworkManager crashes completely, with the follwing error message:

NetworkManager[6914]: **
NetworkManager[6914]: ERROR:platform/nm-linux-platform.c:2212:build_rtnl_addr: assertion failed: (!nle)

Let me know if further information or testing is necessary. I'll be happy to set up a dual-stacked OpenVPN instance somewhere for testing too, if that would be helpful.

Tore
Comment 7 Tore Anderson 2013-12-17 11:25:17 UTC
As I also mentioned on the mailing list, some change in NetworkManager and/or NetworkManager-openvpn in Fedora 20 have broken the patches attached to this bug:

When I connect to a VPN server that pushes IPv6 routing information, NetworkManager crashes completely. The crash happens even if I've set the IPv6 method on the VPN connection to "ignore". Also, the tunnel itself may go over IPv4, the crash still happens.

<info> VPN connection 'foo' (IP6 Config Get) reply received.
<info> VPN Gateway: 192.0.2.1
<info> Tunnel Device: tun0
<info> IPv4 configuration:
<info>   Internal Gateway: 100.66.2.5
<info>   Internal Address: 100.66.2.6
<info>   Internal Prefix: 32
<info>   Internal Point-to-Point Address: 100.66.2.5
<info>   Maximum Segment Size (MSS): 0
<info>   Static Route: 10.0.0.0/8   Next Hop: 100.66.2.5
<info>   Static Route: [..SNIP..]
<info>   Forbid Default Route: yes
<info>   Internal DNS: 10.0.0.10
<info>   DNS Domain: 'foobar.no'
<info> IPv6 configuration:
<info>   Internal Address: 2001:db8::1000
<info>   Internal Prefix: 112
<info>   Internal Point-to-Point Address: 2001:db8::1
<info>   Maximum Segment Size (MSS): 0
<info>   Static Route: 2001:db8::/32   Next Hop: 2001:db8::1
<info>   Static Route: [..SNIP..]
<info>   Forbid Default Route: yes
<info>   DNS Domain: 'foobar.no'
<info> (tun0): link connected
**
ERROR:platform/nm-linux-platform.c:2212:build_rtnl_addr: assertion failed: (!nle)

Hope this can be fixed and updated patches posted...

I can generate an ABRT dump if anyone would find that useful.
Comment 8 Pavel Simerda 2013-12-17 13:17:33 UTC
Detailed information from the input of build_rtnl_addr would be most welcome including its source. Both would be part of a backtrace from the assertion.
Comment 9 Tore Anderson 2013-12-18 09:14:38 UTC
Created attachment 264466 [details]
ABRT-grabbed backtrace

(In reply to comment #8)
> Detailed information from the input of build_rtnl_addr would be most welcome
> including its source. Both would be part of a backtrace from the assertion.

Attached!

Tore
Comment 10 Nicolas Iooss 2013-12-23 19:11:40 UTC
Created attachment 264816 [details]
more compact version of the abort backtrace

I reproduced the bug on my system with NetworkManager version "git master" and network-manager-openvpn plugin patched with the patches I previously made. Here is a more compact version of the abort backtrace on my system.
Comment 11 Nicolas Iooss 2013-12-23 19:13:50 UTC
Hello, I confirm this bug with the master branch of NetworkManager git repository. build_rtnl_addr() fails to add an IPv6 peer address to the newly created tunnel interface. build_rtnl_addr() fails in assertion line 2277 of src/platform/nm-linux-platform.c (http://cgit.freedesktop.org/NetworkManager/NetworkManager/tree/src/platform/nm-linux-platform.c?id=c4edeb6da487740610c4f798c76e0f71c9df1e85#n2277):

    /* Peer/point-to-point address */
    if (peer_addr) {
        auto_nl_addr struct nl_addr *nlpeer = nl_addr_build (family, peer_addr, addrlen);

        nle = rtnl_addr_set_peer (rtnladdr, nlpeer);
        g_assert (!nle); /* This assertion fails with nle = -11 */
    }

I don't know anything about libnl functions but I've found a comment which suggests that IPv6 peer addresses doesn't work (http://git.infradead.org/users/tgr/libnl.git/blob/549010c52adc9baceacbd07f09f51f1a9de69f7d:/lib/route/addr.c#l43) and indeed rtnl_addr_set_peer returns -NLE_AF_NOSUPPORT for non-IPv4 addresses (http://git.infradead.org/users/tgr/libnl.git/blob/549010c52adc9baceacbd07f09f51f1a9de69f7d:/lib/route/addr.c#l946).

Here the "peer address" is used to set up the "Internal Point-to-Point IPv6 Address" of the VPN. However in my tests it appears that the tunnel still work when the peer address is not set. Hence I propose the following solution:

* I modify my patches to the OpenVPN plugin so that NM_VPN_PLUGIN_IP6_CONFIG_PTP option is no longer set.

* A developer adds the needed logic in NetworkManager to process nicely the "not supported" error reported by libnl instead of violently aborting with an assertion failure.

What do you think?

Nicolas
Comment 12 Nicolas Iooss 2013-12-23 19:45:05 UTC
Created attachment 264817 [details] [review]
New patch for network-manager-openvpn without IPv6 Point-to-Point configuration

This patch translates IPv6-related OpenVPN environment to NetworkManager. The main change since its previous revision is that IPv6 Point-to-Point configuration is no longer transmitted as this causes an assertion failure.

Note: this commit comes from https://git.gnome.org/browse/network-manager-openconnect/commit/?id=1aecd60 , which introduced the same feature in Openconnect plugin (with the same IPv6 PtP bug, cf. https://git.gnome.org/browse/network-manager-openconnect/tree/src/nm-openconnect-service-openconnect-helper.c?id=80493c029d21712f68c4c1372f2a98cb8450a045#n604).
Comment 13 Tore Anderson 2013-12-24 12:18:55 UTC
Hi Nicolas,

Did my letter to St. Nick this year end up in your mailbox by any chance? In any case, you just gave me what I wanted for Christmas this year, so thank you very much! ;-)

I tested the updated patch set, and works very well on Fedora 20 now. I've uploaded updated RPMs to http://fud.no/nm-openvpn-ipv6/.

When testing with openvpn git master (which properly implements dual-stack), IPv6 seems to work very well both when it comes to VPN payload (routing IPv6 through the tunnel) and transport (having the tunneled traffic itself be carried inside IPv6 packets).

I've tested using a dual-stacked hostname as the VPN gateway (in this case, IPv6 is preferred thanks to getaddrinfo()), an IPv4 literal, and an IPv6 literal. All works just as expected. The host route to the VPN gateway gets correctly added in all cases. This is a significant improvement over the stock F20 nm-openvpn + openvpn git master if a dual-stacked hostname is used; in this case, while openvpn will generally use IPv6 transport, nm-openvpn would ignore that and add an IPv4 host route to the VPN gateway instead (which serves no useful purpose).

I also tested using a dual-stacked hostname where the IPv6 address was intentionally broken with ip6tables rules. In this case, IPv6 was attempted first and failed. After the timeout, the openvpn binary then automatically fell back on using the IPv4 address of the VPN gateway instead, which worked - and an IPv4 host route was correctly added in this case, too.

So as far as I can tell, these patches implement everything that is necessary for full IPv6 support in nm-openvpn (transport *and* payload), where the transport part will automatically start working when OpenVPN 2.4 is released. (Until then, transport will remain IPv4 only, but that's OK.)

Merry Christmas everyone!

Tore
Comment 14 Dan Williams 2014-01-10 04:46:33 UTC
Patches merged to git master, thanks!
Comment 15 Nicolas Iooss 2014-01-10 21:37:05 UTC
I've tested tonight the git master branches of NetworkManager and OpenVPN plugin. Tunneling IPv6 seems to work fine: I can connect to http://ipv6-test.com/ and see both IPv4 and IPv6 addresses (my OpenVPN server provides a dual-stack Internet connectivity).

Thanks too for commit 90782cf which fixes the PtP issue with IPv6 addresses!
Here's the link of this commit, for future reference: http://cgit.freedesktop.org/NetworkManager/NetworkManager/commit/?id=90782cf023c2fc2c223203a97ca2ea56a0c61c55