Введение
Для начала что такое FTP? File Transport Protocol предназначен, как не трудно догадаться, для обмена файлами между двумя машинами в сети. Этот протокол специально разрабатывался и соответственно оптимизирован для файлового обмена. FTP сервер - это файловый сервер. На нем обычно размещают большое количество файлов, предназначенных для тотального скачивания.
Воспользоваться хранимой на таком сервере информацией можно с помощью ftp-клиента. В unix среде стандартом такого клиента является одноименная программа
ftp
. Практически все сценарии оболочки (по нашему скрипты), при необходимости используют именно ее. Вот ссылка на русский
man ftp.
К примеру, как происходит обычный сеанс связи:
gena@u158:~:$ ftp server
Connected to server..
220 fs.net.psiline.ru FTP server (Version 6.00LS) ready.
Name (server:gena): anonymous
331 Guest login ok, send your email address as password.
Password:
230 Guest login ok, access restrictions apply.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
200 PORT command successful.
150 Opening ASCII mode data connection for '/bin/ls'.
total 64
dr-xr-xr-x 2 0 operator 512 May 5 2003 bin
dr-xr-xr-x 2 0 operator 512 May 5 2003 etc
drwxrwxrwt 2 0 operator 512 Feb 11 2004 incoming
drwxr-xr-x 3 0 operator 512 May 5 2003 pub
226 Transfer complete.
ftp> cd /pub/FreeBSD/distfiles
250 CWD command successful.
ftp> get zip23.tar.gz
local: zip23.tar.gz remote: zip23.tar.gz
200 PORT command successful.
150 Opening ASCII mode data connection for 'zip23.tar.gz' (723283 bytes).
226 Transfer complete.
725952 bytes received in 0.684 secs (1e+03 Kbytes/sec)
ftp> exit
221 Goodbye.
gena@u158:~:$
В данном случае "server" - это алиас (псевдоним) ftp-сервера
fs.net.psiline.ru
, расположенного в моей сети. С таким же успехом я мог ввести
$ ftp fs.net.psiline.ru
или подставить IP любого ftp-сервера. Сообщение 220 - это приветствие, где часто можно прочитать что это за сервер, тип и версию демона ftp. Дальше нам предлагают зарегистрироваться. Здесь ничего нового - login & pass, вот только в данном случае применен универсальный login - anonymous, т.к. этот сервер анонимный, т.е. предоставляет доступ любому желающему. При этом используется имя - anonymous, а пароль - адрес электронной почты. В данном случае я вместо пароля просто нажал Enter. Успешность авторизации выражается в сообщениях 331 и 230. Также нам сообщается, что это система UNIX и используется бинарный формат передачи данных. Ну а дальше стандартные команды по перемещению внутри сервера. Команда
get
забирает файл с сервера, а
put
загружает на него. По окончании работы, команда
exit
завершает работу с сервером и возвращает нас в оболочку.
Командная строка - это конечно хорошо, но для человеческой работы совершенно необходим нормальный клиент. Из консольных подойдет встроенный в
MC, а для Иксов самым популярным по сей день является
gFTP.
Для Linux стандартными являются эти два сервера. Первый разработан Вашингтонским университетом. Он немного сложноват в настройке да и к тому же отсутствует в стандартном комплекте Slackware. Второй более прост, не менее популярен, а главное, он есть на первом диске. Пожалуй недостатком обоих является следствие их популярности, а именно: в них часто находят уязвимости. Лекарство от этого одно - периодическое обновление до последней версии. Можно конечно найти себе другой сервер, т.к. в данный момент есть из чего выбирать.
Буква "d" на конце указывает, что это demon, т.е. программа постоянно "висит" в памяти и ждет входящего соединения. На самом деле это не всегда так. Чаще всего, работой таких демонов управляет супердемон inetd. Присутствие его в системе выдаст стандартная комбинация команд:
gena@u158:~:$ ps -ax|grep inetd
1291 ? Ss 0:00 /usr/sbin/inetd
Супердемон inetd отслеживает все попытки подключения и в зависимости от сервиса запускает тот или иной демон. Это если вкратце. Такой способ экономит память и в общем случае оптимизирует систему. Однако, если файловый сервер и есть цель построения системы, нагрузка на него высока, то демон запускают напрямую в режиме standalone. Думаю, что для большинства других конфигураций, первый вариант предпочтителен.
Для того, чтобы inetd обрабатывал запросы ftp необходимы две вещи:
1. Настоены и имеют права на запуск (755) следующие стартовые скрипты:
/etc/rc.d/rc.inet1
/etc/rc.d/rc.inet2
/etc/rc.d/rc.inetd
2. В файле
/etc/inetd.conf
раскомментирована строчка
ftp stream tcp nowait root /usr/sbin/tcpd proftpd
Про установку писать особо нечего. Если CDROM у вас монтируется в /mnt/cdrom и там в данный момент подмонтирован первый установочный диск Slackware 10.0, то команда
gena@u158:~:$ installpkg /mnt/cdrom/slackware/n/proftpd-1.2.9-i486-3.tgz
все сделает в лучшем виде. После этого, повторюсь, нужно убедиться, что в файле
/etc/inetd.conf
раскомментирована строчка, отвечающая за запуск демона. Если мы ее подправили, то нужно перезапустить inetd, чтобы изменения вступили в силу:
# /etc/rc.d/rc.inetd restart
Starting Internet super-server daemon: /usr/sbin/inetd
Результат нашей работы проверяем или командой
$ nmap localhost
, а если нет
nmap
, то
$ netstat -l
. Наличие активности на 21 порту подтвердит правильность наших действий. Теперь можно попробовать подключиться:
$ ftp localhost
Connected to localhost.
220 ProFTPD 1.2.9 Server (Genas FTP) [127.0.0.1]
Name (localhost:gena):
В отличии от wu-ftpd, этот демон хранит все свои настройки в одном единственном файле
/etc/proftpd.conf
, что очень удобно. По-умолчанию этот файл выглядит
так. Как видите, формат очень похож на таковой web-сервера Apache с его конфигурационным файлом
/etc/apache/httpd.conf
. Это еще один плюс в использовании proftpd.
В конфигурации по-умолчанию вы получаете обычный (не анонимный) ftp-сервер на 21 порту. Работать с таким сервером смогут только пользователи, имеющие аккуант на этой машине. Т.е. чтобы подключиться, нужно ввести тот же login и password, что и при локальном входе в систему. При этом вы автоматически попадете в домашнюю директорию, а к остальным будете иметь доступ согласно локальным правам данного пользователя. В этом же файле есть все необходимое для организации анонимного ftp-сервера. Все, что нужно сделать - это создать (если еще нет) каталог
/home/ftp
и в файле
/etc/ftpusers
закомментировать строчку с именем
ftp
, тем самым убирая этого пользователя из "черного" списка.
Выше я вкратце дал ту необходимую информацию, которой достаточно для запуска файлового сервера в конфигурации по-умолчанию. А теперь более подробно.
Cписок интересных ключей запуска proftpd
-n | режим демона. При этом в /etc/proftpd.conf должна быть строчка ServerType standalone |
-c файл | использование альтернативного файла конфигурации |
-p 0|1 | использование постоянного пароля: 0-запрет; 1-добро. Также определяется директивой PersistentPasswd |
-t | тест конфигурационного файла |
-v | просто показывает свою версию |
Файлы
Вот кусок из
$ man proftpd
, со списком программ и их конфигурационных файлов, где можно покопаться.
FILES
/usr/sbin/proftpd
/etc/proftpd.conf
/usr/bin/ftpwho
/usr/bin/ftpcount
/usr/bin/ftptop
/usr/sbin/ftpshut
/var/log/xferlog
/var/run/run/proftpd.pid
/var/run/run/proftpd.scoreboard
Наиболее интересной программой из этого списка является
ftptop
. Она в режиме реального времени отображает всех подключенных в данный момент пользователей, выполняемые команды и проч.
ftptop/0.9: Mon Dec 13 00:56:40 2004
1 Total FTP Sessions: 0 downloading, 0 uploading, 1 idle
PID S USER CLIENT SERVER TIME COMMAND
17848 I ftp localhost 0.0.0.0:21 194 idle
Подобную информацию в виде среза дает
ftpwho
. Ее стоит запускать с ключиком -v.
root@u158:/etc/X11:# ftpwho -v
inetd FTP daemon:
17871 ftp [ 0m11s] 0m11s idle
client: localhost [127.0.0.1]
server: 0.0.0.0:21 (Genas FTP)
location: /
Service class - 1 user
Оставшиеся еще проще -
ftpcount
показывает общее число подключенных пользователей, а
ftpshut
выключает (выгружает из памяти) ftp-сервер через заданное количество времени.
Директивы
Полный список директив на английском лучше смотреть на сайте разработчиков
[1] . Список основных директив на русском я взял из статьи Д.Колиснеченко
[2] .
Директива | Описание |
AccessGrantMsg message | Ответное сообщение, которое будет отправлено пользователю в случае его регистрации или получения анонимного доступа. Символы %u будут заменены на имя пользователя, которое он ввел при регистрации. |
Allow from all | host | network [,host | network[, ...]] | Используется внутри блока Limit. Ограничивает доступ к серверу (а именно разрешает доступ). По умолчанию allow from all |
AllowAll | Разрешает доступ к блокам Directory, Anonymous, Limit |
AllowForeignAddress on | off | Разрешает клиенту указывать при соединении соединения адрес, который не соответствует ему. По умолчанию off. Может использоваться в блоках VirtualHost, Anonymous, <Global> |
AllowGroup group_list | Разрешает доступ определенным группам. Используется в блоке Limit |
AllowUser user_list | Разрешает доступ определенным группам. Используется в блоке Limit |
AnonRequirePassword on | off | Требует пароль при анонимной регистрации. Пароль должен совпадать с паролем того пользователя, который запустил демон. По умолчанию опция выключена. |
<Anonymous directory> | Создает анонимную учетную запись, directory - корневой каталог анонимного сервера. |
AuthGroupFile path | Позволяет указать путь к альтернативному файлу group. По умолчанию используется файл /etc/group |
AuthUserFile path | Указывает альтернативный файл passwd |
Bind address | Разрешает привязку дополнительного IP-адреса к основному или виртуальному хосту. |
DefaultRoot directory | Задает корневой каталог по умолчанию |
Deny from all | host | network | Запрещает доступ к серверу. Блок Limit |
DenyAll | Запрещает анонимным пользователям доступ к объектам, указанным в блоке Limit |
DenyUser user_list | Запрещает доступ определенным пользователям |
<Directory> path | Используется в VirtualHost, Anonymous для того, чтобы определить особенные параметры доступа к каталогу и его подкаталогам |
DisplayFirstChdir filename | Текстовый файл filename будет выводиться, когда пользователь впервые за время сеанса войдет в данный каталог. Используется в VirtualHost, Directory, Anonymous |
DisplayLogin filename | Этот файл будет отображен, когда пользователь зарегистрируется |
<Global> | Используется для задания параметров, которые будут использоваться как основным, так и всеми виртуальными серверами |
<Limit command> | Ограничение на выполнение данной FTP-команды, например LOGIN, WRITE |
MaxClients number | none | message | Ограничение на количество клиентов. Message будет отображено, если пользователю будет отказано в доступе. Блоки Anonymous, Global |
MaxLoginAttempts | Максимальное количество попыток зарегистрироваться. По умолчанию 3. Блоки VirtualHost, Global |
Order allow, deny | deny, allow | Порядок выполнения директив Allow и Deny в блоке Limit |
PersistentPassword on | off | При значении on будут использованы системные файлы /etc/passwd и /etc/group, несмотря на то, что командой chroot корневой каталог был изменен. |
RequireValidShell on | off | Разрешает или запрещает регистрацию при использовании оболочек (shells), которые не указаны в файле /etc/shells |
ServerAdmin email | Определяет email администратора сервера. |
ServerType | Определяет режим работы сервера standalone (по умолчанию) или inetd. В первом случае сервер будет запускаться автоматически из стартовых сценариев системы, во втором - его будет запускать сервер inetd при попытке соединения. |
TimeoutIdle seconds | Время в секундах, в течение которого пользователь имеет право не проявить активности. По умолчанию 60 (1 минута). |
User username | Имя пользователя, присвоенное демону ProFTP< |
UserAlias Alias User | Создает псевдоним (alias) для пользователя (user) |
<VirtualHost address> | Создает виртуальный сервер |
Этих директив должно хватить "за глаза".
Права доступа
Как и в Apache здесь балом правит директива
<Limit>
. Вы наверняка заметили ее в файле по-умолчанию. Первый раз мы встречаем ее в блоке
<Anonymous ~ftp>
# Limit WRITE everywhere in the anonymous chroot
<Limit WRITE>
DenyAll </Limit>
Как написано в комментарии - этот блок запрещает запись всем анонимным пользователям. Второй раз директива
<Limit>
встречается при описании папки, специально предназначенной для закачки файлов на сервер анонимными пользователями. В даном случае этот блок закомментирован.
# An upload directory that allows storing files but not retrieving
# or creating directories.
# <Directory incoming/*>
# <Limit READ>
# DenyAll
# </Limit>
#
# <Limit STOR>
# AllowAll
# </Limit>
# </Directory>
Если же удалить символы комментария, то первый лимит
<Limit READ>
указывает на запрет чтения (скачивания) из каталога, а второй
<Limit STOR>
разрешает запись в каталог. Разрешение или запрещение операций
WRITE, READ, STOR
и
LOGIN
определяется внутренними директивами
Allow, AllowAll, AllowGroup, AllowUser, Deny, DenyAll, DenyUser
, описанными выше.
WRITE | Операции записи |
READ | Операции чтения |
STOR | Операции создания(приема) файлов |
LOGIN | Операции по регистрации |
Файл .ftpaccess
Это специальный файл, опять же проведу параллель с Apache и его
.htaccess
. Т.е. туда можно поместить такие же директивы, как и в
/etc/proftpd.conf
, но их приоритет будет выше, чем в упомянутом файле. Поместив
.ftpaccess
в каку-либо директорию, мы тем самым описываем использование каталогов начиная с данного и всех вложенных. Если во вложенной папке тоже есть такой файл с директивами, противоретящими предыдущему
.ftpaccess
, то они будут более приоритетными. Используется принцип наследования.
Анонимный сервер
Построение анонимного сервера на основе
proftpd
проще чем на
wu-ftpd
, требующего дополнительный пакет. Выше уже была рассмотрена организация анонимного сервера на основе конфигурации по-умолчанию. Для описания используется директива
<Anonymous путь_к_каталогу>
. В качестве директории обычно выбирают или
/var/ftp
или
/home/ftp
или любой другой по вашему усмотрению. В моем случае директория
/home
физически расположена на отдельном разделе в формате XFS, специально разработанным для подобных целей. Поэтому каталог по-умолчанию меня более чем устроил. При запуске,
proftpd
сделает для этого каталога команду
chroot
, т.е. для анонимного пользователя это будет корневой каталог, выше которого ему не подняться. Внутри блока
<Anonymous>
прописываются директивы, относящиеся к конфигурации анонимного сервера. Вот немного подрехтованный блок из файла по-умолчанию.
# Блок конфигурации анонимного FTP-сервера.
# Чтобы все заработало, удалите пользователя "ftp" из "/etc/ftpusers".
<Anonymous ~ftp>
# Отключаем проверку командного интерпретатора.
RequireValidShell off
# Определяем под именем какого локального пользователя будет
# работать клиент, а также его группу.
User ftp
Group ftp
# Делаем псевдоним "anonymous" для пользователя "ftp".
UserAlias anonymous ftp
# Лимит клиентов
MaxClients 10
# Запрет на запись
<Limit WRITE>
DenyAll
</Limit>
# Директория для закачки файлов на сервер.
# Запрещается чтение(копирование), а также создание директорий.
<Directory upload/*>
<Limit READ>
DenyAll
</Limit>
<Limit STOR>
AllowAll
</Limit>
</Directory>
</Anonymous>
В самом начале нам заботливо напоминают, что из файла
/etc/ftpusers
необходимо убрать пользователя ftp, иначе ничего работать не будет. Дальше идет наш блок. Директория
~ftp
- для тех кто не знает, и есть
/home/ftp
. Пример прокомментирован, так что на этом и закончим его обсуждение.
Хочу акцентировать ваше внимание на тот факт, что все директории, начиная от
/home/ftp
должны принадлежать пользователю ftp и группе ftp и иметь права хотябы 755. На эти грабли даже я наступал :). Хорошо бы еще задать дисковую квоту или всему каталогу, или каталогам, предназначенных для закачки на сервер, а то с легкой руки хорошего друга можете остаться на нуле. Ведь Linux вам не Windows :) - он не будет надоедать вам сообщениями мол а место-то кончается - уже 2Гб осталось :). У меня например, бывало, что компиляция толстых программ забивала вин под голый 0 так, что даже MC не мог сохранить свой 1кб настроек.
Виртуальный сервер
Это понятие лучше пояснить на примере хостинга, т.е. web-сервера, предназначенного для размещения более чем одного сайта. Подавляющее большинство сайтов в интернете размещено именно на таких серверах. Физически, это может быть одна или несколько машин, объединенных в сеть, но обслуживающих огромное количество доменов (читай сайтов). Отсюда и выражение "Виртуальный", т.е. физически не существующий. То же самое можно сказать и о виртуальных ftp-серверах.
В случае конфигурации виртуального ftp-сервера на основе
proftpd
, необходимо использовать директиву
VirtualHost
:
<VirtualHost ftp.xxxxxx.ru>
ServerName "Genas FTP"
MaxClients 10
<Limit READ>
llowAll
</Limit>
<Anonymous /var/ftp/xxxxxx>
RequireValidShell on
User ftp
Group ftp
UserAlias anonymous ftp
<Directory upload/*>
<Limit READ>
DenyAll
</Limit>
<Limit STOR>
AllowAll
</Limit>
</Directory>
</Anonymous>
</VirtualHost>
Таких блоков может быть много и в каждом могут быть применены свои директивы. В заголовок вставляют доменное имя, которое должно быть прописано в DNS-сервере вашей сети и указывало бы на адрес вашего ftp-сервера. Если у сервера несколько IP адресов, то на каждый из них также можно повесить по виртуальному файловому серверу. В таком случае вместо доменного имени в директиве
VirtualHost
указывают IP адрес.
Вопросы безопасности
Как уже говорилось, proftpd довольно популярный сервер, а потому многие хакеры ищут и находят в нем все новые уязвимости. Почти все самые критичные уязвимости, найденные в нем, были основаны на переполнении буфера при передаче того или иного параметра. И если от таких ошибок в коде мы защититься не в силах, то от более многочисленных и соответственно более вероятных мелких ошибок можно защититься. Например, чтобы не быть подверженным DoS можно и нужно ограничить максимальное количество клиентов, и максимальное количество процессов, создаваемых супердемоном inetd при подключении новых пользователей:
MaxClients 30
MaxInstances 30
Также, для предотвращения подбора пароля, необходимо ограничивать число неудачных попыток:
MaxLoginAttempts 3
Если же злоумышленнику все-же удалось угадать или подсмотреть пароль, то директива:
DefaultRoot ~
не даст ему возможности подняться выше домашнего каталога пользователя. Вместо ~ можно конечно указать любой другой путь. По-умолчанию, это / - корень.
RequireValidShell on
Эта директива укажет демону на необходимость проверки используемого командного интерпретатора. Использоваться будет только "правильный", один из зарегистрированных в системе (
/etc/shells
).
Ссылки по теме
- http://www.proftpd.org/docs/directives/configuration_full.html
- http://www.troubles.ru/Doc/ProFTPD.htm
- http://linux.yaroslavl.ru/docs/serv/ProFTPD.html