Bug #14646
closedOpenVPN can select the wrong interface IP address when multiple addresses are present
100%
Description
If there are multiple IP addresses and VIPs on an interface, OpenVPN can unintentionally select the wrong address.
In the OpenVPN code when it attempts to find the interface address it first does this:
$interface = get_failover_interface($settings['interface']);
Then a bit below that:
$iface_ip=get_interface_ip($interface);
There are multiple problems with that arrangement:
- It is redundant (
get_interface_ip()
checks the failover interface on its own) - The check for "any" can never succeed because if
$settings['interface']
was 'any' then by the time it's checked the variable would beNULL
as that would be returned byget_failover_interface()
get_failover_interface()
returns the real OS interface (e.g.igb1
,vtnet0
) andget_interface_ip()
works best when given the friendly config interface ('wan', 'lan', 'opt1') otherwise it falls through to a less reliable method of determining the interface address (find_interface_ip()
) even if the IP address is hardcoded on the interface inconfig.xml
It would appear that this one change would be a minimal diff to eliminate the problematic behavior:
diff --git a/src/etc/inc/openvpn.inc b/src/etc/inc/openvpn.inc
index 0281a094cb..1e63e3dfbf 100644
--- a/src/etc/inc/openvpn.inc
+++ b/src/etc/inc/openvpn.inc
@@ -899,7 +899,7 @@ function openvpn_reconfigure($mode, $settings) {
// OpenVPN defaults to SHA1, so use it when unset to maintain compatibility.
$digest = !empty($settings['digest']) ? $settings['digest'] : "SHA1";
- $interface = get_failover_interface($settings['interface']);
+ $interface = $settings['interface'];
// The IP address in the settings can be an IPv4 or IPv6 address associated with the interface
$ipaddr = $settings['ipaddr'];
That change works here in some local testing though I don't have a lab system which exhibits the problem behavior observed by customers in the field.
Updated by Jim Pingle about 1 year ago
- Status changed from New to Feedback
- % Done changed from 0 to 100
Applied in changeset 340aa54839a5b3a8fb74b66919511cebb307bb57.
Updated by Georgiy Tyutyunnik about 1 year ago
wasn't able to reproduce the original issue as it's stated in the ticket.
However, found a somewhat linked issue:
If I run an openVPN server on an interface and disable the said interface, the socket remains hanging but in this way:
root openvpn 6696 7 tcp4 :1194 *:
so the openvpn server start listening on each interface, which enables me to connect to it using the different interface IP.
After applying the patch openvpn process stops if I disable the interface for it, and listening socket is not present.
tested on:
Version 23.05.1-RELEASE (amd64)
built on Wed Jun 28 03:57:27 UTC 2023
FreeBSD 14.0-CURRENT
Updated by Jordan G about 1 year ago
Wasn't sure if this applied to clients and servers. After applying changeset via system_patches I rebooted upstream gateway and only one of my openVPN clients automatically failed over to my other WAN. Both tunnels were using the same gateway group; after resaving the affected tunnel and testing again, both tunnels reconnected as expected. This particular config could be to blame it's been re-used a few times, will test with different setup as well.
Updated by Jim Pingle about 1 year ago
In my testing here, the behavior is correct when that is set to a failover group.
get_interface_ip(<group name>)
returns the expected address for whichever address is active for the group at the time. If I disable the tier 1 gateway it returns whatever the next tier is.