[Из песочницы] Облака — белогривые лошадки или безопасный ownCloud для «маленьких» в FreeNAS

imageownCloud, как утверждает Википедия — это Свободное и открытое веб-приложение для синхронизации данных, расшаривания файлов и удалённого хранения документов в «облаке». И, как мне кажется, довольно интересное решение для организации собственного домашнего облака.Однако, ownCloud, устанавливающийся в виде плагина в системе FreeNAS, да и просто из коробки, имеет ряд недостатков, от которых хотелось бы избавится даже при использовании дома:

Во-первых, устанавливается в связке с SQLite, что подходит только если у вас небольшое кол-во файлов и пользователей, и абсолютно не подходит, если вы планируете синхронизацию с помощью клиента. У меня же хранилище уже расползлось почти на 5Tb и установленный таким образом ownCloud просто отказывался видеть часть файлов. Да и без синхронизации отдача от облака не велика. Заменим базу данных на MariaDB. Во-вторых, отсутствует работа по https, а мне совсем не нравится мысль о том, что кто-то может перехватить мои файлы. Включим https. В-третьих, начисто отсутствует защита от банального подбора пароля методом брутфорса. Защитимся от брутфорса с помощью fail2ban. В-четвёртых, мне лень часто просматривать логи на предмет взлома, но очень хочется оперативно узнавать о таких попытках. Настроим push-оповещения о попытках подбора пароля с помощью сервиса pushover.net. Хочу сразу оговориться. Я не являюсь IT-специалистом, я всего лишь менеджер проектов в одном из российских системных интеграторов, а данная «инструкция» родилась в попытках настроить все 4 указанных пункта на своей домашней системе, FreeNAS работающей из-под Esxi. Инструкция написана новичком для новичков, поэтому если где-то есть явные ляпы или ошибки в командах и конфигах, то прошу указать их в комментариях.Все настройки будем делать из консоли, ручками, максимально приближено к тому, как это, как мне видится, делают «взрослые» айтишники.

1 Подготовка Jail для ownCloud1.1 Создаём Jail Данный шаг описывать не буду. Если у вас получилось установить FreeNAS и он у вас работает, то проблем с данным шагом у вас быть не должно. Создание первого Jail может занять довольно продолжительное время.1.2 Открываем доступ по SSH к данному Jail Удобнее всего дальнейшую настройку выполнять не через web-терминал, а через полноценную программу-терминал. Например, putty. Для этого откроем доступ по SSH к нашему Jail и создадим нового пользователя, от которого и будем проводить дальнейшую настройку.Выбираем в web-интерфейсе FreeNAS созданный нами Jail и нажимаем внизу кнопку Shell.

image

В веб-консоли Jail вводим:

# sysrc sshd_enable=«YES» Запускаем демон для работы ssh: # service sshd start Создаём пользователя от имени которого будем потом настраивать нашу систему. Пользователь будет иметь привилегии superuser, для чего мы включим его в группу wheel. # adduser Настройки adduser Usrname: Новый пользователь от имени которого мы будем производить все манипуляции в терминале. Вводим, например, superstepa.Full name: Полное имя этого пользователя. Вводим, например, Dyadya Stepa Policeman.Uid (Leave empty for default): Ну раз просят оставить пустым, то так и сделаем. Смело жмём Enter.Login group [superstepa]: Мы хотим чтобы наш пользователь обладал всеми правами местного администратора — superuser, а следовательно включаем его в группу wheel.Login group is wheel. Invite superstepa into other groups? []: Нажимаем Enter.Login class [default]: Жмём Enter.Shell (sh csh tcsh git-shell nologin) [sh]: Оставляем по-умолчанию sh. Просто жмём Enter.Home directory [/home/superstepa]: И опять Enter.Home directory permissions (Leave empty for default): И снова Enter.Use password-based athentications? [yes]: Хотим чтобы аутентификация этого пользователя проходила по паролю? Конечно да! Жмём Enter.Use an empty password? (yes/no) [no]: Мы же за безопасность и не хотим чтобы у нового пользователя с правами superuser был пустой пароль. А значит очередной раз жмём Enter.Use a random password? (yes/no) [no]: Я просто уверен, что придуманный нами пароль самый надежный. И мы хотим использовать именно его. А следовательно Enter.Enter password: Ага, а вот и он. Вводим свой пароль.Enter password again: Вводим его снова.Lock out the account after creation? [no]: Нет, блокировать этот аккаунт не нужно. Просто Enter.OK? (yes/no): Проверяем всё ли верно и если да, то пешем yes.Add another user? (yes/no): Других пользователей нам не надо. No.

2 Установка и подготовка к работе ownCloud Присоединяемся с помощью программы-терминала к нашему Jail.Вводим имя созданного нами пользователя и его пароль.На приглашение командной строки $ пишем su. Теперь приглашение командной строки сменится на что-то типа root@ownCloud:/usr/home/superstepa #, а все наши команды будут выполняться от имени superuser.Для упрощения, приглашение командной строки я буду обозначать символом #, а мои комментарии, которые вводить не надо, буду начинать с //.2.1 Устанавливаем необходимые пакеты Сначала обновляем текущие пакеты: # pkg upgrade Затем устанавливаем необходимые для работы ownCloud пакеты (на все возникающие вопросы отвечаем yes): # pkg install mariadb100-server php56-extensions php56-bz2 php56-curl php56-exif php56-fileinfo php56-gd php56-mbstring php56-mcrypt php56-pdo_mysql php56-openssl php56-zip php56-zlib pecl-APCu pecl-intl Для того, чтобы включить работу по https, собираем с нужными нам пакетами, а затем и устанавливаем из портов, web-сервер nginx: # portsnap fetch extract // скачиваем копию коллекции портов, это может занять много времени # cd /usr/ports/www/nginx && make config // конфигурируем и собираем web-сервер nginx В процессе сборки убеждаемся, что выбраны следующие пакеты: IPV6HTTPHTTP_CACHEHTTP_DAVHTTP_FLVHTTP_GZIP_STATICHTTP_PERLHTTP_REWRITEHTTP_SSLHTTP_STATUSWWW

# make install 2.2 Создаём самоподписанные ключи и сертификаты # cd /usr/local/etc/nginx/ Создаём корневой ключ server.key (алгоритм шифрования des3, длиной 1024 bit): # openssl genrsa -des3 -out server.key 1024 Для этого система дважды попросит ввести парольную фразу. Придумываем её и вводим.Создаём корневой сертификат:

# openssl req -new -key server.key -out server.csr Отвечать на вопросы можно как угодно. Главное: — на первый запрос Enter pass phrase for server.key ввести правильный пароль от корневого ключа созданного ранее, — обязательно ответить на все вопросы, иначе клиент ownCloud в дальнейшем может отказаться от синхронизации файлов, — запомнить введённые данные, чтобы в дальнейшем можно было легко вспомнить, что сертификат именно Ваш, — запомнить пароль введённый на вопросе A challenge password []:.Можно изменить срок действия нашего сертификата, например до 10000 дней, добавив в команду выше аргумент -days 10000. # cp server.key server.key.org //копируем наш ключ # openssl rsa -in server.key.org -out server.key //удаляем пароль из ключа # openssl x509 -req -days 3650 -in server.csr -signkey server.key -out server.crt // Генерируем сертификат 2.3 Включаем автозапуск web-сервера, PHP и базы данных # sysrc nginx_enable=«YES» php_fpm_enable=«YES» mysql_enable=«YES» 2.4 Устанавливаем редактор для удобного редактирования конфигов Всё-таки мы еще «маленькие» и пользоваться предустановленным редактором vi нам еще сложновато, поэтому поставим простенький редактор nano (на все возникающие вопросы отвечаем yes). # pkg install nano Внимание: После установки редактора, попробуйте его запустить командой nano. В каких-то непонятных пока мне случаях что-то идёт не так и вместо запуска появляется следующая ошибка: Shared object «libiconv.so.2» not found, required «libgmoudle-2.0.so.0

Для того чтобы это исправить выполним всего 2 команды: # pkg delete -f gettext # pkg upgrade 2.5 Корректируем конфиг веб-сервера nginx Как настоящие администраторы, всегда перед корректировкой конфига делаем его копию, чтобы в случае возникновения проблем всегда можно было откатиться назад: # cp /usr/local/etc/nginx/nginx.conf /usr/local/etc/nginx/nginx.old И редактируем файл конфига: # nano /usr/local/etc/nginx/nginx.conf Всё содержимое конфига заменяем на следующее: worker_processes 2; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; log_format main '$remote_addr — $remote_user [$time_local] »$request» ' access_log logs/access.log main; sendfile off; keepalive_timeout 65; gzip off; ssl_certificate /usr/local/etc/nginx/server.crt; // для того чтобы работал https ssl_certificate_key /usr/local/etc/nginx/server.key; // для того чтобы работал https server { listen 443 ssl; // для того чтобы работал https root /usr/local/www; location = /robots.txt { allow all; access_log off; log_not_found off; } location = /favicon.ico { access_log off; log_not_found off; } location ^~ /owncloud { index index.php; try_files $uri $uri/ /owncloud/index.php$is_args$args; client_max_body_size 512M; // максимальный размер файла для загрузки location ~ ^/owncloud/(?:\.|data|config|db_structure\.xml|README) { deny all; } location ~ \.php (?:$|/) { fastcgi_split_path_info ^(.+\.php)(/.*)$; fastcgi_pass unix:/var/run/php-fpm.sock; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; include fastcgi_params; fastcgi_param MOD_X_ACCEL_REDIRECT_ENABLED on; } location ~* \.(?: jpg|gif|ico|png|css|js|svg)$ { expires 30d; add_header Cache-Control public; } } } } Выход из редактора по нажатию Ctrl+X. Не забываем при выходе сохранять изменения.2.6 Корректируем конфиг php # cp /usr/local/etc/php.ini-production /usr/local/etc/php.ini # nano /usr/local/etc/php.ini В файле находим следующие строки (используем Ctrl+W для поиска) и даём им указанные значения: always_populate_raw_post_data = -1 // не забываем убирать ; в начале строки date.timezone = Europe/Moscow // либо указать Ваш часовой пояс cgi.fix_pathinfo=0 upload_max_filesize = 512M // либо указать максимальный размер файла доступный для загрузки в наше облако post_max_size = 512M // либо указать максимальный размер файла доступный для загрузки в наше облако 2.7 Корректируем php-fpm.conf: # cp /usr/local/etc/php-fpm.conf /usr/local/etc/php-fpm.old # nano /usr/local/etc/php-fpm.conf В файле находим следующие строки (используем Ctrl+W для поиска) и даём им указанные значения: listen = /var/run/php-fpm.sock listen.owner = www // не забываем убирать ; в начале строки listen.group = www env[PATH] = /usr/local/bin:/usr/bin:/bin 2.8 Корректируем /var/db/mysql/my.cnf: # cp /var/db/mysql/my.cnf /var/db/mysql/my.old # nano /var/db/mysql/my.cnf В файле будет пусто, поэтому внесём в него следующие строки: [server] skip-networking skip-name-resolve innodb_flush_method = O_DIRECT skip-innodb_doublewrite innodb_flush_log_at_trx_commit = 2 innodb_file_per_table expire_logs_days = 1 2.9 Запускаем веб-сервер nginx, PHP, MariaDB и настраиваем базу данных: # service nginx start && service php-fpm start && service mysql-server start Если всё было сделано верно, то всё запустится без ошибок и можно попробовать пройти в браузере по адресу https://.Нам напомнят, что сертификат у нас самоподписанный, но приняв его мы попадём на страницу с надписью 403 Forbidden.image

Настраиваем базу данных MariaDB:

# mysql_secure_installation Настройки MariaDB: Enter current password for root (enter for none): По умолчанию пароля нет, жмём Enter.Set root password? [Y/n]: Вводим Y.New password: Вводим новый пароль root.Re-enter new password: Повторяем введённый ранее пароль.На все остальные вопросы отвечаем Y, либо просто жмём Enter

Настраиваем базу данных ownСloud введя свои значения, где owncloud — название базы, ownclouduserdb — имя пользователя для работы с базой, а passwordownclouddb — пароль этого пользователя: # mysql -u root -p CREATE DATABASE owncloud; GRANT ALL PRIVILEGES ON owncloud.* TO 'ownclouduserdb' IDENTIFIED BY 'passwordownclouddb'; FLUSH PRIVILEGES; quit; 2.10 Скачиваем и устанавливаем актуальную версию OwnCloud По ссылке смотрим текущую актуальную версию ownCloud. На момент написания статьи это была версия 8.0.2.Скачиваем архив, где вместо 8.0.2 указываем текущую актуальную версию:

# fetch «http://download.owncloud.org/community/owncloud-8.0.2.tar.bz2» Разархивируем: # tar jxf owncloud-*.tar.bz2 -C /usr/local/www Удаляем ненужный теперь нам архив: # rm owncloud-*.tar.bz2 Назначаем системных владельцев (пользователя и группу) ownCloud: # chown -R www: www /usr/local/www/owncloud /mnt/files 2.11 Создаём задание в crone: # setenv EDITOR nano // для редактирования будем использовать установленный нами редактор nano # crontab -u www -e Прописываем в нём: */15 * * * * /usr/local/bin/php -f /usr/local/www/owncloud/cron.php Если всё было прописано верно, то мы получим следующее системное сообщение: crontab: installing new crontab

Идём теперь в браузере по адресу https:///owncloud и производим там последние настройки. Не забываем, что нам надо изменить тип применяемой базы данных, а для этого нажмём Хранилище и база данных и выберем наш тип базы: MySQL/MariaDB.imageЗаполняем поля Имя пользователя: Имя администратора нашего облака. Например, Stepanadministratovich.Пароль: Пароль администратора.Каталог с данными: Я предпочитаю /mnt/files/. В этот каталог я потом монтирую существующие у меня Volumes хранилища FreeNAS. Если надо объяснить как, то пишите в комментариях.Пользователь базы данных: Мы его создавали ранее на шаге 2.9 ownclouduserdb.Пароль базы данных: Также назначали ранее на шаге 2.9 passwordownclouddb.Название базы данных: Всё тот-же шаг 2.9 owncloud.

Наш ownCloud уже готов к работе.image

3 Дополнительные настройки 3.1 Просим поисковых роботов (Yandex, Google и т.д.) не индексировать наш сайт: # ln -s /usr/local/www/owncloud/robots.txt /usr/local/www 4 Защита от подбора пароля 4.1 Устанавливаем fail2ban из портов: # cd /usr/ports/security/py-fail2ban # make install clean Структура каталогов fail2ban Fail2ban лежит по следующему пути: /usr/local/etc/fail2ban. Структура расположенных там каталогов и файлов: папка action.d — содержит файлы действийпапка filter.d — файлы фильтровфайл fail2ban.conf — основной файл конфигурациифайл jail.conf — файл настройки защиты конкретных сервисов

4.2 Настраиваем логирование в ownCloud: Создаём файл в который будут писаться логи ownCloud при неудачной попытке входа: touch /var/log/owncloud-acces.log Файл должен быть доступен для записи пользователю www: # cd /var/log/ # chown www: www owncloud-acces.log Включаем логирование неудачных входов в ownCloud: # nano /usr/local/www/owncloud/config/config.php В файле находим или добавляем перед самой последней строкой следующие строки (пользуйтесь поиском Ctrl+W) и даём им указанные значения: 'logtimezone' => 'Europe/Moscow', // или другой Ваш часовой пояс 'logfile' => '/var/log/owncloud-acces.log', 'loglevel' => '2', 'log_authfailip' => true, Проверим ведётся ли логирование неудачных входов: Несколько раз пробуем войти в web-интерфейс ownCloud с заведомо неправильным паролем или именем пользователя.Затем выполним в консоли команду:

# nano /var/log/owncloud-acces.log Если всё сделано правильно, то в файле появятся записи вида: {«reqId»: «es09787k250rv52fu0iu44124z494687», «remoteAddr»:»192.168.1.1», «app»: «core», «message»: «Login failed: 'Admin' (Remote IP: '192.168.1.10', X-Forwarded-For: '')», «level»:2, «time»:»2015–04–04T18:59:50+03:00»}

4.3 Создаём файл фильтра для fail2ban: nano /usr/local/etc/fail2ban/filter.d/owncloud.conf В файле пишем следующее: [Definition] failregex={«app»: «core», «message»: «Login failed: user '.*' , wrong password, IP: HOST>», «level»:2, «time»:».*»} // для версий ownCloud<= 7.0.1 {"app":"core","message":"Login failed: '.*' \(Remote IP: '', X-Forwarded-For: '.*'\)», «level»:2, «time»:».*»} // для версий ownCloud=7.0.2–7.0.5 {«reqId»:».*», «remoteAddr»:»», «app»: «core», «message»: «Login failed: .*», «level»:2, «time»:».*»} // для версий ownCloud>=8 По сути это парсер, который во всей той служебной информации, которую ownCloud пишет в свой лог, должен найти ip-адрес того, кто пытался подобрать пароль на вход. Те элементы, что никогда не меняются в записях лога — указаны тут в явном виде. Те, что меняются — заменены на *. Ну, а собственно ip-адресс, который мы ищем, заменён на переменную \.4.4 Редактируем файл настроек сервисов: # cp /usr/local/etc/fail2ban/jail.conf /usr/local/etc/fail2ban/jail.old # nano /usr/local/etc/fail2ban/jail.conf Добавляем в самом низу файла jail.conf: [owncloud] enabled = true filter = owncloud port = https logpath = /var/log/owncloud-acces.log // путь к файлу логов ownCloud, который указывали на шаге 4.2 ignoreip = 192.168.1.59 // здесь указываются ip-адреса которые банится не будут maxretry = 2 // количество неудачных попыток до бана bantime = 86400 // время бана в секундах findtime = 600 // время в течение которого введено необходимое для бана к-во попыток в секундах action = bsd-ipfw // указываем какие файлы действий выполнять pushover-notify // описание данного файла действий будет ниже по тексту статьи, вводить здесь название данного действия необходимо с новой строки и после нажатия клавиши Tab. 4.5 Проверяем работает ли наш фильтр и может ли он найти в логе ownCloud нужные строки с попытками неудачного входа: # fail2ban-regex /var/log/owncloud-acces.log /usr/local/etc/fail2ban/filter.d/owncloud.conf Если всё верно, то в низу выдачи будет строка вида: Lines: 2 lines, 0 ignored, 2 matches, 0 missed [processed in 0.0 sec]

4.6 Настраиваем действия, которые будут производится в случае неудавшихся попыток входа: # cp /usr/local/etc/fail2ban/action.d/bsd-ipfw.conf /usr/local/etc/fail2ban/action.d/bsd-ipfw.local # nano /usr/local/etc/fail2ban/action.d/bsd-ipfw.conf Оставляем в нём всё по умолчанию. В нём уже прописано правило, что при отправке в бан, ip-адрес добавляется в table (1) файервола ipfw: actionban = ipfw table \ add \

Добавляем в сам файервол ipfw правило, блокирующее все ip-адреса, находящиеся в таблице table (1), т.к. пока нет никаких правил у файервола что делать с адресами из этой нашей таблицы (1): # ipfw add 1 deny all from table\(1\) to me Немного примеров по работе с ipfw: ipfw list //Просмотреть имеющиеся правила ipfw delete 13 //Удалить правило 13 ipfw add 14 <правило> //Добавить правило 14 ipfw table 1 add 192.168.1.5 //добавление в таблицу ipfw table 1 add 192.168.1.0/24 //добавление в таблицу подсеть ipfw table 1 list //посмотреть что в таблице ipfw add deny ip from table (10) to me //Всё с таблицы 50 ко мне ipfw table 1 delete 192.168.1.5 //удаляем из таблицы ipfw table 1 flush //чистим всю таблицу 4.7 Запускаем fail2ban: Перед запуском создадим для fail2ban файл описывающий действие pushover-notify, о котором была уже речь выше и о котором мы ещё поговорим: #touch /usr/local/etc/fail2ban/action.d/pushover-notify.conf Прописываем автостарт fail2ban в /etc/rc.conf: # sysrc fail2ban_enable=«YES» И запускаем его: # /usr/local/etc/rc.d/fail2ban start Если всё сделали правильно, то он запустится, если нет — разбирайтесь где ошибка. Если запустился, то проверяем на бан: заходим со стороннего ip-адреса с неправильным паролем. Должно забанить на время, которое мы указали в файле jail.conf.Немного примеров по работе с fail2ban, которые могут пригодится в процессе отладки: fail2ban-client status // Посмотреть какие джейлы активны fail2ban-client status owncloud // Посмотреть статус конкретного джейла, где owncloud — это имя нашего джейла fail2ban-client set owncloud unbanip MYIP // Удалить конкретный ip-адрес из бана, где MYIP — этот самый ip-адрес Собственно теперь у нас есть ownCloud, работающий на «взрослой» базе данных по https с защитой от подбора паролей.Почти всё, но давайте ещё добавим уведомление о блокировке при неправильном вводе пароля в виде push-уведомлений на наш телефон.5 Уведомление о блокировке ip-адреса Для push-уведомлений будем использовать сервис pushover.net. Я думаю Вам теперь не составит труда разобраться с его API. Но если возникнут сложности, то пишите в комментариях и я добавлю соотвествующее описание по работе с данным сервисом.5.1 Настраиваем уведомления pushover о неудачных попытках входа и бане: # nano /usr/local/etc/fail2ban/action.d/pushover-notify.conf В файле прописываем следующее: [Definition] actionstart= actionstop= actioncheck= actionban = url -k https://api.pushover.net/1/messages.json -F token= -F user= -F title=«ownCloud Alarm» -F message=» is banned after attemts against » actionunban = url -k https://api.pushover.net/1/messages.json -F token= -F user= -F title=«ownCloud Alarm» -F message=» is unbanned»

[Init] name = default token = [API Token/key (application key)] user = [User key] , где [API Token/key (application key)] и [User key] соответствующие значения с сайта pushover.net.Перезапускаем fail2ban # /usr/local/etc/rc.d/fail2ban restart Проверяем работу уведомлений выполнив несколько неудачных попыток входа в ownCloud: image

Вот и всё. Не забываем пробросить на роутере порты 80 и 443 для доступа к ownCloud.И да, для большей безопасности можно заменить стандартные порты на что-то более экзотическое.

© Habrahabr.ru