ocserv_script/ocserv_logon.sh

141 lines
6.4 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#!/usr/bin/bash
#################################################################################
#
# Logon-скрипт для ocserv.
#
# На основе переменных передаваемых ocserv и географических
# данных формирует файл-журнал с данными пользовательских сессий
#
#################################################################################
# Автор: Сергей Калинин
# https://nuk-svk.ru
# svk@nuk-svk.ru
#################################################################################
# Список переменных:
# REASON, VHOST, USERNAME, GROUPNAME, DEVICE, IP_REAL (the real IP of the client),
# IP_REAL_LOCAL (the local interface IP the client connected), IP_LOCAL
# (the local IP in the P-t-P connection), IP_REMOTE (the VPN IP of the client),
# IPV6_LOCAL (the IPv6 local address if there are both IPv4 and IPv6
# assigned), IPV6_REMOTE (the IPv6 remote address), IPV6_PREFIX, and
# ID (a unique numeric ID); REASON may be "connect" or "disconnect".
# In addition the following variables OCSERV_ROUTES (the applied routes for this
# client), OCSERV_NO_ROUTES, OCSERV_DNS
LOG_DIR="/var/log/ocserv"
LOG_FILE=${LOG_DIR}/sessions.log
# Формат выходной строки (text, json)
LOG_FORMAT="json"
# Коды стран разрешённые к соединению
# можно передать ввиде списка "RU SA IC TW"
ALLOW_COUNTRY_CODES="RU"
if [ ! -d "$LOG_DIR" ]; then
mkdir -p ${LOG_DIR}
fi
# Получаем географические данные по IP адресу, вернет строку вида:
#109.106.141.24,RU,Russia,VOR,Voronezhskaya Oblast',Voronezh,394000,Europe/Moscow,51.6592,39.2269,0
# можно получать в json - "curl -s https://freegeoip.live/json/${IP_REAL}"
GEO_DATA=`curl --connect-timeout 5 -s https://freegeoip.live/csv/${IP_REAL}`
if [ -z "${GEO_DATA}" ]; then
COUNTRY_CODE="RU"
LAT="0"
LON="0"
else
# Выбираем код страны и координаты
COUNTRY_CODE=`echo ${GEO_DATA} | cut -d"," -f 2`
LAT=`echo ${GEO_DATA} | cut -d"," -f 9`
LON=`echo ${GEO_DATA} | cut -d"," -f 10`
fi
DATE=`date +'%d.%m.%Y %T'`
# Преобразуем имена пользователей к нижнему регистру
USER_NAME=`echo ${USERNAME} | tr '[:upper:]' '[:lower:]'`
# Проверяем имя пользователя на имя домена,
# сперва в формате "user@domain" потом "domain\user" \\domain\user
# и выдергиваем только имя пользователя
TEMP_USER_NAME=`echo ${USER_NAME} | egrep -E "[[:alnum:]]+@" -o | tr -d "@"`
if [ -n "${TEMP_USER_NAME}" ]; then
SHORT_USER_NAME="${TEMP_USER_NAME}"
else
TEMP_USER_NAME=`echo $USER_NAME | awk -F '\\' '{print $2}'`
if [ -n "${TEMP_USER_NAME}" ]; then
SHORT_USER_NAME="${TEMP_USER_NAME}"
else
TEMP_USER_NAME=`echo $USER_NAME | awk -F '\\' '{print $4}'`
if [ -n "${TEMP_USER_NAME}" ]; then
SHORT_USER_NAME="${TEMP_USER_NAME}"
else
SHORT_USER_NAME="${USER_NAME}"
fi
fi
fi
# Проверяем что ocserv вернул нам реальный ip адрес (откуда пользователь заходит)
# если адреса нет - в соединении отказываем
# И соответствующим образом формируем строку для журнала в нужном формате
if [ "x${IP_REAL}" = "x" ]; then
if [ ${LOG_FORMAT} == 'json' ]; then
OUT_STRING="{\"session-datetime\": \"${DATE}\", \"reason\": \"empty_real_ip\", \"remote-user\": \"${SHORT_USER_NAME}\", \
\"remote-user-group\": \"${GROUPNAME}\", \"session-id\": \"${ID}\", \
\"country_code\": \"${COUNTRY_CODE}\", \"location\": {\"lat\": ${LAT},\"lon\": ${LON}}}"
else
OUT_STRING="${DATE} ${SHORT_USER_NAME} \"Empty real IP address\" ${ID} ${VHOST} ${DEVICE} ${IP_REAL} ${IP_REAL_LOCAL} \
${IP_LOCAL} ${IP_REMOTE} ${OCSERV_ROUTES} ${OCSERV_NO_ROUTES} ${OCSERV_DNS} ${COUNTRY_CODE}"
fi
echo "${OUT_STRING}" >> ${LOG_FILE}
exit 1
fi
# Формируем выходную строку, для раазрешенного соединения, в нужном формате
if [ ${LOG_FORMAT} == 'json' ]; then
OUT_STRING="{\"session-datetime\": \"${DATE}\", \"reason\": \"${REASON}\", \"remote-user\": \"${SHORT_USER_NAME}\", \
\"remote-user-group\": \"${GROUPNAME}\", \"session-id\": \"${ID}\", \"vhost\": \"${VHOST}\", \"device\": \"${DEVICE}\", \
\"real-ip\": \"${IP_REAL}\", \"real-local-ip\": \"${IP_REAL_LOCAL}\", \"local-ip\": \"${IP_LOCAL}\", \"remote-ip\": \"${IP_REMOTE}\", \
\"ocserv-routes\": \"${OCSERV_ROUTES}\", \"ocserv-no-routes\": \"${OCSERV_NO_ROUTES}\", \"ocserv-dns\": \"${OCSERV_DNS}\", \
\"country_code\": \"${COUNTRY_CODE}\", \"location\": {\"lat\": ${LAT},\"lon\": ${LON}}}"
else
OUT_STRING="${DATE} ${SHORT_USER_NAME} ${REASON} ${ID} ${VHOST} ${DEVICE} ${IP_REAL} ${IP_REAL_LOCAL} \
${IP_LOCAL} ${IP_REMOTE} ${OCSERV_ROUTES} ${OCSERV_NO_ROUTES} ${OCSERV_DNS} ${COUNTRY_CODE}"
fi
# Если значение COUNTRY_CODE пустое (e.g. RFC 1918 addresses) то
if [ "x${COUNTRY_CODE}" = "x" ]; then
echo "${OUT_STRING}" >> ${LOG_FILE}
# Разрешаем соединение
exit 0
# Запрещаем соединение
# exit 1
fi
# Если COUNTRY_CODE совпадает с одним из разрешенных то пишем в лог
# и благополучно завершаем скрипт
for c in $ALLOW_COUNTRY_CODES; do
if [ "${c}" = "${COUNTRY_CODE}" ]; then
echo "${OUT_STRING}" >> ${LOG_FILE}
exit 0
fi
done
# Если COUNTRY_CODE не совпадает с разрешенным то даём отлуп
# И пишем о сём факте в лог
if [ ${LOG_FORMAT} == 'json' ]; then
OUT_STRING="{\"session-datetime\": \"${DATE}\", \"reason\": \"not_allowed_country_code\", \"remote-user\": \"${SHORT_USER_NAME}\", \
\"remote-user-group\": \"${GROUPNAME}\", \"session-id\": \"${ID}\", \"real-ip\": \"${IP_REAL}\", \
\"country_code\": \"${COUNTRY_CODE}\", \"location\": {\"lat\": ${LAT},\"lon\": ${LON}}}"
else
OUT_STRING="${DATE} ${SHORT_USER_NAME} \"Not allowed country code\" ${ID} ${VHOST} ${DEVICE} ${IP_REAL} ${IP_REAL_LOCAL} \
${IP_LOCAL} ${IP_REMOTE} ${OCSERV_ROUTES} ${OCSERV_NO_ROUTES} ${OCSERV_DNS} ${COUNTRY_CODE}"
fi
echo "${OUT_STRING}" >> ${LOG_FILE}
exit 1