TFTP в Linux. Организация сервера TFTP

10/19/2015

В репозиториях операционных систем на базе ядра 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 по истечению таймаута корректно завершиться.

Темы: