Серверы FTP · 6 min read · Dec 17, 2025
PostgreSQL и Proftpd
Итак, вы хотите настроить ftp-сервер, вам нужна расширенная функциональность, и вы не знаете, к кому обратиться? Попробуйте proftpd.
Часть 1: Настройка proftpd с использованием PostgreSQL в качестве бэкенда
Этот учебник очень узкоспециализированный, я собираюсь рассмотреть только proftpd и только в той мере, чтобы сделать его работоспособным с Postgres. Предполагается базовое понимание proftpd и Postgres. Этот учебник поможет вам быстро запустить proftpd и использовать базу данных, если эта база данных имеет триггеры, возможности этой конфигурации практически безграничны.
Получение Proftpd
Сначала вам понадобится proftpd, я буду использовать Dapper от Ubuntu; есть мета-пакет, подготовленный благодаря Франческо Паоло Ловерджине, под названием “proftpd-pgsql”, который установит копию proftpd, скомпилированную с следующими модулями. В качестве примечания, хотя proftpd поставляется с модулями, конфигурационный файл является стандартным шаблоном proftpd. Я настоятельно рекомендую вам ознакомиться с документацией mod_sql, которая, хотя и не идеальна, все же полезна — документация на сайте proftpd очень старая, используйте вместо этого: Ссылка на документацию. Также будьте осторожны с версией, proftpd сейчас на 1.3, хотя я буду использовать 1.2.10 — версия, используемая в Dapper.
Список модулей, скомпилированных в эту версию proftpd:
mod_core.c
mod_xfer.c
mod_auth_unix.c
mod_auth_file.c
mod_auth.c
mod_ls.c
mod_log.c
mod_site.c
mod_auth_pam.c
mod_quotatab.c
mod_sql.c
mod_sql_postgres.c
mod_quotatab_sql.c
mod_ratio.c
mod_tls.c
mod_rewrite.c
mod_radius.c
mod_wrap.c
mod_quotatab_file.c
mod_delay.c
mod_readme.c
mod_ifsession.c
mod_cap.cПродолжайте и выполните команду для установки proftpd-pgsql:
apt-get install proftpd-pgsqlНастройка прав доступа.
Для моих целей (помните, я — центр вселенной) все, что мне нужно, это одноразовая структура, потому что группы хранятся на другом уровне, а не в unix-правах. Поэтому все файлы должны приходить со статическими правами — меня интересует только владелец и группа владельца. Мой план заключался в том, чтобы сделать пользователя по умолчанию proftpd, ftp, членом своей собственной, удачно названной группы, которую я собирался создать — ‘ftp’. Затем я собирался сделать Postgres членом этой группы, смотрите часть 2 для объяснения. Мне нужно было, чтобы оба были членами одной группы, и мне нужно было, чтобы папка chroot proftpd имела права 775, чтобы вся группа могла добавлять (перемещать) файлы, я также сделал папку владельцем пользователя ‘ftp’ с группой ‘ftp’. Я достиг этого с помощью следующего скрипта.
groupadd ftp
usermod -G ftp ftp
usermod -G ftp,postgres postgres
chown ftp:ftp ./ftp_directory/
chmod 775 ./ftp_directory/Настройка Postgres
Теперь мы собираемся подготовить наши sql таблицы. Я проектирую, используя схемы, и именно для этого предназначен префикс ‘ftp.’ в таблицах. Я поместил все свои таблицы в схему ftp, есть одна вещь, которую стоит отметить, я был крайне ограничительным в отношении прав доступа для этого проекта, потому что я не уверен, насколько безопасен mod_sql. В результате я создал специального пользователя, по имени proftp, для proftpd в своей базе данных (которую используют больше приложений, чем proftpd), этот пользователь ограничен выборками из auth_table и вставками в таблицу file_log. Я настойчиво рекомендую вам принять какую-либо форму этой политики. По крайней мере, это предотвращает некоторую степень разрушительных атак SQL-инъекций или утечек информации в случае, если код mod_sql не так безопасен, как нам хотелось бы думать. Быстрый поиск в Google показывает предыдущую проблему безопасности с кодовой базой mod_sql. Каждый запрос, который mod_sql отправляет в базу данных, дополнен условием “LIMIT 1”, и с mod_delay, также настроенным по умолчанию, я считаю это достаточным для этого проекта.
Мой sql инициализационный скрипт выглядит следующим образом.
ALTER USER proftp UNENCRYPTED PASSWORD 'dealermadeftp';
CREATE SCHEMA ftp;
GRANT USAGE ON SCHEMA ftp TO proftp;
CREATE TABLE ftp.users (
pkid serial PRIMARY KEY,
userid text NOT NULL UNIQUE,
passwd text,
uid int,
gid int,
homedir text,
shell text
);
GRANT SELECT ON ftp.users TO proftp;
INSERT INTO ftp.users ( userid, passwd ) VALUES ( 'ecarroll', 'adm1n' );
INSERT INTO ftp.users ( userid, passwd ) VALUES ( 'jgallagher', 'adm1n' );
CREATE TABLE ftp.file_log (
pkid serial PRIMARY KEY,
userid text REFERENCES ftp.users(userid),
abs_path text,
file text,
dns text,
time_transaction text,
ts_in timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP
);
GRANT INSERT ON ftp.file_log TO proftp;
GRANT UPDATE ON TABLE ftp.file_log_pkid_seq TO proftp;
Подключитесь к вашей базе данных и выполните это с:
\i script_nameили вы можете использовать отправку ‘–file script_name’ в psql в качестве аргумента командной строки.
Тем, кто использует менее мощные базы данных (используя этот учебник с mysql), возможно, стоит заменить text на varchar; но, из-за дизайна Postgres, в этом нет преимущества.
Настройка proftpd
Эта часть сложная и немного отличается, если вы используете 1.3 — еще раз, этот учебник предназначен для 1.2.10.
Я добавил эту часть в свой стандартный конфигурационный файл proftpd, расположенный по адресу /etc/proftpd.conf:
AuthOrder mod_sql.c
SQLAuthTypes Plaintext Empty
SQLAuthenticate users
SQLConnectInfo proftpd@localhost proftp dealermadeftp
SQLDefaultUID 110 # ИЗМЕНИТЕ ДЛЯ UID ВАШИХ FTP-ПОЛЬЗОВАТЕЛЕЙ, НАЙДЕННЫХ В /etc/passwd
SQLDefaultGID 1001 # ИЗМЕНИТЕ ДЛЯ GID ВАШИХ FTP-ПОЛЬЗОВАТЕЛЕЙ, НАЙДЕННЫХ В /etc/groups
SQLDefaultHomedir /home/ftp
RequireValidShell off
SQLUserInfo ftp.users userid passwd uid gid homedir shell
SQLNegativeCache off
SQLLogFile /var/log/proftpd-sql
SQLLog STOR newfile
SQLNamedQuery newfile FREEFORM "INSERT INTO ftp.file_log(userid,abs_path,file,dns,time_transaction) VALUES ('%U','%f','%J','%V','%T')"
# %U => userid
# %D => --Ничего,
# %f => abs_path
# %J => file
# %h => dns_remote, %V => dns_local
# %a => remote_ip, %L => local_ip
# %t => localtime
# %T => transfer_time
- Шаблонные переменные прокомментированы и предназначены только для вашего собственного справки. Краткий обзор конфигурации:
- Здесь мы устанавливаем AuthOrder на mod_sql.c, что, в свою очередь, включает mod_sql.
- Я выбрал использовать пароли в открытом виде или, в случае, если я не назначу один, разрешить пустые пароли. (Позже я реализую триггер для SHA1 паролей в базе данных.)
- Затем я устанавливаю SQLAuthenticate на users, я решил не использовать группы для этого проекта, если вам нужны группы, больше информации можно найти в этих таблицах на: Этот сайт для документации по группам.
- SQLConnectInfo — это DSN в формате “database@host user password,”.
- SQLDefaultUID, SQLDefaultGID, SQLDefaultHomedir настраивают значения по умолчанию, оставляя большинство моих столбцов NULL, я редко переопределяю это.
- RequireValidShell также установлен на off, если вы установите его на on и введете недопустимую оболочку, вы не пройдете аутентификацию.
- SQLUserInfo соответствует таблицам Postgres, это буквальное сопоставление, снова “ftp.” указывает на схему для таблицы аутентификации.
- SQLNegativeCache кэширует неудачи аутентификации,
- SQLLogFile для подробного ведения журнала во время настройки вашего сервера. Я отключу это, когда перейду в продакшн.
- SQLLog указывает, какое действие FTP вы хотите записать, поскольку мои пользователи могут только загружать, я записываю только STOR, формат — ‘ftpaction query_to_execute’.
- SQLNamedQuery Проверьте синтаксис в документации для лучшего объяснения, формат, который я использую, — ‘qryname FREEFORM custom_query_here’, я делаю это в основном потому, что хочу захватить много шаблонных переменных proftpd, есть другие более простые синтаксисы.
Вот и все. Если все пойдет по плану, вы должны быть готовы к работе. Теперь, когда кто-то загружает файл, это должно быть результатом:
proftpd=# select * from ftp.file_log;
pkid | userid | abs_path | file | dns | time_transaction | ts_in
------+----------+------------------------+---------------+-------+------------------+-------------------------------
1 | ecarroll | /home/ftp/foo/testfile | /foo/testfile | AMD64 | 0.000 | 2006-06-11 20:49:12.623375-05
(1 row)
Часть II: За пределами ‘работы’
… Но работа никогда не бывает достаточной, верно? Давайте перейдем к ответу на следующий вопрос, размещенный в FAQ по конфигурации для proftpd:
Могу ли я перемещать файлы из каталога загрузки после загрузки?
И ответ: конечно, можете. Я достигну этого с помощью хранимой процедуры, чтобы файлы перемещались правильным образом — на лету — без демона.
Сначала вам нужно установить untrusted plperlu на систему, это можно сделать с помощью
apt-get install postgresql-plperl-8.1Затем вам нужно установить plperlu в базу данных
createlang plperlu your_database_hereДалее нам нужно создать быстрый триггер на perl-скрипт, который будет срабатывать при каждой вставке в нашу таблицу ftp_log
CREATE OR REPLACE FUNCTION ftp_file() RETURNS TRIGGER AS $$
use warnings;
use Cwd;
use File::Basename;
use File::Spec;
use File::Copy;
move (
$_TD->{new}{abs_path},
File::Spec->catfile( '/home/ftp/', basename($_TD->{new}{file}) )
);
return;
$$ LANGUAGE 'plperlu' VOLATILE;
CREATE TRIGGER ftp_file
BEFORE INSERT
ON ftp.file_log
FOR EACH ROW
EXECUTE PROCEDURE ftp_file()
;
Этот sql-скрипт можно установить так же, как и предыдущий (тот, который использовался для создания таблиц)
Get new posts in your inbox
No spam. Unsubscribe anytime.