Лабораторная работа "Управление системными и сетевыми сервисами" - efanov/mephi GitHub Wiki

Цель

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

Задачи

  • Изучить назначение, состав и возможности системного менеджера systemd.
  • Изучить командный интерфейс systemctl.
  • Научиться создавать собственные юниты.

Командный интерфейс

  • Команды, изучаемые в лабораторной работе: systemctl, systemd-cgls, shutdown, hostnamectl, timedatectl, localectl, loginctl.
  • Вспомогательные команды, изучаемые в лабораторной работе: ps, curl.

Задание

Процессы и контрольные группы

  1. Сравните вывод команд:

     $ ps xaf
      6434 ?        Ss     0:00 /usr/sbin/httpd -DFOREGROUND
      6460 ?        S      0:00  \_ /usr/sbin/httpd -DFOREGROUND
      6461 ?        S      0:00  \_ /usr/sbin/httpd -DFOREGROUND
      6462 ?        S      0:00  \_ /usr/sbin/httpd -DFOREGROUND
      6464 ?        S      0:00  \_ /usr/sbin/httpd -DFOREGROUND
      6465 ?        S      0:00  \_ /usr/sbin/httpd -DFOREGROUND
     ...
    
     $ ps xawf -eo pid,user,cgroup,args
      6434 root     1:name=systemd:/system.slic /usr/sbin/httpd -DFOREGROUND
      6460 apache   1:name=systemd:/system.slic  \_ /usr/sbin/httpd -DFOREGROUND
      6461 apache   1:name=systemd:/system.slic  \_ /usr/sbin/httpd -DFOREGROUND
      6462 apache   1:name=systemd:/system.slic  \_ /usr/sbin/httpd -DFOREGROUND
      6464 apache   1:name=systemd:/system.slic  \_ /usr/sbin/httpd -DFOREGROUND
      6465 apache   1:name=systemd:/system.slic  \_ /usr/sbin/httpd -DFOREGROUND
     ...
    
     $ systemd-cgls
     ├─1 /usr/lib/systemd/systemd --switched-root --system --deserializ
     └─system.slice
       ├─httpd.service
       │ ├─6434 /usr/sbin/httpd -DFOREGROUND
       │ ├─6460 /usr/sbin/httpd -DFOREGROUND
       │ ├─6461 /usr/sbin/httpd -DFOREGROUND
       │ ├─6462 /usr/sbin/httpd -DFOREGROUND
       │ ├─6464 /usr/sbin/httpd -DFOREGROUND
       │ └─6465 /usr/sbin/httpd -DFOREGROUND
     ...
    

Расположение юнитов в файловой системе

  1. Изучите содержимое каталогов, в которых хранятся юниты:

     $ ls -l /usr/lib/systemd/system/
     $ ls -l /run/systemd/system/
     $ ls -l /etc/systemd/system/
    

Изучение команды systemctl

  1. Выведите информацию о доступных типах юнитов:

     $ systemctl -t help
     Available unit types:
     service
     socket
     busname
     target
     snapshot
     device
     mount
     automount
     swap
     timer
     path
     slice
     scope
    
  2. Выведите информацию о состоянии всех юнитов с помощью systemctl status.

  3. Выведите информацию о состоянии всех юнитов с помощью systemctl --type=service.

  4. Выведите информацию о состоянии сервиса с помощью systemctl status имя.тип. Например:

     $ systemctl status auditd.service 
     ● auditd.service - Security Auditing Service
        Loaded: loaded (/usr/lib/systemd/system/auditd.service; enabled)
        Active: active (running) since Sat 2016-10-22 15:41:04 MSK; 8h ago
       Process: 734 ExecStartPost=/sbin/auditctl -R /etc/audit/audit.rules (code=exited, status=0/SUCCESS)
      Main PID: 733 (auditd)
        CGroup: /system.slice/auditd.service
                ├─733 /sbin/auditd -n
                ├─743 /sbin/audispd
                └─745 /usr/sbin/sedispatch
    
  5. Выведите информацию о состоянии сервиса другим способом. Например:

     $ systemctl is-active auditd.service
     inactive
     $ systemctl is-enabled auditd.service
     enabled
    
  6. Выведите информацию о зависимостях сервисов друг от друга. Например:

     $ systemctl list-dependencies --after auditd.service 
     auditd.service
     ● ├─system.slice
     ● ├─systemd-journald.socket
     ● ├─systemd-tmpfiles-setup.service
     ● └─local-fs.target
     $ systemctl list-dependencies --before auditd.service 
     auditd.service
     ● ├─crond.service
     ● ├─systemd-update-utmp.service
     ● ├─shutdown.target
     ● │ ├─systemd-reboot.service
     ● │ └─final.target
     ● │   └─systemd-reboot.service
     ● └─sysinit.target
    
  7. Выведите информацию:

     $ systemctl list-units --type=service
       UNIT                        LOAD   ACTIVE SUB     DESCRIPTION
     ...
       auditd.service              loaded active running Security Auditing Service
       cgconfig.service            loaded active exited  Control Group configuration 
       cups.service                loaded active running CUPS Printing Service
       dbus.service                loaded active running D-Bus System Message Bus
       firewalld.service           loaded active running firewalld - dynamic firewall
     ...
       wpa_supplicant.service      loaded active running WPA Supplicant daemon
    
     LOAD   = Reflects whether the unit definition was properly loaded.
     ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
     SUB    = The low-level unit activation state, values depend on unit type.
    
     69 loaded units listed. Pass --all to see loaded but inactive units, too.
     To show all installed unit files use 'systemctl list-unit-files'.
    
  8. Измените команду:

     $ systemctl list-units --type=service --all
     $ systemctl list-units --type=socket --all
    
  9. Выведите информацию о файлах юнитов и определите, какие сервисы разрешены (будут запускаться при загрузке) и какие запрещены.

     $ systemctl list-unit-files --type=service
    
  10. Выведите информацию о сервисах с ошибками.

     $ systemctl --failed --type=service
    

Управление сервисами

  1. Выполните запуск, останов, перезагрузку web-сервера Apache. Обратите внимание на изменение PID процессов после restart. Для контроля работы web-сервера Apache можно использовать команду curl 127.0.0.1.

     # systemctl status httpd.service
     ● httpd.service - The Apache HTTP Server
        Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled)
        Active: inactive (dead)
     # systemctl start httpd.service
     # systemctl status httpd.service
     ● httpd.service - The Apache HTTP Server
        Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled)
        Active: active (running) since Sun 2016-10-23 00:50:54 MSK; 2s ago
      Main PID: 16547 (httpd)
        Status: "Processing requests..."
        CGroup: /system.slice/httpd.service
                ├─16547 /usr/sbin/httpd -DFOREGROUND
                ├─16549 /usr/sbin/httpd -DFOREGROUND
                ├─16550 /usr/sbin/httpd -DFOREGROUND
                ├─16552 /usr/sbin/httpd -DFOREGROUND
                ├─16554 /usr/sbin/httpd -DFOREGROUND
                └─16556 /usr/sbin/httpd -DFOREGROUND
     # systemctl restart httpd.service
     # systemctl status httpd.service
     ● httpd.service - The Apache HTTP Server
        Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled)
        Active: active (running) since Sun 2016-10-23 00:51:06 MSK; 2s ago
      Main PID: 16566 (httpd)
        Status: "Processing requests..."
        CGroup: /system.slice/httpd.service
                ├─16566 /usr/sbin/httpd -DFOREGROUND
                ├─16569 /usr/sbin/httpd -DFOREGROUND
                ├─16571 /usr/sbin/httpd -DFOREGROUND
                ├─16574 /usr/sbin/httpd -DFOREGROUND
                ├─16575 /usr/sbin/httpd -DFOREGROUND
                └─16576 /usr/sbin/httpd -DFOREGROUND
     # systemctl stop httpd.service
    
  2. Настройте запуск web-сервера Apache во время загрузки системы.

     # systemctl enable httpd.service
     Created symlink from /etc/systemd/system/multi-user.target.wants/httpd.service to /usr/lib/systemd/system/httpd.service.
     # systemctl status httpd.service 
     ● httpd.service - The Apache HTTP Server
        Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
        Active: inactive (dead)
          Docs: man:httpd(8)
                man:apachectl(8)
     ...
     # systemctl start httpd.service 
     # systemctl status httpd.service 
     ● httpd.service - The Apache HTTP Server
        Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
        Active: active (running) since Сб 2019-03-30 23:21:25 MSK; 1s ago
          Docs: man:httpd(8)
                man:apachectl(8)
      Main PID: 22529 (httpd)
        Status: "Processing requests..."
         Tasks: 7
        CGroup: /system.slice/httpd.service
                ├─22529 /usr/sbin/httpd -DFOREGROUND
                ├─22533 /usr/sbin/httpd -DFOREGROUND
                ├─22534 /usr/sbin/httpd -DFOREGROUND
                ├─22535 /usr/sbin/httpd -DFOREGROUND
                ├─22536 /usr/sbin/httpd -DFOREGROUND
                ├─22537 /usr/sbin/httpd -DFOREGROUND
                └─22538 /usr/sbin/httpd -DFOREGROUND
     ...
     # systemctl disable httpd.service
     Removed symlink /etc/systemd/system/multi-user.target.wants/httpd.service.
    

Определите, что изменилось в выводе команд systemctl status?

  1. Запретите запуск web-сервера Apache как во время загрузки системы, так и в ручную.

     # systemctl mask httpd.service
     Created symlink from /etc/systemd/system/httpd.service to /dev/null.
     # systemctl status httpd.service 
     ● httpd.service
        Loaded: masked (/dev/null; bad)
     ...
     # systemctl start httpd.service
     Failed to start httpd.service: Unit is masked.
     # systemctl unmask httpd.service
     Removed symlink /etc/systemd/system/httpd.service.
    

Управление таргетами

  1. Выведите информацию о загруженных активных target-юнитах:

     $ systemctl list-units --type=target
     UNIT                   LOAD   ACTIVE SUB    DESCRIPTION
     basic.target           loaded active active Basic System
     graphical.target       loaded active active Graphical Interface
     multi-user.target      loaded active active Multi-User System
     network.target         loaded active active Network
     ...
    
     LOAD   = Reflects whether the unit definition was properly loaded.
     ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
     SUB    = The low-level unit activation state, values depend on unit type.
    
  2. Выведите информацию обо всех target-юнитах:

     $ systemctl list-units --type=target --all
    
  3. Выведите target-юнит по умолчанию. Например:

     $ systemctl get-default 
     graphical.target
    
  4. Выведите ссылку на target-юнит по умолчанию. Например:

     $ ls -l /etc/systemd/system/default.target
     lrwxrwxrwx. 1 root root 36 Jan  4  2015 /etc/systemd/system/default.target -> /lib/systemd/system/graphical.target
    
  5. Измените (установите другой) target-юнит по умолчанию. Например:

     $ systemctl set-default multi-user.target
    
  6. Измените target-юнит в рамках текущей сессии. Например:

     $ systemctl isolate multi-user.target
    
  7. Переведите систему в rescue-режим (аналог однопользовательского режима в init) (systemctl isolate rescue.target). Убедитесь в том, что смонтированы локальные файловые системы, но сетевые средства не подняты. Например:

     $ systemctl --no-wall rescue
    
  8. Переведите систему в emergency-режим (systemctl isolate emergency.target). Убедитесь в том, что смонтирована только корневая файловая система в режиме "только для чтения" и сетевые средства не подняты. Например:

     $ systemctl --no-wall emergency
    

Управление работой системы и питанием компьютера

  1. Выгрузите систему и отключите питание компьютера:

     # systemctl poweroff
    
  2. Выгрузите систему без отключения питания компьютера:

     # systemctl halt
    
  3. Повторите действия без рассылки пользователям предупреждения. Например:

     # systemctl --no-wall poweroff
    
  4. Выгрузите систему и отключите питание компьютера в определенное время с помощью shutdown --poweroff чч:мм, где чч:мм - время в 24-часовом формате. Убедитесь в том, что за 5 минут до выгрузки системы будет создан файл /run/nologin для предотвращения новых входов пользователей в систему.

  5. Выгрузите систему без отключения питания компьютера через определенный промежуток времени с помощью shutdown --halt +_минут_. Вместо +0 можно написать now. Запущенную выгрузку можно отменить с помощью shutdown -c.

  6. Перезагрузите систему с помощью systemctl --no-wall reboot.

  7. Приостановите работу системы с помощью systemctl suspend.

  8. Остановите систему с помощью systemctl hibernate.

  9. Изучите другие утилиты systemd.

$ hostnamectl 
   Static hostname: localhost.localdomain
         Icon name: computer-laptop
           Chassis: laptop
        Machine ID: fd321e68b3a144c7a27a4544579ff946
           Boot ID: 373996d0f8e54d19b988f41e05877884
  Operating System: Fedora 31 (Workstation Edition)
       CPE OS Name: cpe:/o:fedoraproject:fedora:31
            Kernel: Linux 5.3.7-301.fc31.x86_64
      Architecture: x86-64

$ timedatectl 
               Local time: Sat 2020-05-16 01:38:03 MSK
           Universal time: Fri 2020-05-15 22:38:03 UTC
                 RTC time: Fri 2020-05-15 22:38:03
                Time zone: Europe/Moscow (MSK, +0300)
System clock synchronized: no
              NTP service: inactive
          RTC in local TZ: no

$ localectl 
   System Locale: LANG=en_US.UTF-8
       VC Keymap: us
      X11 Layout: us,ru
     X11 Variant: ,
     X11 Options: grp:caps_toggle

$ loginctl 
SESSION  UID USER    SEAT  TTY 
      2 1000 user1 seat0 tty2

1 sessions listed.

$ loginctl session-status 2
2 - user1 (1000)
           Since: Fri 2020-05-15 22:44:47 MSK; 2h 55min ago
          Leader: 1524 (gdm-session-wor)
            Seat: seat0; vc2
             TTY: tty2
         Service: gdm-password; type wayland; class user
           State: active
            Unit: session-2.scope
                  ├─1524 gdm-session-worker [pam/gdm-password]
                  ├─1560 /usr/bin/gnome-keyring-daemon --daemonize --login
                  ├─1564 /usr/libexec/gdm-wayland-session /usr/bin/gnome-session
                  └─1569 /usr/libexec/gnome-session-binary

May 15 22:44:47 localhost.localdomain gdm-password][1524]: pam_unix(gdm-password:sess>
May 15 22:44:47 localhost.localdomain systemd[1]: Started Session 2 of user user1.

$ loginctl show-user user1
UID=1000
GID=1000
Name=user1
Timestamp=Fri 2020-05-15 22:44:47 MSK
TimestampMonotonic=1895453025
RuntimePath=/run/user/1000
[email protected]
Slice=user-1000.slice
Display=2
State=active
Sessions=2
IdleHint=no
IdleSinceHint=0
IdleSinceHintMonotonic=0
Linger=no

Создание собственных юнитов

Юнит-файл состоит из секций, включающих пары ключ-значение.

    [Имя секции]
    Директива1=значение
    Директива2=значение

Секция [Unit]

    Description=
    Documentation=
    Requires=
    Wants=

Секция [Install]

    WantedBy=
    RequiredBy=
# cat mephi.service 
[Unit]
Decription=MEPhI hello service
After=sshd.service
[Service]
ExecStart=/usr/bin/printf "Hello, MEPhI!"
[Install]
WantedBy=multi-user.target

# ls -lZ mephi.service 

# journalctl -b
...
May 16 00:57:40 localhost.localdomain setroubleshoot[3979]: SELinux is preventing systemd from read access on the file mephi.service. For complete SELinux messages run: sea>
May 16 00:57:40 localhost.localdomain python3[3979]: SELinux is preventing systemd from read access on the file mephi.service.
                                                     
                                                     *****  Plugin catchall (100. confidence) suggests   **************************
                                                     
                                                     If you believe that systemd should be allowed read access on the mephi.service file by default.
                                                     Then you should report this as a bug.
                                                     You can generate a local policy module to allow this access.
                                                     Do
                                                     allow this access for now by executing:
                                                     # ausearch -c 'systemd' --raw | audit2allow -M my-systemd
                                                     # semodule -X 300 -i my-systemd.pp
                                                     
May 16 00:57:50 localhost.localdomain systemd[1]: dbus-:[email protected]: Succeeded.
May 16 00:57:50 localhost.localdomain audit[1]: SERVICE_STOP pid=1 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 msg='unit=dbus-:1.7-org.fedoraproje>
May 16 00:57:50 localhost.localdomain systemd[1]: dbus-:[email protected]: Consumed 2.020s CPU time.

# ausearch -m avc -ts recent
----
time->Sat May 16 00:57:08 2020
type=AVC msg=audit(1589579828.032:1963): avc:  denied  { read } for  pid=1 comm="systemd" name="mephi.service" dev="sda2" ino=411971 scontext=system_u:system_r:init_t:s0 tcontext=unconfined_u:object_r:user_home_t:s0 tclass=file permissive=0

[root@localhost system]# restorecon -v mephi.service 
Relabeled /usr/lib/systemd/system/mephi.service from unconfined_u:object_r:user_home_t:s0 to unconfined_u:object_r:systemd_unit_file_t:s0

# systemctl start mephi.service 
# journalctl -u mephi.service 
-- Logs begin at Thu 2019-10-10 15:56:01 MSK, end at Sat 2020-05-16 01:11:06 MSK. --
May 16 01:11:04 localhost.localdomain systemd[1]: Started MEPhI hello service.
May 16 01:11:04 localhost.localdomain printf[4417]: Hello, MEPhI!
May 16 01:11:04 localhost.localdomain systemd[1]: mephi.service: Succeeded.

# cat mephi.path
[Unit]
Description="Check for MEPhI file in /tmp"
After=sshd.service
[Path]
PathExists=/tmp/mephi.file
Unit=mephi.service
[Install]
WantedBy=multi-user.target

# systemctl enable mephi.path 
Created symlink /etc/systemd/system/multi-user.target.wants/mephi.path → /usr/lib/systemd/system/mephi.path.
# systemctl start mephi.path 
# touch /tmp/mephi.file

Откройте второй терминал и запустите мониторинг журнала

# journalctl -f -u mephi
-- Logs begin at Thu 2019-10-10 15:56:01 MSK. --
May 16 01:11:04 localhost.localdomain systemd[1]: Started MEPhI hello service.
May 16 01:11:04 localhost.localdomain printf[4417]: Hello, MEPhI!
May 16 01:11:04 localhost.localdomain systemd[1]: mephi.service: Succeeded.
May 16 01:30:24 localhost.localdomain systemd[1]: Started MEPhI hello service.
May 16 01:30:24 localhost.localdomain printf[4894]: Hello, MEPhI!
May 16 01:30:24 localhost.localdomain systemd[1]: mephi.service: Succeeded.

Оформление результатов лабораторной работы

Задание "Управление системными службами"

Необходимо разработать скрипт "Управление системными службами и журналами (systemctl, journalctl)" со страницы Задание: разработка сценариев управления средствами безопасности.

Загрузите получившийся скрипт в собственный репозиторий на GitHub.

Задание "Сканер безопасности служб"

Разработать скрипт сканирования безопасности служб, который выведет перечень служб, нарушающих безопасность. Проверки безопасности:

  1. Служба работает под некоторым пользователем Х, и при этом файл юнита или файлы, которые запускает служба, имеют права на запись другому пользователю Y. Права нужно проверять как через владельца и группу-владельца, так и через ACL.
  2. Служба работает под пользователем, отличным от root, но при этом запускает SUID-ный исполняемый файл, владелец которого - root.

Примеры нарушений:

  1. Служба работает под пользователем root, но права на запись в файл юнита есть у пользователя test. В таком случае сторонний пользователь (злоумышленник) сможет незаметно поменять поведение сервиса.
  2. Служба работает под пользователем nginx, запускает скрипт через ExecStart=/opt/start-nginx.sh, но права на запись в файл /opt/start-nginx.sh есть у пользователя test. В таком случае сторонний пользователь (злоумышленник) сможет запустить произвольный скрипт с правами пользователя nginx.
  3. Служба работает под пользователем kibana, запускает скрипт через ExecStartPre=/usr/local/bin/clear-cache.sh $OPTIONS, но файл /usr/local/bin/check-config.sh является SUID-ным. В таком случае злоумышленник может выполнить вредоносные действия, передав произвольные аргументы в команду check-config.sh, которая выполнятся под root.

Для тестирования разместите несколько различных юнитов в /etc, которые нарушают те или иные критерии и запустите их.

Загрузите получившийся скрипт в собственный репозиторий на GitHub.

Литература