Opened 3 years ago

Last modified 10 months ago

#934 new Bug / Defect

Client cannot connect using IPv6 transport

Reported by: jimc Owned by:
Priority: minor Milestone:
Component: IPv6 Version: OpenVPN 2.4.0 (Community Ed)
Severity: Not set (select this one, unless your'e a OpenVPN developer) Keywords: ipv6 listen bind dual-stack linux
Cc: plaisthos

Description

This is for OpenVPN-openvpn-2.4.2 on OpenSuSE "Tumbleweed" 2017-09-14.

When the server configuration specifies "proto udp" or "proto tcp-server"
the server reports on syslog:

Could not determine IPv4/IPv6 protocol. Using AF_INET

(See also ticked 805, https://community.openvpn.net/openvpn/ticket/805 )

If the client conf says "remote server.example.com 1194 udp6" or
"remote server.example.com 443 tcp6-client", packets arrive on the
server but no connection ensues, because an AF_INET socket does not
accept IPv6 traffic.

This is the configuration that the sysadmin will try first and
logically it should work, which is why I'm reporting this as a bug.
But it's mostly a documentation problem.

Workaround: The server configuration should say "proto udp6" or
"proto tcp6-server". The AF_INET6 socket can accept IPv4 mapped
source addresses. As far as I can tell, this can only be turned off by
the IPV6_V6ONLY socket option (see setsockopt(2) and ipv6(7)).
With the "6" the client successfully connects using both IPv4+6
transport and UDP and TCP protocol.

Suggestion for a permanent solution: When the address family is not
specified explicitly, use AF_INET6. For udp4 or tcp4 use AF_INET as
you do now. For udp6 or tcp6 turn on the IPV6_V6ONLY socket option.
The documentation needs to be more clear about address family selection.
It should also be clear that with TCP the family should precede the
mode, e.g. tcp6-client or tcp6-server. Also state that the same
rules apply for the client's "remote" option and it needs "tcp-client"
(or 4 or 6) (or server, for a static VPN) if the protocol (TCP) is
specified explicitly.

Change History (2)

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

Cc: plaisthos added
Keywords: listen bind dual-stack linux added; connect removed
Priority: majorminor

If the AF is not specified, we default to "what getaddrinfo() recommends to us" - and yes, on dual-stack systems, what we get depends on the OS defaults and that sucks (the BSDs will give us an AF_INET6 sockaddr if asking for "unspecified, I want to listen").

We can't just default to AF_INET6 as some of the Linuxes still disable IPv6 by default, so the listen would fail. Code could be changed to make this still work, but it's somewhat complicated due to the inner structure of socket.c where "address resolution", "socket initialization" and "binding" happens in totally different places (not the best design but that's what we have).

OTOH, on a *client*, the default should always be to use "udp" or "tcp" with "use what DNS tells us that the server has, and try both for dual-stack servers" (= forcing udp4 or udp6 is almost never the right answer). This is particularily important if the client happens to be behind a DNS64/NAT64 box where a v4-only server can show up as v6-enabled (due to the NAT64).

comment:2 Changed 10 months ago by seblu

Even with a Linux system configured to return AF_INET6 first, tcp-server only bind to AF_INET.

getaddrinfo returns AF_INET6

python -c 'import socket; print(socket.getaddrinfo(None, "42"))'
[(<AddressFamily.AF_INET6: 10>, <SocketKind.SOCK_STREAM: 1>, 6, '', ('::1', 42, 0, 0)), (<AddressFamily.AF_INET6: 10>, <SocketKind.SOCK_DGRAM: 2>, 17, '', ('::1', 42, 0, 0)), (<AddressFamily.AF_INET6: 10>, <SocketKind.SOCK_RAW: 3>, 0, '', ('::1', 42, 0, 0)), (<AddressFamily.AF_INET: 2>, <SocketKind.SOCK_STREAM: 1>, 6, '', ('127.0.0.1', 42)), (<AddressFamily.AF_INET: 2>, <SocketKind.SOCK_DGRAM: 2>, 17, '', ('127.0.0.1', 42)), (<AddressFamily.AF_INET: 2>, <SocketKind.SOCK_RAW: 3>, 0, '', ('127.0.0.1', 42))]

openvpn fails determine IPv4/IPv6 protocol

# openvpn --config foo.conf
Tue Oct  8 13:41:17 2019 OpenVPN 2.4.7 [git:makepkg/2b8aec62d5db2c17+] x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] built on Feb 19 2019
Tue Oct  8 13:41:17 2019 library versions: OpenSSL 1.1.1d  10 Sep 2019, LZO 2.10
Tue Oct  8 13:41:17 2019 TUN/TAP device vpn opened
Tue Oct  8 13:41:17 2019 Could not determine IPv4/IPv6 protocol. Using AF_INET
Tue Oct  8 13:41:17 2019 Listening for incoming TCP connection on [AF_INET][undef]:42
Tue Oct  8 13:41:17 2019 TCPv4_SERVER link local (bound): [AF_INET][undef]:42
Tue Oct  8 13:41:17 2019 TCPv4_SERVER link remote: [AF_UNSPEC]
Tue Oct  8 13:41:17 2019 GID set to openvpn
Tue Oct  8 13:41:17 2019 UID set to openvpn
Tue Oct  8 13:41:17 2019 Initialization Sequence Completed

Setting tcp6-server manually is a workaround.

The current openvpn starting guide (i.e. https://community.openvpn.net/openvpn/wiki/GettingStartedwithOVPN) and several places on the internet (e.g. https://serverfault.com/questions/651832/openvpn-with-mixed-ipv4-and-ipv6-clients) claims that tcp-server should be used since openvpn 2.4. This looks to be incorrect at least on Linux.

Note: See TracTickets for help on using tickets.