* [PATCH 0/3] OpenVPN: Fix N2N connections shown as DISCONNECTED while up
@ 2026-10-27 22:21 Antonio Quartulli
2026-10-27 22:21 ` [PATCH 1/3] ovpn-functions.pl: Add a helper to get the status of N2N connections Antonio Quartulli
` (3 more replies)
0 siblings, 4 replies; 6+ messages in thread
From: Antonio Quartulli @ 2026-10-27 22:21 UTC (permalink / raw)
To: development; +Cc: Antonio Quartulli
Hi all!
This is my first contribution to IPFire, so bear with me if I am doing
things the wrong way :)
This is what this small series addresses:
In P2P mode OpenVPN leaves its management state at AUTH/WAIT when a new
session attempt never completes (e.g. a stray packet from the internet),
although the tunnel keeps working. The WUI then shows the N2N connection
as DISCONNECTED (bug #13897).
A fix for OpenVPN has already been published for review [1], but it is
not integrated yet. These patches fix IPFire while OpenVPN still
misbehaves.
A test harness is included to verify the fix and possibly perform
regression testing in the future.
Notes:
- index.cgi and ovpnmain.cgi now require the new
/var/ipfire/ovpn-functions.pl, so it needs to be shipped with the next
Core Update. I left the filelists to you.
- wio.cgi (WIO addon) still uses the old check and has the same problem;
I can send a follow-up if wanted.
[1] https://gerrit.openvpn.net/c/openvpn/+/2040
Antonio Quartulli (3):
ovpn-functions.pl: Add a helper to get the status of N2N connections
ovpnmain.cgi/index.cgi: Use OpenVPN::n2n_status()
tests: Add tests for OpenVPN::n2n_status()
config/cfgroot/ovpn-functions.pl | 96 +++++++++++++++++++
config/rootfiles/common/configroot | 1 +
html/cgi-bin/index.cgi | 12 +--
html/cgi-bin/ovpnmain.cgi | 58 +----------
lfs/configroot | 1 +
.../ovpn-functions.pl/data/auth_pending | 6 ++
.../cfgroot/ovpn-functions.pl/data/connected | 7 ++
.../data/connected_stray_session | 8 ++
.../cfgroot/ovpn-functions.pl/data/empty | 1 +
.../cfgroot/ovpn-functions.pl/data/exiting | 7 ++
.../ovpn-functions.pl/data/never_connected | 6 ++
.../ovpn-functions.pl/data/notifications | 11 +++
.../ovpn-functions.pl/data/reconnected | 11 +++
.../ovpn-functions.pl/data/reconnecting | 9 ++
.../cfgroot/ovpn-functions.pl/data/truncated | 3 +
.../cfgroot/ovpn-functions.pl/n2n_status.pl | 73 ++++++++++++++
.../config/cfgroot/ovpn-functions.pl/test.sh | 70 ++++++++++++++
17 files changed, 315 insertions(+), 65 deletions(-)
create mode 100644 config/cfgroot/ovpn-functions.pl
create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/auth_pending
create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/connected
create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/connected_stray_session
create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/empty
create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/exiting
create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/never_connected
create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/notifications
create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/reconnected
create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/reconnecting
create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/truncated
create mode 100644 tests/config/cfgroot/ovpn-functions.pl/n2n_status.pl
create mode 100755 tests/config/cfgroot/ovpn-functions.pl/test.sh
--
2.55.0
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH 1/3] ovpn-functions.pl: Add a helper to get the status of N2N connections 2026-10-27 22:21 [PATCH 0/3] OpenVPN: Fix N2N connections shown as DISCONNECTED while up Antonio Quartulli @ 2026-10-27 22:21 ` Antonio Quartulli 2026-10-27 22:21 ` [PATCH 2/3] ovpnmain.cgi/index.cgi: Use OpenVPN::n2n_status() Antonio Quartulli ` (2 subsequent siblings) 3 siblings, 0 replies; 6+ messages in thread From: Antonio Quartulli @ 2026-10-27 22:21 UTC (permalink / raw) To: development; +Cc: Antonio Quartulli OpenVPN switches the management state to AUTH and WAIT when a new session is started while a tunnel is up, and keeps it there if that session never completes (e.g. a stray packet from the internet), although the tunnel keeps working. Therefore determine the status from the state history: an N2N connection is up if it has reached CONNECTED and has not restarted since. Signed-off-by: Antonio Quartulli <antonio@mandelbit.com> --- config/cfgroot/ovpn-functions.pl | 96 ++++++++++++++++++++++++++++++ config/rootfiles/common/configroot | 1 + lfs/configroot | 1 + 3 files changed, 98 insertions(+) create mode 100644 config/cfgroot/ovpn-functions.pl diff --git a/config/cfgroot/ovpn-functions.pl b/config/cfgroot/ovpn-functions.pl new file mode 100644 index 000000000..3c6c02660 --- /dev/null +++ b/config/cfgroot/ovpn-functions.pl @@ -0,0 +1,96 @@ +#!/usr/bin/perl +############################################################################### +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2026 Antonio Quartulli <antonio@mandelbit.com> # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see <http://www.gnu.org/licenses/>. # +# # +############################################################################### + +package OpenVPN; + +use strict; +use Net::Telnet; + +# Returns "CONNECTED" or "DISCONNECTED" for the N2N connection whose +# management interface listens on the given port. +# +# The current state alone cannot be trusted: when a new session is started +# while the tunnel is up (a peer that gives up, or just a stray packet from +# the internet), OpenVPN switches the state to AUTH and WAIT and keeps it +# there if that session never completes, although the tunnel keeps working. +# +# Therefore we look at the state history: the tunnel is up if the process +# has reached CONNECTED and has not restarted since. A tunnel that goes down +# is detected by ping-restart, which logs RECONNECTING. +sub n2n_status($) { + my $port = shift; + + # Create a new Telnet session + my $telnet = new Net::Telnet( + Port => $port, + Timeout => 3, + Errmode => "return", + ); + + # Connect + $telnet->open("127.0.0.1") or return "DISCONNECTED"; + + # Fetch the state history + my @output = $telnet->cmd( + String => "state all", + Prompt => "/(?:^|\n)(?:END|ERROR:.*)\n/" + ); + + $telnet->close(); + + # Collect all states, skipping the banner and any notifications + my @states; + + foreach my $line (@output) { + if ($line =~ m/^\d+,([A-Z_]+),/) { + push(@states, $1); + } + } + + return "DISCONNECTED" unless (@states); + + # The history always starts with CONNECTING, unless it has been truncated. + # A truncated history comes from a process that has not been restarted + # for a long time, which does not happen to an unconnected tunnel + # because of ping-restart. OpenVPN keeps the last 100 states only, so + # ~50 stray packets within one ping-restart interval after a restart + # could still make a down tunnel look connected. + my $connected = ($states[0] ne "CONNECTING"); + + foreach my $state (@states) { + if ($state eq "CONNECTED") { + $connected = 1; + + # The process starts (CONNECTING, logged once), restarts + # (RECONNECTING) or exits (EXITING) + } elsif ($state =~ m/^(CONNECTING|RECONNECTING|EXITING)$/) { + $connected = 0; + } + + # Any other state (WAIT, AUTH, ...) is either part of the initial + # connection or an attempt to start a new session that does not + # affect the existing one + } + + return $connected ? "CONNECTED" : "DISCONNECTED"; +} + +1; diff --git a/config/rootfiles/common/configroot b/config/rootfiles/common/configroot index 72e05e865..ffe1ebe72 100644 --- a/config/rootfiles/common/configroot +++ b/config/rootfiles/common/configroot @@ -138,6 +138,7 @@ var/ipfire/network-functions.pl var/ipfire/optionsfw #var/ipfire/optionsfw/settings var/ipfire/ovpn +var/ipfire/ovpn-functions.pl #var/ipfire/ovpn/ccd.conf #var/ipfire/ovpn/ccdroute #var/ipfire/ovpn/ccdroute2 diff --git a/lfs/configroot b/lfs/configroot index 3df566f50..0b14f6501 100644 --- a/lfs/configroot +++ b/lfs/configroot @@ -82,6 +82,7 @@ $(TARGET) : cp $(DIR_SRC)/config/cfgroot/location-functions.pl $(CONFIG_ROOT)/ cp $(DIR_SRC)/config/cfgroot/ipblocklist-functions.pl $(CONFIG_ROOT)/ cp $(DIR_SRC)/config/cfgroot/ids-functions.pl $(CONFIG_ROOT)/ + cp $(DIR_SRC)/config/cfgroot/ovpn-functions.pl $(CONFIG_ROOT)/ cp $(DIR_SRC)/config/cfgroot/wireguard-functions.pl $(CONFIG_ROOT)/ cp $(DIR_SRC)/config/cfgroot/lang.pl $(CONFIG_ROOT)/ cp $(DIR_SRC)/config/cfgroot/countries.pl $(CONFIG_ROOT)/ -- 2.55.0 ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 2/3] ovpnmain.cgi/index.cgi: Use OpenVPN::n2n_status() 2026-10-27 22:21 [PATCH 0/3] OpenVPN: Fix N2N connections shown as DISCONNECTED while up Antonio Quartulli 2026-10-27 22:21 ` [PATCH 1/3] ovpn-functions.pl: Add a helper to get the status of N2N connections Antonio Quartulli @ 2026-10-27 22:21 ` Antonio Quartulli 2026-10-27 22:21 ` [PATCH 3/3] tests: Add tests for OpenVPN::n2n_status() Antonio Quartulli 2026-10-28 17:28 ` [PATCH 0/3] OpenVPN: Fix N2N connections shown as DISCONNECTED while up Michael Tremer 3 siblings, 0 replies; 6+ messages in thread From: Antonio Quartulli @ 2026-10-27 22:21 UTC (permalink / raw) To: development; +Cc: Antonio Quartulli Both pages now use the same check, so a working N2N tunnel is no longer shown as DISCONNECTED after an incomplete session attempt. Fixes: #13897 Signed-off-by: Antonio Quartulli <antonio@mandelbit.com> --- html/cgi-bin/index.cgi | 12 ++------ html/cgi-bin/ovpnmain.cgi | 58 ++------------------------------------- 2 files changed, 5 insertions(+), 65 deletions(-) diff --git a/html/cgi-bin/index.cgi b/html/cgi-bin/index.cgi index 0f51ba9ff..b5f23a59a 100644 --- a/html/cgi-bin/index.cgi +++ b/html/cgi-bin/index.cgi @@ -20,7 +20,6 @@ ############################################################################### use strict; -use Net::Telnet; use Sort::Naturally; # enable only the following on debugging purpose @@ -31,6 +30,7 @@ require '/var/ipfire/general-functions.pl'; require "${General::swroot}/lang.pl"; require "${General::swroot}/header.pl"; require "${General::swroot}/wireguard-functions.pl"; +require "${General::swroot}/ovpn-functions.pl"; require "/opt/pakfire/lib/functions.pl"; my %cgiparams=(); @@ -504,17 +504,11 @@ END $count++; my $tport = $ovpnconfig{$dkey}[22]; next if ($tport eq ''); - my $tnet = new Net::Telnet ( Timeout=>5, Errmode=>'return', Port=>$tport); - $tnet->open('127.0.0.1'); - my @output = $tnet->cmd(String => 'state', Prompt => '/(END.*\n|ERROR:.*\n)/'); - my @tustate = split(/\,/, $output[1]); - my $display; + my $display = _('DISCONNECTED'); my $display_colour = $Header::colourred; - if ( $tustate[1] eq 'CONNECTED' || ($tustate[1] eq 'WAIT')) { + if (&OpenVPN::n2n_status($tport) eq "CONNECTED") { $display_colour = $Header::colourgreen; $display = _('CONNECTED'); - } else { - $display = $tustate[1]; } if ($count %2){ $col = $color{'color22'}; diff --git a/html/cgi-bin/ovpnmain.cgi b/html/cgi-bin/ovpnmain.cgi index 35561f4e7..d28f895cd 100644 --- a/html/cgi-bin/ovpnmain.cgi +++ b/html/cgi-bin/ovpnmain.cgi @@ -31,7 +31,6 @@ use MIME::Base32; use MIME::Base64; use Net::DNS; use Net::Ping; -use Net::Telnet; use Sort::Naturally; use URI::Encode qw(uri_encode uri_decode);; @@ -39,6 +38,7 @@ require '/var/ipfire/general-functions.pl'; require "${General::swroot}/header.pl"; require "${General::swroot}/countries.pl"; require "${General::swroot}/location-functions.pl"; +require "${General::swroot}/ovpn-functions.pl"; # enable only the following on debugging purpose #use warnings; @@ -1024,60 +1024,6 @@ sub writecollectdconf { &General::system("/usr/local/bin/collectdctrl", "restart"); } -sub openvpn_status($) { - my $port = shift; - - # Create a new Telnet session - my $telnet = new Net::Telnet( - Port => $port, - Timeout => 1, - Errmode => "return", - ); - - # Connect - $telnet->open("127.0.0.1"); - - # Send a command - my @output = $telnet->cmd( - String => "state", - Prompt => "/(END.*\n|ERROR:.*\n)/" - ); - - my ($time, $status) = split(/\,/, $output[1]); - - ### - #CONNECTING -- OpenVPN's initial state. - #WAIT -- (Client only) Waiting for initial response from server. - #AUTH -- (Client only) Authenticating with server. - #GET_CONFIG -- (Client only) Downloading configuration options from server. - #ASSIGN_IP -- Assigning IP address to virtual network interface. - #ADD_ROUTES -- Adding routes to system. - #CONNECTED -- Initialization Sequence Completed. - #RECONNECTING -- A restart has occurred. - #EXITING -- A graceful exit is in progress. - #### - - if ($status eq "CONNECTING") { - return "DISCONNECTED"; - } elsif ($status eq "WAIT") { - return "DISCONNECTED"; - } elsif ($status eq "AUTH") { - return "DISCONNECTED"; - } elsif ($status eq "GET_CONFIG") { - return "DISCONNECTED"; - } elsif ($status eq "ASSIGN_IP") { - return "DISCONNECTED"; - } elsif ($status eq "ADD_ROUTES") { - return "DISCONNECTED"; - } elsif ($status eq "RECONNECTING") { - return "CONNECTED"; - } elsif ($status eq "EXITING") { - return "DISCONNECTED"; - } - - return $status; -} - # Hook to regenerate the configuration files if ($ENV{"REMOTE_ADDR"} eq "") { &writeserverconf(); @@ -5309,7 +5255,7 @@ END my $port = $confighash{$key}[22]; if ($port ne "") { - $connstatus = &openvpn_status($confighash{$key}[22]); + $connstatus = &OpenVPN::n2n_status($port); } } -- 2.55.0 ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 3/3] tests: Add tests for OpenVPN::n2n_status() 2026-10-27 22:21 [PATCH 0/3] OpenVPN: Fix N2N connections shown as DISCONNECTED while up Antonio Quartulli 2026-10-27 22:21 ` [PATCH 1/3] ovpn-functions.pl: Add a helper to get the status of N2N connections Antonio Quartulli 2026-10-27 22:21 ` [PATCH 2/3] ovpnmain.cgi/index.cgi: Use OpenVPN::n2n_status() Antonio Quartulli @ 2026-10-27 22:21 ` Antonio Quartulli 2026-10-28 17:28 ` [PATCH 0/3] OpenVPN: Fix N2N connections shown as DISCONNECTED while up Michael Tremer 3 siblings, 0 replies; 6+ messages in thread From: Antonio Quartulli @ 2026-10-27 22:21 UTC (permalink / raw) To: development; +Cc: Antonio Quartulli Run n2n_status() against a fake management interface, including a new session that never completes on an established tunnel (#13897). Signed-off-by: Antonio Quartulli <antonio@mandelbit.com> --- .../ovpn-functions.pl/data/auth_pending | 6 ++ .../cfgroot/ovpn-functions.pl/data/connected | 7 ++ .../data/connected_stray_session | 8 ++ .../cfgroot/ovpn-functions.pl/data/empty | 1 + .../cfgroot/ovpn-functions.pl/data/exiting | 7 ++ .../ovpn-functions.pl/data/never_connected | 6 ++ .../ovpn-functions.pl/data/notifications | 11 +++ .../ovpn-functions.pl/data/reconnected | 11 +++ .../ovpn-functions.pl/data/reconnecting | 9 +++ .../cfgroot/ovpn-functions.pl/data/truncated | 3 + .../cfgroot/ovpn-functions.pl/n2n_status.pl | 73 +++++++++++++++++++ .../config/cfgroot/ovpn-functions.pl/test.sh | 70 ++++++++++++++++++ 12 files changed, 212 insertions(+) create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/auth_pending create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/connected create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/connected_stray_session create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/empty create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/exiting create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/never_connected create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/notifications create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/reconnected create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/reconnecting create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/truncated create mode 100644 tests/config/cfgroot/ovpn-functions.pl/n2n_status.pl create mode 100755 tests/config/cfgroot/ovpn-functions.pl/test.sh diff --git a/tests/config/cfgroot/ovpn-functions.pl/data/auth_pending b/tests/config/cfgroot/ovpn-functions.pl/data/auth_pending new file mode 100644 index 000000000..aca1f1b57 --- /dev/null +++ b/tests/config/cfgroot/ovpn-functions.pl/data/auth_pending @@ -0,0 +1,6 @@ +1793050400,CONNECTING,,,,,, +1793050417,CONNECTED,SUCCESS,10.8.0.1,127.0.0.1,21195,, +1793050448,AUTH_PENDING,,,,,, +1793054017,RECONNECTING,ping-restart,,,,, +1793054022,WAIT,,,,,, +END diff --git a/tests/config/cfgroot/ovpn-functions.pl/data/connected b/tests/config/cfgroot/ovpn-functions.pl/data/connected new file mode 100644 index 000000000..afd358d07 --- /dev/null +++ b/tests/config/cfgroot/ovpn-functions.pl/data/connected @@ -0,0 +1,7 @@ +1793050400,CONNECTING,,,,,, +1793050401,WAIT,,,,,, +1793050402,AUTH,,,,,, +1793050403,GET_CONFIG,,,,,, +1793050404,ASSIGN_IP,,10.8.0.1,,,, +1793050417,CONNECTED,SUCCESS,10.8.0.1,127.0.0.1,21195,, +END diff --git a/tests/config/cfgroot/ovpn-functions.pl/data/connected_stray_session b/tests/config/cfgroot/ovpn-functions.pl/data/connected_stray_session new file mode 100644 index 000000000..78a3a5bd5 --- /dev/null +++ b/tests/config/cfgroot/ovpn-functions.pl/data/connected_stray_session @@ -0,0 +1,8 @@ +1793050400,CONNECTING,,,,,, +1793050401,WAIT,,,,,, +1793050402,AUTH,,,,,, +1793050404,ASSIGN_IP,,10.8.0.1,,,, +1793050417,CONNECTED,SUCCESS,10.8.0.1,127.0.0.1,21195,, +1793054017,AUTH,,,,,, +1793054018,WAIT,,,,,, +END diff --git a/tests/config/cfgroot/ovpn-functions.pl/data/empty b/tests/config/cfgroot/ovpn-functions.pl/data/empty new file mode 100644 index 000000000..dce2c1d51 --- /dev/null +++ b/tests/config/cfgroot/ovpn-functions.pl/data/empty @@ -0,0 +1 @@ +END diff --git a/tests/config/cfgroot/ovpn-functions.pl/data/exiting b/tests/config/cfgroot/ovpn-functions.pl/data/exiting new file mode 100644 index 000000000..cc3fd5300 --- /dev/null +++ b/tests/config/cfgroot/ovpn-functions.pl/data/exiting @@ -0,0 +1,7 @@ +1793050400,CONNECTING,,,,,, +1793050401,WAIT,,,,,, +1793050402,AUTH,,,,,, +1793050404,ASSIGN_IP,,10.8.0.1,,,, +1793050417,CONNECTED,SUCCESS,10.8.0.1,127.0.0.1,21195,, +1793054017,EXITING,SIGTERM,,,,, +END diff --git a/tests/config/cfgroot/ovpn-functions.pl/data/never_connected b/tests/config/cfgroot/ovpn-functions.pl/data/never_connected new file mode 100644 index 000000000..d40357abd --- /dev/null +++ b/tests/config/cfgroot/ovpn-functions.pl/data/never_connected @@ -0,0 +1,6 @@ +1793050400,CONNECTING,,,,,, +1793050401,WAIT,,,,,, +1793050402,AUTH,,,,,, +1793050462,WAIT,,,,,, +1793050463,AUTH,,,,,, +END diff --git a/tests/config/cfgroot/ovpn-functions.pl/data/notifications b/tests/config/cfgroot/ovpn-functions.pl/data/notifications new file mode 100644 index 000000000..a2db8e956 --- /dev/null +++ b/tests/config/cfgroot/ovpn-functions.pl/data/notifications @@ -0,0 +1,11 @@ +>HOLD:Waiting for hold release:0 +1793050400,CONNECTING,,,,,, +>STATE:1793050401,WAIT,,,,,, +1793050401,WAIT,,,,,, +1793050402,AUTH,,,,,, +>LOG:1793050403,I,Peer Connection Initiated +1793050417,CONNECTED,SUCCESS,10.8.0.1,127.0.0.1,21195,, +>STATE:1793054017,AUTH,,,,,, +1793054017,AUTH,,,,,, +1793054018,WAIT,,,,,, +END diff --git a/tests/config/cfgroot/ovpn-functions.pl/data/reconnected b/tests/config/cfgroot/ovpn-functions.pl/data/reconnected new file mode 100644 index 000000000..3b1530458 --- /dev/null +++ b/tests/config/cfgroot/ovpn-functions.pl/data/reconnected @@ -0,0 +1,11 @@ +1793050400,CONNECTING,,,,,, +1793050401,WAIT,,,,,, +1793050402,AUTH,,,,,, +1793050404,ASSIGN_IP,,10.8.0.1,,,, +1793050417,CONNECTED,SUCCESS,10.8.0.1,127.0.0.1,21195,, +1793054017,RECONNECTING,ping-restart,,,,, +1793054022,WAIT,,,,,, +1793054023,AUTH,,,,,, +1793054024,GET_CONFIG,,,,,, +1793054025,CONNECTED,SUCCESS,10.8.0.1,127.0.0.1,21195,, +END diff --git a/tests/config/cfgroot/ovpn-functions.pl/data/reconnecting b/tests/config/cfgroot/ovpn-functions.pl/data/reconnecting new file mode 100644 index 000000000..97c0d32d6 --- /dev/null +++ b/tests/config/cfgroot/ovpn-functions.pl/data/reconnecting @@ -0,0 +1,9 @@ +1793050400,CONNECTING,,,,,, +1793050401,WAIT,,,,,, +1793050402,AUTH,,,,,, +1793050404,ASSIGN_IP,,10.8.0.1,,,, +1793050417,CONNECTED,SUCCESS,10.8.0.1,127.0.0.1,21195,, +1793054017,RECONNECTING,ping-restart,,,,, +1793054022,WAIT,,,,,, +1793054023,AUTH,,,,,, +END diff --git a/tests/config/cfgroot/ovpn-functions.pl/data/truncated b/tests/config/cfgroot/ovpn-functions.pl/data/truncated new file mode 100644 index 000000000..a4137f117 --- /dev/null +++ b/tests/config/cfgroot/ovpn-functions.pl/data/truncated @@ -0,0 +1,3 @@ +1793050417,AUTH,,,,,, +1793050418,WAIT,,,,,, +END diff --git a/tests/config/cfgroot/ovpn-functions.pl/n2n_status.pl b/tests/config/cfgroot/ovpn-functions.pl/n2n_status.pl new file mode 100644 index 000000000..5876ef2f0 --- /dev/null +++ b/tests/config/cfgroot/ovpn-functions.pl/n2n_status.pl @@ -0,0 +1,73 @@ +#!/usr/bin/perl +# +# Runs OpenVPN::n2n_status() against a fake OpenVPN management interface +# and prints the result. +# +# Usage: n2n_status.pl <ovpn-functions.pl> <data file|--no-server|--close> +# +# The fake management interface sends the banner, waits for "state all" +# and replies with the content of the data file. + +use strict; +use warnings; +use IO::Socket::INET; + +my ($functions, $mode) = @ARGV; + +require $functions; + +my $server = IO::Socket::INET->new( + LocalAddr => "127.0.0.1", + LocalPort => 0, + Proto => "tcp", + Listen => 1, + ReuseAddr => 1, +) or die "Could not create socket: $!\n"; + +my $port = $server->sockport(); + +# Nothing listening on the port +if ($mode eq "--no-server") { + $server->close(); + print OpenVPN::n2n_status($port) . "\n"; + exit 0; +} + +my $pid = fork() // die "Could not fork: $!\n"; + +if ($pid == 0) { + my $client = $server->accept() or exit 1; + + # Close the connection right away + if ($mode eq "--close") { + $client->close(); + exit 0; + } + + open(my $fh, "<", $mode) or die "Could not open $mode: $!\n"; + my @reply = <$fh>; + close($fh); + + $client->autoflush(1); + print $client ">INFO:OpenVPN Management Interface Version 5 -- type 'help' for more info\r\n"; + + while (my $line = <$client>) { + last if ($line =~ m/^state all\r?\n/); + } + + foreach my $line (@reply) { + chomp($line); + print $client "$line\r\n"; + } + + # Wait for the client to disconnect + while (<$client>) {} + + exit 0; +} + +$server->close(); + +print OpenVPN::n2n_status($port) . "\n"; + +waitpid($pid, 0); diff --git a/tests/config/cfgroot/ovpn-functions.pl/test.sh b/tests/config/cfgroot/ovpn-functions.pl/test.sh new file mode 100755 index 000000000..2110cf4f7 --- /dev/null +++ b/tests/config/cfgroot/ovpn-functions.pl/test.sh @@ -0,0 +1,70 @@ +#!/bin/bash + +SCRIPT_PATH="$(dirname "$(readlink -f "$0")")" + +ROOT="$(readlink -f "${SCRIPT_PATH}/../../../..")" + +. ${ROOT}/tests/lib.sh + +n2n_status() { + perl "${SCRIPT_PATH}/n2n_status.pl" "${ROOT}/config/cfgroot/ovpn-functions.pl" "$@" +} + +# Run n2n_status() against a fake management interface replying with the given +# state history and check the result +test_n2n_status() { + local data="${1}" + local expected="${2}" + local status + + status="$(n2n_status "${data}")" + + if [[ "${status}" == "${expected}" ]]; then + log_test_succeded "n2n_status() returns '${status}' for '${data##*/}'" + return 0 + else + log_test_failed "n2n_status() returns '${status}' for '${data##*/}' and not '${expected}'" + return 1 + fi +} + +if ! perl -MNet::Telnet -e 1 &>/dev/null; then + log_test_failed "The perl module Net::Telnet is not installed" + exit 1 +fi + +# The tunnel came up +test_n2n_status "${SCRIPT_PATH}/data/connected" "CONNECTED" + +# A new session that never completes does not affect the tunnel (#13897) +test_n2n_status "${SCRIPT_PATH}/data/connected_stray_session" "CONNECTED" + +# Notifications are ignored +test_n2n_status "${SCRIPT_PATH}/data/notifications" "CONNECTED" + +# The tunnel went down and came back up +test_n2n_status "${SCRIPT_PATH}/data/reconnected" "CONNECTED" + +# The process has been running for a long time +test_n2n_status "${SCRIPT_PATH}/data/truncated" "CONNECTED" + +# The tunnel went down +test_n2n_status "${SCRIPT_PATH}/data/reconnecting" "DISCONNECTED" + +# The tunnel never came up +test_n2n_status "${SCRIPT_PATH}/data/never_connected" "DISCONNECTED" + +# A state containing "END" does not end the history early +test_n2n_status "${SCRIPT_PATH}/data/auth_pending" "DISCONNECTED" + +# The process is exiting +test_n2n_status "${SCRIPT_PATH}/data/exiting" "DISCONNECTED" + +# No states at all +test_n2n_status "${SCRIPT_PATH}/data/empty" "DISCONNECTED" + +# The management interface closes the connection +test_n2n_status --close "DISCONNECTED" + +# The management interface is not running +test_n2n_status --no-server "DISCONNECTED" -- 2.55.0 ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 0/3] OpenVPN: Fix N2N connections shown as DISCONNECTED while up 2026-10-27 22:21 [PATCH 0/3] OpenVPN: Fix N2N connections shown as DISCONNECTED while up Antonio Quartulli ` (2 preceding siblings ...) 2026-10-27 22:21 ` [PATCH 3/3] tests: Add tests for OpenVPN::n2n_status() Antonio Quartulli @ 2026-10-28 17:28 ` Michael Tremer 2026-10-28 19:20 ` Antonio Quartulli 3 siblings, 1 reply; 6+ messages in thread From: Michael Tremer @ 2026-10-28 17:28 UTC (permalink / raw) To: Antonio Quartulli; +Cc: development Hello Antonio, Thank you so much for your patch. I am happy to merge this and create a separate file with the function so that it can be re-used properly. From which version of OpenVPN will this work? All the best, -Michael > On 27 Oct 2026, at 22:21, Antonio Quartulli <antonio@mandelbit.com> wrote: > > Hi all! > > This is my first contribution to IPFire, so bear with me if I am doing > things the wrong way :) > > This is what this small series addresses: > > In P2P mode OpenVPN leaves its management state at AUTH/WAIT when a new > session attempt never completes (e.g. a stray packet from the internet), > although the tunnel keeps working. The WUI then shows the N2N connection > as DISCONNECTED (bug #13897). > > A fix for OpenVPN has already been published for review [1], but it is > not integrated yet. These patches fix IPFire while OpenVPN still > misbehaves. > > A test harness is included to verify the fix and possibly perform > regression testing in the future. > > Notes: > - index.cgi and ovpnmain.cgi now require the new > /var/ipfire/ovpn-functions.pl, so it needs to be shipped with the next > Core Update. I left the filelists to you. > - wio.cgi (WIO addon) still uses the old check and has the same problem; > I can send a follow-up if wanted. > > [1] https://gerrit.openvpn.net/c/openvpn/+/2040 > > Antonio Quartulli (3): > ovpn-functions.pl: Add a helper to get the status of N2N connections > ovpnmain.cgi/index.cgi: Use OpenVPN::n2n_status() > tests: Add tests for OpenVPN::n2n_status() > > config/cfgroot/ovpn-functions.pl | 96 +++++++++++++++++++ > config/rootfiles/common/configroot | 1 + > html/cgi-bin/index.cgi | 12 +-- > html/cgi-bin/ovpnmain.cgi | 58 +---------- > lfs/configroot | 1 + > .../ovpn-functions.pl/data/auth_pending | 6 ++ > .../cfgroot/ovpn-functions.pl/data/connected | 7 ++ > .../data/connected_stray_session | 8 ++ > .../cfgroot/ovpn-functions.pl/data/empty | 1 + > .../cfgroot/ovpn-functions.pl/data/exiting | 7 ++ > .../ovpn-functions.pl/data/never_connected | 6 ++ > .../ovpn-functions.pl/data/notifications | 11 +++ > .../ovpn-functions.pl/data/reconnected | 11 +++ > .../ovpn-functions.pl/data/reconnecting | 9 ++ > .../cfgroot/ovpn-functions.pl/data/truncated | 3 + > .../cfgroot/ovpn-functions.pl/n2n_status.pl | 73 ++++++++++++++ > .../config/cfgroot/ovpn-functions.pl/test.sh | 70 ++++++++++++++ > 17 files changed, 315 insertions(+), 65 deletions(-) > create mode 100644 config/cfgroot/ovpn-functions.pl > create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/auth_pending > create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/connected > create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/connected_stray_session > create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/empty > create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/exiting > create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/never_connected > create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/notifications > create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/reconnected > create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/reconnecting > create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/truncated > create mode 100644 tests/config/cfgroot/ovpn-functions.pl/n2n_status.pl > create mode 100755 tests/config/cfgroot/ovpn-functions.pl/test.sh > > -- > 2.55.0 > > ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 0/3] OpenVPN: Fix N2N connections shown as DISCONNECTED while up 2026-10-28 17:28 ` [PATCH 0/3] OpenVPN: Fix N2N connections shown as DISCONNECTED while up Michael Tremer @ 2026-10-28 19:20 ` Antonio Quartulli 0 siblings, 0 replies; 6+ messages in thread From: Antonio Quartulli @ 2026-10-28 19:20 UTC (permalink / raw) To: Michael Tremer; +Cc: development Hi Michael, On 28/10/2026 18:28, Michael Tremer wrote: > Hello Antonio, > > Thank you so much for your patch. Thanks for considering it! :) > > I am happy to merge this and create a separate file with the function so that it can be re-used properly. > > From which version of OpenVPN will this work? This code aims at working around the existing OpenVPN (mis)behaviour and therefore works for all versions. When my fix will be merged in upstream OpenVPN (see my comment in bug #13897) this code in IPFire will become mostly a no-op, but nothing will break. I hope this helps clarifying the scenario. Regards, > > All the best, > -Michael > >> On 27 Oct 2026, at 22:21, Antonio Quartulli <antonio@mandelbit.com> wrote: >> >> Hi all! >> >> This is my first contribution to IPFire, so bear with me if I am doing >> things the wrong way :) >> >> This is what this small series addresses: >> >> In P2P mode OpenVPN leaves its management state at AUTH/WAIT when a new >> session attempt never completes (e.g. a stray packet from the internet), >> although the tunnel keeps working. The WUI then shows the N2N connection >> as DISCONNECTED (bug #13897). >> >> A fix for OpenVPN has already been published for review [1], but it is >> not integrated yet. These patches fix IPFire while OpenVPN still >> misbehaves. >> >> A test harness is included to verify the fix and possibly perform >> regression testing in the future. >> >> Notes: >> - index.cgi and ovpnmain.cgi now require the new >> /var/ipfire/ovpn-functions.pl, so it needs to be shipped with the next >> Core Update. I left the filelists to you. >> - wio.cgi (WIO addon) still uses the old check and has the same problem; >> I can send a follow-up if wanted. >> >> [1] https://gerrit.openvpn.net/c/openvpn/+/2040 >> >> Antonio Quartulli (3): >> ovpn-functions.pl: Add a helper to get the status of N2N connections >> ovpnmain.cgi/index.cgi: Use OpenVPN::n2n_status() >> tests: Add tests for OpenVPN::n2n_status() >> >> config/cfgroot/ovpn-functions.pl | 96 +++++++++++++++++++ >> config/rootfiles/common/configroot | 1 + >> html/cgi-bin/index.cgi | 12 +-- >> html/cgi-bin/ovpnmain.cgi | 58 +---------- >> lfs/configroot | 1 + >> .../ovpn-functions.pl/data/auth_pending | 6 ++ >> .../cfgroot/ovpn-functions.pl/data/connected | 7 ++ >> .../data/connected_stray_session | 8 ++ >> .../cfgroot/ovpn-functions.pl/data/empty | 1 + >> .../cfgroot/ovpn-functions.pl/data/exiting | 7 ++ >> .../ovpn-functions.pl/data/never_connected | 6 ++ >> .../ovpn-functions.pl/data/notifications | 11 +++ >> .../ovpn-functions.pl/data/reconnected | 11 +++ >> .../ovpn-functions.pl/data/reconnecting | 9 ++ >> .../cfgroot/ovpn-functions.pl/data/truncated | 3 + >> .../cfgroot/ovpn-functions.pl/n2n_status.pl | 73 ++++++++++++++ >> .../config/cfgroot/ovpn-functions.pl/test.sh | 70 ++++++++++++++ >> 17 files changed, 315 insertions(+), 65 deletions(-) >> create mode 100644 config/cfgroot/ovpn-functions.pl >> create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/auth_pending >> create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/connected >> create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/connected_stray_session >> create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/empty >> create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/exiting >> create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/never_connected >> create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/notifications >> create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/reconnected >> create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/reconnecting >> create mode 100644 tests/config/cfgroot/ovpn-functions.pl/data/truncated >> create mode 100644 tests/config/cfgroot/ovpn-functions.pl/n2n_status.pl >> create mode 100755 tests/config/cfgroot/ovpn-functions.pl/test.sh >> >> -- >> 2.55.0 >> >> > -- Antonio Quartulli CEO and Co-Founder Mandelbit Srl https://www.mandelbit.com ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-10-28 19:20 UTC | newest] Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2026-10-27 22:21 [PATCH 0/3] OpenVPN: Fix N2N connections shown as DISCONNECTED while up Antonio Quartulli 2026-10-27 22:21 ` [PATCH 1/3] ovpn-functions.pl: Add a helper to get the status of N2N connections Antonio Quartulli 2026-10-27 22:21 ` [PATCH 2/3] ovpnmain.cgi/index.cgi: Use OpenVPN::n2n_status() Antonio Quartulli 2026-10-27 22:21 ` [PATCH 3/3] tests: Add tests for OpenVPN::n2n_status() Antonio Quartulli 2026-10-28 17:28 ` [PATCH 0/3] OpenVPN: Fix N2N connections shown as DISCONNECTED while up Michael Tremer 2026-10-28 19:20 ` Antonio Quartulli
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox