Блог - Linux, программирование, Я!

linux на сервереBasic HTTP авторизация для Nginx

В принципе это тривиальная операция описанная в документации к Nginx, но немного усложняет этот процесс необходимость создавать htpasswd файл, причем в самом Nginx средств для его создания нет (и это правильно), но предлагается создавать его используя утилиту htpasswd входящую в состав Apache. Что самое смешное, на многих серверах, где используется Nginx, апача нет и не ожидается. Более того, большинство администраторов хостингов, "познавших" для себя Nginx начинают нескрываемо недолюбливать апач и верят, что наступит тот час, когда для Nginx наконец сделают аналог htaccess и апач, исправно служивший им долгие годы, наконец-то сгинет в небытие. Чтобы исправить сей досадный факт, добавлю в статью онлайн-формочку для генерации htpasswd фйла.

Давайте для примера создадим отдельный поддомен для хранения секретной информации с доступом по логину/паролю и в нагрузку в ней будут директория для доступа к которой понадобится дополнительная пара логин/пароль и директория с включенным листингом файлов тоже с отдельным доступом. Т.е. структура примерно такая:
/ (доступ к файлам по _логин-пароль_1)
--otherpass/ (доступ к файлам по _логин-пароль_2)
--listed/ (включен автоиндекс файлов, т.е. можнго просмотреть какие файлы тут лежат, доступ к файлам по _логин-пароль_3)

Создадим виртуалхост Nginx

Допустим, для поддомена adminka.example.com. Для этого создадим файл

sudo nano /etc/nginx/sites-available/adminka.example.com

со следующим содержимым:

server {
        listen   80;
        server_name  adminka.example.com;
        access_log  /var/log/nginx/adminka_example_com.log;#можно написать /var/log/nginx/$host.log но придется заранее создать лог-файл и выставить на него правильные права
        root   /var/www/$host/htdocs;
        index  index.html index.htm index.php;
}

Ок, сохраняем, делаем этот хост доступным (включаем в конфиг нджинкса):

sudo ln -s /etc/nginx/sites-available/adminka.example.com /etc/nginx/sites-enabled/adminka.example.com

Создаем директории для htdocs

mkdir /var/www/{adminka.example.com,adminka.example.com/htdocs,adminka.example.com/htdocs/{otherpass,listed}

Если кто не понял, эта команда делает то же, что и 4 следующие:

mkdir /var/www/adminka.example.com
mkdir /var/www/adminka.example.com/htdocs
mkdir /var/www/adminka.example.com/htdocs/otherpass
mkdir /var/www/adminka.example.com/htdocs/listed

Рестартим Nginx

sudo service nginx configtest
sudo service nginx restart

Проверяем: http://adminka.example.com/
Ага

403 Forbidden
nginx/0.7.64

Пароли не просит, листинг директории у нас не включен и index файла мы не создавали. То же самое для директорий otherpass и listed. Соответственно получаем 403 ошибку "доступ запрещен".

Добавим листинг (если нужен)

Мы договорились, что в директории listed у нас разрешен просмотр содержимого директории... Редактируем конфиг

sudo nano /etc/nginx/sites-available/adminka.example.com
server {
  listen   80;
        server_name  adminka.example.com;
        access_log  /var/log/nginx/adminka_example_com.log;
        root   /var/www/$host/htdocs;
        index  index.html index.htm index.php;
        location /listed/ {
                autoindex on;
        }
}

Сохраняем, перезапускаем, пробуем: http://adminka.example.com/listed/
Ага, работает:

Index of /listed/
_________
../
_________

Но где же обещанные пароли? Спокойно, сейчас все будет!

Добавляем Basic HTTP authorization.

Пароли для разных директорий будем хранить в разных htpasswd файлах за пределами htdocs. Например так:

/var/www/adminka.example.com/
--/root_htpasswd
--/listed_htpasswd
--/otherpass_htpasswd
server {
  listen   80;
        server_name  adminka.example.com;
        access_log  /var/log/nginx/adminka_example_com.log;
        root   /var/www/$host/htdocs;
        index  index.html index.htm index.php;
        location / {
                auth_basic "Unauthorized"; # текст сообщения сервера с предложением ввести пароль
                auth_basic_user_file /var/www/$host/root_htpasswd; # путь к htpasswd файлу
        }
        location /listed/ {
                auth_basic "Unauthorized";
                auth_basic_user_file /var/www/$host/listed_htpasswd;
                autoindex on;
        }
        location /otherpass/ {
                auth_basic "Unauthorized";
                auth_basic_user_file /var/www/$host/otherpass_htpasswd;
                autoindex on;
        }
}

Создаем htpasswd файлы (см. далее), сохраняем, перезапускаем, проверяем!

Генерация хеша пароля

HTTP авторизация в Nginx работает так же как и в Apache, т.е. с использованием htpasswd файла, но с тем лишь ограничением, что для шифрования пароля можно использовать только стандартный алгоритм DES с двухсимвольной солью. В Linux для этого используется C-функция crypt() (см man 3 crypt).

Можно использовать утилиту htpasswd из комплекта поставки Apache

htpasswd -nd seriy
New password:
Re-type new password:
seriy:4lQ0JcanrGr9E

Вывод этой утилиты состоит из 3-х частей: первая, до двоеточия "seriy" - это имя пользователя, "4l" - это двухсимвольная соль для функции crypt() и остальная часть "Q0JcanrGr9E" - это сам хеш пароля. Единственная проблема такого подхода - придется устанавливать apache.

Вот пара примеров кода для генерации htpasswd ( your_password - ваш пароль, salt - соль для пароля, должна содержать 2(!!!) символа из набора "./0-9A-Za-z"):
используя php:

php -r 'echo crypt("your_password", "salt");'

используя Python:

python -c 'import crypt; print crypt.crypt("your_password", "salt")'

Если кто предложит примеры на других языках - (perl, ruby) буду благодарен. Возможно для этого можно использовать утилиту mcrypt но я в ней не смог разобраться.

В завершение - вот простенькая веб-формочка для генерации htpasswd онлайн.

  1. 2010-06-04 14:03:12 | #

    […] PS пишет: server { listen 80; server_name adminka.example.com; access_log /var/log/nginx/adminka_example_com.log;#можно написать /var/log/nginx/$host.log но придется заранее создать лог-файл и выставить на него правильные права root … htpasswd -nd seriy New password: Re-type new password: seriy:4lQ0JcanrGr9E. Вывод этой утилиты состоит из 3-х частей: первая, до двоеточия «seriy» – это имя пользователя, «4l» – это двухсимвольная соль для функции crypt() и остальная часть … […]

  2. 2012-02-27 05:42:37 | #

    А вот так осуществляется контроль доступа к файлам на Nginx и PHP:
    http://odiszapc.ru/2012/02/26/nginx-access/

  3. rock
    2012-09-14 03:12:46 | #

    Что тут писать-то?

                        #!/usr/bin/python
    # -*- coding: utf-8 -*-
    
    from sys import argv
    from random import choice
    from string import ascii_letters, digits
    from getpass import getpass
    from crypt import crypt
    
    if __name__=="__main__":
            name = argv[1:2]
            if not name:
                    print "Введите имя пользователя:",
                    name = raw_input()
                    if not name:
                            print "ОШИБКА: Введите имя пользователя."
                            exit(1)
            else:
                    name = name[0]
    
            salt = ''.join(choice(ascii_letters.join(digits)) for char in range(2))
    
            passwd = getpass("Введите пароль: ")
            if not passwd == getpass("Введите пароль еще раз: "):
                    print "ОШИБКА: Пароль и подтверждение не совпадают."
                    exit(2)
    
            passwdHash = crypt(passwd, salt)
    
            print name + ':' + passwdHash
    
            exit(0)
                      
  4. Incognito
    2012-12-18 16:51:16 | #

    у меня почему к listed постоянно пароль запрашивает, а к корневой один раз ввел в браузере и после этого открывается без запроса пароля, так и должно быть?
    как нибудь время жизни пароля задать можно?

  5. Павел
    2013-08-03 05:11:00 | #

    Апач устанавливать не нужно, достаточно установить apache2-utils.
    Для Debian Linux:
    aptitude install apache2-utils

  6. Дмитро Раби
    2013-12-20 13:38:17 | #

    На crypt на ruby:
    'password'.crypt('salt')

    • Дмитро Раби
      2013-12-20 13:39:09 | #

      Парсер лох, ковычки нужны одинарые или двайные «лапки»

  7. mad_crack
    2014-01-21 18:25:28 | #

    Каталоги можно сделать командой покороче, если использовать ключик -p

    mkdir -p /var/www/adminka.example.com/htdocs/{otherpass,listed}

  8. 2017-07-25 04:36:50 | #

    Продам мопед.