Как настроить прозрачную аутентификацию в NGINX через LDAP

Мы предоставляем услуги удаленного администрирования серверов

Как настроить прозрачную аутентификацию в NGINX через LDAP

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

Используемые термины: 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-get 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-get 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-get update

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

б) для CentOS:

yum install epel-release

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

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

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

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

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

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

wget https://nginx.org/download/nginx-1.20.0.tar.gz

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

tar zxvf 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 install

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

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

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

useradd —no-create-home nginx

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

mkdir -p /var/lib/nginx

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

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

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-get update

apt-get install nginx

б) Для CentOS:

yum install epel-release

yum install nginx

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

systemctl start nginx

systemctl enable nginx

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

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

а) для Ubuntu/Debian:

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

б) для CentOS:

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

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

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

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

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

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

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

wget https://nginx.org/download/nginx-1.16.1.tar.gz

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

tar zxvf nginx-*.tar.gz

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

cd nginx-*/

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

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

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

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

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

В ответ мы получим список опций — нам нужно все, что идет после 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. Нам нужно его скопировать в каталог с библиотеками. В зависимости от системы и опций сборки, этот каталог может находиться по разному пути.

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

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

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

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

* более точный путь можно посмотреть командой nginx —V — среди полученных опций найти —modules-path.

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: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

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

systemctl restart nginx

Создание учетной записи в AD и файла keytab

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

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

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

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

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

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

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

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

ktpass /princ HTTP/[email protected] /mapuser [email protected] /crypto ALL /ptype KRB5_NT_PRINCIPAL /out C:spnego.keytab /pass *

* где:

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

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

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

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

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

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

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

а) на Ubuntu/Debian:

apt-get install heimdal-clients

б) на Centos:

yum install krb5-workstation

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

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

kinit -kt spnego.keytab HTTP/[email protected]

* напомним, что spnego.keytab — имя нашего файла; HTTP/[email protected] — принципал, для которого сгенерирован файл.

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

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

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

Credentials cache: FILE:/tmp/krb5cc_0
        Principal: HTTP/[email protected]

  Issued                Expires               Principal
Apr 28 15:04:47 2021  Apr 29 01:04:47 2021  krbtgt/[email protected]

В данном ответе мы видим, что нам выдан билет для принципала HTTP/[email protected] Идем дальше.

Настройка 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 одновременно