установка ProFTPd для типового хостинга

с виртуальными пользователями в MySQL

Постановка задачи: установить сервер proFTPd на сервер с платформой debian через ssh; в качестве альтернативного хранилища пользователей - использовать базу данных MySQL; настроить использование шифрованных паролей и использование сертификатов SSL для FTP-сервера; задействовать механизм назначения прав пользователей и групп; установить квоты произвольного типа (hard и soft); оптимизировать сервер, обеспечив защиту ftp сервера от атак, ошибок и сбоев; проверить работу сервера с русскоязычными названиями файлов; протестировать работу сервера из шелла cmd, браузеров и "проводника" windows.

Введение или матчасть

Несомненными лидерами среди FTP-серверов на сегодняшний день являются pure-ftpd, proftpd и vsftpd. Когда у Вас сотни пользователей и десятки доменов на сервере, неудобно на каждого заводить системного пользователя, поэтому в этой статье я сохранил методику настройки proftpd 1.3.4a с хранением списка виртуальных пользователей в MySQL.

Как обычно, подробная справка найдется на сайте производителя – http://www.proftpd.org/docs/

Итак, приступаем к настроке сервера ftp - ProFTPD:

  1. Установка proftpd под Debian Lenny
  2. Настройка proftpd для работы с виртуальными пользователями в MySQL
  3. Тестирование начальной конфигурации
  4. Добавление виртуальных пользователей, расстановка прав
  5. Увеличиваем безопасность ftp-сервера (опционально)
  6. Добавляем сертификат SSL к серверу ProFTPD
  7. Шифруем Palintext пароли в БД

1. Установка proftpd под Debian Wheezy

debian:/# apt-cache search proftpd

proftpd-mod-mysql - versatile, virtual-hosting FTP daemon - MySQL module
proftpd - versatile, virtual-hosting FTP daemon

debian:/# apt-get install proftpd proftpd-mod-mysql

запустится конфигуратор – выбираем тип "самостоятельно" из предложенного , так как у нас предполагается нагруженный ftp сервер.

Preconfiguring packages ...
Selecting previously unselected package libfile-copy-recursive-perl.
...
Adding system user `proftpd' (UID 105) ...
Adding new user `proftpd' (UID 105) with group `nogroup' ...
Not creating home directory `/var/run/proftpd'.
Adding system user `ftp' (UID 106) ...
Adding new user `ftp' (UID 106) with group `nogroup' ...
Creating home directory `/srv/ftp' ...
`/usr/share/proftpd/templates/welcome.msg' -> `/srv/ftp/welcome.msg.proftpd-new'
[....] Starting ftp server: proftpd ok
Setting up proftpd-mod-mysql (1.3.4a-5+deb7u1) ...
Setting up proftpd-mod-vroot (0.9.2-2+b2) ...

2. Настройка proftpd для работы с виртуальными пользователями в MySQL

Обратите внимание на то, что было создано в вашей системе:

Adding system user `proftpd' (UID 105) ...
Adding new user `proftpd' (UID 105) with group `nogroup' ...
Not creating home directory `/var/run/proftpd'.
Adding system user `ftp' (UID 106) ...
Adding new user `ftp' (UID 106) with group `nogroup' ...
Creating home directory `/srv/ftp' ...

В частности, нас интересуют идентификаторы вновь созданных пользователей proftpd:

debian:/# cat /etc/passwd | grep ftp

proftpd:x:105:65534::/var/run/proftpd:/bin/false
ftp:x:106:65534::/srv/ftp:/bin/false

Запомним порядковый номер пользователя и группу proftpd (105, 65534), а также тип шелла - /bin/false. Домашний каталог нового пользователя - /srv/ftp.

Создадим файл для хранения логов сервера proftpd с базой MySQL и даём на него необходимые права:

debian:/# touch /var/log/proftpd/proftpd_sql.log
debian:/# chown proftpd:root /var/log/proftpd/proftpd_sql.log

Далее создаём БД, где будут храниться пользователи, ошибки и логи доступа к нашему серверу ftp.

debian:/# mysql -u root -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 75
Server version: 5.5.35-0+wheezy1-log (Debian)
Type 'help;' or '\h' for help.Type '\c' to clear the current input statement.

mysql> create database proftpd;
Query OK, 1 row affected (0.02 sec)

mysql> grant all on proftpd.* to 'proftpd'@'localhost' identified by 'proftpdPASSWORD';
Query OK, 0 rows affected (0.19 sec)

mysql> quit
Bye

Прежде чем создавать таблицы в БД, уточним какие таблицы нам нужны и какой функционал мы будем вкладывать в них. Нам понадобятся 6 таблиц:

  1. group_ftp - Таблица групп пользователей ProFTP и их членов
  2. users_ftp - Таблица пользователей сервера FTP
  3. quotalimits_ftp - Основная таблица квот доступа сервера FTP
  4. quotatallies_ftp - Интегральная таблица квот доступа сервера FTP
  5. errors_ftp - Логи ошибок работы сервера FTP
  6. access_ftp - Логи доступа к серверу FTP
-- phpMyAdmin SQL Dump
-- version 2.11.8.1deb5+lenny7
-- http://www.phpmyadmin.net
--
-- Версия сервера: 5.0.51
-- Версия PHP: 5.2.6-1+lenny9

--
-- База данных: `proftpd`
--

-- --------------------------------------------------------

--
-- Структура таблицы `group_ftp`
--

CREATE TABLE IF NOT EXISTS `group_ftp` (
  `groupname` varchar(16) NOT NULL default '',
  `gid` int(11) NOT NULL default '65534',
  `members` varchar(16) NOT NULL default '',
  KEY `groupname` (`groupname`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Таблица групп пользователей ProFTP и их членов';

-- --------------------------------------------------------

--
-- Структура таблицы `users_ftp`
--

CREATE TABLE IF NOT EXISTS `users_ftp` (
  `id` int(11) NOT NULL auto_increment,
  `username` varchar(20) NOT NULL,
  `password` varchar(50) NOT NULL,
  `descr` text character set koi8u NOT NULL,
  `groupname` varchar(24) NOT NULL,
  `uid` int(11) NOT NULL,
  `gid` int(11) NOT NULL,
  `homedir` varchar(50) NOT NULL,
  `shell` varchar(20) NOT NULL,
  `last_login` int(15) NOT NULL,
  `login_count` int(15) NOT NULL,
  `last_err_login` int(15) NOT NULL,
  `err_login_count` int(15) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COMMENT='Таблица пользователей сервера FTP';

--
-- Структура таблицы `access_ftp`
--

CREATE TABLE IF NOT EXISTS `access_ftp` (
  `id` int(32) NOT NULL auto_increment,
  `timestamp` int(15) NOT NULL,
  `user_name` varchar(64) NOT NULL,
  `file_and_path` tinytext NOT NULL,
  `bytes` int(15) NOT NULL default '0',
  `client_name` varchar(127) NOT NULL,
  `client_IP` varchar(15) NOT NULL,
  `client_command` varchar(5) NOT NULL,
  `send_time` varchar(9) NOT NULL default '0',
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COMMENT='Логи доступа к серверу FTP';

-- --------------------------------------------------------

--
-- Структура таблицы `errors_ftp`
--

CREATE TABLE IF NOT EXISTS `errors_ftp` (
  `id` int(32) NOT NULL auto_increment,
  `timestamp` int(15) NOT NULL,
  `user_name` varchar(64) NOT NULL,
  `file_and_path` tinytext NOT NULL,
  `client_name` varchar(127) NOT NULL,
  `client_IP` varchar(15) NOT NULL,
  `client_command` varchar(5) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COMMENT='Логи ошибок работы сервера FTP';


-- --------------------------------------------------------

--
-- Структура таблицы `quotalimits_ftp`
--

CREATE TABLE IF NOT EXISTS `quotalimits_ftp` (
  `id` int(32) NOT NULL auto_increment,
  `name` varchar(30) default NULL,
  `quota_type` enum('user','group','class','all') NOT NULL,
  `per_session` enum('false','true') NOT NULL,
  `limit_type` enum('soft','hard') NOT NULL,
  `bytes_in_avail` float NOT NULL,
  `bytes_out_avail` float NOT NULL,
  `bytes_xfer_avail` float NOT NULL,
  `files_in_avail` int(10) unsigned NOT NULL,
  `files_out_avail` int(10) unsigned NOT NULL,
  `files_xfer_avail` int(10) unsigned NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COMMENT='Основная таблица квот доступа сервера FTP';

-- --------------------------------------------------------

--
-- Структура таблицы `quotatallies_ftp`
--

CREATE TABLE IF NOT EXISTS `quotatallies_ftp` (
  `id` int(32) NOT NULL auto_increment,
  `name` varchar(30) NOT NULL,
  `quota_type` enum('user','group','class','all') NOT NULL,
  `bytes_in_used` float NOT NULL,
  `bytes_out_used` float NOT NULL,
  `bytes_xfer_used` float NOT NULL,
  `files_in_used` int(10) unsigned NOT NULL,
  `files_out_used` int(10) unsigned NOT NULL,
  `files_xfer_used` int(10) unsigned NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COMMENT='Интегральная таблица квот доступа сервера FTP';

[users_ftp]

id: уникальный номер
username: имя пользователя
password: пароль
descr: комментарий
groupname: группа
uid: uid
gid: gid
homedir: домашний каталог
shell: определяем шелл для пользователя
last_login: последний вход
login_count: количество входов
last_err_login: последний неудачный вход
err_login_count: количество неудачных входов

[quotalimits_ftp]

name: имя виртуального пользователя
quota_type: тип ограничения по (user,qroup,class или all - для всех)
per_session: true - использовать квоту только на текущую сессию, в этом случае ни куда не записывается размер использованной квоты и для каждой новой сессии используется указанная квота. false - в этом случае использование квоты заноситься в базу данных.
limit_type: soft - возможно некоторое превышение квоты
hard - жёстко заданная квота, превышение невозможно
bytes_in_avail лимит загрузки в байтах ( если 150 Мб то 157286400 байт) 0 = нет лимита
bytes_out_avail лимит скачивания в байтах. 0 = нет лимита
bytes_xfer_avail: Лимит передачи в байтах.0 = нет лимита
files_in_avail: Лимит количества загружаемых файлов. 0 = нет лимита
files_out_avail: Лимит количесва скачиваемых файлов. 0 = нет лимита
files_xfer_avail: Лимит количесва передачи файлов. 0 = нет лимита

Добавить этот дамп БД можно любым доступным Вам способом (через phpMyadmin, webmin, через командную строку). Так как ftp сервер я ставлю в ряду первых, то phpMyAdmin (PMA) и Webmin еще не сконфигурирован, поэтому с учётом работы по ssh самым простым способом залить дамп-файл будет через перенаправление потока ввода:

debian:/# cd /srv/ftp/
debian:/# tee proftpd.sql

Копируем содержимое приведенного выше файла proftpd.sql в буфер обмена, нажимаем правую кнопку мыши в консоли putty и закрываем полученный файл с сохранением по Ctrl+C

Замечание: учтите только кодировку, в которой работает терминал putty. У меня это utf8, что совпадает с кодировкой БД, если же на вкладке настроек putty->window->Translation стоит отличная от utf8, то и кодировка файла созданного tee будет соответствующей.

Вносим дамп в БД:

debian:/# mysql -u proftpd -p proftpd < proftpd.sql
Enter password:

Теперь заполним созданную базу первичными данными для отладки. Создадим двух пользователей: demon с мягкой квотой в 1GB(1073741824 bytes), и admin - без квот.

Замечание: Обратите внимание, что оба этих пользователя будут относиться к виртуальной ftp-группе proftpd и наследовать ID-реального системного пользователя proftpd(105). Вы можете присваивать любой другой номер ID, не совпадающий с системными и создавать и помещать в любые другие группы, чтобы они не пересекались в "системном" пространстве.

--
-- Дамп `users_ftp`, `group_ftp`, `quotatallies_ftp`, `quotalimits_ftp` для создания 2-х пользователей
--

USE `proftpd`;

INSERT INTO `users_ftp` (`id`, `username`, `password`, `descr`, `groupname`, `uid`, `gid`, `homedir`, `shell`, `last_login`, `login_count`, `last_err_login`, `err_login_count`) VALUES
(1, 'admin', '111', 'Администратор хостинга', 'proftpd', 105, 65534, '/var/www/public_html', '/bin/false', 0, 0, 0, 0),
(2, 'demon', '111', 'Администратор ftp хостинга', 'proftpd', 105, 65534, '/var/www/vhosts/site.ru', '/bin/false', 0, 0, 0, 0);

INSERT INTO `group_ftp` (`groupname`, `gid`, `members`) VALUES 
('proftpd', 65534, 'admin, demon');

INSERT INTO `quotalimits_ftp` (`id`, `name`, `quota_type`, `per_session`, `limit_type`, `bytes_in_avail`, `bytes_out_avail`, `bytes_xfer_avail`, `files_in_avail`, `files_out_avail`, `files_xfer_avail`) VALUES
(1, 'demon', 'user', 'false', 'soft', 1073741824, 0, 0, 0, 0, 0);
INSERT INTO `quotatallies_ftp` (`id`, `name`, `quota_type`, `bytes_in_used`, `bytes_out_used`, `bytes_xfer_used`, `files_in_used`, `files_out_used`, `files_xfer_used`) VALUES
(1, 'demon', 'user', 0, 0, 0, 0, 0, 0);

Технический нюанс: Также обратите внимание, что при задействовании квот, необходимо внести записи в ДВЕ таблицы: quotalimits_ftp и quotatallies_ftp. Так как сам сервер у меня почему то отказался вносить эту запись самостоятельно при первом запуске. Тоесть, если Вы хотите задействовать квоты для пользователя - создавайте записи по аналогии в обоих таблицах - quotalimits_ftp и quotatallies_ftp, в одной устанавливайте квоту и тип, а в другой устанавливайте значение по нулям.

Замечание: Жёсткая квота (жесткий предел) жёстко оборвёт фаил при закачке по достижении заданного значения, мягкая квота (мягкий предел) позволит Вам дозакачать файл (что может привести к превышению на гигабайты!), а потом запретит закачивать, пока Вы не освободите достаточно места для операции.

Закачиваем в БД по аналогии с предыдущим дампом через перенаправление потока ввода:

debian:/# cd /home/ftp/
debian:/# tee proftpd_user.sql

Снова копируем содержимое приведенного выше файла proftpd_user.sql в буфер обмена, нажимаем правую кнопку мыши в консоли putty и закрываем полученный файл с сохранением по Ctrl+C. Вносим дамп в БД:

debian:/# mysql -u proftpd -p proftpd < proftpd_user.sql
Enter password:

Создаём директорию для пользователя `demon` и даём на неё права пользователю `proftpd`:

debian:/# mkdir -p /home/ftp/demon
debian:/# chown proftpd:nogroup  /home/ftp/demon

В версии ProFTPd 1.3.4a конфигурационные файлы поделены на несколько файлов. Проёдемся по ним по очереди, основной файл конфигурации /etc/proftpd/proftpd.conf:

 
debian:/# vim /etc/proftpd/proftpd.conf

ServerName	"ProFTPD Development server"

User	proftpd
Group	nogroup
TransferLog /var/log/proftpd/xferlog.log
SystemLog /var/log/proftpd/proftpd.log

# Нам надо чтобы ВСЕ пользователи по ftp были ограниченны своей домашней директорией, то надо раскомментировать
# следующую строку:
# DefaultRoot ~
# Здесь можете указать, кому можно иметь доступ ко всему серверу Можно указать отдельную группу 
# или конкретных пользователей.
DefaultRoot ~ !demon

# Комментируем старый механизм квотирования
[...]
#<IfModule mod_quotatab.c>
#QuotaEngine off
#</IfModule>
[...]

# Alternative authentication frameworks
#
#Include /etc/proftpd/ldap.conf
Include /etc/proftpd/sql.conf
[...]

Теперь расскоментируем "альтернативный способ авторизации" наших клиентов в файле конфигурации /etc/proftpd/modules.conf:

debian:/# vim /etc/proftpd/modules.conf

... задействуем следующие модули:

[...]
# Install proftpd-mod-mysql or proftpd-mod-pgsql to use this
LoadModule mod_sql.c
[...]
# Install proftpd-mod-mysql to use this
LoadModule mod_sql_mysql.c
[...]
# Install proftpd-mod-pgsql or proftpd-mod-mysql to use this
LoadModule mod_quotatab_sql.c
[...]

В завершение разберемся, как устроен файл конфигурации /etc/proftpd/sql.conf... Принципиальных вариантов настройки SQL для этого сервера в интернете несколько. Основные отличия в использовании нестандартных полей в таблицах, чтобы расширить функциональность сервера. Например Вы можете использовать краткую форму указания параметров запроса для таблицы:

SQLUserInfo ftpuser userid passwd uid gid homedir shell

Или написать запрос самостоятельно, с указанием всех необходимых аргументов:

debian:/# vim /etc/proftpd/sql.conf

#
# Proftpd configuration for SQL-based authentication.
# 20/04/2011
# (This is not to be used if you prefer a PAM-based SQL authentication)
#
<IfModule mod_sql.c>
#
# Choose a SQL backend among MySQL or PostgreSQL.
# Both modules are loaded in default configuration, so you have to specify the backend
# or comment out the unused module in /etc/proftpd/modules.conf.
# Use 'mysql' or 'poastgres' as possible values.
#

SQLBackend              mysql

# The passwords in MySQL are encrypted using CRYPT
# Тип авторизации (для начала будем хранить пароли открытым текстом, потом зашифруем)
SQLAuthTypes            Plaintext Crypt

# Кого и как аутентифицируем, можно указать конкретно группы, 
# или создать группы для каждого клиента в таблице group_sql 
SQLAuthenticate         users groups

# инфа для соединения с MySQL сервером:
# имя_БД@хост_где_БД:порт имя_пользователя_БД пароль
SQLConnectInfo proftpd@localhost:3306 proftpd proftpdPASSWORD

# Here we tell ProFTPd the names of the database columns in the "usertable"
# we want it to interact with. Match the names with those in the db
# Первое значение - имя таблицы, остальное что будет выбираться из неё
SQLUserInfo `users_ftp` `username` `password` `uid` `gid` `homedir` `shell`

# Here we tell ProFTPd the names of the database columns in the "grouptable"
# we want it to interact with. Again the names match with those in the db
SQLGroupInfo `group_ftp` `groupname` `gid` `members`

# set min UID and GID - otherwise these are 999 each
# Установите минимальный ID пользователя/группы который будет иметь возможность использовать наш FTP
SQLMinID        30

# Изменим пользователя и группу по умолчанию (65533:65533) на нашего пользователя 105(proftpd) 
# и группу 65534(nogroup) 
SQLDefaultUID   105
SQLDefaultGID   65534

# create a user's home directory on demand if it doesn't exist
CreateHome on

# Update count every time user logs in
# Записываем удачные логины в БД. 
SQLLog PASS counter_login
SQLNamedQuery counter_login UPDATE "`last_login`=UNIX_TIMESTAMP(), `login_count`=`login_count`+1 \
WHERE `username`='%u'" `users_ftp`

# Записываем также неудачные логины в БД
SQLLog ERR_PASS counter_err
SQLNamedQuery counter_err UPDATE "`last_err_login`=UNIX_TIMESTAMP(), `err_login_count`=`err_login_count`+1 \
WHERE `username`='%U'" `users_ftp`

# Update modified everytime user uploads or deletes a file
# логируем что сохраняем работу с ftp данными
# %u - имя пользователя (с которым залогинился)
# %f - полный путь и имя файла который был скачан
# %b - число байт, которые были скачаны
# %h - имя клиента (из DNS), если не удалось разрешить - IP
# %a - IP-адрес клиента
# %m - имя команды полученной от клиента (RETR/STOR)
# %T - время (секунд) ушедшее на передачу файла клиенту
SQLLog RETR,STOR,DELE log_story_transfer
SQLNamedQuery log_story_transfer INSERT "'', UNIX_TIMESTAMP(),'%u', '%f', '%b', '%h', '%a', '%m', '%T'" `access_ftp`

# записываем ошибки при сохранении и чтении файлов
SQLLOG ERR_RETR,ERR_STOR,ERR_DELE,ERR_RMD,ERR_RNTO log_err_modify
SQLNamedQuery log_err_modify INSERT "'', UNIX_TIMESTAMP(), '%u', '%f', '%h', '%a', '%m'" `errors_ftp`

# Лог файл работы с SQL
SQLLogFile /var/log/proftpd/proftpd_sql.log

# User quotas
# Управление квотами
# ===========
QuotaEngine on
QuotaDirectoryTally on

# директива настраивает mod_quotatab принять каталоге операций (например, создание каталогов, удаление каталога)
# во внимание при подсчете
# Отображения информации квоты в мегабайтах
QuotaDisplayUnits Mb

# директиву можно использовать для включения / выключения mod_quotatab
QuotaShowQuotas on

SQLNamedQuery get-quota-limit SELECT "name, quota_type, per_session, limit_type, \
bytes_in_avail, bytes_out_avail, bytes_xfer_avail, files_in_avail, files_out_avail, \
files_xfer_avail FROM quotalimits_ftp WHERE name = '%{0}' AND quota_type = '%{1}'"

SQLNamedQuery get-quota-tally SELECT "name, quota_type, bytes_in_used, bytes_out_used, \
bytes_xfer_used, files_in_used, files_out_used, files_xfer_used FROM quotatallies_ftp \
WHERE name = '%{0}' AND quota_type = '%{1}'"

SQLNamedQuery update-quota-tally UPDATE "bytes_in_used = bytes_in_used + %{0}, \
bytes_out_used = bytes_out_used + %{1}, bytes_xfer_used = bytes_xfer_used + %{2}, \
files_in_used = files_in_used + %{3}, files_out_used = files_out_used + %{4}, \
files_xfer_used = files_xfer_used + %{5} WHERE name = '%{6}' AND quota_type = '%{7}'" quotatallies_ftp

SQLNamedQuery insert-quota-tally INSERT "%{0}, %{1}, %{2}, %{3}, %{4}, %{5}, %{6}, %{7}" quotatallies_ftp

QuotaLimitTable sql:/get-quota-limit
QuotaTallyTable sql:/get-quota-tally/update-quota-tally/insert-quota-tally

QuotaLog /var/log/proftpd/proftpd_quota.log

RootLogin off

# Нужен ли реальный shell конектящимся юзерам (берутся из /etc/shells)
RequireValidShell off

</IfModule>

Примечание: Если вы не можете записать в ftp папку используя связку proftpd + mysql (ошибка 550) – проверьте права/владельца на папку и под каким пользователем/группой происходит запись. По умолчанию, proftpd пишет файлы как 65533:65533 и игнорирует то, что указано в /etc/proftpd/proftpd.conf. Соответственно, изменим пользователя и группу по умолчанию на нашего пользователя 105(proftpd) и зададим группу 65534(nogroup) именно в файле конфигурации /etc/proftpd/sql.conf:

SQLDefaultUID   105
SQLDefaultGID   65534

Перезапускаем сервис и смотрим логи на предмет ошибок.

debian:/# /etc/init.d/proftpd restart
Stopping ftp server: proftpd.
Starting ftp server: proftpd.

3. Тестирование начальной конфигурации

Проверим клиентом ftp, входящим в состав любой Widows. Попробуем залить файл на сервер.

    Microsoft   Windows XP [Версия 5.1.2600]
    (С) Корпорация Майкрософт,   1985-2001.
    C:\Documents and Settings\Dmitry Vl.Ivanov>ftp 192.168.1.254
    Связь с 192.168.1.254.
    220 ProFTPD 1.3.1 Server (ProFTPD Home server) [::ffff:192.168.1.254]
    Пользователь (192.168.1.254:(none)): demon
    331 Password required for demon
    Пароль:
    230 User demon logged in
    ftp> append
    Локальный файл c:\test.rar
    Удаленный файл test.rar
    200 PORT command successful
    150 Opening ASCII mode data connection for test.rar
    226 Transfer complete
    ftp: 559748 байт отправлено за 0,17 (сек) со скоростью 3254,35 (КБ/сек).
    ftp> quit
    221 Goodbye.

Прошло удачно? Не получилось? Читаем логи, проверяем разрешения на папки и пароли к БД MySQL и пароль ftp-пользователя.

4. Добавление виртуальных пользователей, расстановка прав

Всё работает? Отлично. Теперь небольшая цель-задача: Есть программист php сайта site.ru, которому нужен доступ к своему сайту со всеми правами - дадим ему это право:

Добавляем нового пользователя БД нашего FTP сервера:

debian:/# mysql -u proftpd -p 
Enter password:

USE `proftpd`;

INSERT INTO   `users_ftp` (`username`, `password`, `descr`, `groupname`, `uid`, `gid`,   `homedir`, `shell`, `last_login`, `login_count`, `last_err_login`, `err_login_count`) VALUES 
('developer', 'PASSWORD', 'PHP developer',   'proftpd', 105, 33, '/var/www/vhosts/site.ru/', '/bin/false', 0, 0, 0, 0); 

INSERT INTO `group_ftp` (`groupname`, `gid`, `members`) VALUES ('www-data', 33, 'developer');

INSERT INTO `quotalimits_ftp` (`id`, `name`, `quota_type`, `per_session`, `limit_type`, `bytes_in_avail`, `bytes_out_avail`, `bytes_xfer_avail`, `files_in_avail`, `files_out_avail`, `files_xfer_avail`) VALUES
(2, 'developer', 'user', 'false', 'soft', 157286400, 0, 0, 0, 0, 0);
INSERT INTO `quotatallies_ftp` (`id`, `name`, `quota_type`, `bytes_in_used`, `bytes_out_used`, `bytes_xfer_used`, `files_in_used`, `files_out_used`, `files_xfer_used`) VALUES
(2, 'developer', 'user', 0, 0, 0, 0, 0, 0);

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

В частности, наш гипотетический девелопер будет создавать новые файлы в своей папке помеченные владельцем как proftpd:www-data (105:33). Если данная папка (домашняя папка виртуального пользователя proftpd) не создана, сервер proftpd создаст ёё самостоятельно. Однако, не забудем подправить права на предоставленную пользователю proftpd папку. Для начала выставим группу и владельца для папки, где хранится сайт, изменяем владельца и/или группу для указанных файлов и директорий, рекурсивно:

server:~# chown -v -R proftpd:www-data /var/www/vhosts/site.ru/

Подправим права доступа к файлам и папкам, рекурсивно (если надо):

server:~# chmod -R 775 /var/www/vhosts/site.ru/

Если вас беспокоит безопасность, подправим права на отдельные типы файлов:

server:~# find /home/vhosts/site.ru/ -type f -name '*.php' -exec chmod 644 {} \;
server:~# find /home/vhosts/site.ru/ -type f -name '.htaccess' -exec chmod 600 {}   \;

5. Увеличиваем безопасность proFTPD ftp-сервера, необходимо-достаточный тюнинг серверя для типового хостинга (опционально)

Для этого проверим и установим некоторые дополнительные параметры в конфигурационном файле /etc/proftpd/proftpd.conf:

server:~# vim /etc/proftpd/proftpd.conf

# Если вошел, но не начал передачу в течении 300 сек - выход
TimeoutNoTransfer 300

# Устанавливает  тайм-аут  на подвисшую загрузку
TimeoutStalled 600

# Накладываем ограничения
# Если никаких действий после входа в течении 600 сек - выход
TimeoutIdle 600

# Максимальное число `детей` (работает только в standalohe режиме)
# необходимо для защиты от атак типа `отказ в обслуживании` да и
# от перегрузки сервера поможет :)
MaxInstances 30

# На авторизацию отводится 300 сек, иначе разрыв
TimeoutLogin 300

# Задаём размер-очереди
tcpBackLog 5

# Максимальное количество клиентов и ошибку в случае превышения
MaxClients 10 "Слишком много соединений с сервером (%m)"

# Максимальное количество клиентов с одного хоста
MaxClientsPerHost 4 "%m клиента уже подключены с Вашего хоста, больше не разрешено"

# допускаемое число попыток ввести пароль
MaxLoginAttempts 3 "Слишком много попыток войти"

Примечание: Если Вы хотите, чтобы отображались скрытые файлы (начинающиеся с точки) используйте директивы Directory и ListOptions:

ListOptions -a

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

Примечание: Для того, чтобы у Вас работала докачка файлов на ftp сервер, используйте директиву AllowStoreRestart. Поместите её в файл конфигурации /etc/proftpd/proftpd.conf:

AllowStoreRestart on

Не забудьте перезапустить сервер proFTPD.

Поиск решений ошибок proftpd: если Вы столкнулись с ошибкой proftpd[16632]: mod_tls_memcache/0.1: notice: unable to register 'memcache' SSL session cache: Memcache support not enabled, отключите этот модуль в /etc/proftpd/modules.conf:

#LoadModule mod_tls_memcache.c

Или настройте memcache для proftpd как описано в руководстве - ProFTPD mini-HOWTO - ProFTPD and Memcache... Не забудьте перезапустить сервер proFTPD.

6. Добавляем сертификат SSL к нашему серверу proftpd

Для начала сгенерируем сертификат:

server:~# openssl req -new -x509 -days 365 -nodes -out /etc/ssl/certs/proftpd.cert.pem -keyout /etc/ssl/private/proftpd.key.pem

Generating a 1024 bit RSA private key
.......................++++++
.............++++++
writing new private key to '/etc/ssl/certs/proftpd.key.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:RU
State or Province Name (full name) [Some-State]:Russia
Locality Name (eg, city) []:Russia
Organization Name (eg, company) [Internet Widgits Pty Ltd]:site.ru
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []:ftp.site.ru
Email Address []:root@domain.ru

Подправим права на вновь-созданный сертификат:

debian:/# chmod 600 /etc/ssl/private/proftpd.key.pem
debian:/# chmod 640 /etc/ssl/certs/proftpd.cert.pem

Отредактируем конфигурационный файл /etc/proftpd/tls.conf:

debian:/# vim /etc/proftpd/tls.conf

TLSEngine on
TLSLog /var/log/proftpd/proftpd_tls.log
TLSProtocol SSLv23
TLSOptions NoCertRequest EnableDiags
TLSOptions AllowClientRenegotioations
TLSRSACertificateFile /etc/ssl/certs/proftpd.cert.pem
TLSRSACertificateKeyFile /etc/ssl/private/proftpd.key.pem
TLSVerifyClient off
TLSRequired off
Замечанние: Если вы указали опцию TLSRequired on, то для подключения к FTP возможен только доступ с использованием TLS (другие пользователи с старыми FTP клиентами не поддерживающими TLS подключиться не смогут); но закомментировав эту опцию или установим значение в TLSRequired off к FTP можно будет подключаться и используя TLS и обычным способом.

Включаем TLS в конфигурационном файле /etc/proftpd/proftpd.conf:

debian:/# vim /etc/proftpd/proftpd.conf

#
# This is used for FTPS connections
#
Include /etc/proftpd/tls.conf

Перезапускаем сервис и смотрим логи на предмет ошибок.

debian:/# /etc/init.d/proftpd restart
Stopping ftp server: proftpd.
Starting ftp server: proftpd.

7. Шифруем Palintext пароли в БД

debian:/# mysql -u proftpd -p 
Enter password:

USE `proftpd`;
UPDATE `users_ftp` SET `password` = PASSWORD(`password`);
Заметьте, ничего в этой команде менять не надо, она самостоятельно, с помощью функции PASSWORD() зашифрует пароли и поменяет их. ВАЖНО! Процедура одностороняя, поэтому если в базе пользователей много, сделайте бэкап.

Допишем (если её нет) в файле /etc/proftpd/sql.conf в опцию SQLAuthTypes ключ Backend:

  SQLAuthTypes Backend Plaintext

И перезапустим сервер.

debian:/# /etc/init.d/proftpd restart
Stopping ftp server: proftpd.
Starting ftp server: proftpd.

Теперь можно хранить в базе как шифрованные, так и не шифрованные пароли. Но я настоятельно рекомендую отказаться от аутентификации Plaintext

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

  1. Vitalii — Apr 26, 2017 at 03:01 PM

    Дмитрий Владимирович, Большое спасибо за подсказку, попытаюсь разобраться, но не уверен что выйдет. С SQLем я еще не знаком.

  2. Дмитрий Владимирович — Apr 26, 2017 at 11:37 AM

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

  3. Vitalii. — Apr 25, 2017 at 04:07 PM

    Добрый день.
    Большое спасибо за мануал.
    Столкнулся с одной проблемой. При попытке залить/скачать фаил, сервер обрывает соединение.
    В proftpd.log
    "mod_sql/4.3: unrecoverable backend error: (1366) Incorrect integer value: '' for column 'id' at row 1"
    Подскажите в какой стороне искать решение данной проблемы.
    Заранее благодарен.

  4. Sergey — Mar 31, 2016 at 11:42 AM

    Отличная статья. по ней поднял PROFTPD на CentOS 7. И еарисовался вполне логичный вопрос:
    Нет ли под это счастье скриптов управления (на SHELL или PHP)?

  5. Алексей — Mar 30, 2015 at 06:11 PM

    Спасибо за отличное руководство!

    Обратите внимание на длину полей username и homedir в таблице users_ftp (раздел 2 руководства). Если имя пользователя и путь длиннее 20 и 50 символов соответственно, они при добавлении записей в БД обрежутся без уведомления!!!

    Элементарно, но надо бы предупредить об этом:)

  6. Сергей — Jan 26, 2015 at 12:33 PM

    Добрый день! Я новичок в Linux-e. Пытаюсь настроить FTP-сервер по Вашей статье, однако столкнулся с проблемкой. Дошёл до пункта добавления таблиц в БД proftd (7-й скрин), текст в котором начинается с "-- phpMyAdmin SQL Dump
    -- version 2.11.8.1deb5+lenny7
    -- http://www.phpmyadmin.net
    --
    -- Версия сервера: 5.0.51
    -- Версия PHP: 5.2.6-1+lenny9", но вот никак не пойму, что это за файл конфигурации? Где это настраивается или это добавление таблиц через phpmyadmin? Будьте так любезны, подскажите, пожалуйста.

    Заранее Вам благодарен и прошу прощения наверняка за глупый вопрос(

  7. АлексейМ — Jun 16, 2014 at 02:49 PM

    Добрый день !
    Сделал конфиг как и здесь, пробовал и на 9 и на 10 freeBSD конфигурить proFTPd так, чтобы и аутентификация и работа пользователей шли только через SSL/TLS. Никакого толку. Пускает и без SSL и по SSL. Может есть какая мысль ? Вот конфиг:

    ServerName "ProFTPD fBSD-10"
    ServerType standalone
    DefaultServer on
    ScoreboardFile /var/run/proftpd/proftpd.scoreb
    Port 21
    Umask 022
    MaxInstances 30
    CommandBufferSize 512
    User nobody
    Group nogroup
    AllowOverwrite on

    DenyAll


    include /usr/local/etc/proftpd_ssl.conf

    TLSEngine on
    # TLSRequired on
    TLSRequired auth+data
    TLSLog /var/log/proftpd/proftpd-tls.log
    TLSProtocol SSLv3
    TLSOptions NoCertRequest EnableDiags
    TLSSACertificateFile /usr/local/etc/proftpd_ssl/proftpd.cert.pem
    TLSSACertificateKeyFile /usr/local/etc/proftpd_ssl/proftpd.key.pem
    TLSVerifyClient off

  8. Сергей — Feb 25, 2013 at 10:40 AM

    Наконец-то разобрался с правами вирутальных пользователей... а то все время создавались файлы как 65333:65333.

    Спасибо за статью!

  9. Иван — Oct 21, 2012 at 08:27 PM

    Отличная статья. Спасибо.

    1. Дмитрий Владимирович — Feb 29, 2012 at 12:23 PM

      По умолчанию, proftpd пишет файлы как 65533:65533 и игнорирует то, что указано в /etc/proftpd/proftpd.conf. Соответственно, нам нужно задать пользователя и группу по умолчанию на того кого вы желаете например на нашего пользователя 105(proftpd) и группу 65534(nogroup) именно в файле конфигурации /etc/proftpd/sql.conf:

      SQLDefaultUID 105
      SQLDefaultGID 65534

  10. Andrey — Jan 26, 2012 at 03:02 PM

    Имеется следующая проблема. proftpd запускается от пользователя proftpd, но при подключении к серверу клиента запускается еще один процесс от пользователя 65533.
    Вот вывод ps aux | grep proftpd
    proftpd 4098 0.0 0.0 105744 2236 ? Ss 16:43 0:00 proftpd: (accepting connections)
    65533 4104 0.0 0.0 116388 4388 ? S 16:43 0:00 proftpd: webadmin - xxx.xxx.xxx.xxx: IDLE

    Соответственно и файлы на сервер кладутся с правами пользователя 65533.
    Подскажите, в чем причина?

  11. Andrey — Jun 29, 2011 at 02:11 PM

    Спасибо за подробную статью, но вопрос: как для заведенного пользователя ограничить максимальный размер директории? Скажем 1Гб файлов максимум можно хранить.

    1. Дмитрий Владимирович — Jun 12, 2011 at 10:00 PM

      Обратите внимание на механизм квотирования во 2 разделе. Когда будете заводить нового пользователя установите ему квоту с ограничением в 1ГБ. Не важно один это будет или сотня файлов - больше 1ГБ хранить сервер не даст.

  • 1

Комментарии отключены, сожалеем