Установка ftp-сервера с хранением пользователей в БД

05 Jul 2012 | Автор: anchous |

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

Хранение пользователей в базе данных крайне удобно, так как позволяет использовать ftp не заводя в системе штатные аккаунты, пусть и с ограниченными правами (по этой же причине мне нравится связка dbmail + mysql). Также эти базы можно удобно резервировать, тем более что все пути и чируты прописываются именно в них. Также при желании можно подключить проверку загружаемых файлов через clamav путем патча пакета pfoFTPD, но думаю что это отнесу к какой нить другой статье.

Исхожу из того, что перед установкой мы уже поставили систему FreeBSD 8.2, пропатчили её, поотключали все ненужные сервисы и порты, а также обновили дерево портов.

Ставить ProFTPD руками мне лень, так что я воспользовался стандртным пакетом, идущим в поставке FreeBSD 8.2 /usr/ports/ftp/proftpd-mysql/ . Как обычно переходим в указанную директорию и говорим:

# make && make install && make clean

В связи с тем что пакет proFTD тянет за собой только мускульного клиента, то ставим дополнительно сервер MySQL, либо качнув с офф.сайта полную сборку, либо выкатывая из портов: /usr/ports/databases/mysql55-server/
после этого открываем /etc/rc.conf и говорим там об автостарте установленных демонов:
sshd_enable=”YES”
proftpd_enable=”YES”
mysql_enable=”YES”

рестартим систему, и видим ps -axj что наши демоны поднялись. После этого переходим к настройке аутентификации через mysql, для чего создаем необходимые таблицы и пользователей.

Для начала задаем из под рута владельца баз данных:
mysql -u root -p
Enter password:
mysql>grant select,insert,update,delete,create,drop
->on proftpd.*
->to proftpd@localhost
->identified by ‘myftpserverpassword’;
Query OK, 0 rows affected (0.16 sec)
mysql>\q

где proftpd@localhost пользователь базы данных, а myftpserverpassword его пароль в системе MySQL
После этого логинимся в систему уже новым пользователям и создаем нужные таблички ftpgroup, ftpquotalimits, ftpquotatallies и ftpuser:
mysql -u proftpd -p
Enter password:
mysql>create database proftpd;
mysql>use proftpd;
Database changed
mysql> CREATE TABLE IF NOT EXISTS `ftpgroup` (
-> `groupname` varchar(16) COLLATE utf8_unicode_ci NOT NULL,
-> `gid` smallint(6) NOT NULL DEFAULT ’5500′,
-> `members` varchar(16) COLLATE utf8_unicode_ci NOT NULL,
-> KEY `groupname` (`groupname`)
-> ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT=’ProFTP group table’;

mysql> CREATE TABLE IF NOT EXISTS `ftpquotalimits` (
-> `name` varchar(30) COLLATE utf8_unicode_ci DEFAULT NULL,
-> `quota_type` enum(‘user’,’group’,’class’,’all’) COLLATE utf8_unicode_ci NOT NULL DEFAULT ‘user’,
-> `per_session` enum(‘false’,’true’) COLLATE utf8_unicode_ci NOT NULL DEFAULT ‘false’,
-> `limit_type` enum(‘soft’,’hard’) COLLATE utf8_unicode_ci NOT NULL DEFAULT ‘soft’,
-> `bytes_in_avail` int(10) unsigned NOT NULL DEFAULT ’0′,
-> `bytes_out_avail` int(10) unsigned NOT NULL DEFAULT ’0′,
-> `bytes_xfer_avail` int(10) unsigned NOT NULL DEFAULT ’0′,
-> `files_in_avail` int(10) unsigned NOT NULL DEFAULT ’0′,
-> `files_out_avail` int(10) unsigned NOT NULL DEFAULT ’0′,
-> `files_xfer_avail` int(10) unsigned NOT NULL DEFAULT ’0′,
-> KEY `name` (`name`)
-> ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

mysql> CREATE TABLE IF NOT EXISTS `ftpquotatallies` (
-> `name` varchar(30) COLLATE utf8_unicode_ci NOT NULL DEFAULT ”,
-> `quota_type` enum(‘user’,’group’,’class’,’all’) COLLATE utf8_unicode_ci NOT NULL DEFAULT ‘user’,
-> `bytes_in_used` int(10) unsigned NOT NULL DEFAULT ’0′,
-> `bytes_out_used` int(10) unsigned NOT NULL DEFAULT ’0′,
-> `bytes_xfer_used` int(10) unsigned NOT NULL DEFAULT ’0′,
-> `files_in_used` int(10) unsigned NOT NULL DEFAULT ’0′,
-> `files_out_used` int(10) unsigned NOT NULL DEFAULT ’0′,
-> `files_xfer_used` int(10) unsigned NOT NULL DEFAULT ’0′,
-> KEY `name` (`name`)
-> ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

CREATE TABLE IF NOT EXISTS `ftpuser` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`userid` varchar(32) COLLATE utf8_unicode_ci NOT NULL DEFAULT ”,
`passwd` varchar(40) COLLATE utf8_unicode_ci NOT NULL DEFAULT ”,
`uid` smallint(6) NOT NULL DEFAULT ’5500′,
`gid` smallint(6) NOT NULL DEFAULT ’5500′,
`homedir` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT ”,
`shell` varchar(16) COLLATE utf8_unicode_ci NOT NULL DEFAULT ‘/sbin/nologin’,
`count` int(11) NOT NULL DEFAULT ’0′,
`accessed` datetime NOT NULL DEFAULT ’0000-00-00 00:00:00′,
`modified` datetime NOT NULL DEFAULT ’0000-00-00 00:00:00′,
PRIMARY KEY (`id`),
UNIQUE KEY `userid` (`userid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT=’ProFTP user table’;

В двух табличках с лимитами ftpquotalimits и ftpquotatallies их можно задавать в базе, либо же присвоивать их 0, что означает их отсуствие.

Для начала заводим нужную группу и первого пользователя. Теоретически, если у вас система предполагает больше 30-40 юзверей, то можно подрубить систему управления phpMyAdmin, хотя откровенно говоря для меня её использование является сомнительным улучшением функционала, так что я предпочитаю таки заводить все ручками:

mysql> INSERT INTO `ftpgroup` (`groupname`, `gid`, `members`) VALUES (‘ftpgroup’, 9999, ‘ftpuser’);

При создании пользователя он создается в двух базах параллельно ftpquotalimits и ftpuser:

INSERT INTO `ftpquotalimits` (`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 (‘firstuser’, ‘user’, ‘false’, ‘hard’, 104857600, 0, 0, 0, 0, 0);

INSERT INTO `ftpuser` (`userid`, `passwd`, `uid`, `gid`, `homedir`, `shell`, `count`, `accessed`, `modified`) VALUES (‘firstuser’, encrypt(‘password’), 1001, 1001, ‘/home/ftp/firstuser’, ‘/sbin/nologin’, 0, ’0000-00-00 00:00:00′, ’0000-00-00 00:00:00);

Вроде как со всеми лимитами более менее понятно- единственно что директивы в базе ftpquotalimits следующие:
limit_type – тип акка, бывающий hard и не допускающий превышения лимитов, или же soft разрешающий временное превышение лимитов
bytes_in_avail – лимит на аплоад в байтах, который как и все остальные при значении 0 будет анлимом.

Просмотреть инфу из имеющейся таблички, можно обычной скульной командой:
mysql> select * from ftpuser;
mysql> select * from ftpquotalimits;

Создаем папочку домашних директорий и задаем на неё права:
# mkdir -p /home/ftp/firstuser
# chown -R 1001:1001 /home/ftp/firstuser

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

############ /usr/local/etc/proftpd.conf
ServerName “Mega FTP Server”
ServerType standalone
DefaultServer on
Port 21
UseIPv6 off
Umask 002

# Эти две опы предназначены для противодействия DoS атакам,
# так что их можно конечно увеличивать, но на свой страх и риск.
# Также надо отметить, что они работают только в вариант standalone,
# в inetd варианте надо крутить inetd сервер
MaxInstances 30
CommandBufferSize 512
####
User nobody
Group nogroup
# Эту опцию стоит использовать если наш FTP сидит за NATом,
# так как в противном случае при установке сессии он палит всю
# контору
MasqueradeAddress ftp.domain
MasqueradeAddress Внешний_IP
# Подрубаем Passive FTP mode, так как если FTP сервер
# находится за фаерволом, то вполне возможно
# будут висяки на выборе режима
PassivePorts 49152 65534
# Делаем файлы перезаписываемыми

AllowOverwrite on

# Лимиты
MaxClients 15 “It’s too much coonections. Try after a while”
MaxClientsPerHost 8 “%m clients connected from your host”
MaxLoginAttempts 3 “Obtain account information & try again”

UseReverseDNS off
IdentLookups off
### Ограничиваем скорости закачки до 512Kb
TransferRate RETR,STOR,APPE 512
############
TimeoutIdle 180
TimeoutLogin 120
TimeoutNoTransfer 360
TimeoutStalled 640

SyslogLevel notice
TransferLog /var/log/proftpd-tranfer.log
SystemLog /var/log/proftpd-error.log

LogFormat default “%h %l %u %t \”%r\” %s %b”

# Место для проявления одминского остроумия, в случае удачного коннекта
AccessGrantMsg “welcome aboard!”
# Тоже что и предыдущее, но при начале сессии
ServerIdent on “Knockin’ on Heaven’s Door”
# Можно в принципе все прописать и в файликах
DisplayConnect /usr/local/proftpd/etc/ftp_connect.msg
DisplayLogin /usr/local/proftpd/etc/welcome.msg

# Перезапуск и докачки, что довольно важно при толстых файлах
AllowRetrieveRestart on
AllowStoreRestart on
######################
### MySQL Sections ###
######################

# Обозначаем chroot на домашнюю директорию
DefaultRoot ~
# говорим что данные в БД криптуются используя CRYPT
SQLAuthTypes Crypt
SQLAuthenticate users* groups*
# Логин к базе proftpd
SQLConnectInfo proftpd@localhost:3306 proftpd myftpserverpassword
# поля в табличке пользователей
SQLUserInfo ftpuser userid passwd uid gid homedir shell
# поля в табличке групп
SQLGroupInfo ftpgroup groupname gid members
# минимальное значения для UID и GID
SQLMinID 500
# создание домашней директории по требованию, если отсуствует
CreateHome on 770 dirmode 770
# обнуление статистики пользователя после очередного логина
SQLLog PASS updatecount
SQLNamedQuery updatecount UPDATE “count=count+1, accessed=now() WHERE userid=’%u’” ftpuser
# изменение статистики юзверя после команд аплоада или удаления
SQLLog STOR,DELE modified
SQLNamedQuery modified UPDATE “modified=now() WHERE userid=’%u’” ftpuser
# Включение и использование квот (опционно)
QuotaEngine on
QuotaDirectoryTally on
QuotaDisplayUnits Gb
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 ftpquotalimits 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 ftpquotatallies 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}’” ftpquotatallies
SQLNamedQuery insert-quota-tally INSERT “%{0}, %{1}, %{2}, %{3}, %{4}, %{5}, %{6}, %{7}” ftpquotatallies
QuotaLimitTable sql:/get-quota-limit
QuotaTallyTable sql:/get-quota-tally/update-quota-tally/insert-quota-tally
# Вывод статистики использования места (использовано/доступно)
# после вывода команды LIST (опционно)
SQLNamedQuery gettally SELECT “ROUND((bytes_in_used/1073741824),2) FROM ftpquotatallies WHERE name=’%u’”
SQLNamedQuery getlimit SELECT “ROUND((bytes_in_avail/1073741824),2) FROM ftpquotalimits WHERE name=’%u’”
SQLNamedQuery getfree SELECT “ROUND(((ftpquotalimits.bytes_in_avail-ftpquotatallies.bytes_in_used)/1073741824),2) FROM ftpquotalimits,ftpquotatallies WHERE ftpquotalimits.name = ‘%u’ AND ftpquotatallies.name = ‘%u’”
SQLShowInfo LIST “226″ “Used %{gettally}GB from %{getlimit}GB. You have %{getfree}GB available space.”
#################
RootLogin off
RequireValidShell off
SQLLogFile /var/log/proftpd.log

###############################################

Собственно после этого рестартим демона
# /usr/local/etc/rc.d/proftpd restart
и начинаем ломать голову, как нам этим барахлом управлять

Меня например не напрягает и задать команду из мускульной консоли, тем более что апач ставить без причины ломает, но беда в том, что поколение пепси, к которому принадлежат одмины заказчика, с консолью не особенно дружат, так что для предотвращения возможных rm -Rf /, надо было прикрутить какой нить веб-интерфейс.

Наиболее простое это поставить пхпшный скриптик ftpusermanagement.php, который можно качнуть отсюда: вроде как пишут что там все просто, но я не ставил, так что не знаю

Также можно прикрутить phpMyadmin, и рулить учетками из него, но мне было интересно поставить какой нить специально созданный под это дело пакет.

Так что я остановился на proFTPd Administrator, который и попытался установить, но как выяснилось- безрезультатно

Посколку возиться со вторым апачем ломало, то поставил 1.3, так что
# cd /usr/ports/www/apache13
# make && make install && make clean
# cd /usr/ports/www/php5-session/
# cd /usr/ports/www/php5-tidy/
# make && make install && make clean

Добавляем в /etc/rc.conf строку
apache_enable=”YES”
правим что надо в конфиге /usr/local/etc/apache/httpd.conf
и переходим к настройкам пакета proFTPd Administrator

На самом деле в инсталяторе пакета proFTPd Administrator говорится о том, что его надо накатывать на пустую базу, так как он сам создает необходимую структуру базы данных, но у меня FTP сервер уже стоял, так что пришлось возиться:

# cd /usr/local/www/data
# wget http://mesh.dl.sourceforge.net/sourceforge/proftpd-adm/proftpd_admin_v1.2.tar.gz

# tar -xzf proftpd_admin_v1.2.tar.gz
# mv proftpd_admin_v1.2 proftpd_admin
# cd proftpd_admin

При попытке обращения в веб-морде управлялки может появиться нехорошая ошибка:

Fatal error: Call to undefined function simplexml_load_file() in /usr/local/www/data/proftpd_admin/include_config_utils.php on line 19

говорящая нам о том, что надо подключить в файле php.ini расширение SimpleXML, для чего в имеющийся php.ini добавляем следующую строку:

extension=simplexml.so

После этого ошибка ушла в логи, но осталась, так что разбираемся:
# pkg_info -W simplexml.so
pkg_info: simplexml.so: file is not in PATH

бог с ними с пасами, но надо доставлять библиотечку:
# cd /usr/ports/textproc/php5-simplexml

после этого ошибка изчезает, но морда управлялки все равно не подгружается, так что лезем в конфигуратор:
http://ftp.domain/proftpd_admin/configure.php
где настраиваем все пути

На самом деле на этом моменте я сдался, так как видимо надо было ручками править структуру базы, а у меня были другие планы на ближайшее время, так что пришлось подзабить, поставив вьюношам таки phpmyadmin. Если же у вас хватило терпения докрутить веб-морду до рабочего состояния, то думаю не надо объяснять что доступ к ней надо ограничивать по IP и логину.

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

VN:F [1.9.21_1169]
Rating: 4.0/10 (3 votes cast)
VN:F [1.9.21_1169]
Rating: -1 (from 1 vote)
Установка ftp-сервера с хранением пользователей в БД, 4.0 out of 10 based on 3 ratings

Теги: , , ,

Отзывов: 8 на «Установка ftp-сервера с хранением пользователей в БД»

  1. Автор: Виктор на 07 Jul 2012

    Подскажите, а вы не встречали какой-нибудь патч, позволяющий подключаться к proftpd клиентам настроенные на обратный слэш?
    поясню вопрос, есть довольно большая куча клиентов у которых подключение к фтп-серверу происходит путем выполнения команд

    open xxx.xxx.xxx.xxx #### адрес моего фтп
    ROZMARIN2 #### например такой логин
    rozmarin2 #### например такой пароль
    passiv
    binary
    cd CP\
    get или put какой-то.zip
    quit

    это работает на виндовом filezilla server, клиенты естественно тоже на винде.Есть жгучее желание перевести основной сервер на proftpd
    так вот столкнулся с тем, что команду cd CP\ proftpd обрабатывает некорректно. можете что нибудь посоветовать, чтобы не ломать настройки клиентов

    Спасибо

    [Reply]

    anchous Reply:

    это не патч, это как раз те самые апачевские фичи в proftpd, то есть в вашем случае следует использовать модуль mod_rewrite, и через него как раз переписывать обратные слэши в человеческие:

    < IfModule mod_rewrite.c >
    RewriteEngine on
    RewriteMap replace int:replaceall
    RewriteRule (.*) “${replace:!$1!\\\\!/}”‘
    < /IfModule >

    [Reply]

    Виктор Reply:

    Я читал про рерайтинг на оф.сайте
    но почему-то не работало.
    демон стартовал без проблем, отзывался когда подключался той же filezilla client, но при запуске на клиенте указанного батника proftpd писал что unknown directory
    Правильно ли я понимаю, что эти строки надо прописывать в proftpd.conf?

    [Reply]

    anchous Reply:

    да, его надо прописывать в конфиге, но не смотря на то, что он идет в сырцах, он по-моему по умолчанию не ставится, так что его надо подрубать в процессе сборки пакета

    VN:F [1.9.21_1169]
    Rating: 0.0/5 (0 votes cast)
    VN:F [1.9.21_1169]
    Rating: 0 (from 0 votes)

    Виктор Reply:

    proftpd 1.3.3 на FreeBSD 9.0 ставится по дефолту… проверено!

    Спасибо за ответы, на выходных буду тестить.
    кстати может подскажите до кучи, можно ли менять скин для админки. а то чето она уж очень страшная, хотя и функциональная…

    anchous Reply:

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

    VN:F [1.9.21_1169]
    Rating: 0.0/5 (0 votes cast)
    VN:F [1.9.21_1169]
    Rating: 0 (from 0 votes)
  2. Автор: punker на 27 Sep 2012

    mysql> grant select,insert,update,delete,create,drop
    -> on proftpd.*
    -> tp proftpd@localhost
    -> identified by ‘myftpserverpassword’;
    ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘tp proftpd@localhost
    identified by ‘myftpserverpassword” at line 3

    fbsd 9.0

    [Reply]

    anchous Reply:

    detected: английский язык, кривые команды из mysql
    от меня требуется что то конкретное?

    [Reply]

    VN:F [1.9.21_1169]
    Rating: 0.0/5 (0 votes cast)
    VN:F [1.9.21_1169]
    Rating: 0 (from 0 votes)

Ваш отзыв