Настройка аутентификации NGINX через LDAP с помощью модуля SPNEGO

Обновлено Обновлено: Опубликовано Опубликовано:

Используемые термины: NGINXActive Directory.

Модуль SPNEGO для NGINX — это программный компонент для возможности прохождения аутентификации (Single Sign-On или SSO) через сервер LDAP. В данной инструкции мы рассмотрим процесс его установки и настройки. В качестве сервера LDAP будем использовать Active Directory. Процесс будет рассмотрен для систем Ubuntu/Debian и CentOS.

Подготовка системы

Для корректной работы нашего веб-сервера необходимо:

  1. Задать имя серверу.
  2. Настроить синхронизацию времени.
  3. Настроить брандмауэр.

Рассмотрим настройку по шагам.

1. Имя сервера

В процессе настройки аутентификации через LDAP нам необходимо будет задать в качестве принципала имя нашего сервера:

hostnamectl set-hostname nginx.domain.local

* предполагается, что в нашем случае имя сервера будет nginx.domain.local (домен domain.local).

2. Настройка времени

Для работы с LDAP нам необходимо, чтобы время на последнем совпадало с временем на нашем веб-сервере. Самый правильный способ этого добиться — настроить синхронизацию.

Для начала настраиваем временную зону:

timedatectl set-timezone Europe/Moscow

* в данном примере мы задаем зону по московскому времени. Список все доступных зон можно посмотреть командой timedatectl list-timezones.

Устанавливаем утилиту для синхронизации времени, настраиваем ее, разрешаем запуск демона и стартуем его. Набор команд будет зависеть от дистрибутива Linux.

а) если на системе Ubuntu / Debian:

apt install chrony

vi /etc/chrony/chrony.conf

...
pool domain.local
# pool ...
# pool ...
# pool ...
...

* в данном примере мы указали в качестве сервера синхронизации любой контроллер домена. Остальные настройки pool необходимо закомментировать.

systemctl enable chrony

systemctl restart chrony

б) если на системе CentOS / Red Hat:

yum install chrony

vi /etc/chrony.conf

...
server domain.local
# server ...
# server ...
# server ...
...

* в данном примере мы указали в качестве сервера синхронизации любой контроллер домена. Остальные настройки pool необходимо закомментировать.

systemctl enable chronyd --now

3. Настройка безопасности

Для корректной работы нашего веб-сервера необходимо открыть порты http и https. Действия будут отличаться в зависимости от используемого брандмауэра.

а) Iptables (как правило, на Ubuntu/Debian или ранних версиях CentOS):

iptables -I INPUT -p tcp --match multiport --dports 80,443 -j ACCEPT

Для сохранения правил устанавливаем iptables-persistent и запускаем утилиту:

apt install iptables-persistent

netfilter-persistent save

б) Firewalld (как правило, на поздних версиях CentOS):

firewall-cmd --permanent --add-service=http{,s}

firewall-cmd --reload

Также на системах с активированным SELinux (как правило, )

setenforce 0

sed -i 's/^SELINUX=.*/SELINUX=disabled/g' /etc/selinux/config

Сборка и установка NGINX с модулем SPNEGO

Встроенных средств NGINX недостаточно для реализации нашей задачи, поэтому необходимо использовать бесплатный модуль SPNEGO. Мы можем выполнить это двумя методами:

  1. Собрать NGINX с добавлением модуля.
  2. Собрать динамический модуль SPNEGO и подключить его к уже работающему NGINX.

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

Сборка NGINX с модулем SPNEGO

Выполняем сборку в несколько этапов. Разберем их по очереди:

1. Установка зависимостей

Для сборки нам нужны пакеты, от которых зависит процесс конфигурирования. В зависимости от операционной системы, команды будут отличаться.

а) для Ubuntu/Debian:

apt update

apt install curl git build-essential libpcre++-dev zlib1g-dev libkrb5-dev libssl-dev libxslt-dev libgd-dev

б) для CentOS:

yum install epel-release

yum install curl git pcre-devel openssl-devel libxml2-devel libxslt-devel gd-devel perl-ExtUtils-Embed gperftools-devel

2. Загрузка исходников

Загрузим исходник для nginx и модуля SPNEGO.

Переходим на страницу загрузки nginx и копируем ссылку на нужную версию веб-сервера:

Скачиваем ссылку на исходник NGINX

* в данном примере мы будем загружать nginx версии 1.20.0.

С помощью скопированной ссылки, загружаем исходник веб-сервера:

curl -kOL https://nginx.org/download/nginx-1.20.0.tar.gz

После распаковываем его:

tar -zxf nginx-*.tar.gz

Переходим в распакованную папку:

cd nginx-*/

Клонируем репозиторий для модуля SPNEGO:

git clone https://github.com/stnoonan/spnego-http-auth-nginx-module.git

Мы готовы к сборке.

3. Сборка и установка пакета

Для разных систем мы выполним разные команды конфигурирования пакета.

а) на Ubuntu/Debian:

./configure --prefix=/usr/share/nginx --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-compat --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_xslt_module=dynamic --with-stream=dynamic --with-stream_ssl_module --with-mail=dynamic --with-mail_ssl_module --add-module=spnego-http-auth-nginx-module

б) на Centos:

./configure --prefix=/usr/share/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/client_body --http-proxy-temp-path=/var/lib/nginx/proxy --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --http-scgi-temp-path=/var/lib/nginx/scgi --pid-path=/run/nginx.pid --lock-path=/run/lock/subsys/nginx --user=nginx --group=nginx --with-file-aio --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-stream_ssl_preread_module --with-http_addition_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_slice_module --with-http_stub_status_module --with-http_perl_module=dynamic --with-http_auth_request_module --with-mail=dynamic --with-mail_ssl_module --with-pcre --with-pcre-jit --with-stream=dynamic --with-stream_ssl_module --with-google_perftools_module --with-debug --add-module=spnego-http-auth-nginx-module

Собираем пакет:

make

Выполняем установку:

make install

4. Завершение настройки системы

Чтобы nginx мог корректно запуститься, выполним несколько предварительных действий.

Создадим пользователя nginx:

useradd --no-create-home nginx

Создадим каталог /var/lib/nginx:

mkdir -p /var/lib/nginx

Проверим, что nginx  проходит проверку конфигурационного файла:

nginx -t

Мы должны увидеть:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

5. Создаем юнит в systemd и стартуем сервис

Для запуска nginx в качестве сервиса, создаем файл:

vi /lib/systemd/system/nginx.service

[Unit]
Description=A high performance web server and a reverse proxy server
Documentation=man:nginx(8)
After=network.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;'
ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;'
ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload
ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid
TimeoutStopSec=5
KillMode=mixed
Restart=on-failure

[Install]
WantedBy=multi-user.target

Перечитываем конфигурационные файлы в systemd:

systemctl daemon-reload

Разрешаем автозапуск сервиса и стартуем его:

systemctl enable nginx 

systemctl start nginx

Сборка и подключение динамического модуля

Данный способ немного отличается по действиям и конфигурированию, но суть процесса та же. Рассмотрим его по шагам.

1. Установка NGINX

Предполагается, что nginx установлен в системе. Иначе, установку можно выполнить из репозитория в зависимости от дистрибутива Linux.

а) Для Ubuntu/Debian:

apt update

apt install nginx

б) Для CentOS:

yum install epel-release

yum install nginx

Запускаем NGINX и разрешаем автостарт сервиса:

systemctl start nginx

systemctl enable nginx

2. Установка зависимостей

Для сборки нам нужны пакеты, от которых зависит процесс конфигурирования. В зависимости от операционной системы, команды будут отличаться.

а) для Ubuntu/Debian:

apt install curl git build-essential libpcre++-dev zlib1g-dev libkrb5-dev libssl-dev libxslt-dev libgd-dev

б) для CentOS:

yum install curl git pcre-devel openssl-devel libxml2-devel libxslt-devel gd-devel perl-ExtUtils-Embed gperftools-devel redhat-rpm-config

3. Загрузка исходников

Загрузим исходник для nginx и модуля SPNEGO.

Для начала, смотрим версию установленного NGINX:

nginx -v

Переходим на страницу загрузки nginx и копируем ссылку на установленную версию в нашей системе:

Скачиваем ссылку на исходник NGINX версию 1.16.1

* в данном примере мы будем загружать nginx версии 1.16.1.

С помощью скопированной ссылки, загружаем исходник веб-сервера:

curl -kOL https://nginx.org/download/nginx-1.16.1.tar.gz

После распаковываем его:

tar -zxf nginx-*.tar.gz

Переходим в распакованную папку:

cd nginx-*/

Клонируем репозиторий для модуля SPNEGO:

git clone https://github.com/stnoonan/spnego-http-auth-nginx-module.git

Мы готовы к сборке.

4. Сборка и установка модуля

Смотрим, с какими опциями собран установленный NGINX:

nginx -V

В ответ мы получим список опций — нам нужно все, что идет после configure arguments, например:

--with-cc-opt='-g -O2 -fdebug-prefix-map=/build/nginx-5J5hor/nginx-1.18.0=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -fPIC' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-compat --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_xslt_module=dynamic --with-stream=dynamic --with-stream_ssl_module --with-mail=dynamic --with-mail_ssl_module

Нам нужно ввести команду с синтаксисом:

./configure <список опций nginx -V> --add-dynamic-module=<путь до модуля>

В моем случае, это:

./configure --with-cc-opt='-g -O2 -fdebug-prefix-map=/build/nginx-5J5hor/nginx-1.18.0=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -fPIC' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-compat --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_xslt_module=dynamic --with-stream=dynamic --with-stream_ssl_module --with-mail=dynamic --with-mail_ssl_module --add-dynamic-module=spnego-http-auth-nginx-module

Собираем модуль:

make modules

Готово. В каталоге objs появится файл ngx_http_auth_spnego_module.so. Нам нужно его скопировать в каталог с библиотеками. В зависимости от системы и опций сборки, этот каталог может находиться по разному пути.

Более точный путь можно посмотреть командой:

nginx -V

Среди полученных опций найти --modules-path.

а) Для Ubuntu/Debian (как правило):

mkdir -p /usr/lib/nginx/modules

cp objs/ngx_http_auth_spnego_module.so /usr/lib/nginx/modules/

б) Для CentOS (как правило):

mkdir -p /usr/lib64/nginx/modules

cp objs/ngx_http_auth_spnego_module.so /usr/lib64/nginx/modules/

5. Подключение модуля в NGINX

Наш модуль в нужном каталоге, но чтобы веб-сервер его мог использовать, необходимо внести изменения в конфигурационный файл. Пути немного отличаются для разных дистрибутивов Linux.

а) Ubuntu/Debian:

vi /etc/nginx/modules-enabled/spnego-http-auth-nginx-module.conf

load_module "/usr/lib/nginx/modules/ngx_http_auth_spnego_module.so";

б) CentOS:

vi /usr/share/nginx/modules/spnego-http-auth-nginx-module.conf

load_module "/usr/lib64/nginx/modules/ngx_http_auth_spnego_module.so";

* напомню, что точный путь до файла ngx_http_auth_spnego_module.so может быть другим.

Проверяем, корректность настройки nginx:

nginx -t

Мы должны увидеть:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Можно перезапускать NGINX:

systemctl restart nginx

Для подключения к контроллеру домена нам необходимо подтверждать подлинность. Это выполняется с помощью учетной записи в LDAP и файла keytab.

Создание учетной записи

Открываем консоль управления пользователями и добавляем нового со стандартными правами. От этой учетной записи будут выполняться запросы к AD DS.

В своем примере мы создаем пользователя spnego.

Учетная запись должна быть размещена по пути, в котором присутствуют названия только на латинице. Подразделения и контейнеры не должны быть на русском. В противном случае, при выполнении команды ниже мы получим ошибку «Password set failed! 0x00000020».

Создание keytab-файла

В двух словах, данный файл позволяет пройти идентификацию в Kerberos без запроса пароля. Он содержит пары имен субъектов Kerberos и зашифрованные ключи, полученные из пароля Kerberos.

Мы создадим данный файл на контроллере домена и скопируем на сервер NGINX. Для этого на контроллере домена и от имени администратора запускаем Powershell или обычную командную строку. Вводим:

ktpass /princ HTTP/nginx.domain.local@DOMAIN.LOCAL /mapuser spnego@DOMAIN.LOCAL /crypto ALL /ptype KRB5_NT_PRINCIPAL /out C:\spnego.keytab /pass *

* где:

  • nginx.domain.local — полное имя нашего nginx-сервера;
  • DOMAIN.LOCAL — наш домен;
  • spnego@DOMAIN.LOCAL — учетная запись в AD для выполнения запросов (создана на шаге выше);
  • pass * — пароль, который будет задан пользователю (должен соответствовать требованию AD). Система запросит его ввод дважды.

* регистр важен.

В нашем примере, после выполнения команды на контроллере домена в корне диска С появится файл spnego.keytab. Его копируем на Linux-сервер, например, при помощи WinSCP.

Настройка Linux для интеграции с AD

Для интеграции Linux с нашим LDAP (в данном примере, на основе Active Directory) установим необходимые пакеты и настроим Kerberos. 

Установка пакетов

Необходимые пакеты ставим из репозиториев. 

а) на Ubuntu/Debian:

apt install heimdal-clients

б) на Centos:

yum install krb5-workstation

Проверка файла

Переходим в каталог с файлом keytab и выполняем команду:

kinit -kt spnego.keytab HTTP/nginx.domain.local@DOMAIN.LOCAL

* напомним, что spnego.keytab — имя нашего файла; HTTP/nginx.domain.local@DOMAIN.LOCAL — принципал, для которого сгенерирован файл.

Если мы не знаем имя принципала для файла keytab, вводим команду:

ktutil -k spnego.keytab list

Команда нам ничего не должна вернуть. Это значит, что она выполнена корректно.

Теперь выполним:

klist

Мы должны увидеть что-то на подобие:

Credentials cache: FILE:/tmp/krb5cc_0
        Principal: HTTP/nginx.domain.local@DOMAIN.LOCAL

  Issued                Expires               Principal
Apr 28 15:04:47 2021  Apr 29 01:04:47 2021  krbtgt/DOMAIN.LOCAL@DOMAIN.LOCAL

В данном ответе мы видим, что нам выдан билет для принципала HTTP/nginx.domain.local@DOMAIN.LOCAL. Идем дальше.

Настройка kerberos

Открываем на редактирование файл:

vi /etc/krb5.conf

Приводим его к виду (остальные строки не трогаем):

[libdefaults]
  ...
  default_realm = DOMAIN.LOCAL
  ..

[realms]
  DOMAIN.LOCAL = {
    kdc = 192.168.0.15
    kdc = 192.168.0.16
    kdc = 192.168.0.17
    admin_server = domain.local
  }

DOMAIN.LOCAL — наш домен; kdc — перечень контроллеров домена; admin_server — первичный контроллер (в данном примере будет использоваться случайный).

Настройка аутентификации на NGINX

Переходим к настройке самого веб-сервера. Для начала, перенесем наш файл keytab в каталог NGINX:

mv spnego.keytab /etc/nginx/

Открываем файл nginx с настройками для виртуального домена или главный конфигурационный файл.

а) пример для Ubuntu/Debian:

vi /etc/nginx/sites-enabled/default

б) пример для CentOS:

vi /etc/nginx/nginx.conf

В секции server добавляем:

server {
    ...
    auth_gss on;
    auth_gss_realm DOMAIN.LOCAL;
    auth_gss_keytab /etc/nginx/spnego.keytab;
    auth_gss_service_name HTTP/nginx.domain.local;
    ...
}

Перезапускаем NGINX:

systemctl restart nginx

Готово. Пробуем зайти на наш сайт.

На заметку

Предлагается самостоятельно изучить дополнительные моменты, о которых не будет рассказано в рамках данной инструкции.

1. В качестве альтернативного модуля для осуществления basic-аутентификации через ldap может использоваться nginx-ldap-auth. Он также должен быть загружен и добавлен при сборке.

2. В инструкции используется пример сборки пакета на целевом сервере. Это не совсем правильно, так как оставляет после себя много мусора. Сборку лучше осуществлять на другом компьютере или в контейнере Docker.

Читайте также

Возможно, также будут интересны инструкции:

1. Установка и использование FreeIPA на CentOS

2. Как установить роль контроллера домена на Windows Server

3. Сборка своего RPM-пакета на примере NGINX

4. Как настроить Freeradius для работы с Active Directory и MySQL одновременно

# Active Directory # Linux # NGINX # Безопасность # Серверы
Дмитрий Моск — частный мастер
Была ли полезна вам эта инструкция?

Да            Нет