Соединение OpenVPN, конечно же, может упасть. Может просто отвалиться служба, сервер может закрыть соединение с клиентом и ping-restart, keepalive помогают не всегда.

Нужно сделать восстановление соединения в кратчайшие сроки, если служба упала.

Работаем с OpenVPN client на OpenWRT 14.07

В моем случае туннеля два:

root@openwrt:~# ps | grep openvpn
1354 root 3536 S /usr/sbin/openvpn --syslog openvpn(custom_config) --cd /etc/openvpn --config my-vpn.conf
1357 root 3536 S /usr/sbin/openvpn --syslog openvpn(custom_config2) --cd /etc/openvpn --config my-vpn2.conf

Если один из туннелей упал — нужно его поднять, если упали оба — нужно поднять оба, если всё хорошо, то ничего делать не нужно. Пишем скрипт vpn_watchdog.sh:

#!/bin/ash

#VPN1
vpn1=`pgrep -f my-vpn.conf`
if [ -z "$vpn1" ];
then
logger VPN1 restart
/usr/sbin/openvpn --syslog "openvpn(custom_config)" --cd /etc/openvpn --config my-vpn.conf &
else
logger VPN1 ok
fi

#VPN2
vpn2=`pgrep -f my-vpn2.conf`
if [ -z "$vpn2" ];
then
logger VPN2 restart
/usr/sbin/openvpn --syslog "openvpn(custom_config2)" --cd /etc/openvpn --config my-vpn2.conf &
else
logger VPN2 ok
fi

pgrep с аргументом -f ищет строку по всем аргументам, а не только в имени процесса.

Конструкция if [ -z «$vpn1» ]; проверяет пустая ли строка находится в переменной $vpn1. Если пустая — значит процесса нет и vpn1 нужно перезапустить, в противном  случае «VPN1 ok».

Добавим в cron, пусть проверяет каждую минуту:

crontab -e

*/1 * * * * /etc/openvpn/vpn_watchdog.sh > /dev/null 2>&1

Не забудьте о пустой строке в конце конфига и после внесения изменений перезапустим cron

/etc/init.d/cron restart

О своей работе скрипт пишет в syslog. Понаблюдать за ним можно, запустив logread -f

Всё хорошо:

Wed Oct 21 12:03:01 2015 cron.info crond[794]: crond: USER root pid 2825 cmd /etc/openvpn/vpn_watchdog.sh > /dev/null 2>&1

Wed Oct 21 12:03:01 2015 user.notice root: VPN1 ok

Wed Oct 21 12:03:01 2015 user.notice root: VPN2 ok

Убили принудительно один тунель:

Wed Oct 21 12:04:01 2015 cron.info crond[794]: crond: USER root pid 2842 cmd /etc/openvpn/vpn_watchdog.sh > /dev/null 2>&1

Wed Oct 21 12:04:01 2015 user.notice root: VPN1 restart

Wed Oct 21 12:04:01 2015 user.notice root: VPN2 ok

Если туннель один, то можно не использовать pgrep -f, а службу перезапускать целиком. Получится вот так:

#!/bin/ash

#VPN
vpn=`pgrep openvpn`
if [ -z "$vpn" ];
then
logger VPN restart
/etc/init.d/openvpn restart
else
logger VPN ok
fi

Если Вы знаете, как сделать лучше, напишите, пожалуйста, об этом.