Традиционный способ передачи файлов по протоколу FTP уже считается
устаревшим и небезопасным. Есть более совершенные альтернативы,
например, SFTP, SCP, FTPS и WebDAV. Но тем не менее для анонимного доступа обычный FTP вполне сгодится. Еще одна причина, по которой отказаться от FTP полностью пока нельзя, отсутствие в windows встроенной поддержки безопасных FTP.
В этой статье описываются принципы правильной настройки сервера ProFTPD с виртуальными пользователями, перекодировкой в cp1251 и поддержкой протоколов FTPS (FTP Secure) и SFTP (Secure File Transfer Protocol). Как вы можете видеть из названий, один - безопасность протокола, а другой - безопасный протокол. В этом их кардинальное отличие!
FTPS является обычным FTP поверх SSL/TLS, как HTTPS. Есть две его разновидности: Implicit FTPS - соединение устанавливается через дополнительный порт SSL 990 и Explicit FTPS или сокращенно FTPES, это уже более новая версия, который сейчас всеми и ипользуется, соединение и управление по одному стандартному порту 21.
А вот SFTP это абсолютно новый протокол, разработан с нуля, основан на SSH2 и не имеет с FTP ничего общего. У него больше возможностей, например есть докачка файлов после разрыва
соединения. В рамках SSH шифруется все. Конечно скорость передачи у SFTP будет меньше чем у чистого FTP или FTPS.
Я провел сравнение на 100 Мбитной сетке: FTP ~ 10 МБ/с, SFTP ~ 3 МБ/с. У FTPS такая же скорость, как и у обычного FTP. Еще для сравнения я проверил SFTP, встроенный в openssh, там скорость оказалась порядка 7 МБ/с. Почему такая разница по сравнению с proftp сказать сложно, видимо в самой реализации sftp. Попробуйте сравнить у себя, будет интересно узнать, как у вас.
Поэтому, наверно все таки, есть смысл использовать sftp-server от OpenSSH.
Имеем FreeBSD 10, что бы сэкономить время устанавливаем из пакета.
# pkg install proftpd
proftpd.conf
Конфигурационный файл находится в /usr/local/etc/proftpd.conf. Откройте и редактируйте его под себя по ходу чтения статьи.
Сервер запускается через inetd или автономно.
ServerType standalone
Рекомендуется создать специального пользователя и группу FTP для запуска службы. Пароль можно сделать пустым.
# adduser ftpи изменить в конфиге
User ftpПо умолчанию сервер слушает все интерфейсы, что бы указать только заданные адреса, используются директивы
Group ftp
DefaultAddress 192.168.20.1 192.168.30.1По желанию в виртуальных хостах можно переопределить другой адрес.
SocketBindTight on
Для того, что бы включить перекодировку с UTF-8 на CP1251 нужно обязательно задать LangPath
LangEngine onЧто бы задать пользователю корневую директорию, за пределы, которой он не должен выходить, используется
LangPath /usr/share/locale
UseEncoding UTF-8 WINDOWS-1251
DefaultRoot ~знак "~" сообщает, что будет использоваться домашняя директория пользователя.
Если нужно сделать исключение из правил и дать некоторым пользователям полный доступ к chroot директории, то создаете группу, например admins и пишете
DefaultRoot ~ !adminsДля управления анонимным доступом в конфигурациооном файле есть секция
<Anonymous ~ftp>Если у вас используются виртуальные хосты, то эту секцию лучше вынести в <Global>, что бы анонимный вход был доступен на всех ip, а не только на основном!
User ftp
Group ftp
UserAlias anonymous ftp
<Limit WRITE>
DenyAll
</Limit>
</Anonymous>
Виртуальные пользователи
По умолчанию для аутентификации пользователей proftp смотрит файл /etc/passwd. Но использование виртуальных пользователей безопаснее, поскольку это не позволяет злоумышленнику перехватить системные аккаунты, которые передаются в открытом виде! Для этого используются директивы AuthUserFile и AuthGroupFile в конфигурационном файле.
AuthUserFile /usr/local/etc/proftpd/ftpd.passwd
AuthUserFile используется в дополнение к passwd и не исключает его. Но если все таки нужно его запретить, то используйте AuthOrder.
AuthOrder mod_auth_file.cФорматы файлов AuthUserFile и AuthGroupFile такие же, как /etc/passwd и /etc/group соответственно.
username:password:uid:gid:gecos:homedir:shell
groupname:grouppasswd:gid:member1,member2,...memberN
Для создания и изменения этих файлов используется специальный скрипт ftpasswd. Первый параметр, который надо задать, это --passwd или --group. Потом --name, --uid, --home и --shell. Например,
# ftpasswd --passwd --name=bob --uid=1001 --home=/home/bob --shell=/bin/falseUid должен быть от реального пользователя, например от ftp, таким образом из одного реального пользователя создается много виртуальных.
После выполнения ftpasswd создается файл ftpd.passwd. Для создания файла с другим именем и расположением используется опция --file.
Аналогично для групп
# ftpasswd --group --name=group-name --gid=group-id --member=user-member1 \ --member=user-member2 ... --member=user-memberN
Так же можно использовать параметр --hash для вычисления хэша либо пароля.
По умолчанию proftp не пускает пользователей у которых шел не перечислен в файле /etc/shell. Поэтому, если вы используете недействительный шел, например /usr/sbin/nologin, то обязательно задайте директику RequireValidShell off.
Ограничение доступа
У proftpd есть удобный механизм ограничения доступа. Создаются различные правила для клиента на выполнение FTP команд. Это может быть запрет на переименование, удаление, запись файлов в определенную папку и др. (полный список можно посмотреть на сайте).
Для создания правил в конфигурационном файле указывается секция <Limits>... </Limits> с нужными командами. Их можно просто перечислить или использовать группы ALL, DIRS, LOGIN, READ и WRITE.
Затем внутри секции определяется действие: разрешить или запретить: DenyAll, AllowAll, AllowUser, AllowGroup, Deny from, Allow from. Их порядок играет имеет значение, если порядок "Allow,Deny", то разрешающее правило важнее, если наоборот "Deny,Allow", то запрет.
Например, следующие команды разрешают смену директории и загрузку файлов в эту директорию, при условии, что файловая система так же имеет соответствующие разрешения.
<Limit ALL>
DenyAll
</Limit>
<Limit CDUP CWD PWD XCWD XCUP>
AllowAll
</Limit>
<Limit STOR STOU>
AllowAll
</Limit>
Для этой цели можно использовать группу WRITE, но тогда пользователь сможет так же создавать и удалять поддиректории.
Или еще один пример, разрешается авторизация только двум пользователям и группе.
Или еще один пример, разрешается авторизация только двум пользователям и группе.
<Limit LOGIN>
AllowUser barb
AllowUser dave
AllowGroup ftpuser
DenyAll
</Limit>
Поскольку активный режим работы FTP-сервера не безопасен, это когда сервер должен сам подключиться к клиенту. То его можно отключить средствами <Limits>.
Пример, назначается папка для загрузок для анонимного доступа.
Еще можно использовать классы для группировки пользователей.
<Limit EPRT PORT>Обычно <Limits> удобно использовать внутри секции <Directory>, тогда все вложенные поддиректории будут наследовать свойства. Следующий пример описывает папку, у которой нельзя увидеть содержимое, но можно загружать и скачивать файлы.
DenyAll
</Limit>
<Directory /path/to/dir>Если в пути вы указываете суффикс
<Limit LIST NLST MLSD MLST STAT>
DenyAll
</Limit>
</Directory>
/*
, то это означает, что конфигурация применяется только для содержимого, но не для самой папки.Пример, назначается папка для загрузок для анонимного доступа.
<Anonymous ~ftp>В ftp протоколе команда STOR служит для аплоада файлов клиентом.
User ftp
Group ftp
UserAlias anonymous ftp
<Limit WRITE>
DenyAll
</Limit>
<Directory upload/*>
<Limit STOR>
AllowAll
</Limit>
</Directory>
</Anonymous>
Еще можно использовать классы для группировки пользователей.
<Class internal>
From 192.168.0.0/16
From *.example.com
</Class>
А потом назначить действия сразу целым классам с помощью AllowClass и DenyClass.
<Limit ALL>
AllowClass internal
DenyAll
</Limit>
По умолчанию proftpd слушает все интерфейсы, но если надо только один, то используйте параметр DefaultAddress.
Сервер за NAT
Особый случай, если ваш ftp-сервер находится за NAT и вы хотите предоставить к нему доступ извне. Для этого вам надо задать опцию MasqueradeAddress с ip-адресом nat-сервера. А на NAT-сервере настроить форвардинг порта 21 и диапазона портов для пассивного режима, которые задаются в конфиге PassivePorts 40000-45535.
Особый случай, если ваш ftp-сервер находится за NAT и вы хотите предоставить к нему доступ извне. Для этого вам надо задать опцию MasqueradeAddress с ip-адресом nat-сервера. А на NAT-сервере настроить форвардинг порта 21 и диапазона портов для пассивного режима, которые задаются в конфиге PassivePorts 40000-45535.
Но как только вы зададите опцию MasqueradeAddress, пользователи из локальной сети не смогут больше подключаться! Выходом из этой ситуации будет использование данной опции не в глобальных настройках, а на виртуальном хосте.
<VirtualHost your_local_ip>
MasqueradeAddress nat_ip
Port 1121
</VirtualHost>
Теперь FTP-сервер, кроме 21, еще будет работать на 1121 порту. На NAT-сервере настраиваем перенаправление портов. В моем случае это ядерный NAT.
nat 1 config log if rl0 reset same_ports deny_in redirect_port tcp 192.168.15.2:1121 21 redirect_port tcp 192.168.15.2:40000-45535 40000-45535Один важный момент, в списке правил перед строкой nat не должно быть явно разрешающих правил для используемых портов, т.е. таких
add 1085 nat 1 ip from any to any via rl0
1030 allow tcp from any to me 21, 20, 40000-45535Иначе пакеты не дойдут до nat и соответственно не будут перенаправляться. Была у меня такая проблема, долго не мог понять почему не работает ftp через nat, а они просто напросто не доходили до редиректа.
Еще, если вы пытаетесь таким же способом редиректить штатный фряшный ftpd через ipfw, то ничего не получится! У него нет такой замечательной опции MasqueradeAddress. В этом случае надо использовать ftp-proxy.
Теперь внутри локальной сети FTP сервер будет работать, как обычно на 21 порту. Из вне доступ так же будет по 21 порту через nat-сервер, благодаря форвардингу redirect_port tcp 192.168.15.2:1121 21.
Виртуальные хосты
Это возможность организовать одновременно несколько ftp-серверов на одном. Они называются виртуальными. Но имейте в виду, что протокол FTP не поддерживает виртуальные хосты на основе имен. Например, нельзя создать soft.server.ru и video.server.ru, как в Apache. FTP виртуальные хосты могут быть основаны только на уникальности пары IP/порт.
Поэтому, если ваш сервер имеет несколько ip-адресов, например, локальная сеть и внешняя, то для каждой из них нужно настроить виртуальные хосты. Это делается с помощью секции <VirtualHost>.
<VirtualHost 10.0.0.1>
ServerName "My local FTP server"
</VirtualHost>
<VirtualHost 1.2.3.4>
ServerName "My external FTP server"
</VirtualHost>
Так же можно использовать виртуальные хоcты с одинаковым ip-адресом, но на разных портах.
<VirtualHost myhost.mydomain.com>
Port 2001
...
</VirtualHost>
Все глобально установленные параметры в конфигурационном файле не относятся к виртуальным хостам, их нужно задавать отдельно для каждого! Поэтому ради удобства, что бы не дублировать общие параметры в каждом виртуальном хосте, их можно вынести в секцию <Global>, тогда они будут доступны для всех.
В <Global> так же следует вынести секцию <Anonimous ~>
Таким образом, с помощью виртуальных хостов, мы одновременно запустим ftp, sftp и ftps на разных портах.
Но для этого сначала нужно перекомпилировать ptoftpd с дополнительными модулями.
В <Global> так же следует вынести секцию <Anonimous ~>
Таким образом, с помощью виртуальных хостов, мы одновременно запустим ftp, sftp и ftps на разных портах.
Но для этого сначала нужно перекомпилировать ptoftpd с дополнительными модулями.
#./configure --with-modules=mod_sftp:mod_tls:mod_sql:mod_sql_mysql \
--with-includes=/usr/local/include/mysql \
--with-libraries=/usr/local/lib/mysql
# make
# make install
Выяснилось, что в портах Freebsd, начиная c версии 1.3.4 Proftpd стал использовать динамически подключаемые модули. Поэтому пересборка не требуется, достаточно указать директиву LoadModul в proftpd.conf.
Выносим общие параметры в секцию
Выносим общие параметры в секцию
<Global>
PassivePorts 40000 45535
AuthUserFile /usr/local/etc/proftpd/ftpd.passwd
RequireValidShell no
MaxLoginAttempts 6
LangEngine on
UseEncoding UTF-8 WINDOWS-1251
DefaultRoot ~ !admins
</Global>
Подгружаем SFTP модуль
LoadModule mod_sftp.cИ добавляем виртуальный хост
<VirtualHost 192.168.10.1>Подгружаем TLS модуль
MasqueradeAddress myhost.mydomain.com
SFTPEngine on
Port 8022
SFTPHostKey /etc/ssh/ssh_host_dsa_key
SFTPHostKey /etc/ssh/ssh_host_rsa_key
SFTPHostKey /etc/ssh/ssh_host_ecdsa_key
SFTPLog /var/log/sftp.log
SFTPCompression off
</VirtualHost>
LoadModule mod_tls.cДобавляем виртуальный хост
<VirtualHost 192.168.10.1>
MasqueradeAddress myhost.mydomain.com
TLSEngine on
Port 1021
TLSLog /var/log/tls.log
TLSProtocol SSLv23
TLSRequired auth
TLSOptions NoCertRequest
TLSRSACertificateFile /usr/local/etc/proftpd/ssl/cert.pem
TLSRSACertificateKeyFile /usr/local/etc/proftpd/ssl/key.pem
TLSVerifyClient off
</VirtualHost>
Параметр TLSRequired определяет политику безопасности, когда использовать SSL/TLS и может иметь несколько значений:
- off - Клиенты могут подключаться, как по обычному FTP, так и используя шифрование,
- ctrl - шифруется только управляющий канал, поэтому пароли будут спрятаны,
- data - шифруются только данные (не рекомендуется),
- on - шифруются оба канала,
- auth - шифрование управляющего канала, но только в момент авторизации,
- auth+data - шифрование авторизации и данных, клиенту разрешается использовать команду CCC (Clear Command Channel), что позволяет лучше работать через фаервол.
Для FTPS еще нужно сгенерировать сертификат OpenSSL и положить в /usr/local/etc/proftpd/ssl/
# openssl req -new -x509 -days 365 -nodes -out /usr/local/etc/proftpd/ssl/cert.pem -keyout /usr/local/etc/proftpd/ssl/key.pemДобавим автозапуск в rc.conf
# echo 'proftpd_enable="YES"' >> /etc/rc.confНе забываем про ротацию логов
# vi /etc/newsyslog.confЧтобы запустить Proftpd используем команду
/var/log/proftpd.log 600 7 * @T00 JC
# service proftpd startПо умолчанию сервер пытается связать ip-адрес и имя хоста. Поэтому, если они не соответствуют действительности, вы получите следующее сообщение при старте.
warning: unable to determine IP address of 'hostname'Тут либо правильно настройте DNS, либо добавьте имя в файл /etc/hosts.
# vi /etc/hosts
192.168.10.5 your_domain_name
Проверим, что слушаются 21, 1021 и 8022 порты.
# sockstatТеперь можно подключаться любым клиентом, например, Filezilla, он понимает ftps, ftpes и sftp. Так же удобно использовать ftps/ftpes через Total Commander, но к нему еще нужно скачать OpenSSL библиотеки. Их можно взять тут, просто запустите установщик и он сам скопирует нуждные dll в системную папку. После этого в свойствах ftp-соединения станет доступной галочка SSL/TLS.
USER COMMAND PID FD PROTO LOCAL ADDRESS FOREIGN ADDRESS
ftp proftpd 87980 0 tcp4 *:21 *:*
ftp proftpd 87980 1 tcp4 *:8022 *:*
ftp proftpd 87980 2 tcp4 *:1021 *:*
Что бы посмотреть активных пользователей есть команда ftpwho.
Mysql
Кто хочет можно хранить пользователей в базе mysql. Для этого нужно поставить порт proftpd-mod_sql_mysql. Он автоматически установит mysql-client. Но mysql-server вам надо поставить самим.Кстати хороший мануал на русском языке есть на сайте mysql.ru. После установки нужно создать конфигурациооный файл my.cnf и положить его в /var/db/mysql/my.cnf. Шаблоны лежат тут /usr/local/share/mysql/. Можно восползоваться, например my-medium.cnf. В него я добавил такие параметры.
Mysql
Кто хочет можно хранить пользователей в базе mysql. Для этого нужно поставить порт proftpd-mod_sql_mysql. Он автоматически установит mysql-client. Но mysql-server вам надо поставить самим.Кстати хороший мануал на русском языке есть на сайте mysql.ru. После установки нужно создать конфигурациооный файл my.cnf и положить его в /var/db/mysql/my.cnf. Шаблоны лежат тут /usr/local/share/mysql/. Можно восползоваться, например my-medium.cnf. В него я добавил такие параметры.
[client]
character_set_client=utf8
[mysqld]
character-set-server=utf8
init-connect="SET NAMES utf8"
skip-networking
#log-bin=mysql-bin
#binlog_format=mixed
Еще необходимо проинициализировать таблицы привилегий.
# cd /usr/localСкрипт mysql_install_dbсоздает две базы данных: одна mysql, она обеспечивает привилегии доступа и другая test для тестирования. Для пользователя root устанавливается пустой пароль.
# ./bin/mysql_install_db
# chown -R mysql:mysql /var/db/mysql
Добавляем в rc.conf строчку
# echo 'mysql_enable="YES"' >> /etc/rc.confЗапускаем MySQL сервер
# service mysql-server startУбеждаемся, что он запустился
# ps ax | grep mysqlУстанавливаем пароль для пользователя root.
15840 - Is 0:00,17 /bin/sh /usr/local/bin/mysqld_safe --defaults-extra-file
16374 - I 0:01,01 /usr/local/libexec/mysqld --defaults-extra-file=/var/db/
# /usr/local/bin/mysqladmin -uroot password 'password'Заходим
# mysql -uroot -p'pasword'
Позднее пароль можно поменять так
Теперь нужно создать таблицы users и groups, где будут храниться пользователи. Но сначала создадим базу данных proftpd и пользователся ftp для подключения к базе.
Добавим нового пользователя для доступа к ptoftpdmysql> use mysql;Чтобы каждый раз не вводить пароль его можно сохранить в файле .my.cnf
mysql> update user set password=PASSWORD('my_password') where user='root' and host='localhost';
mysql> flush privileges;
mysql> quit
# touch /root/.my.cnfИ для входа просто писать из под руда # mysql
# chmod 0600 /root/.my.cnf
# vi /root/.my.cnf
[client]
password=passwd
Теперь нужно создать таблицы users и groups, где будут храниться пользователи. Но сначала создадим базу данных proftpd и пользователся ftp для подключения к базе.
mysql> CREATE DATABASE proftpd;
mysql> grant select,insert,update,delete on proftpd.* to ftp@localhost identified by 'password';
mysql> USE proftpd;
mysql> CREATE TABLE users (
userid VARCHAR(30) NOT NULL UNIQUE,
passwd VARCHAR(80) NOT NULL,
uid INTEGER,
gid INTEGER,
homedir VARCHAR(255),
shell VARCHAR(255) );
mysql> CREATE TABLE groups (
groupname VARCHAR(30) NOT NULL,
gid INTEGER NOT NULL,
members VARCHAR(255) );
mysql> insert into users values('new_user',ENCRYPT('passwd'),'5001','5001','/home/new_user','/sbin/nologin');Изменить можно так
mysql> exit;
mysql> UPDATE users SET passwd=ENCRYPT('new_pass'), gid=14 WHERE userid='user';Удалить так
mysql> DELETE FROM users WHERE userid='user';Создаем домашний каталог пользователя
# mkdir /home/new_userНастраиваем proftpd для авторизации через mysql
# chown 5001:5001 /home/new_user
AuthOrder mod_sql.c
SQLConnectInfo proftpd@localhost:3306 ftp password
SQLAuthTypes Crypt
SQLUserInfo users userid passwd uid gid homedir shell
DefaultRoot ~
RequireValidShell off
SQLGroupInfo groups groupname gid members
SQLAuthenticate users groups
SQLLogFile /var/log/proftpd.log
Опцию SQLLogFile включается только на момент отладки, потом не забудьте ее закомментировать!
Логирование
Еще, что касается логов. По умолчанию proftpd ведет логирование используя syslog. Размещение определяется согласно /etc/syslog.conf в /var/log/xferlog.
Можно настраивать различные уровни логирования: err, notice, warn, info и debug, но они распространяются только на syslog.
Еще, что касается логов. По умолчанию proftpd ведет логирование используя syslog. Размещение определяется согласно /etc/syslog.conf в /var/log/xferlog.
Можно настраивать различные уровни логирования: err, notice, warn, info и debug, но они распространяются только на syslog.
SyslogLevel notice
Если хочется иметь отдельные файлы логов, то можно прописать:
Детализация варьируется от 0 до 9 - самая подробная.TransferLog /var/log/proftpd-transfer.log
SystemLog /var/log/proftpd-error.log
ExtendedLog /var/log/proftpd-extended.log
DebugLevel 9Можно перезагружать proftpd и проверять.
# service proftpd restartУдачных, Вам, настроек!