Как я vsftpd настроил

в 13:25, , рубрики: linux, системное администрирование

В связи с недавними событиями популярного почтового сервиса, который хранил личные файлы пользователей в свободном доступе, я решил настроить FTP сервер для своих нужд, — чтобы знакомые могли напрямую мне передавать файлы и скачивать их. Нет, тем сервисом я не пользовался и давно зарекся не доверять третьим лицам ничего лишнего, однако, если не свой личный FTP, то коткточто? Конечно OpenSSH, но будете ли вы каждому знакомому человеку объяснять, что нужно для этого скачать/установить, или все же просто сообщите ссылку на свой FTP? Так же, консольный ftp-клиент есть «из коробки» даже в Windows (если вы понимаете, о чем я).

Все происходит на локалхосте (то есть, на домашнем компьютере), поэтому обязательным условием является наличие внешнего IP. И Linux. Конечно же Linux, куда же без него…

I. Почему и зачем?

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

Не имею ничего против anonymous-пользователей, — пускай, буду выкладывать на паблик всякую ерунду. Чтобы не ощущать дискомфорт, для anonymous будут жесткие ограничения вроде скорости 16КБайт/секунду.
anonymous смогут заливать файлы на сервер в отдельную директорию.
Нарушать структуру FHS не буду, поэтому anonymous попадают в директорию /srv/ftp, и в ней, уже следуя традициям, создаю две директории для загрузки и отдачи файлов.

mkdir /srv/ftp/{incoming,pub}
chown root:ftp /srv/ftp/{incoming,pub}
chmod g+w /srv/ftp/incoming

Уже для себя, хочу иметь пользователя на сервере со своим логином:паролем, а в идеале — создавать сколько угодно различных пользователей, и они будут работать с корневой директорией в моем хомяке ~/Downloads (которая так же используется другими программами).
Полагаю вы догадались. что эти пользователи на сервере — те самые знакомые, которым я хочу предоставить свободный доступ к файлообмену.
В нее они могут свободно загружать, скачивать файлы с неограниченной скоростью. И мне не нужно ничего лишний раз костылить с правами и придумыванием новых директорий. Все загрузки, — браузер, торрент, фтп, — все лежит в одном месте. Удобно.

Делать нечто вроде хостинга, чтобы у каждого пользователя сервера была своя директория (а в ней например, расшаренный сайт), у меня задачи не стояло, но я рассмотрю и этот случай.

Все? Больше никаких экзотичных пожеланий нет? Тогда начнем.

Перво-наперво накатываем сам FTP сервер. Мой выбор пал на vsftpd, — маленький, надежный, быстрый, безопасный (я бы даже сказал параноидальный) сервер, да и сам выбор очевиден:

vsftpd is the default FTP server in the Ubuntu, CentOS, Fedora, NimbleX, Slackware and RHEL Linux distributions.

© en.wikipedia.org/wiki/Vsftpd

II. Установка

Рассказывать про установку лишний раз не стану, в каждом дистрибутиве свой пакетный менеджер, и про три заветные команды ./configure && make && su -c "make install" вы и так наслышаны… vsftpd у вас установлен.

Для многих пользователей может быть привычным запускать программу, жмякать кнопочки и расставлять галочки для управления пользователями и правами на директории/файлы.
В случае с vsftpd имеются лишь базовые настройки сервера, а права на файлы — реальные права, которые устанавливаются через chmod. Поэтому например, чтобы разрешить пользователям загружать файлы на сервер, вам соответственно нужно просто разрешить запись в директорию стандартными средствами. В vsftpd вы лишь только включаете функцию, что файлы можно загружать на сервер, а в какую директорию, какой пользователь может загружать — это устанавливается стандартными chmod/chown. Так, для ясности.

III. Базовая настройка

Для проверки работоспособности сервера его необходимо запустить от пользователя root, командой vsftpd. Жмякаем Ctrl + C чтобы его выключить.
Консольным клиентом ftp (в любой(?) операционной системе) будем проверять, как мы его настроили.
Файл с настройками /etc/vsftpd.conf, но он нам не нужен, поэтому открываем любимым текстовым редактором, затираем все и пишем свой конфиг. И так…

Включаем работу сервера в режиме самостоятельного демона, без всяких inetd, и ведение логов (по-умолчанию /var/log/vsftpd.log)

listen=YES
xferlog_enable=YES

Включаем 20 порт для обмена непосредственно данными через команду PORT, и ограничиваем количество одновременных соединений.

connect_from_port_20=YES
max_clients=50
max_per_ip=3

Приветствуем пользователей при подключении к FTP, и включаем файлы .message, которые можно создавать в директориях и затем пользователи смогут их читать при заходе в данную директорию. Просто приятные рюшечки.

ftpd_banner=Welcome to Voglea FTPd
dirmessage_enable=YES

Прячем пользователей в системе, так, что при листинге директорий имя/группа всех объектов будет просто именоваться ftp, а не иметь id реального владельца этого объекта, и включаем возможность загружать файлы на сервер — для этого мы его и настраиваем, же.

hide_ids=YES
write_enable=YES

Включаем локальных пользователей, — теперь логиниться на FTP можно под своим реальным пользователем в системе, и вы попадаете в свой хомяк (/home/%USERNAME%). Меня это не устроило, но об этом мы еще поговорим. И устанавливаем права на новые создаваемые файлы, -rw-r--r-- т.е. владелец файла может его читать/изменять, группа и остальные только читать. По-умолчанию устанавливаются права -rwxrwxrwx, но зачем оно нам?

local_enable=YES
local_umask=022

Включаем виртуальных пользователей на сервере. Это несомненно безопаснее, чем авторизироваться под реальным пользователем системы и попадать в хомяк. Так же, эта настрока позволяет более гибко настраивать доступ пользователям, о чем поговорим еще ниже. И укажем пользователя, с правами которого будет выполняться сессия — ftp — он у нас совсем без прав, поэтому это безопасно. Под этим пользователем будут создаваться (загружаться на сервер) новые файлы. Можете указать nobody или еще кого.

guest_enable=YES
guest_username=ftp

Запираем пользователя в его хомяке. Без этой настройки, вы могли бы зайти в любую директорию в системе и прочитать любой файл (ну, все зависит от прав).

chroot_local_user=YES

Все, наша система с такими настройками в безопасности.

IV. Пользователи

И теперь-то настроим наших виртуальных пользователей на сервере.
Укажем директорию, где будет лежать персональный конфиг каждого такого пользователя.

user_config_dir=/etc/vsftpd_user_conf

Создадим файл ~/logins.txt с примерным содержанием

username
password
spoofing
blahblahblah
root
toor

где построчно записан логин пользователя, затем следует его пароль.

Выполним команду для конвертации файла в базу данных Berkeley

db_load -T -t hash -f ~/logins.txt /etc/vsftpd_login.db
chmod 600 /etc/vsftpd_login.db

однако в зависимости от версии программы, у вас может быть db3_load, db4_load.

Укажем PAM, какой файл с базой нужно использовать серверу, — создайте файл /etc/pam.d/ftp и запишите в него

auth required /lib/security/pam_userdb.so db=/etc/vsftpd_login
account required /lib/security/pam_userdb.so db=/etc/vsftpd_login

В зависимости от того, каких вы пользователей укажете в ~/logins.txt (и затем процесс конвертирования базы нужно повторить), — вы сможете логиниться на ftp под этими пользователями.
И для каждого пользователя в отдельности вы можете указать персональные настройки, — напоследок создадим директорию mkdir /etc/vsftpd_user_conf, где эти самые настройки будут храниться.

V. Наш ~/Downloads

Создаем файл /etc/vsftpd_user_conf/spoofing (с логином нашего виртуального пользователя на сервере) и переопределяем настройки по-умолчанию, которые были ранее указаны (или не указаны вовсе) в /etc/vsftpd.conf.
Суть в том, что эти настройки теперь работают только для этого пользователя.

Бзик vsftpd, который не желал писать в директорию, указанную корневой для пользователя и от этого выдавал ошибку 500 OOPS: vsftpd: refusing to run with writable root inside chroot (). То есть например, по-умолчанию при логине на сервере вы попадаете в /home/spoofing/Downloads. Установите ей права chmod ga+w /home/spoofing/Downloads и возникнет эта ошибка. С чем связана такая паранойя, что в «корень нельзя писать» — не знаю, но да ладно. Все же разрешаем запись и избавляемся от ошибки.

allow_writeable_chroot=YES

Переопределяем пользователя, с правами которого будут создаваться новые (загружаемые на сервер) файлы. Ранее в конфиге у нас был указан пользователь ftp, но нам же в нашем ~/Downloads не нужны никакие «чужие» файлы? Так же, сессия на сервере будет создаваться под нашим пользователем, а значит не будет вовсе никаким проблем с доступом в наш /home/spoofing, чтобы зайти в ~/Downloads.

guest_username=spoofing

И наконец, указываем сам ~/Downloads, которая для этого пользователя будет корневой директорией на сервере. И убираем лимит на загрузки.

local_root=/home/spoofing/Downloads
local_max_rate=0

Теперь при логине под пользователем spoofing на сервере вы попадаете в свою директорию /home/spoofing/Downloads, можете в нее загружать файлы и скачивать.
Сессия происходит под вашим уже настоящим пользователем spoofing, только поэтому вы и можете попасть в свой~, и загружаемые файлы создаются под вашим пользователем. Так-то.

Теперь точно так же создаем других пользователей на сервере, но чтобы все они могли работать только с одним общим ~/Downloads.
Для этого описываем их в ~/logins.txt, пересоздаем базу Berkeley, копируем содержимое /etc/vsftpd_user_conf/spoofing в /etc/vsftpd_user_conf/{другие, логины, новых, пользователей}. Все.

VI. anonymous

Перед началом мы уже создали необходимые директории /srv/ftp/{incoming,pub} и установили права на запись в /srv/ftp/incoming.

Разрешим anonymous логиниться.

anonymous_enable=YES

Разрешим загружать файлы, создавать директории, но а вот переименовывать и удалять уже созданные файлы — нельзя.

anon_upload_enable=YES
anon_mkdir_write_enable=YES
anon_other_write_enable=NO

Ограничим пропускную способность в 16384 байт, и укажем, с какими правами создавать новые файлы.

anon_max_rate=16384
anon_umask=022

Все, теперь anonymous попадая в свою домашнюю /srv/ftp увидит incoming для загрузки файлов и pub
Сессия на сервере выполняется под пользователем ftp, — тот, которого мы указали в /etc/vsftpd.conf, под ним же будут создаваться новые загружаемые файлы.

VII. Хостинг

К примеру, ваши сайты лежат в /srv/http/example.com, /srv/http/example.net, /srv/http/example.org и через FTP вы хотите иметь полный доступ к файлам каждого сайта отдельно.

Создайте пользователей на сервере с именами example.com, example.net, example.org, а в /etc/vsftpd.conf установите корневую директорию с сайтами

local_root=/srv/http/$USER
user_sub_token=$USER

Логинясь под именами доменов — вы попадаете в корень каждого из сайтов. Все просто.

Другой вариант, если вы будете создавать каждого пользователя по отдельности в /etc/vsftpd_user_conf, каждому из которых будете устанавливать персональные настройки для доступа к файлам сайта.

VIII. Безопасность

Это конечно хорошо, что файлы хранятся не в открытом доступе на каком-то файлообменнике, а переходят напрямую от пользователя к пользователю через прямое подключение по FTP. Однако, было бы прекрасным трафик еще и шифровать, чтобы никто не узнал какие именно файлы вы передаете.

Настроим SSL/TLS, и прежде включим его в /etc/vsftpd.conf.

ssl_enable=YES

Выберите, какой протокол вам нравится.

ssl_tlsv1=YES
ssl_sslv2=NO
ssl_sslv3=NO

Генерируем сертификат.

openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout /etc/ssl/certs/vsftpd.pem -out /etc/ssl/certs/vsftpd.pem

Указываем путь до него.

rsa_cert_file=/etc/ssl/certs/vsftpd.pem

И, я считаю обязательным всем локальным пользователям подключаться к вашему серверу по зашифрованному соединению. Вдруг, девушка захочет перекинуть свои фотографии жанра Ню?
Поэтому включаем обязательный SSL/TLS для локальных пользователей, а вот anonymous оно пожалуй не нужно, расходовать лишь процессорное время.

force_local_logins_ssl=YES
force_local_data_ssl=YES

allow_anon_ssl=NO

IX. Проверяем

anonymous'ы, множество локальных пользователей, которые сразу работают с вашим ~/Downloads, обязательное соединение через SSL/TLS.
Шикарно, безопасно, удобно, и, — все работает. Проверим.

Загружаем файл curl'ом на ftp://localhost/incoming

┌─[myhost ~]
└─╼ curl -v -T ~/Desktop/userpic.jpg ftp://localhost/incoming/
* About to connect() to localhost port 21 (#0)
* Trying ::1…
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Connection refused
* Trying 127.0.0.1…
* connected
* Connected to localhost (127.0.0.1) port 21 (#0)
< 220 Welcome to Voglea FTPd
> USER anonymous
< 331 Please specify the password.
> PASS ftp@example.com
< 230 Login successful.
> PWD
< 257 "/"
* Entry path is '/'
> CWD incoming
< 250 Directory successfully changed.
> EPSV
* Connect data stream passively
< 229 Entering Extended Passive Mode (|||8210|).
* Trying 127.0.0.1…
* connected
* Connecting to 127.0.0.1 (127.0.0.1) port 8210
> TYPE I
< 200 Switching to Binary mode.
> STOR userpic.jpg
< 150 Ok to send data.
} [data not shown]
* We are completely uploaded and fine
* Remembering we are in dir «incoming/»
100 77050 0 0 100 77050 0 25418 0:00:03 0:00:03 --:--:-- 25437< 226 Transfer complete.
100 77050 0 0 100 77050 0 20654 0:00:03 0:00:03 --:--:-- 20656
* Connection #0 to host localhost left intact
> QUIT
< 221 Goodbye.
* Closing connection #0

Проверяем файл в /srv/ftp/incoming

┌─[myhost ~]
└─╼ ls -la /srv/ftp/incoming/
total 88K
drwxrwxr-x 2 root ftp 4.0K Jan 17 20:31 ./
dr-xr-xr-x 4 root ftp 4.0K Jan 17 15:26 ../
-rw-r--r-- 1 ftp ftp 76K Jan 17 20:31 userpic.jpg

Проверяем подключение к серверу

┌─[myhost ~]
└─╼ ftp localhost
ftp: connect to address ::1: Connection refused
ftp: Trying 127.0.0.1…
Connected to localhost.localdomain.
220 Welcome to Voglea FTPd
Name (localhost.localdomain:spoofing): anonymous
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls -la
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
dr-xr-xr-x 4 ftp ftp 4096 Jan 17 07:26.
dr-xr-xr-x 4 ftp ftp 4096 Jan 17 07:26…
drwxrwxr-x 2 ftp ftp 4096 Jan 17 12:31 incoming
drwxr-xr-x 2 ftp ftp 4096 Jan 16 15:08 pub
226 Directory send OK.
ftp> cd incoming
250 Directory successfully changed.
ftp> ls -la
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
drwxrwxr-x 2 ftp ftp 4096 Jan 17 12:31.
dr-xr-xr-x 4 ftp ftp 4096 Jan 17 07:26…
-rw-r--r-- 1 ftp ftp 77050 Jan 17 12:31 userpic.jpg
226 Directory send OK.
ftp> quit
221 Goodbye.

anonymous'ы — работают.

Утилита ftp не умеет работать с SSL/TLS

┌─[myhost ~]
└─╼ ftp localhost
ftp: connect to address ::1: Connection refused
ftp: Trying 127.0.0.1…
Connected to localhost.localdomain.
220 Welcome to Voglea FTPd
Name (localhost.localdomain:spoofing): spoofing
530 Non-anonymous sessions must use encryption.
ftp: Login failed.
421 Service not available, remote server has closed connection
ftp> quit

Пробуем через curl --ftp-ssl загрузить файл

┌─[myhost ~]
└─╼ curl -v -T Desktop/userpic.jpg -k --ftp-ssl ftp://spoofing:blahblahblah@localhost
* About to connect() to localhost port 21 (#0)
* Trying ::1…
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Connection refused
* Trying 127.0.0.1…
* connected
* Connected to localhost (127.0.0.1) port 21 (#0)
< 220 Welcome to Voglea FTPd
> AUTH SSL
< 234 Proceed with negotiation.
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: none
* SSLv3, TLS handshake, Client hello (1):
} [data not shown]
* SSLv3, TLS handshake, Server hello (2):
{ [data not shown]
* SSLv3, TLS handshake, CERT (11):
{ [data not shown]
* SSLv3, TLS handshake, Request CERT (13):
{ [data not shown]
* SSLv3, TLS handshake, Server finished (14):
{ [data not shown]
* SSLv3, TLS handshake, CERT (11):
} [data not shown]
* SSLv3, TLS handshake, Client key exchange (16):
} [data not shown]
* SSLv3, TLS change cipher, Client hello (1):
} [data not shown]
* SSLv3, TLS handshake, Finished (20):
} [data not shown]
* SSLv3, TLS change cipher, Client hello (1):
{ [data not shown]
* SSLv3, TLS handshake, Finished (20):
{ [data not shown]
* SSL connection using DES-CBC3-SHA
* Server certificate:
* subject: C=RU; ST=Russian Federation; L=Sosnovoborsk, Krasnoyarsk Krai; O=Voglea.NET; OU=Hackers Online; CN=voglea.com; emailAddress=postmaster@voglea.com
* start date: 2013-01-17 08:07:16 GMT
* expire date: 2014-01-17 08:07:16 GMT
* issuer: C=RU; ST=Russian Federation; L=Sosnovoborsk, Krasnoyarsk Krai; O=Voglea.NET; OU=Hackers Online; CN=voglea.com; emailAddress=postmaster@voglea.com
* SSL certificate verify result: self signed certificate (18), continuing anyway.
> USER spoofing
< 331 Please specify the password.
> PASS nopassword
< 230 Login successful.
> PBSZ 0
< 200 PBSZ set to 0.
> PROT P
< 200 PROT now Private.
> PWD
< 257 "/"
* Entry path is '/'
> EPSV
* Connect data stream passively
< 229 Entering Extended Passive Mode (|||55772|).
* Trying 127.0.0.1…
* connected
* Connecting to 127.0.0.1 (127.0.0.1) port 55772
> TYPE I
< 200 Switching to Binary mode.
> STOR userpic.jpg
< 150 Ok to send data.
* Doing the SSL/TLS handshake on the data stream
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: none
* SSL re-using session ID
* SSLv3, TLS handshake, Client hello (1):
} [data not shown]
* SSLv3, TLS handshake, Server hello (2):
{ [data not shown]
* SSLv3, TLS change cipher, Client hello (1):
{ [data not shown]
* SSLv3, TLS handshake, Finished (20):
{ [data not shown]
* SSLv3, TLS change cipher, Client hello (1):
} [data not shown]
* SSLv3, TLS handshake, Finished (20):
} [data not shown]
* SSL connection using DES-CBC3-SHA
* Server certificate:
* subject: C=RU; ST=Russian Federation; L=Sosnovoborsk, Krasnoyarsk Krai; O=Voglea.NET; OU=Hackers Online; CN=voglea.com; emailAddress=postmaster@voglea.com
* start date: 2013-01-17 08:07:16 GMT
* expire date: 2014-01-17 08:07:16 GMT
* issuer: C=RU; ST=Russian Federation; L=Sosnovoborsk, Krasnoyarsk Krai; O=Voglea.NET; OU=Hackers Online; CN=voglea.com; emailAddress=postmaster@voglea.com
* SSL certificate verify result: self signed certificate (18), continuing anyway.
} [data not shown]
* We are completely uploaded and fine
* Remembering we are in dir ""
* SSLv3, TLS alert, Client hello (1):
} [data not shown]
100 77050 0 0 100 77050 0 24781 0:00:03 0:00:03 --:--:-- 24798< 226 Transfer complete.
100 77050 0 0 100 77050 0 20302 0:00:03 0:00:03 --:--:-- 20308
* Connection #0 to host localhost left intact
> QUIT
< 221 Goodbye.
* Closing connection #0
* SSLv3, TLS alert, Client hello (1):
} [data not shown]

Проверяем файл в /home/spoofing/Downloads

┌─[myhost ~]
└─╼ cd ~/Downloads/
┌─[myhost ~/Downloads]
└─╼ pwd
/home/spoofing/Downloads
┌─[myhost ~/Downloads]
└─╼ ls -la
total 84K
drwxr-xr-x 2 spoofing users 4.0K Jan 17 20:51 ./
drwx------ 17 spoofing users 4.0K Jan 17 19:20 ../
-rw-r--r-- 1 spoofing users 76K Jan 17 20:51 userpic.jpg

Похоже, что все работает.
Файлы, которые загружаются пользователями — попадают прямо в мой ~/Downloads, владельцем которых устанавливаюсь я, а не ftp, и сразу с нужными правами.

X. T3h end

Для тех, кому хочется все и сразу, а не собирать «по крошкам». Вся статья в «десять строчек».

# mkdir /srv/ftp/{incoming,pub}

# chown root:ftp /srv/ftp/{incoming,pub}

# chmod g+w /srv/ftp/incoming

Файл ~/logins.txt

spoofing
blahblahblah

# db_load -T -t hash -f ~/logins.txt /etc/vsftpd_login.db

Файл /etc/pam.d/ftp

auth required /lib/security/pam_userdb.so db=/etc/vsftpd_login
account required /lib/security/pam_userdb.so db=/etc/vsftpd_login

Файл /etc/vsftpd_user_conf/spoofing

allow_writeable_chroot=YES

guest_username=spoofing

local_root=/home/spoofing/Downloads
local_max_rate=0

Файл /etc/vsftpd.conf

listen=YES
xferlog_enable=YES

connect_from_port_20=YES
max_clients=50
max_per_ip=3

ftpd_banner=Welcome to Voglea FTPd
dirmessage_enable=YES

hide_ids=YES
write_enable=YES

local_enable=YES
local_umask=022

guest_enable=YES
guest_username=ftp

chroot_local_user=YES

user_config_dir=/etc/vsftpd_user_conf

anonymous_enable=YES
anon_upload_enable=YES
anon_mkdir_write_enable=YES
anon_other_write_enable=NO
anon_world_readable_only=NO
anon_max_rate=16384
anon_umask=022

ssl_enable=YES
ssl_tlsv1=YES
ssl_sslv2=NO
ssl_sslv3=NO
rsa_cert_file=/etc/ssl/certs/vsftpd.pem

force_local_logins_ssl=YES
force_local_data_ssl=YES

allow_anon_ssl=NO

# openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout /etc/ssl/certs/vsftpd.pem -out /etc/ssl/certs/vsftpd.pem

# vsftpd &

Автор: Spoofing

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js