среда, 31 октября 2012 г.

Заметки о systemd, часть 6, xinetd

Об этой возможности systemd нужно написать особо и обязательно. Это тот механизм, который авторы systemd называют сокет-активация: запуск служб динамически, по требованию сетевого подключения снаружи. Это в точности то, что выполняют inetd и xinetd.

Есть такой PDF-документ (я не знаю оригинала цельным текстом, похоже, что отдельные главы разбросаны статьями в личном блоге Леннарта Поттеринга, а переводчиком собраны в единый текст), назван "systemd для администраторов":
Lennart Poettering (автор)
Сергей Пташник (русский перевод)
17 июля 2012 г.
И есть там такая глава: "11. Службы с активацией в стиле inetd". С неё и начнём изучение вопроса. Несколько вводных цитат:
Уже многие годы inetd считается одной из базовых служб Unix-систем.
...
Наиболее популярные из них — BSD inetd и xinetd. Хотя inetd во многих дистрибутивах до сих пор устанавливается по умолчанию, сейчас он уже редко используется для запуска сетевых служб
...
Одной из ключевых возможностей systemd (а также launchd от Apple) является сокет-активация — тот же самый механизм, давным-давно реализованный inetd,
...
Тем не менее, systemd ничуть не хуже inetd может запускать службы в ответ на входящие сетевые соединения.
Автор в описаниях показывает запуск сокет-активируемой службы SSH, проверить это "в натуре" я предполагаю, для начала, не отступая от его рекомендаций. Поэтому я сначала, для аналогий, подготовлю запуск такой службы средствами xinetd. Создаём новый конфигурационный файл вот с таким примерно содержимым:
# cat /etc/xinetd.d/my-sshd
service ssh
{
socket_type = stream
protocol = tcp
wait = no
user = root
server = /usr/sbin/sshd
server_args = -i
}


Остановим все службы, которые могли бы представлять сервис SSH, и убедимся, что запросы SSH не обслуживаются (их некому обслуживать):
# systemctl stop sshd.service
# systemctl status xinetd.service
$ ssh 192.168.1.5

ssh: connect to host 192.168.1.5 port 22: Connection refused


Вот теперь мы можем запустить суперсервер xinetd и убедится, что в такой конфигурации он обеспечивает поддержку SSH:
# systemctl start xinetd.service
$ ssh 192.168.1.5olej@192.168.1.5's password:
Last login: Fri Oct 5 23:07:20 2012 from notebook.localdomain
$ who
olej :0 2012-10-24 16:40 (:0)
olej pts/0 2012-10-24 16:41 (:0.0)
olej pts/2 2012-10-24 17:10 (:0.0)
olej pts/4 2012-10-24 17:16 (:0.0)
olej pts/6 2012-10-24 17:26 (:0.0)
olej pts/8 2012-10-24 18:18 (:0.0)
olej pts/9 2012-10-24 19:35 (notebook.localdomain)


А это то, как запуск SSH для этой сессии выглядел в системном журнале:
# tail -n2 /var/log/messages
Oct 24 19:35:28 notebook xinetd[4587]: START: ssh pid=4606 from=::ffff:192.168.1.5
Oct 24 19:35:35 notebook systemd-logind[642]: New session 5 of user olej.

Это всё были вещи достаточно общеизвестные, но нужные нам для сравнения с альтернативной возможностью: использование для той же цели сокет-активация в systemd.

А теперь, освежив в памяти как оно работает, переходим к активации той же службы SSH средствами systemd (вместо использования xinetd). Пока мы работаем со службой SSH будем в точности следовать рекомендациям упоминаемой выше главы 11. Создаём и заполняем 2 файла (sshd.socket и sshd@.service), содержимое их легко понятно по аналогии с обсуждавшимся выше /etc/xinetd.d/my-sshd :
# touch sshd.socket
# touch sshd@.service
ls -l *ssh*
-rw-r--r--. 1 root root 283 апр. 6 2012 sshd.service
-rw-r--r-- 1 root root 106 окт. 25 14:52 sshd@.service
-rw-r--r-- 1 root root 128 окт. 25 14:50 sshd.socket
$ cat sshd.socket
[Unit]
Description=SSH Socket for Per-Connection Servers
[Socket]
ListenStream=22
Accept=yes
[Install]
WantedBy=sockets.target
$ cat sshd@.service
[Unit]
Description=SSH Per-Connection Server
[Service]
ExecStart=-/usr/sbin/sshd -i
StandardInput=socket

Перед проверкой работоспособности обязательно убеждаемся, что у нас не запущен автономный сервер sshd или xinetd :
# service sshd stop
$ service sshd status

Redirecting to /bin/systemctl status sshd.service
sshd.service - OpenSSH server daemon
Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled)
Active: failed (Result: exit-code) since Thu, 25 Oct 2012 12:38:10 +0300; 2h 18min ago
Process: 758 ExecStart=/usr/sbin/sshd -D $OPTIONS (code=exited, status=255)
Process: 749 ExecStartPre=/usr/sbin/sshd-keygen (code=exited, status=0/SUCCESS)
CGroup: name=systemd:/system/sshd.service
$ ps -A | grep xinetd
756 ? 00:00:00 xinetd
# service xinetd stop
Redirecting to /bin/systemctl stop xinetd.service
$ service xinetd status
Redirecting to /bin/systemctl status xinetd.service
xinetd.service - Xinetd A Powerful Replacement For Inetd
Loaded: loaded (/usr/lib/systemd/system/xinetd.service; enabled)
Active: inactive (dead) since Thu, 25 Oct 2012 15:02:19 +0300; 10s ago
Process: 750 ExecStart=/usr/sbin/xinetd -stayalive -pidfile /var/run/xinetd.pid $EXTRAOPTIONS (code=exited, status=0/SUCCESS)
Main PID: 756 (code=exited, status=0/SUCCESS)
CGroup: name=systemd:/system/xinetd.service


Вот теперь, когда мы поместим оба предложенных выше файла в каталог /etc/systemd/system, мы можем запустить его (то есть активировать в текущем сеансе работы):
# systemctl start sshd.socket
# systemctl status sshd.socket
sshd.socket - SSH Socket for Per-Connection Servers
Loaded: loaded (/usr/lib/systemd/system/sshd.socket; disabled)
Active: active (listening) since Thu, 25 Oct 2012 15:07:29 +0300; 6s ago
Accepted: 0; Connected: 0
CGroup: name=systemd:/system/sshd.socket

Для проверки делаем 2 отдельных подключения (сеансов SSH), 1-е из показанных - удалённое, а 2-е - локальное:

$ ssh 192.168.1.5
The authenticity of host '192.168.1.5 (192.168.1.5)' can't be established.
RSA key fingerprint is 45:32:32:17:bd:6f:9c:d5:19:09:d0:fa:e2:06:bb:41.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.1.5' (RSA) to the list of known hosts.
olej@192.168.1.5's password:
Last login: Thu Oct 25 14:57:15 2012 from localhost.localdomain
-bash-4.2$ cat /etc/system-release
RFRemix release 17 (Beefy Miracle)

$ ssh localhost
olej@localhost's password:
Last login: Thu Oct 25 15:09:33 2012 from atom

Как видно, оба сеанса SSH работоспособны, хотя предварительно (до вызова) сервер sshd и не был запущен (мы это предварительно проверили) ...
$ ps -A | grep ssh
4555 pts/6 00:00:00 ssh
4563 ? 00:00:00 sshd
4565 ? 00:00:00 sshd
4669 pts/3 00:00:00 ssh
4670 ? 00:00:00 sshd
4673 ? 00:00:00 sshd

А вот одно из самых интересных следствий - активные экземпляры служб, соответствующие открытым сеансам, обладают динамически образуемыми именами:
$ systemctl --full | grep ssh
sshd.service loaded failed failed OpenSSH server daemon
sshd@0-192.168.1.5:22-192.168.1.7:47966.service loaded active running SSH Per-Connection Server
sshd@1-127.0.0.1:22-127.0.0.1:56938.service loaded active running SSH Per-Connection Server
sshd.socket loaded active listening SSH Socket for Per-Connection Servers

Ну вот и всё.
Этого вполне достаточно, чтобы утверждать, что всё совершенно успешно работает.