Page MenuHomeVyOS Platform

OpenVPN site-to-site: "keep-alive interval 0" leaves ping-restart armed and flaps an idle tunnel
Open, NormalPublic

Description

keep-alive interval 0 is how the CLI turns the OpenVPN keepalive off. Server mode rendered it as keepalive 0 0 (T9334); site-to-site mode renders the two directives that helper stands for, and neither is guarded:

data/templates/openvpn/server.conf.j2

ping {{ keep_alive.interval }}
ping-restart {{ keep_alive.failure_count }}

So interval 0 with the default failure-count produces ping 0 / ping-restart 60. OpenVPN accepts both, since --ping and --ping-restart are parsed with a lower bound of 0 unlike --keepalive, which is why nothing fails visibly:

vyos@vyos:~$ grep -n "^ping" /run/openvpn/vtun20.conf
22:ping 0
23:ping-restart 60
vyos@vyos:~$ systemctl is-active openvpn@vtun20.service
active

A zero send timeout leaves the ping timer unarmed while the restart timer stays armed, so the configuration that asked for no keepalive gets "send no keepalives, and tear the tunnel down after 60 seconds of silence". Two site-to-site tunnels pointed at each other, both with keep-alive interval 0, left idle:

Sep 18 10:31:52 vyos openvpn-vtun20[19257]: Timers: ping-restart 60
Sep 18 10:33:02 vyos openvpn-vtun20[19257]: Inactivity timeout (--ping-restart), restarting
Sep 18 10:33:02 vyos openvpn-vtun20[19257]: SIGUSR1[soft,ping-restart] received, process restarting
Sep 18 10:33:02 vyos openvpn-vtun20[19257]: Restart pause, 2 second(s)
Sep 18 10:33:05 vyos openvpn-vtun20[19257]: Initialization Sequence Completed
Sep 18 10:33:05 vyos openvpn-vtun20[19257]: Timers: ping-restart 60
Sep 18 10:34:14 vyos openvpn-vtun20[19257]: Inactivity timeout (--ping-restart), restarting

Timers: ping-restart 60 is the whole timer set - no ping timer is armed at all. Both peers restart in lockstep about once a minute for as long as the tunnel carries no traffic. The same cycle shows on vtun21.

This is what the option parsing produces:

init.c, OpenVPN 2.7

if (c->options.ping_send_timeout)
    event_timeout_init(&c->c2.ping_send_interval, c->options.ping_send_timeout, 0);
if (c->options.ping_rec_timeout)
    event_timeout_init(&c->c2.ping_rec_interval, c->options.ping_rec_timeout, now);

verify() does not catch it either: the keep-alive validation added in T8264 sits under if openvpn['mode'] == 'server':, so site-to-site is never checked.

Steps to reproduce

Two tunnels pointed at each other on one router are enough:

set interfaces openvpn vtun20 mode site-to-site
set interfaces openvpn vtun20 local-host 127.0.0.1
set interfaces openvpn vtun20 local-port 1194
set interfaces openvpn vtun20 remote-host 127.0.0.1
set interfaces openvpn vtun20 remote-port 1195
set interfaces openvpn vtun20 local-address 10.9.0.1
set interfaces openvpn vtun20 remote-address 10.9.0.2
set interfaces openvpn vtun20 shared-secret-key <name>
set interfaces openvpn vtun20 encryption cipher aes256
set interfaces openvpn vtun20 keep-alive interval 0

set interfaces openvpn vtun21 mode site-to-site
set interfaces openvpn vtun21 local-host 127.0.0.1
set interfaces openvpn vtun21 local-port 1195
set interfaces openvpn vtun21 remote-host 127.0.0.1
set interfaces openvpn vtun21 remote-port 1194
set interfaces openvpn vtun21 local-address 10.9.0.2
set interfaces openvpn vtun21 remote-address 10.9.0.1
set interfaces openvpn vtun21 shared-secret-key <name>
set interfaces openvpn vtun21 encryption cipher aes256
set interfaces openvpn vtun21 keep-alive interval 0

commit

cat /run/openvpn/vtun20.conf shows ping 0 and ping-restart 60. Leave both tunnels idle and watch journalctl -fu openvpn@vtun20: the tunnel comes up, then restarts roughly every 70 seconds without any traffic at all.

Expected behaviour

interval 0 leaves both directives out of the generated file, the same way T9334 makes server mode leave keepalive out.

Version

VyOS rolling 2026.09.17-0028. The template has rendered it this way for years, so every release with site-to-site support is affected.

Details

Version
2026.09.17-0028-rolling
Is it a breaking change?
Perfectly compatible
Issue type
Bug (incorrect behavior)

Event Timeline

b3r1k triaged this task as Normal priority.
b3r1k created this object in space S1 VyOS Public.