Как то понадобилось настроить ВПН сервер с максимально жестокими политиками доступа: авторизация по ключу - для каждого юзера отдельного, авторизация по паре логин+пароль. причем ключ и пара логин+пароль у каждого юзера строго индивидуальны. стал рыть маны, искать статьи на сайте в основном делал по статье поэтому не буду пересказывать как ставить и настраивать, как генерить ключи (по статье сам лично разобрался, разумеется не без пива =))
А расскажу лучше про фишки OpenVPN. Вот выдержка из мана:
--auth-user-pass-verify script method Require the client to provide a username/password (possibly in addition to a client certificate) for authentication.
OpenVPN will execute script as a shell command to validate the username/password provided by the client.
If method is set to "via-env", OpenVPN will call script with the environmental variables username and password set to the user- name/password strings provided by the client. Be aware that this method is insecure on some platforms which make the envi- ronment of a process publicly visible to other unprivileged pro- cesses.
If method is set to "via-file", OpenVPN will write the username and password to the first two lines of a temporary file. The filename will be passed as an argument to script, and the file will be automatically deleted by OpenVPN after the script re- turns. The location of the temporary file is controlled by the --tmp-dir option, and will default to the current directory if unspecified. For security, consider setting --tmp-dir to a volatile storage medium such as /dev/shm (if available) to pre- vent the username/password file from touching the hard drive.
The script should examine the username and password, returning a success exit code (0) if the client's authentication request is to be accepted, or a failure code (1) to reject the client.
This directive is designed to enable a plugin-style interface for extending OpenVPN's authentication capabilities.
To protect against a client passing a maliciously formed user- name or password string, the username string must consist only of these characters: alphanumeric, underbar ('_'), dash ('-'), dot ('.'), or at ('@'). The password string can consist of any printable characters except for CR or LF. Any illegal charac- ters in either the username or password string will be converted to underbar ('_').
Care must be taken by any user-defined scripts to avoid creating a security vulnerability in the way that these strings are han- dled. Never use these strings in such a way that they might be escaped or evaluated by a shell interpreter.
Смысл в следующем: есть возможность запускать в дополнение авторизации по ключам отдельный пользовательский скрипт для авторизации, и передавать ему логин пасс либо через переменные окружения (via-env), либо через файл (via-file). Скрипт после проверки должен завершатся либо с кодом 0 - проверка успешна, либо с кодом 1 - сбой авторизации Сразу скажу что в логине можно использовать только буквы латинского алфавита, цифры, ('_'), ('-'), ('.'), ('@'). (про русские имена пользователей можно СРАЗУ ЗАБЫТЬ!)
Я не стал передавать параметры через файл - потенциальная дырка, а передал через переменные окружения (via-env)
Не стану выкладывать полный код (писался для довольно специфичной базы), приведу лишь выдержку которой вполне хватит для того чтобы разобратся как дальше дописать под себя
#!/usr/local/bin/php
<?php
$host="localhost";
$user="db_user";
$pass="db_pass";
$db_name="db_name";
mysql_connect($host,$user,$pass) OR DIE("Не могу прислюнявица к мускулу!");
mysql_select_db($db_name) or die(mysql_error());
mysql_query("SET NAMES koi8r");
mysql_query("SET CHARSET koi8r");
mysql_query("SET collation_connection = koi8r_general_ci");
mysql_query("SET collation_database = koi8r_general_ci");
mysql_query("SET collation_database = koi8r_general_ci");
mysql_query("SET character_set_client = koi8r");
mysql_query("SET character_set_connection = koi8r");
mysql_query("SET character_set_database = koi8r");
mysql_query("SET character_set_results = koi8r");
$login = getenv("username"); // получаем логин
$pass = getenv("password"); // получаем пасс
$cn = getenv("common_name"); // получаем имя сертификата под которым юзер пытается войти
if (($login != $pass) && ($login !="") && ($pass !=""))
{
$res = mysql_query('select * from `vpn` where `login`="'.$login.'" and `enabled`=1');
if (mysql_num_rows($res) == 1)
{
$row = mysql_fetch_array($res);
if (($row['pass'] == $pass) && ($login== $cn)) { exit(0); }
#порт на котором работает сервер
port 23
# протокол - советую udp
proto udp
# - используемый тип устройства и номер
dev tun0
#указываем файл CA
ca /usr/local/etc/openvpn/keys/ca.crt
#указываем файл с сертификатом сервера
cert /usr/local/etc/openvpn/keys/server.crt
#указываем файл с ключем сервера
key /usr/local/etc/openvpn/keys/server.key
#указываем файл Диффи Хельман
dh /usr/local/etc/openvpn/keys/dh1024.pem
#задаем IP-адрес сервера и маску подсети
# (виртуальной сети) - можно произвольную, (я выбрал такую)
server 172.16.250.0255.255.255.0
#задаем МАРШРУТ который передаём клиентту
# и маску подсети для того чтобы он "видел"
# сеть за опенвпн сервером (сеть 192.168.0.0/24)
push "route 192.168.0.0255.255.255.0"
push "route 192.168.10.0255.255.255.0"
push "route 192.168.20.0255.255.255.0"
# указываем где хранятся файлы с
# настройками IP-адресов клиентов
client-config-dir ccd
# добавляем маршрут сервер-клиент
route 172.16.250.0255.255.255.252
# включаем TLS аутификацию
tls-server
# указываем tls-ключ, и указываем 0 для сервера, а 1 для клиента
tls-auth keys/ta.key 0
# таймаут до реконекта
tls-timeout 120
auth MD5 #
# включаем шифрацию пакетов
cipher BF-CBC
keepalive 10120
# сжатие трафика
comp-lzo
# максимум клиентов
max-clients 100
user nobody
group nobody
# Не перечитывать ключи после получения
# SIGUSR1 или ping-restart
persist-key
# Не закрывать и переоткрывать TUN\TAP
# устройство, после получения
# SIGUSR1 или ping-restart
persist-tun
# логгирование (не забудьте создать эту дирректорию /var/log/openvpn/)
status /var/log/openvpn/openvpn-status.log
log /var/log/openvpn/openvpn.log
# Уровень информации для отладки
verb 3
auth-user-pass-verify /usr/local/bin/vpn_check via-env
# ВОТ ОНА СТРОКА ДЛЯ СКРИПТА АВТОРИЗАЦИИ
конфиг клиента:
dev tun
proto udp
remote vpn.mydomain.ru
port 23
client
resolv-retry infinite
ca ca.crt
cert client.crt
key client.key
tls-client
tls-auth ta.key 1
auth MD5
cipher BF-CBC
ns-cert-type server
comp-lzo
persist-key
persist-tun
verb 3
auth-user-pass
все остальное делал по статье, добавил скриптик для упрощения генерации ключей, админку прикрутил на пыхе, поднял nginx - и жить стало легче! P.S. сервер работает не первый месяц в продакшне - нестабильности не выявил =)