logo

Select Sidearea

Populate the sidearea with useful widgets. It’s simple to add images, categories, latest post, social media icon links, tag clouds, and more.
hello@youremail.com
+1234567890

Эволюция файлового сервера

Эволюция файлового сервера

Централизованное хранение файлов — большое преимущество, позволяющее повысить управляемость рабочими данными организации. Когда файлы хранятся на разрозненных серверах или локальных компьютерах пользователей, всегда будет сложно в критический момент найти важную информацию. Существует множество подходов избежать сложностей и организовать свои файловые сервера. В этой статье речь пойдет об организации файлового сервера на Linux, поддерживающего различные способы доступа для пользователей домена к их личным и общим корпоративным папкам. Это Samba для использования по локальной сети, ftps для удобства работы с большими файлами, web-доступ и облачное хранилище, предоставляющее пользователям возможность самостоятельно публиковать файлы и синхронизировать личные каталоги с локальными файлами компьютера. По сути, это этапы эволюции, через которые прошел файловый сервер с ростом требований к нему.

Базовая система

Для размещения сервера был выбран хост с двумя дисковыми массивами — быстрым RAID 10 из SSD и медленным RAID 10 из 1 Tb HDD. Второй массив почти полностью предполагалось отдать под нужды хранилища, а на первом размещались основные диски виртуальных машин.

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

Доступ к файлам из локальной сети

Первое, что требуется от корпоративного файлового сервера — позволить всем пользователям безопасно хранить свои файлы. Доступ с помощью samba привычен почти всем офисным пользователям, так как дает возможность подключить сетевой диск или попасть в нужный каталог введя UNC-путь («\\») в Проводнике или воспользовавшись сетевым окружением. Каждый офисный пользователь компьютера так или иначе сталкивался с подобной технологией. С точки зрения организации файлового хранилища в локальной сети с доменом Active Directory это очень удобный и эффективный вариант — на папки назначаются права в соответствиями с группами домена, таким образом происходит разграничение доступа, а на стороне пользователя все есть для того, чтобы получать и записывать файлы — достаточно Проводника Windows.

Для того, чтобы сделать все что необходимо, потребуется настроить доменные службы и аутентификацию, а также настроить общую папку и создать дерево каталогов. Дерево организовано следующим образом — ОсновнаяГруппа/ЛогинПользователя. В главной директории также размещена папка, доступная всем для чтения, в каждой группе — общая папка группы, доступная на чтение всем участникам группы. У групп и организации есть группы администраторов, которые получают права записи в соответствующие папки. Настройки samba выглядят так:

[global]
workgroup = CORP
realm = CORP.RU
security = ADS
   encrypt passwords = true
   dns proxy = no 
   socket options = TCP_NODELAY
   domain master = no
   local master = no
   preferred master = no
   os level = 0
   domain logons = no
   load printers = no
   show add printer wizard = no
   printcap name = /dev/null
   disable spoolss = yes
idmap config * : range = 10000-20000
idmap config * : backend = tdb 
winbind enum groups = yes
winbind enum users = yes
winbind use default domain = yes
template shell = /bin/false
winbind refresh tickets = yes


[ftpROOT]
comment = My shared folder
path = /opt/ftpROOT
public = no
writable = yes
guest ok = no
valid users = +CORP\corp_users
admin users = +CORP\corp_admins

Конфигурация kerberos:

[libdefaults]
  default_realm = CORP.RU
  kdc_timesync = 1
  ccache_type = 4
  forwardable = true
  proxiable = true
  v4_instance_resolve = false
  v4_name_convert = {
    host = {
      rcmd = host
      ftp = ftp
    }
    plain = {
      something = something-else
    }
  }
  fcc-mit-ticketflags = true

[realms]
  CORP.RU = {
    kdc = win-dc
    admin_server = win-dc
    default_domain = CORP.RU
  }

[domain_realm]
  .corp.ru = CORP.RU
  corp.ru = CORP.RU
[login]
  krb4_convert = false
  krb4_get_tickets = false

Доступ по FTP

Для того, чтобы пользоваться личными каталогами из интернета одним из вариантов доступа может быть протокол FTP. Такое решение хорошо подходит для передачи больших файлов, так как во многих клиентах поддерживается докачка, а у пользователей файлового сервера имелась потребность в такой возможности. В качестве протокола изпользоватлся ftps, чтобы избежать передачи логинов и другой информации в незашифрованом виде.
В качестве службы фтп использовался сервер vsftp. Он мало чем отличается от других FTP серверов, просто со временем сложились предпочтения к нему. Необходимо настроить возможность входа на сервер доменным пользователям. Конфигурация демона vsftpd выглядит следующим образом:

listen=YES
listen_port=990
implicit_ssl=YES
pasv_min_port=65000
pasv_max_port=65100
listen_ipv6=NO
anonymous_enable=YES
local_enable=YES
write_enable=YES
local_umask=22
dirmessage_enable=YES
use_localtime=YES
xferlog_enable=YES
connect_from_port_20=YES
idle_session_timeout=600
data_connection_timeout=120
guest_enable=YES
guest_username=ftp
virtual_use_local_privs=YES
write_enable=YES
chroot_local_user=YES
local_root=/home/ftp/$USER
user_sub_token=$USER
allow_writeable_chroot=YES
chmod_enable=YES
session_support=YES
pam_service_name=ftp
rsa_cert_file=/etc/ssl/private/ftp.corp.ru.pem
rsa_private_key_file=/etc/ssl/private/ftp.corp.ru.key
ssl_enable=YES
utf8_filesystem=YES
force_local_data_ssl=YES
force_local_logins_ssl=YES
ssl_tlsv1=YES
ssl_sslv2=YES
ssl_sslv3=YES
require_ssl_reuse=NO

Для пользователей происходит вызов chroot, это значит, что попав на ФТП он не сможет подняться по уровням выше собственного каталога, узнать логины других пользователей и структуру подразделений. Также выполнен ряд настроек, касающихся пути к каталогу пользователя, SSL. Необходимо также позаботиться чтобы у пользователя, от имени которого запущен демон vsftpd были соответствующие права на каталоги.

Далее необходимо связать между собой домашние каталоги пользователей FTP и персональные папки, к которым пользователи имеют доступ по SAMBA. Сделать это можно с помощью создания ссылок, разрешив vsftp следовать по ним. Обслуживанием дерева занимается небольшой скрипт:

#!/bin/bash
FTPROOT=/opt/ftpROOT
HOMEDIRS=/home/ftp
cd $FTPROOT
for i in *; do
  echo $i;
  cd $i
  pwd
  for j in *; do
    if [ ! -L $HOMEDIRS/$j ]; then
      ln -s $FTPROOT/$i/$j $HOMEDIRS/
    fi
    /usr/bin/setfacl -R -dm "user:www-data:r-x" $FTPROOT/$i/$j
    /usr/bin/setfacl -R -m "user:www-data:r-x" $FTPROOT/$i/$j
    if [ ! -h $FTPROOT/$i/$j/index.php ]; then 
      ln $FTPROOT/index.php $FTPROOT/$i/$j/index.php
    fi
    echo "   $j";
  done
  cd ..
done

Этот скрипт обходит все каталоги пользователей в структуре общего ресурса, создает на них ссылки, устанавливает права и копирует файл index.php, о котором речь пойдет далее.
После того, как все запущено, доменные пользователи могут попадать на сервер по протоколу ftps под своими учетными записями от операционной системы. После подключения они, не видя и не вводя ни чего лишнего, оказываются в ссвоей персональной папке, с которой работают в офисной сети.

nginx

Следующее требование, которое должен удовлетворять файловый сервер — способность отдать файлы по http или https, чтобы за ними можно было обратиться из интернета без использования FTP-клиента. Для этих целей подойдет любой веб-сервер, в данном случае использовался nginx + php-fpm. Необходимо настроить его так, чтобы локации вели в определенные каталоги. Также для доступа к личным папкам необходимо наладить доменную авторизацию. У nginx нет поддержки работы с доменом, но такие возможности дает промежуточный сервис https://github.com/nginxinc/nginx-ldap-auth nginx-ldap-auth. Это просто промежуточный сервис, состоящий из локального веб-сервера и коннектора к LDAP. php-fpm необходимо для обработки вебстраницы со списком файлов. Ее имеет смысл сделать чтобы запретить просмотр каталогов.

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

Файл конфигурации nginx выглядит следующим образом:

worker_processes 4;
user ftp;
include /etc/nginx/modules-enabled/*.conf;
events{
  worker_connections 1024;
}
http{
  include mime.types;
  server{
    server_name ftp.corp.ru;
    listen 81;
    root /opt/ftpROOT;
    default_type application/octet-stream;
    location = /auth-proxy {
            internal;
            proxy_set_header X-Ldap-URL      "ldap://172.21.99.4:389";
            proxy_pass http://127.0.0.1:8888;
            proxy_pass_request_body off;
            proxy_set_header Content-Length "";
            proxy_cache_key "$http_authorization$cookie_nginxauth";
            proxy_set_header X-Ldap-BaseDN   "ou=users,dc=corp,dc=ru";
            proxy_set_header X-Ldap-BindDN   "cn=user,dc=corp,dc=ru";
            proxy_set_header X-Ldap-BindPass "Password";
            proxy_set_header X-CookieName "nginxauth";
            proxy_set_header Cookie nginxauth=$cookie_nginxauth;
            proxy_set_header X-Ldap-Template "(sAMAccountName=%(username)s)";
    }
    location ~ ^/dists$ {
            root /opt/ftpROOT/AllAxioma/dists;
            include snippets/fastcgi-php.conf;
            fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
    }
    location ^~ /dists/ {
            default_type application/octet-stream;
            root /opt/ftpROOT/AllAxioma;
    }
    location ~ ^/([a-zA-Z0-9]+)$ {
            auth_request /auth-proxy;
            root /opt/ftpROOT/$1/$remote_user; 
            include snippets/fastcgi-php.conf;
            fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
    }
    location ~ ^/([a-zA-Z0-9]+)/(.*) {
            auth_request /auth-proxy;
            default_type application/octet-stream;
            alias /opt/ftpROOT/$1/$remote_user/$2;
    }
  }
}

В конфигурации самая сложная локация auth-proxy содержит настройки для работы аутентификации пользователей Active Directory. Остальные 4 локации — запрос страницы общедоступных дистрибутивов и непосредственно дистрибутивов, а две другие — локации к персональным каталогам. url персональных директорий не содержит в себе логин, только название основной доменной группы, а адрес корневого каталога в итоге формируется на основе введенного доменного логина. В качестве протокола использован http, но сам сервер находится за обратным прокси, терминирующим ssl, поэтому доменные логины/пароли и вся остальная информация передается между пользователем и сервером по зашифрованному соединению.
Для работы nginx в предыдущем абзаце в скрипте написана строка копирования index.php:

<!DOCTYPE html>
<html><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <meta charset="UTF-8">
    <title>Список файлов</title>
	<link rel="stylesheet" type="text/css" href="css">
	<link type="text/javascript" href="js">
  </head>
  <body>
  <div class="hierarchy">
<?php
function dirEntryHTML($htmlpath, $httpbasename='', $name='.', $indent="\r\n\t"){
	$realpath=realpath($_SERVER['DOCUMENT_ROOT'].$htmlpath.'/'.$name);
	if($realpath==__FILE__) return; // не показываем самого себя
	if(is_file($realpath)) return $indent.'<li class="file"><a href="'.$httpbasename.$htmlpath.'/'.$name.'">'.$name.'</a></li>';
	else{
		$html=$indent.'<li class="folder">';
		if($name!='.') $html.=$indent."\t<span class=\"folder-name\">$name</span>";
		$html.=$indent."\t<ol class=\"folder-list\">";
		if ($handle = opendir($realpath)) {
			while (false !== ($file = readdir($handle))) {
				if($file!='.' && $file!='..') $html.=dirEntryHTML($htmlpath.'/'.$name, $httpbasename, $file, $indent."\t\t");
			}
		}
		return $html.$indent."\t</ol>".$indent."</li>\r\n";
	}
}
if(!preg_match('/'.basename(__FILE__).'$/',$_SERVER['REQUEST_URI'])) $requri=$_SERVER['REQUEST_URI'].'/'.basename(__FILE__);
else $requri=$_SERVER['REQUEST_URI'];
$basename=substr($requri, 0, -strlen($_SERVER['PHP_SELF']));
echo dirEntryHTML(substr(dirname(__FILE__),strlen($_SERVER['DOCUMENT_ROOT'])), $basename);
?>
  </div>
  
  </body>
</html>

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

owncloud

В качестве доступа через веб, в том числе и WebDAV использовалось облако owncloud. Для его работы требуется СУБД, в конкретно этом случае использовался Postgres и веб-сервер. Официально OwnCloud работает с apache. Попытки запустить его на nginx оказались безуспешными (не удалось заставить работать дополнительные методы web-dav). В установке OwnCloud нет ни чего сложного, файлы облака появляются в каталоге /var/www/owncloud, установка и настройка требует не много усилий, установщик будет сообщать каких модулей ему не хватает прежде чем запуститься.

После установки может потребоваться сделать какие-то изменения, файл настроек config/config.php имеет понятный синтаксис, а рядом находится config.sample.php с понятными пояснениями настроек.

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

Для настройки авторизации следует воспользоваться официальной документацией https://doc.owncloud.com/server/admin_manual/configuration/user/user_auth_ldap.html. После того, как авторизация пользователей начнет происходить, обязательно нужно в Advanced настроить параметр User Home Folder Naming Rule, указав там sAMAccountName для работы с Active Directory. Иначе при именовании папок они будут именоваться не логинами пользователей, а идентификаторами и разобраться в них будет крайне сложно.

После того, как LDAP-авторизация заработала и папка вошедшего доменного пользователя появляется с его логином в пути по умолчанию (каталог data в корне owncoud), слеует связать персональные каталоги пользователей, созанные ранее, с облачными каталогами и индексировать размещенные в них файлы. Это можно селать с пмощью небольшого сценария:

#!/bin/bash
FTPROOT="/opt/ftpROOT"
cd $FTPROOT
for i in * ; do
  if [ -d $i ] ; then
    if [[ $i != "lost+found" ]] ; then
      if [[ $i != "AllAxioma" ]] ; then
        cd $i;
        for j in * ; do
          if [ -d $j ] ; then
            if [ ! -d "$FTPROOT/.shadow/$j/files" ] ; then
              /bin/mkdir -p "$FTPROOT/.shadow/$j/files"
            fi
            /bin/chown -R ftp:www-data "$FTPROOT/.shadow/$j"
            ISMNT=`/bin/mount | /bin/grep $j | /usr/bin/awk '{print $3}'`
            if [ -z "$ISMNT" ] ; then
              /bin/mount --bind $j "$FTPROOT/.shadow/$j/files"
            fi
            echo "$FTPROOT/.shadow/$j/files"
          fi
        done
        cd $FTPROOT
      fi
    fi
  fi
done
/usr/bin/sudo -u ftp /var/www/owncloud/occ files:scan --all

В качестве каталога данных создана специальная скрытая папка, содержащая каталоги пользователей для облака. Необходимость в ней обусловлена тем, что помимо файлов, в каталоге пользователя также хранится кэш и служебная информация, а файлы находятся в подкаталоге files. Эта папка не доступна для работы по samba пользователям, только владельцу — пользователю, от имени которого запущен сервер.

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

Заключение

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

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

roox
1 Comment
  • Oleg Estrov
    Ответить
    Posted at 12:50, 06.05.2020

    Интересная статья, делающая понятным вещи, с которыми я даже не сталкивался

Post a Comment

Comment
Name
Email
Website