Application: "OpenVPN v2.1/2.4", "EasyRSA", "Bash".
Задача: проработка методики настройки клиентского подключения к сервису "OpenVPN".
Исходим из того, что сервис "OpenVPN" настроен в соответствии с заглавной заметкой этого раздела.
Последовательность дальнейших действий такова:
1. Создание SSL-сертификата и файла конфигурации для клиента "OpenVPN";
2. Автоматизация процесса создания набора клиентских сертификатов и конфигурации;
3. Пример процедуры отзыва клиентского сертификата.
2. Автоматизация процесса создания набора клиентских сертификатов и конфигурации;
3. Пример процедуры отзыва клиентского сертификата.
Создание SSL-сертификата и файла конфигурации для клиента "OpenVPN".
Следующий логичный шаг - в создании уникальных сертификатов для клиентов, подписываемых ранее подготовленным "корневым" сертификатом (тем же, что и сертификат самого сервера "OpenVPN").
Аналогично созданию сертификата сервера, одной командой прогоняем всю цепочку операций создания условно клиентского сертификата:
# cd /etc/openvpn/server/easy-rsa
# ./easyrsa build-client-full usernameOne nopass
# ./easyrsa build-client-full usernameOne nopass
Просматриваем содержимое приватной и публичной части полученного клиентского сертификата:
# openssl rsa -noout -text -in ./pki/private/usernameOne.key | less
# openssl x509 -noout -text -in ./pki/issued/usernameOne.crt | less
# openssl x509 -noout -text -in ./pki/issued/usernameOne.crt | less
Копируем в выделенное место нужные клиенту сертификаты:
# mkdir -p /etc/openvpn/server/clients/usernameOne
# cp /etc/openvpn/server/easy-rsa/pki/ca.crt /etc/openvpn/server/clients/usernameOne
# cp /etc/openvpn/server/easy-rsa/pki/ta.key /etc/openvpn/server/clients/usernameOne
# cp /etc/openvpn/server/easy-rsa/pki/issued/usernameOne.key.crt /etc/openvpn/server/clients/usernameOne
# cp /etc/openvpn/server/easy-rsa/pki/private/usernameOne.key.key /etc/openvpn/server/clients/usernameOne
# cp /etc/openvpn/server/easy-rsa/pki/ca.crt /etc/openvpn/server/clients/usernameOne
# cp /etc/openvpn/server/easy-rsa/pki/ta.key /etc/openvpn/server/clients/usernameOne
# cp /etc/openvpn/server/easy-rsa/pki/issued/usernameOne.key.crt /etc/openvpn/server/clients/usernameOne
# cp /etc/openvpn/server/easy-rsa/pki/private/usernameOne.key.key /etc/openvpn/server/clients/usernameOne
Конфигурация клиента описывается единственным файлом, во многом повторяющим настройки сервера:
# vi /etc/openvpn/server/clients/usernameOne/usernameOne.ovpn
# Включаем режим работы в качестве клиента VPN:
client
# Включаем режим IP-туннелирования "Layer 3":
dev tun
# Указываем протокол и адрес, на котором VPN-сервер будет принимать подключения
# (намеренно используем порт "для сайтов", чтобы дать клиентам возможность проходить
# из зашоренных корпоративных локальных сетей через защитные экраны и прокси):
proto tcp
remote ovpn.example.net 443
# Указываем месторасположение SSL-сертификатов:
ca ca.crt
cert usernameOne.crt
key usernameOne.key
# Включаем предварительную простую HMAC-аутентификацию при инициировании соединения:
key-direction 1
tls-auth ta.key 0
# Включаем сверку имени VPN-сервера с указанным в SSL-сертификате
remote-cert-tls server
# Включаем шифрование чуть более высокого относительно стандартного уровня:
cipher AES-256-CBC
# Включаем сжатие трафика между клиентом и сервером:
comp-lzo
client
# Включаем режим IP-туннелирования "Layer 3":
dev tun
# Указываем протокол и адрес, на котором VPN-сервер будет принимать подключения
# (намеренно используем порт "для сайтов", чтобы дать клиентам возможность проходить
# из зашоренных корпоративных локальных сетей через защитные экраны и прокси):
proto tcp
remote ovpn.example.net 443
# Указываем месторасположение SSL-сертификатов:
ca ca.crt
cert usernameOne.crt
key usernameOne.key
# Включаем предварительную простую HMAC-аутентификацию при инициировании соединения:
key-direction 1
tls-auth ta.key 0
# Включаем сверку имени VPN-сервера с указанным в SSL-сертификате
remote-cert-tls server
# Включаем шифрование чуть более высокого относительно стандартного уровня:
cipher AES-256-CBC
# Включаем сжатие трафика между клиентом и сервером:
comp-lzo
Теперь передаём сертификаты и файл конфигурации клиенту, который применяет их на своей стороне.
Пример запуска клиента "OpenVPN" с указанием конкретного конфигурационного файла:
# openvpn --config ./usernameOne.ovpn --verb 3
Автоматизация создания набора клиентских сертификатов и конфигурации.
В современных версиях клиентов "OpenVPN" реализована поддержка включения x509-сертификатов в тело конфигурационного файла. Таким образом пользователю достаточно передать всего один файл с типовым расширением ".ovpn", чтобы предоставить ему возможность подключения к сервису.
Для пользователя это действительно многократно упрощает подключения, а нам придётся озаботится автоматизацией рутинных процедур сборки всего необходимого в единый конфигурационный пакет.
Установим APT-пакет с архиватором:
# apt-get install zip
Напишем простенький bash-скрипт, создающий нового (или обновляющий существующего) пользователя сервиса "OpenVPN", собирающего сертификаты и конфигурацию в единый пакет:
# mkdir -p /etc/openvpn/server/clients
# vi /etc/openvpn/server/clients/make-client.sh
# vi /etc/openvpn/server/clients/make-client.sh
#!/bin/bash
# Принимаем аргументы запроса
CLIENTNAME="${1}"
# Проверяем наличие необходимых входящих переменных
[ -z "${CLIENTNAME}" -o -z "${CLIENTNAME}" ] && { echo "Usage: $(basename $0) clientname"; exit 1; }
# Используемые ресурсы
KEYSDIR="/etc/openvpn/server/easy-rsa/pki"
CLIENTDIR="/etc/openvpn/server/clients/${CLIENTNAME}"
LOG="/var/log/openvpn/make-client.log
DATE=$(date +'%Y%m%dT%H%M%S')
# Переходим в директорию "EeasyRSA"
cd /etc/openvpn/server/easy-rsa
# Проверяем наличие сертификата для указанного имени клиента
./easyrsa show-cert "${CLIENTNAME}" 1>/dev/null 2>&1
# Прерываем работу в случае обнаружения сертификата для указанного имени клиента
[ "${?}" -eq "0" ] && { echo "Certificate for this client already exists!"; exit 1; }
# Запрашиваем создание клиентских сертификатов
echo "${DATE}" >> "${LOG}"
./easyrsa build-client-full "${CLIENTNAME}" nopass 1>>"${LOG}" 2>&1
# Прерываем работу в случае сбоя создания сертификатов
[ "${?}" -ne "0" ] && { echo "Certificate creation failed!"; exit 1; }
# Копируем в выделенное место нужные клиенту сертификаты
mkdir -p "${CLIENTDIR}"
cp "${KEYSDIR}/ca.crt" "${CLIENTDIR}"
cp "${KEYSDIR}/ta.key" "${CLIENTDIR}"
cp "${KEYSDIR}/issued/${CLIENTNAME}.crt" "${CLIENTDIR}"
cp "${KEYSDIR}/private/${CLIENTNAME}.key" "${CLIENTDIR}"
# Создаём клиентский файл конфигурации
cat << EOF > "${CLIENTDIR}/${CLIENTNAME}.ovpn"
client
dev tun
proto tcp
remote ovpn.example.net 443
;ca ca.crt
;cert ${CLIENTNAME}.crt
;key ${CLIENTNAME}.key
;tls-auth ta.key 0
key-direction 1
cipher AES-256-CBC
remote-cert-tls server
comp-lzo
EOF
# Дополняем конфигурацию включением содержимого сертификатов и ключей
echo "<ca>" >> "${CLIENTDIR}/${CLIENTNAME}.ovpn"
sed -n '/BEGIN CERTIFICATE/,/END CERTIFICATE/p' < "${KEYSDIR}/ca.crt" >> "${CLIENTDIR}/${CLIENTNAME}.ovpn"
echo -e "</ca>\n<cert>" >> "${CLIENTDIR}/${CLIENTNAME}.ovpn"
sed -n '/BEGIN CERTIFICATE/,/END CERTIFICATE/p' < "${KEYSDIR}/issued/${CLIENTNAME}.crt" >> "${CLIENTDIR}/${CLIENTNAME}.ovpn"
echo -e "</cert>\n<key>" >> "${CLIENTDIR}/${CLIENTNAME}.ovpn"
sed -n '/BEGIN PRIVATE KEY/,/END PRIVATE KEY/p' < "${KEYSDIR}/private/${CLIENTNAME}.key" >> "${CLIENTDIR}/${CLIENTNAME}.ovpn"
echo -e "</key>\n<tls-auth>" >> "${CLIENTDIR}/${CLIENTNAME}.ovpn"
sed -n '/BEGIN OpenVPN Static key V1/,/END OpenVPN Static key V1/p' < "${KEYSDIR}/ta.key" >> "${CLIENTDIR}/${CLIENTNAME}.ovpn"
echo "</tls-auth>" >> "${CLIENTDIR}/${CLIENTNAME}.ovpn"
# Пакуем набор клиентских файлов в архив, для удобства передачи
cd "${CLIENTDIR}"
zip ${CLIENTNAME}.zip ca.crt ta.key ${CLIENTNAME}.crt ${CLIENTNAME}.key ${CLIENTNAME}.ovpn
exit $?
# Принимаем аргументы запроса
CLIENTNAME="${1}"
# Проверяем наличие необходимых входящих переменных
[ -z "${CLIENTNAME}" -o -z "${CLIENTNAME}" ] && { echo "Usage: $(basename $0) clientname"; exit 1; }
# Используемые ресурсы
KEYSDIR="/etc/openvpn/server/easy-rsa/pki"
CLIENTDIR="/etc/openvpn/server/clients/${CLIENTNAME}"
LOG="/var/log/openvpn/make-client.log
DATE=$(date +'%Y%m%dT%H%M%S')
# Переходим в директорию "EeasyRSA"
cd /etc/openvpn/server/easy-rsa
# Проверяем наличие сертификата для указанного имени клиента
./easyrsa show-cert "${CLIENTNAME}" 1>/dev/null 2>&1
# Прерываем работу в случае обнаружения сертификата для указанного имени клиента
[ "${?}" -eq "0" ] && { echo "Certificate for this client already exists!"; exit 1; }
# Запрашиваем создание клиентских сертификатов
echo "${DATE}" >> "${LOG}"
./easyrsa build-client-full "${CLIENTNAME}" nopass 1>>"${LOG}" 2>&1
# Прерываем работу в случае сбоя создания сертификатов
[ "${?}" -ne "0" ] && { echo "Certificate creation failed!"; exit 1; }
# Копируем в выделенное место нужные клиенту сертификаты
mkdir -p "${CLIENTDIR}"
cp "${KEYSDIR}/ca.crt" "${CLIENTDIR}"
cp "${KEYSDIR}/ta.key" "${CLIENTDIR}"
cp "${KEYSDIR}/issued/${CLIENTNAME}.crt" "${CLIENTDIR}"
cp "${KEYSDIR}/private/${CLIENTNAME}.key" "${CLIENTDIR}"
# Создаём клиентский файл конфигурации
cat << EOF > "${CLIENTDIR}/${CLIENTNAME}.ovpn"
client
dev tun
proto tcp
remote ovpn.example.net 443
;ca ca.crt
;cert ${CLIENTNAME}.crt
;key ${CLIENTNAME}.key
;tls-auth ta.key 0
key-direction 1
cipher AES-256-CBC
remote-cert-tls server
comp-lzo
EOF
# Дополняем конфигурацию включением содержимого сертификатов и ключей
echo "<ca>" >> "${CLIENTDIR}/${CLIENTNAME}.ovpn"
sed -n '/BEGIN CERTIFICATE/,/END CERTIFICATE/p' < "${KEYSDIR}/ca.crt" >> "${CLIENTDIR}/${CLIENTNAME}.ovpn"
echo -e "</ca>\n<cert>" >> "${CLIENTDIR}/${CLIENTNAME}.ovpn"
sed -n '/BEGIN CERTIFICATE/,/END CERTIFICATE/p' < "${KEYSDIR}/issued/${CLIENTNAME}.crt" >> "${CLIENTDIR}/${CLIENTNAME}.ovpn"
echo -e "</cert>\n<key>" >> "${CLIENTDIR}/${CLIENTNAME}.ovpn"
sed -n '/BEGIN PRIVATE KEY/,/END PRIVATE KEY/p' < "${KEYSDIR}/private/${CLIENTNAME}.key" >> "${CLIENTDIR}/${CLIENTNAME}.ovpn"
echo -e "</key>\n<tls-auth>" >> "${CLIENTDIR}/${CLIENTNAME}.ovpn"
sed -n '/BEGIN OpenVPN Static key V1/,/END OpenVPN Static key V1/p' < "${KEYSDIR}/ta.key" >> "${CLIENTDIR}/${CLIENTNAME}.ovpn"
echo "</tls-auth>" >> "${CLIENTDIR}/${CLIENTNAME}.ovpn"
# Пакуем набор клиентских файлов в архив, для удобства передачи
cd "${CLIENTDIR}"
zip ${CLIENTNAME}.zip ca.crt ta.key ${CLIENTNAME}.crt ${CLIENTNAME}.key ${CLIENTNAME}.ovpn
exit $?
Очевидно, что для создания новой "учётной записи" клиента "OpenVPN" нужно будет запустить скрипт с единственным аргументом:
# /etc/openvpn/server/clients/make-client.sh usernameOne
Результат работы скрипта ищем в директории "/etc/openvpn/server/clients/".
Отзыв клиентского сертификата.
Учитывая то, что аутентификация в "OpenVPN" базируется на x509-сертификатах, единственный способ запретить доступ к сервису определённому пользователю - отзыв сертификата такового.
Переходим в директорию настроенных в заглавной заметке скриптов "Easy-RSA":
# cd /etc/openvpn/server/easy-rsa
Запускаем скрипт, отзывающий сертификат указанного пользователя:
# ./easyrsa revoke usernameOne
Запускаем скрипт, обновляющий список отозванных сертификатов, который проверяет сервер "OpenVPN" на этапе аутентификации подключающегося клиента:
# ./easyrsa gen-crl