Eu tenho duas ideias
1. Você poderia ter o OpenVPN aguardando até que não haja atividade (se possível, talvez à noite?) e depois soltar a conexão ou resolver novamente o IP dos servidores (e talvez fazer algo complicado / criativo com DNS) automaticamente. Eu não testei nada disso, apenas olhei para a documentação. Parece que isso pode funcionar para você, você só precisa experimentar.
Além disso, não vejo nada de errado com a queda das conexões do cliente para reconectá-las reiniciando as instâncias ou diminuindo momentaneamente o link de backup, contanto que os usuários possam lidar com uma breve desconexão. Você estava preocupado com isso? Ou apenas interessado em que isso aconteça automaticamente?
Extraído da página de manual do OpenVPN: link
--inactive n (Experimental) Causes OpenVPN to exit after n seconds of inactivity on the TUN/TAP device. The time length of inactivity is measured since the last incoming tunnel packet.
--ping n Ping remote over the TCP/UDP control channel if no packets have been sent for at least n seconds (specify --ping on both peers to cause ping packets to be sent in both directions since OpenVPN ping packets are not echoed like IP ping packets). When used in one of OpenVPN's secure modes (where --secret, --tls-server, or --tls-client is specified), the ping packet will be cryptographically secure. This option has two intended uses:
(1) Compatibility with stateful firewalls. The periodic ping will ensure that a stateful firewall rule which allows OpenVPN UDP packets to pass will not time out.
(2) To provide a basis for the remote to test the existence of its peer using the --ping-exit option.
--ping-exit n Causes OpenVPN to exit after n seconds pass without reception of a ping or other packet from remote. This option can be combined with --inactive, --ping, and --ping-exit to create a two-tiered inactivity disconnect. For example,
openvpn [options...] --inactive 3600 --ping 10 --ping-exit 60
when used on both peers will cause OpenVPN to exit within 60 seconds if its peer disconnects, but will exit after one hour if no actual tunnel data is exchanged.
--ping-restart n Similar to --ping-exit, but trigger a SIGUSR1 restart after n seconds pass without reception of a ping or other packet from remote. This option is useful in cases where the remote peer has a dynamic IP address and a low-TTL DNS name is used to track the IP address using a service such as http://dyndns.org/ + a dynamic DNS client such as ddclient.
If the peer cannot be reached, a restart will be triggered, causing the hostname used with --remote to be re-resolved (if --resolv-retry is also specified).
In server mode, --ping-restart, --inactive, or any other type of internally generated signal will always be applied to individual client instance objects, never to whole server itself. Note also in server mode that any internally generated signal which would normally cause a restart, will cause the deletion of the client instance object instead.
In client mode, the --ping-restart parameter is set to 120 seconds by default. This default will hold until the client pulls a replacement value from the server, based on the --keepalive setting in the server configuration. To disable the 120 second default, set --ping-restart 0 on the client.
See the signals section below for more information on SIGUSR1.
Note that the behavior of SIGUSR1 can be modified by the --persist-tun, --persist-key, --persist-local-ip, and --persist-remote-ip options.
Also note that --ping-exit and --ping-restart are mutually exclusive and cannot be used together.
Sugiro ler o manual. Há mais coisas lá.
Veja também esta discussão específica do PfSense sobre o assunto: link
2. Outra ideia é executar um script (para reiniciar o OpenVPN?) na alteração do status da interface. Isso também, não vou testar nem nada mas eu encontrei alguma discussão sobre isso.
Aparentemente, você pode armazenar comandos em /etc/devd.conf
A minha contém:
# $Id$
# $FreeBSD: src/etc/devd.conf,v 1.26.2.1 2005/09/03 22:49:22 sam Exp $
options {
directory "/etc/devd";
directory "/usr/local/etc/devd";
pid-file "/var/run/devd.pid";
set scsi-controller-regex
"(aac|adv|adw|aha|ahb|ahc|ahd|aic|amd|amr|asr|bt|ciss|ct|dpt|\
esp|ida|iir|ips|isp|mlx|mly|mpt|ncr|ncv|nsp|stg|sym|trm|wds)\
[0-9]+";
};
# CARP notify hooks. This will call carpup/carpdown with the
# interface (carp0, carp1) as the first parameter.
notify 100 {
match "system" "CARP";
match "type" "MASTER";
action "/usr/local/sbin/pfSctl -c 'interface carpmaster $subsystem'";
};
notify 100 {
match "system" "CARP";
match "type" "BACKUP";
action "/usr/local/sbin/pfSctl -c 'interface carpbackup $subsystem'";
};
notify 100 {
match "system" "CARP";
match "type" "INIT";
action "/usr/local/sbin/pfSctl -c 'interface carpbackup $subsystem'";
};
# When a USB keyboard arrives, attach it as the console keyboard.
attach 100 {
device-name "ukbd0";
action "kbdcontrol -k /dev/ukbd0 < /dev/console 2>/dev/null";
};
detach 100 {
device-name "ukbd0";
action "kbdcontrol -k /dev/kbd0 < /dev/console 2>/dev/null";
};
#
# Signal upper levels that an event happened on ethernet class interface
#
notify 0 {
match "system" "IFNET";
match "type" "LINK_UP";
media-type "ethernet";
action "/usr/local/sbin/pfSctl -c 'interface linkup start $subsystem'";
};
notify 0 {
match "system" "IFNET";
match "type" "LINK_DOWN";
media-type "ethernet";
action "/usr/local/sbin/pfSctl -c 'interface linkup stop $subsystem'";
};
#
# Signal upper levels that an event happened on 802.11 class interface
#
notify 0 {
match "system" "IFNET";
match "type" "LINK_UP";
match "subsystem" "[a-z]+[0-9]+_wlan[0-9]+";
action "/usr/local/sbin/pfSctl -c 'interface linkup start $subsystem'";
};
# Notify all users before beginning emergency shutdown when we get
# a _CRT or _HOT thermal event and we're going to power down the system
# very soon.
notify 10 {
match "system" "ACPI";
match "subsystem" "Thermal";
match "notify" "0xcc";
action "logger -p kern.emerg 'WARNING: system temperature too high, shutting down soon!'";
};
Talvez isso funcione para você