TFTP в Linux. Организация сервера TFTP
В репозиториях операционных систем на базе ядра Linux вы найдете множество серверов, реализующих протокол TFTP: некоторые делают упор на простоте конфигурации и малом потребление ресурсов, другие предоставляют расширенные возможности, но все они созданы с одной целью - принимать и отдавать файлы. Мы будем рассматривать настройку TFTP сервера в Linux на примере atftpd - сервера TFTP с расширенными возможностями. Будьте уверены, освоив atftpd, вы без труда справитесь с любым другим TFTP сервером в Linux.
Установка atftp в Linux
Попытка установить сервер atftpd из репозиториев приведет к установке еще одного сервера - одного из супер-серверов inet - демона, запускающего программы по событию, в данном случае по факту появления на 69 порту UDP запросов на подключение. Вы скажите: "А что же тут плохого?". Вообщем-то ничего, но если вы используете Debian версии 8 и выше или Ubuntu версии 15.04 и выше, то вы наверняка слышали о SystemD. SystemD - новый менеджер инициализации, пришедший на смену init. На конец 2015 года поддержка SystemD не реализована для серверов TFTP - мы сделаем это вручную. Поэтому, лучше устанавливать TFTP сервер из исходных текстов и сразу перейти в соответствующий раздел нашей статьи, но если вы всё же решили поизвести установку atftpd из репозиторией комадой
apt-get install atftpd
незабудьте остановить подтянувшийся inet и, собственно, сам atftpd
systemctl stop atftpd inetd
А также выключить их
systemctl disable atftpd inetd
Для избежания недоразумений также рекоменду удалить скрипт запуска atftpd из /etc/init.d/
rm /etc/init.d/atftpd
И стереть его упоминание из конфигурационного файла inet с помощью, например редактора nano:
nano /etc/inetd.conf #удалите строчку, начинающуюся с tftp
Избежать всего этого поможет сборка TFTP сервера из исходных текстов. Для этого нужно скачать архив с исходниками например c сайта sourceforge с помощью wget
wget http://downloads.sourceforge.net/project/atftp/atftp-0.7.1.tar.gz #версия может отличаться
Распаковать архив:
tar -xzvf atftp-0.7.1.tar.gz #версия может отличаться
Перейти в каталог с распакованным содержимым
cd atftp-0.7.1 #версия может отличаться
Выполнить конфигурационный скрипт, указав в качестве папки назначения /opt/atftp (вы, конечно, можете выбрать любую другую папку)
./configure --prefix=/opt/atftp
Создать эту папку
mkdir /opt/atftp
Собрать atftp
make
И, наконец, собранные файлы, закинуть в папку назначения
make install
На последок почистим за собой
cd ..
rm -R atftp-0.7.1
и создадим символические ссылки на исполняемые файлы
ln -svi /opt/atftp/sbin/atftpd /sbin/
ln -svi /opt/atftp/bin/atftp /usr/bin/
Настройка TFTP сервера atftpd
TFTP сервер atftpd не читает никакой конфигурационный файл. Вместо этого все параметры ему передаются в качестве ключей запуска, например:
--logfile /PATH_TO_FLE #задает файл в который atftpd будет писать лог
--verbose=FROM_1_TO_7 # задает уровень документирования событий
--user USER.GROUP #задает от имени какого пользователя и группы будет запущен atftpd
--port PORT_NUMBER #задает UDP порт, который будет слушать сервер
--bind-address SERVER_IP_ADDRESS #задает IP адрес, который будет слушать сервер
В конце командной строки atftpd следует передать полный абсолютный путь до папки, в которой и будет осуществляться вся деятельность TFTP сервера в вашей ОС Linux
Далее мы рассмотрим несколько примеров сценариев запуска atftpd, в зависимости от которых нам понадобяться те или иные ключи запуска
Запуск atftpd из командной строки
Этот способ подойдет тем, хочет единовременно запустить TFTP сервер, отдать или принять файл и завершиться.
Минимальный набор команд будет такой:
atftpd --daemon --no-fork /mnt/share
Вы наверняка заметили два новых ключа запуска: "daemon" и "no-fork". Ключ "--daemon" заставляет atftpd "висеть" в ожидании соединения, а ключ "--no-fork" предотвращает его переход в фон. Когда все операции с передачей файлов будут завершены, мы сможете просто нажать Ctrl+C для завершения atftpd. Если же ключ "--no-fork" не использовать, то завершить процесс можно будет командой
pkill atftpd
Стоить отметить тот факт, что чтобы папка, которую мы передали TFTP серверу для работы, была доступна не только на чтение, но и на запись, нужно выдать это право обезличенному пользователю (anonymous), так как TFTP, как протокол, вообще не предусматривает никакой аутенфикации:
chmod -R o=rwx /mnt/share #папка может отличаться
Запуск atftpd автоматически при старте системы
Если вы хотите, чтобы atftpd запускался автоматически при старте компьютера, в системах на базе SystemD следует создать в дирректории /lib/systemd/system/ unit-файл atftpd.service для SystemD вот такого минимально содержания:
[Unit]
Description=Extended TFTP server
[Service]
Type=forking
ExecStart=/opt/sbin/atftpd --daemon /mnt/share
[Install]
WantedBy=multi-user.target
В параметре ExecStart нужно указать ту папку и бинарный файл atftpd, в которую вы его устанавливали, а также все ключи запуска, которые считаете нужными. Заметьте, что ключ "--no-fork" в данном случае противопоказан, а вот "--daemon" обязателен, так как по сценарию планируется, что atftpd будет "висеть" в системе постоянно, ожидая соединения
После того, как файл будет создан, нужно, чтобы SystemD перечитал свою конфигурацию
systemctl daemon-reload
а затем активировать уже сам сервис:
systemctl enable atftpd.service
Теперь atftpd будет запускаться автоматически при старте системы. Вручную его можно запускать и останавливать командами
systemctl stop atftpd.service
systemctl start atftpd.service
Запуск atftpd автоматически по запросу
Мы с вами рассмотрели ситуацию, когда TFTP сервер atftpd, запущенный единожды при старте компьютера, остается "висеть" в системе, ожидая новых подключений. При этом вначале статьи упоминули, что при установке из репозиторией atftp тянет за забой супер-сервер inet, способный запускать atftpd только тогда, когда запрос реально поступает на сервер. Это очень удобно с той точки зрения, что пока TFTP не используется - он остановлен и не потребляет системных ресурсов. Так же мы отметили тот факт, что SystemD имеет такую функциональность "из коробки", и что необходимости теперь и в самом супер-сервере inet нет. Осталось научить SystemD это делать. Для этого SystemD должен сам слушать входящий порт на предмет поступления запросов и, в случае обнаружения, запустить atftpd и отдать ему сокет. Кроме того, после обработки соединения atftpd должен еще и корректно завершиться. Чтобы SystemD стал прослушить соответствующий UDP сокет, нужно создать unit-файл, описывающий этот сокет, и положить его туда же - в /lib/systemd/system/. При этом его имя должно соответствовать имени сервис-файла, который ему придеться запускать, за исключением суффикса, который нужно поменять с ".service" на ".socket". В нашем случае файл должен называться atftpd.socket. Создадим его вот с таким содержанием:
[Unit]
Description=TFTP socker for atftpd
[Socket]
ListenDatagram=0.0.0.0:69
[Install]
WantedBy=sockets.target
Запись ListenDatagram=0.0.0.0:69 означает, что SystemD будет слушать порт UDP 69 на всех доступных ему IP адресах. Вы вправе (да и так будет лучше) указать конкретный IP адрес вашего сервера - это улучшит безопасность.
Но это еще не все. Раз мы выбрали способ запуска по событию, мы не хотим более, чтобы atftpd запускался автоматически при старте системы. Выключим его:
systemctl disable atftpd.service
И сам service-файл /lib/systemd/system/atftpd.service тоже подкорректируем:
- убираем ключ "--daemon" - мы больше не хотим, чтобы atftpd "висел" в системе постоянно
- добавляем ключ "--tftpd-timeout 10" - TFTP сервер корректно завершиться, если в течение 10 сек. к нему не поступит более обращений
- добавляем параметр StandartInput=socket в секцию [Service], чтобы SystemD передавал сокет с данными на вход atftpd
- удаляем секцию [Install] целиком - мы больше не хотим, чтобы atftpd запускался при старте системы
Должно получиться что-то вроде этого:
[Unit]
Description=Extended TFTP server
[Service]
ExecStart=/opt/atftp/sbin/atftpd --verbose=7 --logfile /var/log/atftpd --tftpd-timeout 10 /mnt/share
StandardInput=socket
Не забываем перечитывать конфигурацию SystemD:
systemctl daemon-reload
И активируем наш сокет-файл
systemctl enable atftpd.socket
Можно перезагрузиться, можно включить сокет вручную:
systemctl start atftpd.socket
Всё. Командой
netstat -lupvn | grep 69
Можно увидеть, что порт 69 прослушивает некий "init", который на самом деле является символической ссылкой на SystemD
udp 0 0 0.0.0.0:69 0.0.0.0:* 1/init
При этот, если вы обратитесь к серверу каким-нибудь tftp клиентом, SystemD запустит atftpd и передаст ему клиента. А после того, как передача файлов завершиться, atftpd по истечению таймаута корректно завершиться.