Where I would like to use this is in the ability to use multiple remote directives where their visibility depends on the host's current network. Eg. I currently have two remotes in my client config; one with an IETF1918 internal IP, and the other with an external public IP. When I'm in my network, the internal IP is visible and it connects right away. When I'm connected to the internet, I've verified that attempts to connect to the internal IP are greeted with the ICMP port unreachable response (RFC 792, type 3, subtype 3). Yet the client keeps trying until it reaches the ping-restart timeout before it switches to the second remote IP.
A large VPN provider could use this with all public IPs to help segregate clients on connect by their source IP range. Eg. server1 accepts only 0..63 8-bit subnets. server2 accepts comcast-specific IP blocks. server3 accepts 64-127. No client-specific ranges or geo-loc tricks with DNS are needed.
The pertinent portion of v2.4's man page under the remote directive makes the current failure condition clear:
My research indicates that there may be issues with receiving async responses such as ICMP on an unconnected UDP socket. I don't know the sockets interfaces and how they work enough to know if this is a simple fix or just plain impossible. A good test environment would mean routing the test connections via a host that can inject these ICMP responses at will, such as via iptables.The client will move on to the next host in the list, in the event of connection failure. Note that at any given time, the OpenVPN client will at most be connected to one server.
Note that since UDP is connectionless, connection failure is defined by the --ping and --ping-restart options.
An even more useful solution would be to try all remote IPs at once and connect only to the first one to respond, but that's an old wish that didn't even rate a response.. viewtopic.php?f=10&t=16790
A possible alternate solution would be to apply the --connect-timeout setting to UDP connections too. Perhaps start a timer on initial connection, and when it expires, if it's still in the initial state, fail it. Maybe I can try to put a pull request together for that..