Прикладной уровень: возможности системы
Цели:
- Активация интерпретатора
- Сопоставление потока данных интерпретатору
- Обеспечение готовности сервиса-интерпретатора
- Интерпретация
- (…) а откуда нам знать?
Задачи:
Связывание порта и интерпретатора
Запуск и обслуживание интерпретатора - Анонс прикладных служб по сети и распознавание этого анонса
- Учёт потребления ресурсов прикладными службами: иногда изнутри самого приложения не видно, насколько всё плохо
TODO: коротко об управлении systemd
Службы systemd:
Леннарт и юзабилити ;_; - start / restart / stop / status
- cat
systemctl edit и его грабельки
- --full --force
- $SYSTEMD_EDITOR
Связь с интерпретатором
Пространство имён: /etc/services — только well-known и нет прямой связи с приложением
TODO — какие syscall-ы вызывает
- nc
- nc -l
- socat TCP-LISTEN…,fork
- Делает сама служба:
создание и обслуживание сокета (bind() + listen() + accept())
- (если нужно) закрытие сокета respawn при закрытии соединения
- обслуживание нескольких соединений (в т. ч. общие и специфичные для прикладного уровня ограничения по ресурсам, конкуренции между соединениями и т. п.)
- Делает служба запуска
- Запуск произвольных служб, в том числе сетевых
- Запуск интерпретаторов с сокет-активацией
- Запуск/fork() без ожидания
Примеры
netstat
-ltp (и -lup)
-ntp (и -nup)
socat как служба запуска:
socat TCP-LISTEN:1234 EXEC:/usr/bin/cal
TIME_WAIT ⇒ TCP-LISTEN:1234,reuseaddr
Несколько соединений: базовый сервис + fork() : TCP-LISTEN:1234,reuseaddr,fork
Перманентная настройка сети с помощью systemd-networkd
Отступление 0: Просмотр, останов и запуск служб systemd
Отступление 1: .d-схема хранения конфигурационных файлов.
.d-каталог /etc/systemd/network/
Сам systemd-networkd:
systemd.link: переименование и настройка сетевых интерфейсов
systemd.netdev: создание виртуальных сетевых устройств (например, бриджей и VLAN-ов)
См. примеры
systemd.network: настройки параметров сети на интерфейсах и специальных подсистем
См. примеры
Настроим IP сервера с выходом в Интернет через стандартную «виртуальную» сеть VirtualBox (пример по ссылке выше)
- Адрес/подсеть — 10.0.2.15/24
- Маршрутизатор по умолчанию — 10.0.2.2
Файл обязан называться что-то-там.network (других настроек не нужно)
Перечитаем настройки сети и обновим настройки интерфейса
[root@srv ~]# networkctl reload
[root@srv ~]# networkctl reconfigure eth0
[root@srv ~]# networkctl
IDX LINK TYPE OPERATIONAL SETUP
1 lo loopback carrier unmanaged
2 eth0 ether routable configured
3 eth1 ether off unmanaged
4 eth2 ether off unmanaged
5 eth3 ether off unmanaged
5 links listed.
[root@srv ~]# networkctl
delete forcerenew list reconfigure renew up
down label lldp reload status
[root@srv ~]# networkctl status eth0
* 2: eth0
Link File: /lib/systemd/network/99-default.link
Network File: /etc/systemd/network/50-vbox.network
Type: ether
State: routable (configured)
Online state: online
Alternative Names: enp0s3
Path: pci-0000:00:03.0
Driver: pcnet32
Vendor: Advanced Micro Devices, Inc. [AMD]
Model: 79c970 [PCnet32 LANCE] (PCnet - Fast 79C971)
HW Address: 08:00:27:89:d2:0f (PCS Systemtechnik GmbH)
MTU: 1500 (min: 68, max: 1500)
QDisc: fq_codel
Queue Length (Tx/Rx): 1/1
Auto negotiation: no
Speed: 10Mbps
Duplex: half
Port: tp
Address: 10.0.2.15
Gateway: 10.0.2.2
Activation Policy: up
Required For Online: yes
Apr 14 18:09:47 srv systemd-networkd[1096]: eth0: Re-configuring with /etc/systemd/network/50-vbox.network
Apr 14 18:09:47 srv systemd-networkd[1096]: eth0: Link UP
Apr 14 18:09:47 srv systemd-networkd[1096]: eth0: Gained carrier
Apr 14 18:09:51 srv systemd-networkd[1096]: eth0: Re-configuring with /etc/systemd/network/50-vbox.networkЭта настройка перманентна — после перезагрузки должна восстановиться.
Настройка статического маршрута
Тот же файл ….network +
[Route] Gateway=маршрутизатор Destination=сеть
Настройка net.ipv4.ip_forward:
[Network] … IPForward=ipv4
В любом одном файле
TODO
Запуск собственных служб с помощью systemd
- Обычная служба
- Сервис должен уметь в транспортный уровень
Запуск socat как службы
- Сам сервис — только прикладной
- Масштабирование с помощью шаблонов
Заготовки
# systemctl edit --force --full cal.service`
[root@srv ~]# systemctl cat cal.service
# /etc/systemd/system/cal.service
[Unit]
Description=SOCAT Example
[Service]
ExecStart=/usr/bin/socat TCP-LISTEN:1234 EXEC:/usr/bin/cal
# systemctl start cal
# systemctl status cal
# ps | grep cal
root@srv ~]# netcat localhost 1234
April 2022
Su Mo Tu We Th Fr Sa
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
[root@srv ~]# systemctl status cal
* cal.service - SOCAT Example
Loaded: loaded (/etc/systemd/system/cal.service; static)
Active: inactive (dead)
[root@srv ~]# /usr/bin/socat TCP-LISTEN:1234 EXEC:/usr/bin/cal
2022/04/06 18:40:48 socat[1739] E bind(5, {AF=2 0.0.0.0:1234}, 16): Address already in use
# статус и ps — нет!
[root@srv ~]# netstat -ntp
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.1:1234 127.0.0.1:51122 TIME_WAIT -
# можно TCP-LISTEN:1234,reuseaddr
# ещё можно TCP-LISTEN:1234,reuseaddr,fork
# Но не нужно!
[root@srv ~]# systemctl cat hexdump.socket
# /etc/systemd/system/hexdump.socket
[Unit]
Description = Hexdump Socket
[Socket]
ListenStream = 1234
Accept = yes
[root@srv ~]# systemctl cat hexdump@.service
# /etc/systemd/system/hexdump@.service
[Unit]
Description=Hexdump Service
[Service]
ExecStart=/usr/bin/hexdump -C
StandardInput=socket
# если есть предыдущая строка, то по умолчанию:
#StandardOutput=socket
# Это ещё и accept/fork
(не успеем) Связь с отдельными функциями: RPC
Проблема: динамическое выделение входных портов.
- Portmapper (rpcbind, порт 111)
/etc/rpc
Д/З
Задание 8
- Суть: написать и запустить три сетевых сервиса: два вырожденных и один простой
Первый сервис получает на вход произвольный файл, и выдаёт на выход hexdump этого файла в любом удобном формате
- Второй сервис выполняет обратную задачу
- Третий сервис сложнее.
- На вход подаётся три или более текстовых строк в формате ASCII
- Шаблон (первая строка)
- Замена (вторая строка)
- Текст из одной или более строк
- На выходе должен получиться «текст», в котором все вхождения «шаблона» заменены на «замену».
- На вход подаётся три или более текстовых строк в формате ASCII
Задача: оформить все три сервиса как чисто текстовые обработчики с сокет-активацией. с помощью этих сервисов организовать замену произвольного байта на любой другой произвольный байт (допустимо использовать в качестве параметров любое удобное — например, шестнадцатеричное — представление байтов).
- Настройка сети и запуск служб производятся заранее и в отчёт не входят
Подсказка: почитайте systemd.exec: имеет смысл отделить stderr сервиса от stdout
Подсказка: есть соблазн воспользоваться xxd -p / xxd -p -r, но придётся иметь дело с проблемой: xxd -p не вставляет пробелы в поток, и банальная замена двух цифр пожет прийтись не на границу байта. Например в строке из 5 байтов102336495b нет символа с кодом 33
Спойлер:
- Площадка:
srv — хост с двумя вырожденными сервисами (1) и (2)
client — хост с сервисом замены текста (3). для программирования на client доступны (можно пользоваться чем угодно, что найдёте в образе; я выбрал python3):
bash
sed, awk
- … прочие стандартные утилиты linux
python3
perl
- Отчёт:
report 8 srv
Сделать systemctl cat обоим сервисам и их сокетам
Сделать systemctl status обоим сокетам
С помощью netcat проверить, что сервис (2) игнорирует некорректные данные (допустимо преобразовывать корректные или вообще ничего не выводить)
report 8 client
Сделать systemctl cat сервису (3) и его сокету
Если для обработки написан какой-то скрипт на каком-то языке, сделать ему cat
С помощью netcat проверить, что сервис (3) игнорирует некорректные данные (допустимо преобразовывать корректные или вообще ничего не выводить)
Составить командную строку в виде цепочки netcat, объединённых в конвейер с помощью «|», которая заменяет табуляции точками.
(продолжение отчёта srv)
Сделать systemctl status обоим сокетам: должно показать отсутствие соединений в данный момент (Connected:) и увеличить количество обслуженных соединений (Accepted:)
Два отчёта(названия сохранить, должно быть: report.08.srv, report.08.client) переслать одним письмом в качестве приложений на uneexlectures@cs.msu.ru
Пример:
[root@client ~]# cat /etc/crontab.template | { echo " 09"; echo " 2E"; netcat хост-srv порт-1; } | netcat localhost порт-3 | netcat хост-srv порт-2
#
#
#
#minute (0-59),
#|.hour (0-23),
#|.|.day of the month (1-31),
#|.|.|.month of the year (1-12),
#|.|.|.|.day of the week (0-6 with 0=Sunday).
#|.|.|.|.|.commands- адреса и порты заменены
- в качестве строк используются куски шестнадцатеричного дампа
Ещё пример:
[root@client ~]# cal | { echo " 20"; echo " 23"; netcat хост-srv порт-1; } | netcat localhost порт-3 | netcat хост-srv порт-2
#####April#2022#####
Su#Mo#Tu#We#Th#Fr#Sa
################1##2
#3##4##5##6##7##8##9
10#11#12#13#14#15#16
17#18#19#20#21#22#23
24#25#26#27#28#29#30
####################Обратите внимание на то, что банальная замена в простой выдаче xxd 20 на 23 всё бы только испортила (заменились бы части адреса, например), так что в моём решении сервису (3) передаётся строка с пробелом.
[root@client ~]# cal | xxd | sed 's/20/23/' | xxd -r # April 2022 # Su Mo Tu We Th Fr Sa xxd: sorry, cannot seek backwards.
