FTP-сервер на базе Proftpd
Озадачился я как-то поставить для любимых юзверей в локалке фтп-сервер, пусть думаю обмениваются своим любимым поревом.
Чтоб там с пользователями, с записями в базу, с красивой статистикой и т.д. Выбор пал на proftpd. Задумано-сделано. Поехали.
Директорий будет две: download(read-only) и upload(read-write), корневая ftp.
Ставить будем из портов(версия 1.3.4a):
# cd /usr/ports/ftp/proftpd # make install clean
Вносим в /etc/rc.conf:
proftpd_enable="YES"
Cтартуем:
# ./proftpd start Starting proftpd. - Fatal: UseIPv6: Use of the directive requires IPv6 support (--enable-ipv6) on line 19 of '/usr/local/etc/proftpd.conf'
Не айс. Вроде собирал без IPv6, ну да ладно, просто закомментим в конфиге строчку:
#UseIPv6 on
Дубль два:
# ./proftpd start Starting proftpd. - warning: unable to determine IP address of ' ' - error: no valid servers configured - Fatal: error processing configuration file '/usr/local/etc/proftpd.conf'
Снова лезем в конфиг и добавляем:
DefaultAddress localhost
Дубль три:
# ./proftpd start Starting proftpd. - setting default address to 127.0.0.1
Всё стартануло. Проверяем.
# netstat -an | grep "*.21" tcp4 0 0 *.21 *.* LISTEN
Работает.
# proftpd -V - эта команда покажет где находятся конфиги и с какими модулями собран proftpd.
Рихтуем proftpd.conf под наши нужды:
ServerName "My FTP server"
ServerType standalone
DefaultServer on
ScoreboardFile /var/run/proftpd/proftpd.scoreboard
DefaultAddress localhost
Port 21
Umask 022
MaxInstances 30
CommandBufferSize 512
AllowOverwrite on
AllowRetrieveRestart on
AllowStoreRestart on
TimeoutNoTransfer 300
User nobody
Group nogroup
#Загоняем всех подключившихся в папку ftp
DefaultRoot /ftp
### Security
AllowForeignAddress off
DenyFilter \*.*/
MaxClientsPerHost 2 "The %m client are already connected from your host, it is not authorized any more"
MaxLoginAttempts 20 "It is too much attempts to enter "
PathDenyFilter "(^\.ftpaccess$)"
RequireValidShell off
### Логи
DebugLevel 1
TransferLog /var/log/proftpd/proftpd-transfer.log
ExtendedLog /var/log/proftpd/proftpd-extended.log
SystemLog /var/log/proftpd/proftpd-system.log
LogFormat default "%h %l %u %t \"%r\" %s %b"
LogFormat auth "%v [%P] %h %t \"%r\" %s"
LogFormat write "%h %l %u %t \"%r\" %s %b"
<Anonymous /ftp>
User ftp
Group ftp
UserAlias anonymous ftp
MaxClients 10
<Directory /ftp>
<Limit DELE RMD>
DenyAll
</Limit>
</Directory>
<Directory /ftp/download>
<Limit WRITE DELE RMD MKD>
DenyAll
</Limit>
</Directory>
<Directory /ftp/upload>
<Limit WRITE MKD>
AllowAll
</Limit>
<Limit DELE RMD>
DenyAll
</Limit>
</Directory>
</Anonymous>
Добавляем пользователя ftp для анонимного входа(без пароля)
# pw useradd ftp -s /usr/sbin/nologin
В принципе всё. Для простейшего случая, с единственным анонимным пользователем этого достаточно. Можно юзать.
Теперь переходим к дальнейшей настройке сервера и остальным рюшечкам.
Вариант 1. Авторизация из файла
Пользователей можно заводить с помощью утилиты ftpasswd. Взять её можно в архиве /usr/ports/distfiles/proftpd-1.3.3.tar.bz2 /contrib
Запускаем и заводим юзверя или группу таким образом:
# ftpasswd --passwd --name ftp_user --file /etc/proftpd/ftpd.passwd --uid 2000 --gid 2001 --home /ftp --shell /bin/false # ftpasswd --group --name ftp_group –-file /etc/proftpd/ftpd.group --gid 2001 --member ftp_user
в proftpd.conf добавляем:
AuthUserFile /etc/proftpd/ftpd.passwd AuthGroupFile /etc/proftpd/ftpd.group
Ну и собственно права для папок (предварительно завёл пользователя boss).
<Directory /ftp/download>
<Limit WRITE DELE RMD MKD>
DenyAll
</Limit>
</Directory>
<Directory /ftp/upload>
<Limit WRITE MKD>
AllowAll
</Limit>
<Limit DELE RMD>
AllowUser boss
DenyAll
</Limit>
</Directory>
Вариант 2. Авторизация из MySQL и админка
(Взято и адаптировано отсюда http://www.lissyara.su/articles/freebsd/programms/proftpd+mysql/)
Создаём базу proftpd:
mysql> create database proftpd;
Заводим пользователя proftpd
mysql> grant all on proftpd.* to proftpd@localhost identified by 'password';
Создаём таблицы
CREATE TABLE IF NOT EXISTS `users` (
`userid` varchar(30) CHARACTER SET cp1251 COLLATE cp1251_bin NOT NULL,
`name` varchar(255) DEFAULT NULL,
`mail` varchar(255) CHARACTER SET cp1251 COLLATE cp1251_bin NOT NULL,
`uid` int(11) DEFAULT '2000',
`gid` int(11) DEFAULT '2001',
`passwd` varchar(120) CHARACTER SET cp1251 COLLATE cp1251_bin NOT NULL,
`shell` varchar(30) CHARACTER SET cp1251 COLLATE cp1251_bin NOT NULL DEFAULT '/bin/nonexistent',
`homedir` varchar(255) CHARACTER SET cp1251 COLLATE cp1251_bin NOT NULL DEFAULT '/ftp',
`note` text CHARACTER SET cp1251 COLLATE cp1251_bin,
`last_login` int(15) NOT NULL,
`count` int(11) NOT NULL DEFAULT '0',
`last_err_login` int(15) NOT NULL,
`err_login_count` int(15) NOT NULL,
`admin` int(1) NOT NULL DEFAULT '0',
`closed` int(1) NOT NULL DEFAULT '1',
`groupname` varchar(24) DEFAULT 'unregistered',
PRIMARY KEY (`userid`),
KEY `groupname` (`groupname`),
KEY `closed` (`closed`),
KEY `admin` (`admin`),
KEY `count` (`count`),
KEY `passwd` (`passwd`),
KEY `name` (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251;
CREATE TABLE IF NOT EXISTS `xfer_errors` (
`unic_id` int(32) NOT NULL AUTO_INCREMENT,
`timestamp` int(15) NOT NULL,
`user_name` varchar(64) COLLATE cp1251_bin NOT NULL,
`file_and_path` tinytext COLLATE cp1251_bin NOT NULL,
`client_name` varchar(127) COLLATE cp1251_bin NOT NULL,
`client_IP` varchar(15) COLLATE cp1251_bin NOT NULL,
`client_command` varchar(5) COLLATE cp1251_bin NOT NULL,
PRIMARY KEY (`unic_id`),
KEY `user_name` (`user_name`),
KEY `client_name` (`client_name`),
KEY `client_IP` (`client_IP`),
KEY `client_command` (`client_command`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251 COLLATE=cp1251_bin;
CREATE TABLE IF NOT EXISTS `xfer_table` (
`unic_id` int(32) NOT NULL AUTO_INCREMENT,
`timestamp` int(15) NOT NULL,
`user_name` varchar(64) COLLATE cp1251_bin NOT NULL,
`file_and_path` tinytext COLLATE cp1251_bin NOT NULL,
`bytes` int(15) NOT NULL DEFAULT '0',
`client_name` varchar(127) COLLATE cp1251_bin NOT NULL,
`client_IP` varchar(15) COLLATE cp1251_bin NOT NULL,
`client_command` varchar(5) COLLATE cp1251_bin NOT NULL,
`send_time` varchar(9) COLLATE cp1251_bin NOT NULL DEFAULT '0',
PRIMARY KEY (`unic_id`),
KEY `timestamp` (`timestamp`),
KEY `user_name` (`user_name`),
KEY `client_name` (`client_name`),
KEY `client_IP` (`client_IP`),
KEY `client_command` (`client_command`),
KEY `send_time` (`send_time`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251 COLLATE=cp1251_bin;
CREATE TABLE IF NOT EXISTS `quotalimits` (
`userid` varchar(30) NOT NULL,
`quota_type` enum('user','group','class','all') NOT NULL,
`per_session` enum('false','true') NOT NULL DEFAULT 'false',
`limit_type` enum('soft','hard') NOT NULL DEFAULT 'hard',
`bytes_in_avail` float NOT NULL DEFAULT '1.57286e+08',
`bytes_out_avail` float NOT NULL DEFAULT '0',
`bytes_xfer_avail` float 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',
PRIMARY KEY (`userid`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251;
CREATE TABLE IF NOT EXISTS `quotatallies` (
`userid` varchar(30) NOT NULL,
`quota_type` enum('user','group','class','all') NOT NULL,
`bytes_in_used` float NOT NULL DEFAULT '0',
`bytes_out_used` float NOT NULL DEFAULT '0',
`bytes_xfer_used` float 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',
PRIMARY KEY (`userid`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251;
В конфиг добавляем следующее:
LoadModule mod_sql.c LoadModule mod_sql_mysql.c SQLBackend mysql #В каком виде хранятся пароли, в данном случае - открытым текстом #SQLAuthTypes backend SQLAuthTypes Plaintext SQLAuthenticate users SQLConnectInfo proftpd@localhost:3306 proftpd password SQLLogFile /var/log/proftpd/proftpd_mysql.log SQLUserInfo `users` `userid` `passwd` `uid` `gid` `homedir` `shell` SQLLog PASS counter_login SQLLog ERR_PASS counter_err SQLLog RETR,STOR log_story_transfer SQLLOG ERR_RETR,ERR_STOR,ERR_DELE,ERR_RMD,ERR_RNTO log_err_modify SQLNamedQuery counter_login UPDATE "`last_login`=UNIX_TIMESTAMP(),`count`=`count`+1 WHERE `userid`='%u'" `users` SQLNamedQuery counter_err UPDATE "`last_err_login`=UNIX_TIMESTAMP(),`err_login_count`=`err_login_count`+1 WHERE `userid`='%U'" `users` SQLNamedQuery log_story_transfer INSERT ",UNIX_TIMESTAMP(),'%u','%f', '%b', '%h','%a', '%m', '%T'"`xfer_table` SQLNamedQuery log_err_modify INSERT ",UNIX_TIMESTAMP(),'%u', '%f', '%h','%a', '%m'" `xfer_errors`
Добавляем админа:
mysql> INSERT INTO `users` (`userid`, `name`, `mail`, `uid`, `gid`, `passwd`, `shell`, `homedir`, `note`, `last_login`, `count`, `last_err_login`, `err_login_count`, `admin`, `closed`, `groupname`) VALUES ('admin', 'admin',
'admin@domain', 2000, 2001, 'password', '/bin/nonexistent', '/ftp', 'admin', 0, 0, 0, 0, 1, 0, 'admin');
Делаем ему шифрованный пароль(если надо):
mysql> UPDATE users SET passwd=PASSWORD('password') WHERE name='admin';
Скачиваем архив proma.tar и кидаем его содержимое в нужный каталог веб-сервера. Вносим в config.inc.php параметры подключения к БД. Теперь можно залогиниться в админку.
P.S. Чтобы не было проблем с отображением русских букв, добавим в конфиг следующее:
<IfModule mod_lang.c> UseEncoding koi8-r cp1251 </IfModule>
Эта директива сообщит серверу, что локальная кодировка на FreeBSD - koi8-r(eсли она у нас действительно такая), удаленная у клиента cp1251, поэтому при записи файлов с русскими названиями будет произведена конвертация кодировки из одной кодовой страницы в другую.
P.S. Чтобы админка пускала админа с открытым паролем, в файлике /libs/auth.lib.php в 31 строке вносим изменения:
вместо:
$users_passwd = PASSWORD('$passwd')";
должно быть:
$users_passwd = '$passwd'";
P.S. Чтобы пароли для пользователей фтп создавались в открытом виде, в файлике register.inc.php в 35 строке вносим изменения:
вместо:
} else {
$query = "SELECT PASSWORD('$passwd1')";
$result = mysql_query($query) or die("Database query failed.");
должно быть:
} else {
$query = "SELECT '$passwd1'";
$result = mysql_query($query) or die("Database query failed.");
P.S.Чтобы при смене пароля они тоже отображались в базе в открытом виде, в файлике /libs/admin.lib.php делаем следующие изменения в строке 375:
вместо
$query .= ", $table_users.$users_passwd = PASSWORD('$new_passwd1')";
должно быть:
$query .= ", $table_users.$users_passwd = '$new_passwd1'";
P.S.Для авторизации по открытому паролю, в конфиге proftpd.conf делаем:
SQLAuthTypes Plaintext
P.S. Ошибки вида:
mod_sql/4.3: no SQL backends registered mod_sql.c: error initializing session
Лечатся сборкой /usr/ports/databases/proftpd-mod_sql_mysql/ и добавлением в конфиг строчек:
LoadModule mod_sql.c LoadModule mod_sql_mysql.c SQLBackend mysql
Полезности:
- ftpcount - показывает число соединений в настоящий момент (с разбивкой по виртуальным хостам).
- ftpwho - показывает информацию о каждом текущем соединении (-v показывает также текущую рабочую директорию).
- ftptop - аналог программы top для процессов ProFTPD.
Прикручиваем смотрелку логов.
Взять можно здесь: http://www.lissyara.su/articles/freebsd/programms/proftpd+mysql/
Меняем в скрипте данные для подключения к БД и всё.