Initial release
commit
9564f3e870
|
@ -0,0 +1,13 @@
|
|||
# logon/logoff скрипты для VPN сервера ocserv
|
||||
|
||||
- ocserv_logon.sh - скрипт выполняется сервером посчле авторизации пользователя. Формирует журнал с данными сессии и проверяет код страны через GeoIP и на основе пропускает дальше или нет
|
||||
- ocserv_logout.sh - запускается при окончании пользовательской сессии и пишет данные в лог.
|
||||
|
||||
## Использование
|
||||
|
||||
Для использования скрипты компируются в любое удобное место и прописываются в конфиге "/etc/ocserv/ocserv.conf"
|
||||
|
||||
```
|
||||
connect-script = /usr/local/bin/ocserv_logon.sh
|
||||
disconnect-script = /usr/local/bin/ocserv_logout.sh
|
||||
```
|
|
@ -0,0 +1,141 @@
|
|||
#!/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
|
|
@ -0,0 +1,65 @@
|
|||
#!/usr/bin/bash
|
||||
# Ocserv logout script for sending statistics into log
|
||||
#
|
||||
#################################################################################
|
||||
# Автор: Сергей Калинин
|
||||
# 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
|
||||
# STATS_BYTES_IN,
|
||||
# STATS_BYTES_OUT, STATS_DURATION
|
||||
|
||||
LOG_DIR="/var/log/ocserv"
|
||||
LOG_FILE=${LOG_DIR}/sessions.log
|
||||
# Format out string text, json
|
||||
LOG_FORMAT="json"
|
||||
|
||||
if [ ! -d "$LOG_DIR" ]; then
|
||||
mkdir -p ${LOG_DIR}
|
||||
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
|
||||
|
||||
if [ ${LOG_FORMAT} == 'text' ]; then
|
||||
OUT_STRING="${DATE} ${USERNAME} ${REASON} ${ID} ${STATS_BYTES_IN} ${STATS_BYTES_OUT} ${STATS_DURATION}"
|
||||
fi
|
||||
|
||||
if [ ${LOG_FORMAT} == 'json' ]; then
|
||||
OUT_STRING="{\"session-datetime\": \"${DATE}\", \"reason\": \"${REASON}\", \"remote-user\": \"${SHORT_USER_NAME}\", \
|
||||
\"session-id\": \"${ID}\", \"duration\": ${STATS_DURATION}, \"in_bytes\": ${STATS_BYTES_IN}, \"out_bytes\": ${STATS_BYTES_OUT}}"
|
||||
fi
|
||||
|
||||
echo "${OUT_STRING}" >> ${LOG_FILE}
|
Loading…
Reference in New Issue