Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР 130, ОКТЯБРЬ 2009 г.

Воздвигнем NAS на раз! Создаем мультипротокольный NAS из старого компа

Евгений Зобнин (j1m@synack.ru)

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

Аббревиатура NAS расшифровывается как Network Attached Storage (хранилище, подключаемое по Cети). Принадлежащее к этому классу устройство обычно представляет собой небольшой маломощный сервер (возможно на процессоре VIA), построенный на чипсете с многоканальным IDE/SATA-контроллером. Его основная задача - хранить данные и предоставлять к ним доступ по множеству протоколов (CIFS, NFS, FTP/FTPS, HTTP/HTTPS и т.д.) Причем вторая задача решается с помощью прошитой во флеш-память операционной системы, в качестве которой в последнее время все чаще выступает Linux.

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

Анатомия ОС, используемой в NAS-устройстве

Каким же образом настроить операционную систему, чтобы она стала пригодной для использования на NAS-устройствах? Во-первых, она должна быть лишена всего, что не является важным для хранения данных, предоставления удаленного доступа к ним и администрирования. Этого легко добиться, отправив все пакеты, содержащие систему X Window, пользовательские программы и высокоуровневые библиотеки в /dev/null. В результате в системе должно остаться ядро, шелл, набор инструментов командной строки и стандартные библиотеки (glibc, ncurses и т.д.). Во-вторых, система должна содержать все необходимое для организации удаленного доступа к данным: samba (протокол CIFS), nfs-kernel-server (протокол NFS), vsftpd (FTP/FTPS), lighttpd (HTTP/HTTPS), ssh (SFTP) и rsync (для бэкапа данных). В-третьих, система должна уметь загружаться с USB-брелка или LiveCD (нельзя допустить, чтобы ОС обрушилась вместе с отказом одного из жестких дисков).

В идеале ОС должна уметь аутентифицировать пользователей, используя Active Directory или LDAP, но мы ограничимся стандартным файлом /etc/passwd для хранения учетных записей.

Подготовка Flash-брелка

Установить Linux на USB-flash очень просто. Для этого достаточно взять установочный дистрибутивный диск, скормить его приводу, выключить комп, отключить все жесткие диски, включить комп и приступить к установке. Инсталлятор ОС примет USB-флешку за HDD и благополучно установит на нее систему. Но существует еще более простой способ - вставить флешку в гнездо и указать ассоциированное с ней устройство в качестве жесткого диска эмулятору qemu:

$ qemu -cdrom /путь/к/linux.iso -hda /dev/sd* -boot d

После этого следует установить дистрибутив, указав инсталлятору использовать всю флешку для создания единого раздела ОС (без свопа и прочих ухищрений). Причем в качестве файловой системы лучше выбрать ext2, так как журналируемость и flash-накопители - вещи несовместимые (виной тому низкая скорость работы + износ накопителя).

После завершения процедуры следует загрузиться с flash-накопителя (хотя бы используя все тот же qemu) и приступить к зачистке дистрибутива от ненужного хлама: X Window, оконные менеджеры и среды, пользовательский софт и т.д. А освободившееся место использовать для установки samba, nfs-kernel-server, nfs-common, portmap, vsftpd, rsync, lighttpd, openssh-server (названия приведены для дистрибутива Ubuntu 9.04).

Создание хранилища и привязка к нему пользователей

Разобравшись с установкой, приступаем к организации хранилища и настройке сетевых служб. Для этого нам надо создать два подкаталога в каталоге /mnt: share (в нем будет храниться информация, доступная всем) и private (личные каталоги пользователей). Ты можешь сразу подключить к компу все жесткие диски, создать из них RAID и примонтировать его к /mnt (не забыв добавить соответствующую запись в /etc/fstab) или же наращивать дисковый массив постепенно, подключая все новые диски для отдельных пользователей. В конце концов, смысл в том, что каталоги /mnt/share и /mnt/private и будут нашим хранилищем, а что и к чему подключено на более низком уровне, – значения не имеет. Далее установим права на созданные каталоги:

# chmod 1777 /mnt/share
# chown root:users /mnt/private
# chmod 770 /mnt/private

С помощью этих трех команд мы сделали так, чтобы:

  1. к /mnt/share имели доступ все без исключения пользователи и могли создавать и удалять в нем файлы, за исключением тех, владельцами которых они не являются (те же права доступа, что и у каталога /tmp);
  2. к каталогу /mnt/private имели доступ только root и пользователи группы users, что позволит организовать систему разделения прав и защиты приватных каталогов пользователей.

Теперь ты можешь завести в системе пользователей, которые должны иметь доступ к серверу (например, director, buhgalter, admin и т.д.) и создать соответствующие каталоги внутри /mnt/private. Пример:

  • director - домашний каталог /mnt/private/director, владелец director:users, права доступа 700
  • buhgalter - домашний каталог /mnt/private/buhgalter, владелец buhgalter:users, права доступа 700
  • admin - домашний каталог /mnt/private/admin, владелец admin:users, права доступа 700

Протокол CIFS

Обычные пользователи обращаются к NAS-серверу через сетевое окружение Windows, поэтому настройке доступа по протоколу CIFS необходимо уделить особое внимание. Мы воспользуемся вполне стандартной конфигурацией smb.conf, которая выставляет в локальную сеть два ресурса: наш каталог /mnt/share и личный каталог пользователя (/mnt/private/пользователь), куда последний будет попадать после ввода имени и пароля.
Установим сервер Samba:

$ sudo apt-get install samba

После этого открываем файл /etc/samba/smb.conf и пишем в него:

$ sudo vim /etc/samba/smb.conf

[global]
; Рабочая группа
workgroup = WORKGROUP
; Имя сервера
server string = Corporate NAS-server
; Не резолвить имена машин самостоятельно
dns proxy = no
; Для каждого клиента ведем свой лог-файл
log file = /var/log/samba/log.%m
max log size = 1000
; Не использовать syslog
syslog = 0
; Аутентифицировать пользователей с помощью имен и паролей
security = user
; Шифровать пароли
encrypt passwords = true
; Бэкенд, используемый для хранения паролей
passdb backend = tdbsam
; Синхронизировать изменившиеся smb-пароли с паролями в базе /etc/passwd
unix password sync = yes
passwd program = /usr/bin/passwd %u
passwd chat = *Entersnews*spassword:* %nn *Retypesnews*spassword:* %nn *passwordsupdatedssuccessfully* .

; Глобальная шара, доступная всем
[share]
comment = Global Share
path = /mnt/share
valid users = @users
force group = users
create mask = 0666
directory mask = 0777
writable = yes

; Личные каталоги пользователей
[homes]
comment = Private Directories
browseable = no
valid users = %S
writable = yes
create mask = 0600
directory mask = 0700

Добавляем в самбу всех пользователей, которых мы завели в локальной системе, с помощью команды:

$ sudo smbpasswd -a пользователь
<пароль>

Запускаем службу:

$ sudo service samba start

Протокол NFS

IT-отдел предпочитает использовать сетевую файловую систему для доступа к своим данным. Что ж, желание легко удовлетворить с помощью ядерного NFS-сервера:

$ sudo apt-get install nfs-kernel-server nfs-common portmap

Открываем файл /etc/exports и добавляем в него строку:

/mnt 192.168.1.1/24 (rw,no_root_squash,async,subtree_check)

192.168.1.1/24 - это сеть, которой разрешен доступ на монтирование ресурса. Пользователи будут видеть как каталог /mnt/share, так и /mnt/private, но доступ к последнему будут иметь только владельцы соответствующих домашних каталогов.
Запускаем сервер:

$ sudo service nfs-kernel-server start

Протокол FTP

Для полноты картины мы должны организовать доступ к NAS с помощью протокола FTP. Но здесь сразу сталкиваемся с проблемой - протокол FTP не позволяет клиенту указывать собственную кодировку, и пользователям Windows имена файлов будут видны только в случае использования кодировки cp1251, а пользователям UNIX - koi8-r или utf-8. Прибавь к этому неумение сервера vsftpd перекодировать имена из локальной кодировки и получишь полный бардак.

Выход из ситуации – в использовании костылей, а именно установке модифицированной версии vsftpd, скачанной с сайта vsftpd.devnet.ru, и указании серверу перекодировать имена файлов в кодировку cp1251. Это автоматически решит проблему Windows-пользователей. Всех остальных можно занести в специальный список IP-адресов и назначить им другую кодировку, например utf-8. Итак, скачиваем vsftpd-2.1.2-ext1.tgz, распаковываем, собираем и устанавливаем:

$ wget http://vsftpd.devnet.ru/files/2.1.2/ext.1/vsftpd-2.1.2-ext1.tgz
$ tar -xzf vsftpd-2.1.2-ext1.tgz
$ cd vsftpd-2.1.2-ext.1
$ sudo apt-get install build-essential
$ make
$ sudo make install

Добавляем пользователя nobody (с правами которого будет работать сервер) и пользователя ftp (к которому будут приравнены анонимные пользователи):

$ sudo useradd nobody
$ sudo useradd -d /mnt ftp

И создаем каталог /usr/share/empty, в который сервер будет делать chroot:

$ sudo mkdir /usr/share/empty

Добавляем строку «/usr/local/sbin/vsftpd» в файл /etc/rc.local (перед строкой «exit 0»). Открываем /etc/vsftpd.conf и пишем в него строки:

$ sudo vim /etc/vsftpd.conf

# Разрешить анонимных пользователей
anonymous_enable=YES
# Не запускать через inetd
listen=YES
# Разрешать вход локальным пользователям (все пользователи, которых мы добавили ранее, будут попадать в собственные каталоги внутри /mnt/private).
local_enable=YES
# Помещать всех зарегистрированных пользователей в домашний каталог (/mnt/private/пользователь)
chroot_local_user=YES
# Разрешить запись
write_enable=YES
# Маска прав на файлы, созданные зарегистрированными юзерами
local_umask=077
# Маска прав на файлы, созданные анонимными пользователями
anon_umask=000
# Разрешить аплоад для анонимных пользователей
anon_upload_enable=YES
# Разрешить анонимным пользователям создавать каталоги
anon_mkdir_write_enable=YES
# Журналировать все факты скачивания/заливки файлов
xferlog_enable=YES
xferlog_file=/var/log/vsftpd.log
xferlog_std_format=YES
# Разрешаем коннекты с 20-го порта
connect_from_port_20=YES
# Включить перекодировку имен файлов
convert_charset_enable=1
# Локальная кодировка - utf-8
local_charset=UTF8
# Удаленная кодировка - cp1251
remote_charset=WIN1251

Открываем файл /etc/vsftpd/pasv_rules и записываем в него IP-адреса всех, кто не использует кодировку cp1251, в следующей форме:

IP-сервера IP-клиента/маска IP-сервера кодировка yes yes yes yes no

Пример:

192.168.1.1 192.168.1.23/32 192.168.1.1 UTF8 yes yes yes yes no

Запускаем сервер:

$ sudo /usr/local/sbin/vsftpd

Вход на сервер под именем anonymous или ftp позволит пользователю получить доступ к любым каталогам внутри /mnt/share, с возможностью создавать подкаталоги и заливать файлы. Если же пользователь введет имя и пароль, то попадет в свой каталог внутри /mnt/private с полными правами на чтение, запись и удаление файлов. По умолчанию имена файлов закодированы в cp1251, но те, кто заходит с IP-адресов, перечисленных в /etc/vsftpd/pasv_rules, получат особые настройки (например, перекодировку в utf-8).

Протокол HTTP

На всякий случай мы должны настроить доступ и по протоколу HTTP, который в отдельных случаях оказывается единственным способом обращения к сервису. Для этого лучше всего подойдет легкий и производительный web-сервер lighttpd, который будет генерировать список файлов каталога /mnt/share (делать корнем каталог /mnt бессмысленно – просто потому что web-сервер не сможет получить доступ к содержимому каталога /mnt/private). Устанавливаем web-сервер:

$ sudo apt-get install lighttpd

Открываем конфигурационный файл /etc/lighttpd/lighttpd.conf, затираем прежнее содержимое и добавляем новое:

$ sudo vim /etc/lighttpd/lighttpd.conf

# Подключаем модули access и accesslog
server.modules = (
"mod_access",
"mod_accesslog"
)
# Корень web-сервера (то есть корневой каталог с данными)
server.document-root = "/mnt/share"
# Указываем пути к журнальным записям
server.errorlog = "/var/log/lighttpd/error.log"
accesslog.filename = "/var/log/lighttpd/access.log"
# Файл с уникальным идентификатором процесса
server.pid-file = "/var/run/lighttpd.pid"
# Имя и группа пользователя, с правами которого будет работать сервер
server.username = "www-data"
server.groupname = "www-data"
# Включаемые файлы (MIME-типы и внешние модули)
include_shell "/usr/share/lighttpd/create-mime.assign.pl"
include_shell "/usr/share/lighttpd/include-conf-enabled.pl"

Подключаем модуль userdir, предназначенный для генерирования листинга файлов:

$ sudo lighty-enable-mod userdir

После этого в файле /etc/lighttpd/lighttpd.conf появятся строки:

## virtual directory listings
dir-listing.encoding = "utf-8"
server.dir-listing = "enable"

Запускаем сервер:

$ sudo service lighttpd start

Протоколы SFTP и RSYNC

Последний, очень короткий, раздел посвящен настройке доступа к NAS по протоколу SFTP и реализации системы бэкапа. Для начала установим пакеты openssh-server и rsync:

$ sudo apt-get install openssh-server
$ sudo apt-get install rsync

Вместе с первым мы автоматически получили SFTP-сервер, уже полностью настроенный и запущенный системой установки пакетов. Во втором содержится утилита rsync, которую мы будем использовать для бэкапа данных.

Rsync не требует настройки, сервера или плясок с бубном. Главное, произвести обмен ssh-ключами между пользователем root NAS-сервера и пользователем, производящим бэкап на машине-приемнике. Затем достаточно выполнить следующую команду, и ты получишь бэкап всех данных каталога /mnt (повторное выполнение команды приведет к копированию только изменившихся данных):

$ rsync -rc -t -e ssh --rsync-path=/usr/bin/rsync --temp-dir=/tmp root@host.org:/mnt /backup/nas

В качестве источника предпочтительно указать каталог /mnt/private, чтобы не копировать множество бесполезных данных, которые пользователи могут складировать в общую шару, а саму команду добавить в задания cron (советуем настроить ежедневное копирование).

Ограничение доступа

Во избежание захламления открытого для всех подряд каталога /mnt/share, некоторых пользователей лучше отрезать от NAS-сервера с помощью TCP-Wrappers. Для этого устанавливаем пакеты xinetd и tcpd:

$ sudo apt-get install xinetd tcpd

И вписываем IP-адреса неугодных в файл /etc/hosts.deny:

ALL: 192.168.1.12 192.168.1.15

Это автоматически обезопасит NAS-сервер при доступе по протоколам NFS и SFTP. Чтобы vsftpd научился пропускать свои соединения через tcpd, добавим в его конфиг строку «tcp_wrappers=YES» и перезапустим:

$ sudo killall vsftpd
$ /usr/local/sbin/vsftpd

Samba не умеет работать с tcpd, но ее можно запустить под его управлением с помощью xinetd. Остановим samba-демон:

$ sudo service samba stop

Добавим следующую строку в /etc/inetd.conf:

netbios-ssn stream tcp nowait root /usr/sbin/tcpd /usr/sbin/smbd

И – перезапустим xinetd:

$ sudo service xinetd restart

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

Заключение

Создание собственного NAS-сервера из подручных материалов – не такая уж и сложная задача. Конечно, наш NAS не обладает web-интерфейсом, не умеет шифровать передаваемые данные (за исключением протокола SFTP) и не накладывает квоты на пользователей и группы. Но нужно ли все это? Для большинства админов с руками доступ по протоколу SSH гораздо предпочтительнее даже самого гибкого web-интерфейса, шифрование данных совершенно бесполезно в офисных локальных сетях, а квоты рождают больше неудобств, чем приносят пользы (уж лучше время от времени просматривать содержимое хранилища в поисках тех, кто использует NAS не по назначению, и бить по рукам провинившихся, чем включить квотирование и дожидаться момента, когда хранилище забьется).

WARNING

Старые материнские платы могут отказаться грузить ОС с флешки, отформатированной в ФС, отличную от FAT16. В этом случае придется устанавливать ОС на FAT16 или создать отдельный раздел для загрузчика.

Команда lighty-enable-mod присутствует только в дистрибутивах Debian/Ubuntu и производных. Во всех остальных для активации модуля необходимо добавить его имя в переменную server.modules конфигурационного файла lighttpd.conf (не забыв указать префикс mod_).

В Ubuntu xinetd по умолчанию запускается в режиме совместимости с inetd (то есть, читает файл /etc/inetd.conf). В других дистрибутивах, возможно, придется подправлять скрипты инициализации, чтобы указать xinetd флаг '-inetd_compat'.

Содержание
ttfb: 7.6210498809814 ms