Используемые термины: NGINX, Active Directory.
Модуль SPNEGO для NGINX — это программный компонент для возможности прохождения аутентификации (Single Sign-On или SSO) через сервер LDAP. В данной инструкции мы рассмотрим процесс его установки и настройки. В качестве сервера LDAP будем использовать Active Directory. Процесс будет рассмотрен для систем Ubuntu/Debian и CentOS.
Для корректной работы нашего веб-сервера необходимо:
Рассмотрим настройку по шагам.
В процессе настройки аутентификации через LDAP нам необходимо будет задать в качестве принципала имя нашего сервера:
hostnamectl set-hostname nginx.domain.local
* предполагается, что в нашем случае имя сервера будет nginx.domain.local (домен domain.local).
Для работы с 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 ……
systemctl enable chronyd —now
Для корректной работы нашего веб-сервера необходимо открыть порты 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. Мы можем выполнить это двумя методами:
У каждого способа есть свои плюсы и минусы, но мы рассмотрим оба варианта, а выбор оставляем за читателем.
Выполняем сборку в несколько этапов. Разберем их по очереди:
Для сборки нам нужны пакеты, от которых зависит процесс конфигурирования. В зависимости от операционной системы, команды будут отличаться.
а) для 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
Загрузим исходник для 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
Мы готовы к сборке.
Для разных систем мы выполним разные команды конфигурирования пакета.
а) на 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
Чтобы 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 oknginx: configuration file /etc/nginx/nginx.conf test is successful
Для запуска nginx в качестве сервиса, создаем файл:
vi /lib/systemd/system/nginx.service
[Unit]Description=A high performance web server and a reverse proxy serverDocumentation=man:nginx(8)After=network.target
[Service]Type=forkingPIDFile=/run/nginx.pidExecStartPre=/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 reloadExecStop=-/sbin/start-stop-daemon —quiet —stop —retry QUIT/5 —pidfile /run/nginx.pidTimeoutStopSec=5KillMode=mixedRestart=on-failure
[Install]WantedBy=multi-user.target
Перечитываем конфигурационные файлы в systemd:
systemctl daemon-reload
Разрешаем автозапуск сервиса и стартуем его:
systemctl enable nginx
systemctl start nginx
Данный способ немного отличается по действиям и конфигурированию, но суть процесса та же. Рассмотрим его по шагам.
Предполагается, что nginx установлен в системе. Иначе, установку можно выполнить из репозитория в зависимости от дистрибутива Linux.
а) Для Ubuntu/Debian:
apt-get install nginx
б) Для CentOS:
yum install nginx
Запускаем NGINX и разрешаем автостарт сервиса:
yum install wget git pcre-devel openssl-devel libxml2-devel libxslt-devel gd-devel perl-ExtUtils-Embed gperftools-devel redhat-rpm-config
Для начала, смотрим версию установленного NGINX:
Переходим на страницу загрузки nginx и копируем ссылку на установленную версию в нашей системе:
* в данном примере мы будем загружать nginx версии 1.16.1.
wget https://nginx.org/download/nginx-1.16.1.tar.gz
Смотрим, с какими опциями собран установленный 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.
Наш модуль в нужном каталоге, но чтобы веб-сервер его мог использовать, необходимо внести изменения в конфигурационный файл. Пути немного отличаются для разных дистрибутивов 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:
systemctl restart nginx
Для подключения к контроллеру домена нам необходимо подтверждать подлинность. Это выполняется с помощью учетной записи в LDAP и файла keytab.
Открываем консоль управления пользователями и добавляем нового со стандартными правами. От этой учетной записи будут выполняться запросы к AD DS.
В своем примере мы создаем пользователя spnego.
Учетная запись должна быть размещена по пути, в котором присутствуют названия только на латинице. Подразделения и контейнеры не должны быть на русском. В противном случае, при выполнении команды ниже мы получим ошибку «Password set failed! 0x00000020».
В двух словах, данный файл позволяет пройти идентификацию в Kerberos без запроса пароля. Он содержит пары имен субъектов Kerberos и зашифрованные ключи, полученные из пароля Kerberos.
Мы создадим данный файл на контроллере домена и скопируем на сервер NGINX. Для этого на контроллере домена и от имени администратора запускаем Powershell или обычную командную строку. Вводим:
ktpass /princ HTTP/[email protected] /mapuser [email protected] /crypto ALL /ptype KRB5_NT_PRINCIPAL /out C:spnego.keytab /pass *
* где:
* регистр важен.
В нашем примере, после выполнения команды на контроллере домена в корне диска С появится файл spnego.keytab. Его копируем на Linux-сервер, например, при помощи WinSCP.
Для интеграции Linux с нашим LDAP (в данном примере, на основе Active Directory) установим необходимые пакеты и настроим Kerberos.
Необходимые пакеты ставим из репозиториев.
apt-get install heimdal-clients
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 PrincipalApr 28 15:04:47 2021 Apr 29 01:04:47 2021 krbtgt/[email protected]
В данном ответе мы видим, что нам выдан билет для принципала HTTP/[email protected] Идем дальше.
Открываем на редактирование файл:
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 — первичный контроллер (в данном примере будет использоваться случайный).
Переходим к настройке самого веб-сервера. Для начала, перенесем наш файл 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:
Готово. Пробуем зайти на наш сайт.
Предлагается самостоятельно изучить дополнительные моменты, о которых не будет рассказано в рамках данной инструкции.
1. В качестве альтернативного модуля для осуществления basic-аутентификации через ldap может использоваться nginx-ldap-auth. Он также должен быть загружен и добавлен при сборке.
2. В инструкции используется пример сборки пакета на целевом сервере. Это не совсем правильно, так как оставляет после себя много мусора. Сборку лучше осуществлять на другом компьютере или в контейнере Docker.
Возможно, также будут интересны инструкции:
1. Установка и использование FreeIPA на CentOS
2. Как установить роль контроллера домена на Windows Server
3. Сборка своего RPM-пакета на примере NGINX
4. Как настроить Freeradius для работы с Active Directory и MySQL одновременно
Продолжая использовать данный сайт вы принимаете политику конфиденциальности и cookies