Opened 7 years ago

Last modified 7 years ago

#937 new Bug / Defect

Socket option "IPV6_V6ONLY=0" not allowed on DragonFlyBSD and OpenBSD

Reported by: liweitianux Owned by:
Priority: major Milestone:
Component: IPv6 Version: OpenVPN 2.4.3 (Community Ed)
Severity: Not set (select this one, unless your'e a OpenVPN developer) Keywords: ipv6, dual-stack, bind
Cc: Antonio Quartulli, Heiko Hund

Description

Dear OpenVPN developers,

I have just set up an OpenVPN (v2.4.3) server on my VPS with DragonFlyBSD (v4.8.0) as the operating system, and my VPS has (static) IPv4 & IPv6 configured. It works quiet well except for the dual IPv4 & IPv6 listening. If I set proto udp, OpenVPN could only bind to UDP6 on the DragonFlyBSD (prefer IPv6), and showed these warning messages:

Could not determine IPv4/IPv6 protocol. Using AF_INET6
Socket Buffers: R=[42080->42080] S=[9216->9216]
setsockopt(IPV6_V6ONLY=0)
Setting IPV6_V6ONLY=0 failed: Operation not supported (errno=45)
UDPv6 link local (bound): [AF_INET6][undef]:8080
UDPv6 link remote: [AF_UNSPEC]

So this issue is due to that IPV6_V6ONLY=0 is not allowed/supported on DragonFlyBSD, which is also described in its man page ip6(4).

In addition, OpenBSD also explains in its man page ip6(4) that IPV6_V6ONLY is a read-only option, and IPv6 sockets are always IPv6-only, for security considerations.

Therefore, it should be a better/best practice to open two sockets, one for IPv4, and the other for IPv6 only? In this way, OpenVPN daul-stack server will work more consistently across different platforms. And the platform notes about IPv6 on *BSD can be updated/removed.

Best regards,
Aly

Change History (8)

comment:1 Changed 7 years ago by Antonio Quartulli

Hi,

OpenVPN does have real dual-stack support.

When using proto udp you are not using dual-stack, but you are simply telling the system "please use what getaddrinfo() returns first".

When using udp4 or udp6, then you are explicitly opening a IPv4 or IPv6 socket.
Bonus: on linux udp6 sockets are dual-stack, therefore, if you don't specify any IP to bind to, with proto udp6 you are listening on both families.

somebody can correct me if I am wrong.

Cheers,

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

Cc: Antonio Quartulli Heiko Hund added

Yes. Multiple socket operation is in the works, but surprisingly complicated in our existing source (= two different developers have started working on it, and have given up midway).

On all other platforms, dual-stack sockets are a complicated but workable way to get dual-stack support on a single socket - and it's known that OpenBSD is not willing do that. DragonFly? is news to me (but it's good to hear that OpenVPN in general works).

The security argument against dual-stack sockets has always been a bit of arm-waving to me, but indeed they are right that the amount of extra kernel code to support this is high, so bugs creep in...

Anyway - this is a known issue, and we're working on it.

Looking at the platform notes, I see that the socket problem on OpenBSD is already mentioned, but DragonFly? needs more text. What would you suggest to put there?

comment:3 in reply to:  1 ; Changed 7 years ago by Gert Döring

Hi,

Replying to ordex:

OpenVPN does have real dual-stack support.

..

somebody can correct me if I am wrong.

It has dual-stack support, but single-socket - and on OpenBSD, you need to do *two* listening sockets for dual-stack. One v4-only and one v6-only - which we can't do yet.

This is a different rathole from the "getaddrinfo() returns things!" that affects dual-stack single-socket operation on FreeBSD ("udp and udp6 give you dual-stack") vs. Linux ("udp gives you v4-only")...

comment:4 in reply to:  2 Changed 7 years ago by Antonio Quartulli

Replying to cron2:

Yes. Multiple socket operation is in the works, but surprisingly complicated in our existing source (= two different developers have started working on it, and have given up midway).

As cron2 said, implementing multi-socket listening support is extremely hard due to the original OpenVPN design.

There is some work-in-progress which I contributed to, but so far it is stalled...More workforce would be appreciated :)

It got to a point where it works, but major cleanup is still required before it can be considered mergeable and there was not much motivation around..

comment:5 in reply to:  3 ; Changed 7 years ago by David Sommerseth

Replying to cron2:

This is a different rathole from the "getaddrinfo() returns things!" that affects dual-stack single-socket operation on FreeBSD ("udp and udp6 give you dual-stack") vs. Linux ("udp gives you v4-only")...

OpenVPN before v2.4 behaves as described on Linux. As of OpenVPN v2.4.0 and later, --proto udp gives you both UDPv4 and UDPv6. To strictly bind to IPv4 you need to use --proto udp4 or --proto tcp4. And the IPv6 equivalents are udp6 and tcp6.

OpenVPN clients with v2.4 and later will also first try IPv6 addresses before IPv4 if getaddrinfo() returns both.

Version 0, edited 7 years ago by David Sommerseth (next)

comment:6 in reply to:  5 ; Changed 7 years ago by Gert Döring

Hi,

Replying to dazo:

Replying to cron2:

This is a different rathole from the "getaddrinfo() returns things!" that affects dual-stack single-socket operation on FreeBSD ("udp and udp6 give you dual-stack") vs. Linux ("udp gives you v4-only")...

OpenVPN before v2.4 behaves as described on Linux. As of OpenVPN v2.4.0 and later, --proto udp gives you both UDPv4 and UDPv6.

On Linux, this seems to be somewhat dependent on glibc version, phase of the moon, and I don't know what else. We ask getaddrinfo(), and it sometimes returns INADDR_ANY and sometimes the IPv6 equivalent - thus, ending up with an ipv4-only or an ipv6-possibly-dual-stack socket. Since the workaround "just use udp6/tcp6 to force a dual-stack socket on the server" works well enough, neither plaisthos nor I were very much willing to figure out under which circumstances linux does what, and how to make it always do the same.

To strictly bind to IPv4 you need to use --proto udp4 or --proto tcp4. And the IPv6 equivalents are udp6 and tcp6.

Right, though udp6/tcp6 (on the server) will give you a dual-stack socket, unless you turn that off (or happen to be on one of the BSDs that doesn't do dual-stack server sockets), while udp6/tcp6 on a client will give you an IPv6-only connection...

OpenVPN clients with v2.4 and later will also first try IPv6 addresses before IPv4 if getaddrinfo() returns both.

Not generally. We will use the addresses in the order getaddrinfo() returns them - depending on the system preferences, this can be "IPv6 first" or "IPv4 first".

Which is the right way to do it :-) - but it can be annoying to figure out "why is it doing this now?" at times.

comment:7 in reply to:  6 Changed 7 years ago by liweitianux

Hi cron2 and others,

Thanks for looking into and discussing this issue.

Replying to cron2:

Not generally. We will use the addresses in the order getaddrinfo() returns them - depending on the system preferences, this can be "IPv6 first" or "IPv4 first".

Which is the right way to do it :-) - but it can be annoying to figure out "why is it doing this now?" at times.

I think the software's behavior should be deterministic and consistent across supported platforms, without confusions/surprises for the users. Personally I would propose the following IPv4+IPv6 behaviors (take UDP as an example):

  • --proto udp: try to bind/listen on both IPv4 and IPv6, but allow failure on one of them;
  • --proto udp4 or --proto udp6: bind/listen on single-stack IPv4 or IPv6 (thus the --bind ipv6only option can be also removed);
  • --proto udp4,udp6: require to bind/listen on both IPv4 and IPv6, and OpenVPN exits on failure.

Cheers

comment:8 in reply to:  2 Changed 7 years ago by liweitianux

Replying to cron2:

Anyway - this is a known issue, and we're working on it.

Thank you for the hard work.

Looking at the platform notes, I see that the socket problem on OpenBSD is already mentioned, but DragonFly? needs more text. What would you suggest to put there?

I've updated the notes for DragonFlyBSD there, please review it, thanks.

Cheers

Note: See TracTickets for help on using tickets.