NextCloud в качестве сервиса по созданию защищенных ссылок

Привет, Хабр! Хочу поделиться немного нетривиальным кейсом по настройке NextCloud в качестве сервиса по созданию защищенных ссылок, для прямого скачивания данных с подключенного сетевого smb\cifs-диска. Опишу решения нюансов, с которыми столкнулся во время настройки.

Зачем это надо?


Удобная доставка контента конечному пользователю, минуя возню с FTP и невозможность (из-за NDA) воспользоваться публичными сервисами и облаками для передачи файлов (BTsync, Google-\Mail-\Yandex-Disk\Dropbox\etc).





Предисловие


Наш офис имеет определенную инфраструктуру, в неё входит в том числе и ActiveDirectory, в которой у нас находятся сотрудники, состоящие в группах.

Во время сеанса работы за ПК, после логина, средствами настроенных политик, у каждого сотрудника монтируется сетевой диск. Через него время-от-времени идет обмен данными. В диске есть определенная структура папок, права на которые настроены через эти самые группы. Каждый видит то, что ему позволено настройками.

Обычно, для отдачи данных во внешний мир — поднимается, либо отдельный FTP, либо данные выгружаются на уже имеющийся. Признаюсь, это далеко не всегда удобно — как минимум, создание и управление временными логинами и паролями (например, когда партнёрам нужно отдать готовый контент), контроль места на FTP-сервере, ручная выгрузка на FTP-сервер перед “отправкой”.

В какой-то момент нам потребовалось иметь возможность напрямую отдавать конечным пользователям данные во внешний мир именно с нашего сетевого диска и, желательно, чтобы это было относительно безопасно: можно создать ссылку для скачивания (у нее имелось время жизни, пароль, разграничение прав на исходные данные и так далее).

На такую идею нас натолкнули одни из партнеров, так как у них имелся внутренний сервис, но там он был самописным.

Готовых вариантов с ходу в поисковике не нашлось (если у вас есть оные на примете — отпишитесь, пожалуйста в комментариях), а тратить потенциально много человеко-часов на разработку с нуля, тестирование и поддержку — не было желания и ресурсов ни у кого. Да и зачем изобретать велосипед, если зачастую все уже придумано до. Так на ум и пришел сервис NextCloud, который умеет подключать к себе внешние ресурсы.

Речь пойдет о последней стабильной, на данный момент версии — 19, но наш метод настройки подойдет и для более ранних версий — мы изначально реализовали это на 16 версии и потом постепенно обновлялись. Недавно я как раз поднимал его с нуля на последней (19), и опираясь на неё пишу статью.

Что мы хотим получить в конечном итоге:


  • Только сотрудники могут заходить в наш сервис и только через ActiveDirectoty\LDAP, точно так же как заходят на офисный пк, в Jira, Confluence, Nexus и пр.
  • После авторизации в веб интерфейсе NextCloud, сотруднику должен быть подключен наш сетевой диск, с точно такими-же правами, как это происходит при заходе с рабочего компьютера.
  • При первом входе в NextCloud — у каждой учетной записи создаются файлы-примеры в домашнем каталоге, которые занимают места на диске. По хорошему, от этого надо избавиться.
  • Сотрудник не должен иметь возможность загружать что либо, как на подключенный диск, так и в аккаунт NextCloud .*Это просто наша хотелка, на самом деле — она не обязательная.
  • Сотрудник может создавать временные ссылки, защищенные паролем на любые доступные ему ресурсы — будь то папка или отдельный файл. А также управлять ими (ссылками) — отзывать, менять срок жизни и прочее.
  • Конечному пользователю, кому отправлена защищенная ссылка, достаточно её открыть и ввести пароль, чтобы получить возможность скачать расшаренные ему данные.



Развёртка и настройка зависимостей


Для начала, нам надо иметь отдельную виртуалку или сервер, где можно установить операционную систему, и после — NextCloud.

На Хабре есть не одна статья, посвященная развёртке системы и сервиса.

AlexanderS достаточно хорошо и подробно описал процесс от установки системы до самой настройки облака (включая актуализацию статей по годам). Не вижу смысла в очередной раз это всё повторять.

1. Так как мы подключаем в NextCloud сетевой диск, то нам понадобятся пакеты в систему: smbclient, libsmbclient , php-ldap, и php-smbclient.

Ремарка, на случай использования Docker
Если вы тоже используете докер, то напомню — официальный образ не имеет на борту пакетов для работы с samba и вам лучше создать форк, установив их в своем Dockerfile. И, согласно документации, установка пакета php-smbclient внутри их образа немного отличается от классического “apt install package”.

Пример Dockerfile
FROM nextcloud:latest
RUN apt update -y &&  apt install -y --allow-unauthenticated smbclient libsmbclient libsmbclient-dev
RUN pecl install smbclient
RUN docker-php-ext-enable smbclient



2. Из-за особенностей настроек нашего сервера samba (отключена поддержка smb1), на машине с nextcloud, в файлах /etc/samba/smb.conf и /usr/share/samba/smb.conf пришлось поменять строки, отвечающие за протокол:

[global] 
client min protocol = SMB2
client max protocol = SMB3

Продолжение примера Dockerfile
RUN rm -frv /etc/samba/smb.conf /usr/share/samba/smb.conf
ADD smb.conf /etc/samba/
ADD smb.conf /usr/share/samba/


В ином случае, nextcloud так и не смог подключиться к диску.



Настройка nextcloud


Итак, Nextcloud уже установлен, зависимости поставлены, а в сервисе заведен один внутренний юзер, который создался во время установки.

Шаг первый. Подготовка шаблона аккаунтов сотрудников.


Поскольку у нас будет не один сотрудник в системе, а постепенно их количество будет меняться — если заранее не настроить шаблон создаваемого пользователя — у каждого будет в домашней папке несколько файлов-примеров. Хорошо что по этому поводу у nextcloud есть отдельная настройка — skeleton files, которая настраивается в config.php.

  'skeletondirectory' => '/var/www/html/data/donotdeletme',

То есть, можно создать пустую папку и указать в конфиге полный путь к ней.

Шаг Второй. Делаем пользователей «read-only»


Достаточно указать квоту в «1 B» (1 байт) в разделе настроек пользователей (http(s)://nextcloud.domain.tld/settings/users).

Шаг третий — заранее чиним ZipStreamer


ZipStreamer — библиотека, используемая в бекенде NextCloud, она служит для создания архивов «на лету», то есть во время скачивания пачки файлов.



Как это работает
Если вы перейдя по шареной ссылке, нажали кнопку "Dowload All Files"/"Скачать все файлы", то вы заметите, что вам не показывается в браузере (или в менеджере загрузок) конечный вес архива, а полоса загрузки будет неопределенной.



Это связано с тем, что по этой кнопке система в режиме реального времени создает и отдает вам на скачивание архив (в большинстве случаев .zip, в редких кейсах — .tar)

Кстати, в силу особенности этой технологии, возобновление приостановленных загрузок в этом случае невозможно.

Похожее поведение есть у и аналогичных сервисов: Google Drive, Яндекс.Диск, и т.д.

Проблема кроется в том, что по неизвестным причинам, заложенная в NextCloud логика переключения zip в zip64 сбоит, и при случае, если в папке больше 65536 файлов, и\или их общий вес будет превышать 4гб — скорее всего вы столкнетесь с проблемой, что скачанный файл будет либо побит, либо загрузка будет прерываться после скачанных 4гб.

Данной проблеме выделяли достаточное время, на GitHub даже есть, и не один, закрытый тикет (#1755, #15871, #8798), но несмотря на то, что якобы проблема решена — у нас она так и осталась, и с переменным успехом воспроизводилась, очень мешая работе. Пришлось решать её более радикально.

Решение
Поскольку у нас 100% 64хбитная система, то мы принудительно говорим библиотеке использовать 64х-битный режим. «Решение в лоб».

<папка, где установлен nextcloud>/lib/private/Streamer.php:
- $this->streamerInstance = new ZipStreamer(['zip64' => false]);
+ $this->streamerInstance = new ZipStreamer(['zip64' => true]);

Ремарка, на случай использования Docker
В официальном образе происходит при каждом запуске контейнера некий Integrity Check и из одного места в другое распаковываются оригинальные файлы поверх установленных( из /usr/src/nextcloud/* в /var/www/html/*).

Поэтому просто в лоб замапить файл в условном /var/www не получится — при запуске файл либо перетрется оригиналом, либо контейнер запустится и упадет сразу с ошибкой.

Так что мы подменяем патченым файлом исходный в папке /usr/src/nextcloud/lib/private/ еще при сборке в CI нашего форкнутого образа. Получается, наш поправленный файл будет гарантированно всегда использоваться.

Продолжение примера Dockerfile
RUN rm -frv /usr/src/nextcloud/lib/private/Streamer.php
ADD Streamer.php /usr/src/nextcloud/lib/private/
RUN chown nobody:nogroup /usr/src/nextcloud/lib/private/Streamer.php

Эти манипуляции, по крайней мере при использовании докер-образа, в Панели Администрирования точно завалят вам встроенную проверку на подлинность, имейте это ввиду.




Но лично нас пока это устроило.

Шаг четвертый — настраиваем параметры ссылок


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

Шаг пятый — подключаем сетевой диск


  1. Переходим в настройку внешних хранилищ. (http(s)://nextcloud.domain.tld/settings/admin/externalstorages)
  2. Выбираем добавление SMB \ CIFS хранилища.
  3. Заполняем поля имени, домена, папки и тд.
  4. Выбираем «Учетные данные, хранить в базе данных» — именно этот пункт позволяет при заходе пользователя по его связке логина и пароля подключать диск к его учетной записи в NextCloud. (Пункт хранение логина и пароля во время сессии не взлетел).
  5. Не забываем в меню <...> отметить чекбоксами «Только чтение» и разрешение предоставление общего доступа.

Шаг шестой — запускаем пользователей через LDAP


Теперь, когда мы все подготовили — ставим из маркетплейса плагин, и сразу после подключаем LDAP. В нашей системе, мы давали доступ сотрудникам, которые находятся в группе NextcloudAccess. Можете сделать аналогично.



Заключение


Всё, после всех этих нехитрых, но местами не самых очевидных манипуляций — сервис работает, диск подключен, сотрудники добавлены, а пользователи качают и довольны.

Полный пример нашего Dockerfile
FROM nextcloud:latest
ENV DEBIAN_FRONTEND noninteractive

#installing smbclient
RUN apt update -y &&  apt install -y --allow-unauthenticated smbclient libsmbclient libsmbclient-dev
RUN pecl install smbclient
RUN docker-php-ext-enable smbclient

#fix of ZipStreammer
RUN rm -frv /usr/src/nextcloud/lib/private/Streamer.php
ADD Streamer.php /usr/src/nextcloud/lib/private/
RUN chown nobody:nogroup /usr/src/nextcloud/lib/private/Streamer.php

#fix of smb config
RUN rm -frv /etc/samba/smb.conf /usr/share/samba/smb.conf
ADD smb.conf /etc/samba/
ADD smb.conf /usr/share/samba/




Нагрузочное тестирование


«Как дела с нагрузкой?» — спросите вы напоследок.

Замеры в час пик




Наш инстанс сервиса крутится на ~ 6Gb Ram + 6CPU в виртуальной машине среди других VM.

При пике нагрузки на сеть — оперативной памяти использовалось чуть более 2.5Gb, процессор забит не был, а отдача в среднем была около 5Gbit/s (рекорд — доходило и до 8Gbit/s).

Единственное, что заметили — при отдаче сверх 6Gbit/s во внешний мир, у нас периодически отваливается web-интерфейс, но сами загрузки у пользователей продолжают идти.


Выявленные недостатки:


  • В NextCloud нету возможности глобального контроля над всеми созданными ссылками. Они отображаются только внутри каждого аккаунта в отдельном разделе.
  • Если вы расшарите по ссылке корень подключенного диска — это может служить потенциальной утечкой данных, так как в ссылке расшарятся все доступные вашему аккаунту папки.
  • Заметил, что за год использования поднятого сервиса, на данный момент, в базе данных таблица oc_filecache весит ~29Gb и имеет около ~100кк строк (мы используем ванильную MySQL 5.7.x). Это связано с багами #16834, #6395, #7312, #20349. Пока идет наблюдение на втором инстансе.



Спасибо, что дочитали. Если у вас есть вопросы, замечания или пожелания — не стесняйтесь, всегда рад конструктивной критике.



Проверено на: nextcloud 16, 17, 18, 19
Дата написания: 26.07.2020
Дата правок: 05.08.2020
Что поправлено: Поправил формулировку о режиме работы zip\zip64.
Версия: 1.0.0.8

Средняя зарплата в IT

113 000 ₽/мес.
Средняя зарплата по всем IT-специализациям на основании 5 065 анкет, за 2-ое пол. 2020 года Узнать свою зарплату
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 12

    +1
    У нас вообще NextCloud работает как оболочка для Amazon S3 — интерфейс проще, права настраиваются, можно приложение для синхронизации поставить, есть прямые ссылки. Под эту нагрузку вполне хватает бесплатного инстанса Amazon EC2, выходит хороший довесок к облачному хранилищу. До этого был Google Cloud Storage для хранилища, вот там не все хорошо со скоростью и интеграцией.
    А если вообще на локальный диск его направлять, то можно о коммерческих облаках и не задумываться, если, конечно, с бекапами вопрос продуман.
      +1
      Если файлы, которыми вы хотите делиться, это документы, и у вас уже есть сервак, можно подрубить редакторы onlyoffice github.com/ONLYOFFICE/onlyoffice-nextcloud
        0
        спасибо, надо посмотреть будет.

        интересно дополнительно проверить вариацию настройки — readonly smb-диск + onlyoffice (просто в качестве вьювера документов).
          0
          посмотрел, интересная штука с онлиофисом. в случае, если у нас r\o у подключенного диска (в случае кейса как в статье) — файлы можно просто просматривать и экспортировать. оставили у себя в проде на обкатку. спасибо.
          0

          Очень хочется перейти на Nextcloud, но останавливает отсутствие возможности запретить расшаривание папок. Что будет если ваш пользователь расшарит весь диск?


          Сидим пока на Pydio. Но у нас посложнее структура, пользователю монтируется 3-4 диска в винде и соответственно 3-4 workspace в Pydio.


          \file\users\LOGIN — Личный диск (где логин это имя пользователя)
          \file\departments\department_name — Диск отдела (в соответствии с отделом)
          \file\interaction — Диск Взаимодействие (всем)
          Некоторым еще четвёртый.


          Расшаривание папок запрещено (если нужно, то архивация и ссылка на архив), обязательное ограничение на срок жизни ссылок.


          Понятно, что всё в AD и завязано на группы.


          У этого метода есть минус, это безопасность. Чтоб расшарить файл, Pydio/Nextcloud приходится хранить реквизиты пользователя в себе, чтоб потом файл мог скачать не аутентифицированный пользователь по внешней ссылке. Соответственно компрометация Nextcloud/Pydio приведёт к утечке учетных данных пользователей домена.

            0
            но останавливает отсутствие возможности запретить расшаривание папок

            Если я вас правильно понял, то это как раз шаг четвертый в статье — если мы в админке не включим возможность шаринга — то никакую папку или файл не удастся расшарить по ссылке.

            Что будет если ваш пользователь расшарит весь диск?

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

              нюансы сервиса добавил в статью.
                0

                Нужно сохранить возможность расшаривать файлы, но запретить возможность расшаривать папки.


                Пользователи не сильно парятся о безопасности. Да и даже не в этом дело.
                Была папка, там было несколько файлов предназначенных для "внешних" глаз.
                Пользователь 1 её расшарил целиком, в процессе работы Пользователь 2 работая через диск, совершенно не подозревая, что папка расшарена вовне, надобавлял туда файлов не предназначеных для внешнего доступа.


                Или другой пользователь, ему надоело по одной папке расшаривать, расшарил весь диск "Сами ищите что вам нужно".

                  +1

                  Если всё устраивает кроме отсутствия одной фичи, то не проще ли сделать патч с этой фичей и попросить её втянуть в ядро NextCloud'а pull request'ом?

              0
              Проблема кроется в том, что по неизвестным причинам, заложенная в NextCloud логика сбоит, и при случае, если в папке больше 65536 файлов, и\или их общий вес будет превышать 4гб

              The maximum size for both the archive file and the individual files inside it is 4,294,967,295 bytes (232−1 bytes, or 4 GiB minus 1 byte) for standard ZIP.


              Wikipedia

                0
                чуть переформулировал в статье, спасибо. тут сбоит именно логика переключения из zip в zip64, в котором как раз-таки нету таких ограничений.

                For ZIP64, the maximum size is 18,446,744,073,709,551,615 bytes (264−1 bytes, or 16 EiB minus 1 byte).
                  0

                  Если бы использование другой библиотеки можно было включать флагом, неужели разрабы так не сделали?


                  Наверно zip64 сначала должна быть установлена в системе. Например в Ubuntu должен быть установлен пакет lib64z1 (который по умолчанию не ставится)

              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

              Самое читаемое