Настройка OpenVPN. Запретить конкурентные подключения

Не такой уж и праздный вопрос оказался — запретить конкурентные подключения с одним и тем же сертификатом. По умолчанию, если такие соединения случаются, то «живая» сессия будет с тем, кто подключился последним. Предыдущие сессии ломаются и в последствии отвативаются. И это не зависит от того с одного внешнего IP были соединения или с разных. Один читатель этого блога задал подобный вопрос. И вот какое решение удалось найти (сразу скажу — не мое) и протестировать

На стороне сервера

Общая идея состоит в том, что на стороне сервера мы разрешаем конкурентные подключения, однако будем ограничивать их количество

В openvpn.conf добавляем следующие параметры

duplicate-cn
script-security 2
up /etc/openvpn/connectScript.sh
client-connect /etc/openvpn/connectScript.sh
client-disconnect /etc/openvpn/connectScript.sh

duplicate-cn — разрешает одновременные подключения
script-security 2 — разрешает запуск внешних скриптов
up, client-connect, client-disconnect — переменные окружения, передаются в скрипт connectScript.sh (см. Environmental Variables)

Скрипт connectScript.sh

#!/bin/bash

PERSIST_DIR=/tmp/pDir
mkdir -p $PERSIST_DIR
# владелец $PERSIST_DIR должен быть тот же, о чьего имени работает OpenVPN
chown nobody:nobody $PERSIST_DIR

function handle_connect {
CLIENTFILE=$PERSIST_DIR/$common_name
if [ -e "$CLIENTFILE" ]; then
NUMCONN=$(cat $CLIENTFILE)
NEWCONN=$(expr $NUMCONN + 1)
# следующая строка ограничивает кол-во подключений
# в данном случае не больше чем одно
if [ $NEWCONN -gt 1 ]; then exit 1; fi
echo $NEWCONN >$CLIENTFILE
else
echo 1 >$CLIENTFILE
fi
}

function handle_disconnect {
CLIENTFILE=$PERSIST_DIR/$common_name
if [ -e "$CLIENTFILE" ]; then
NUMCONN=$(cat $CLIENTFILE)
NEWCONN=$(expr $NUMCONN - 1)
echo $NEWCONN >$CLIENTFILE
fi
}

case "$script_type" in
  up)
      rm -f $PERSIST_DIR/$common_name
      ;;
  client-connect)
      "handle_connect"
      ;;
  client-disconnect)
      "handle_disconnect"
      ;;
esac

Задаем владельца и права на скрипт

chown nobody:nobody connectScript.sh
chmod 755 connectScript.sh

Проверка конфига и перезапуск сервера

openvpn --config openvpn.conf
rc-service openvpn restart

На стороне клиента

Добавляем в конфиг параметр

explicit-exit-notify

Без этого параметра сервер не получит сообщение о разъединении в случае отключения клиента. Поэтому сценарий отключения будет вызываться только по таймауту

Пробуем

P.S.

Обращаюсь к админам, которым это нужно. Объясните в комментариях, зачем?

0 0 голоса
Оцените статью
Подписаться
Уведомить о
guest
20 комментариев
Межтекстовые Отзывы
Посмотреть все комментарии
Daniel Smith

клиент

Mon Feb 15 17:45:59 2021 SIGUSR1[soft,tls-error] received, process restarting

Mon Feb 15 17:45:59 2021 MANAGEMENT: >STATE:1613393159,RECONNECTING,tls-error,,,,,

Mon Feb 15 17:45:59 2021 Restart pause, 5 second(s)

Mon Feb 15 17:46:04 2021 Outgoing Control Channel Encryption: Cipher ‘AES-256-CTR’ initialized with 256 bit key

Mon Feb 15 17:46:04 2021 Outgoing Control Channel Encryption: Using 256 bit message hash ‘SHA256’ for HMAC authentication

Mon Feb 15 17:46:04 2021 Incoming Control Channel Encryption: Cipher ‘AES-256-CTR’ initialized with 256 bit key

Mon Feb 15 17:46:04 2021 Incoming Control Channel Encryption: Using 256 bit message hash ‘SHA256’ for HMAC authentication

Mon Feb 15 17:46:04 2021 MANAGEMENT: >STATE:1613393164,RESOLVE,,,,,,

Mon Feb 15 17:46:04 2021 TCP/UDP: Preserving recently used remote address: [AF_INET]194.150.235.230:3555

Mon Feb 15 17:46:04 2021 Socket Buffers: R=[65536->65536] S=[65536->65536]

Mon Feb 15 17:46:04 2021 UDP link local: (not bound)

Mon Feb 15 17:46:04 2021 UDP link remote: [AF_INET]194.150.235.230:3555

Mon Feb 15 17:46:04 2021 MANAGEMENT: >STATE:1613393164,WAIT,,,,,,

Mon Feb 15 17:47:04 2021 TLS Error: TLS key negotiation failed to occur within 60 seconds (check your network connectivity)

Mon Feb 15 17:47:04 2021 TLS Error: TLS handshake failed

server

Feb 15 17:46:51 78647 systemd[1]: [email protected]: Main process exited, code=exited, status=1/FAILURE

Feb 15 17:46:51 78647 systemd[1]: [email protected]: Failed with result ‘exit-code’.

Feb 15 17:46:51 78647 systemd[1]: Failed to start OpenVPN connection to server.

Feb 15 17:46:56 78647 systemd[1]: [email protected]: Service hold-off time over, scheduling restart.

Feb 15 17:46:56 78647 systemd[1]: [email protected]: Scheduled restart job, restart counter is at 11403.

Feb 15 17:46:56 78647 systemd[1]: Stopped OpenVPN connection to server.

Feb 15 17:46:56 78647 systemd[1]: Starting OpenVPN connection to server…

Feb 15 17:46:57 78647 ovpn-server[9701]: Options error: —up script fails with ‘/etc/openvpn/connectScript.sh’: No such file or directory (errno=2)

Feb 15 17:46:57 78647 ovpn-server[9701]: Options error: Please correct this error.

Feb 15 17:46:57 78647 ovpn-server[9701]: Use —help for more information.

Feb 15 17:46:57 78647 systemd[1]: [email protected]: Main process exited, code=exited, status=1/FAILURE

Feb 15 17:46:57 78647 systemd[1]: [email protected]: Failed with result ‘exit-code’.

Feb 15 17:46:57 78647 systemd[1]: Failed to start OpenVPN connection to server.

Daniel Smith

понял. попробую запустить обычным пользователем. через каталог home если я правильно понял

Daniel Smith

я смог настроить это у себя. добавив пару строк в конфиг и в скрипт

Daniel Smith

для server config в конце добавил

user root
group root
duplicate-cn
script-security 2
up /etc/openvpn/connectScript.sh
client-connect /etc/openvpn/connectScript.sh
client-disconnect /etc/openvpn/connectScript.sh

скрипт

#!/bin/bash

PERSIST_DIR=/tmp/open
mkdir -p $PERSIST_DIR
chmod -R 777 $PERSIST_DIR
chown -R root:root $PERSIST_DIR

function handle_connect {
CLIENTFILE=$PERSIST_DIR/$common_name
if [ -e "$CLIENTFILE" ]; then
NUMCONN=$(cat $CLIENTFILE)
NEWCONN=$(expr $NUMCONN + 1)
if [ $NEWCONN -gt 1 ]; then exit 1; fi
echo $NEWCONN >$CLIENTFILE
else
echo 1 >$CLIENTFILE
fi
}

function handle_disconnect {
CLIENTFILE=$PERSIST_DIR/$common_name
if [ -e "$CLIENTFILE" ]; then
NUMCONN=$(cat $CLIENTFILE)
NEWCONN=$(expr $NUMCONN - 1)
echo $NEWCONN >$CLIENTFILE
fi
}

case "$script_type" in
 up)
 rm -R $PERSIST_DIR/$common_name
 ;;
 client-connect)
 "handle_connect"
 ;;
 client-disconnect)
 "handle_disconnect"
 ;;
esac

далее в терминале:

chmod 755 connectScript.sh
service openvpn stop
service openvpn start

вот и все.

Daniel Smith

только что проверил получается

Daniel Smith

что бы ключами не делились.

messyjoes

но мы ведь получим тоже самое, если уберём опцию duplicate-cn?

Александр

Ваш скрипт выдавал ошибку

Failed running command (—up/—down): external program exited with error status: 1

изменил

rm -f $PERSIST_DIR/$common_name

на

rm -Rf $PERSIST_DIR/$common_name

И все заработало
Спасибо!

Александр

Эту ошибку

rm: cannot remove ‘/tmp/pDir/’: Is a directory

Александр

Centos 8 на vps

Александр

Наверное, главное что работает