388 lines
14 KiB
Markdown
388 lines
14 KiB
Markdown
# Домашнее задание 15
|
||
|
||
## Selinux
|
||
|
||
## Задание 1 Обеспечить работоспособность приложения при включенном selinux
|
||
|
||
Для выполнения ДЗ будет использоваться Fedora Server 43
|
||
|
||
Наша задача запустить nginx на нестандартном порту 3-мя разными способами
|
||
|
||
Утсанавливаем nginx
|
||
|
||
```bash
|
||
root@fedora:~/otus$ dnf install nginx
|
||
```
|
||
|
||
Теперь изменим немного конфигурацию, добавив нестандартный для nginx порт 8880, дописав строки в /etc/nginx/nginx.conf
|
||
```bash
|
||
server {
|
||
listen 80;
|
||
listen 8880;
|
||
listen [::]:80;
|
||
server_name _;
|
||
root /usr/share/nginx/html;
|
||
```
|
||
|
||
|
||
|
||
Перезапустим nginx
|
||
```bash
|
||
[root@fedora ~]# systemctl restart nginx
|
||
Job for nginx.service failed because the control process exited with error code.
|
||
See "systemctl status nginx.service" and "journalctl -xeu nginx.service" for details
|
||
```
|
||
Мы сразу видим ошибку запуска
|
||
|
||
С помощью **audit2why** посмотрим что в логах selinux (можно так же использовать ausearch)
|
||
```bash
|
||
[root@fedora ~]# cat /var/log/audit/audit.log | grep nginx | audit2why
|
||
type=AVC msg=audit(1769366311.648:1693): avc: denied { name_bind } for pid=8420 comm="nginx" src=8880 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:unreserved_port_t:s0 tclass=tcp_socket permissive=0
|
||
|
||
Was caused by:
|
||
The boolean nis_enabled was set incorrectly.
|
||
Description:
|
||
Allow nis to enabled
|
||
|
||
Allow access by executing:
|
||
# setsebool -P nis_enabled 1
|
||
|
||
```
|
||
|
||
### Способ 1
|
||
|
||
Видим, что selinux запретил запуск на порту 8880, и нам сразу дается подсказка, что можно разрешить через выполнение команды **setsebool -P nis_enabled 1**
|
||
|
||
Выполним данную команду но без **-P**, так как этот параметр сохранит конфиг, и применит его после перезагрузку, нам пока этого не нужно!
|
||
```bash
|
||
[root@fedora ~]# setsebool nis_enabled 1
|
||
```
|
||
|
||
Команда выполнилась пробуем запустить nginx
|
||
```bash
|
||
[root@fedora ~]# systemctl start nginx
|
||
[root@fedora ~]# systemctl status nginx
|
||
● nginx.service - The nginx HTTP and reverse proxy server
|
||
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: disabled)
|
||
Drop-In: /usr/lib/systemd/system/service.d
|
||
└─10-timeout-abort.conf
|
||
Active: active (running) since Sun 2026-01-25 18:43:51 UTC; 3min 27s ago
|
||
Invocation: 4e5110d7d45949f2a26939276808600a
|
||
Process: 8522 ExecStartPre=/usr/bin/rm -f /run/nginx.pid (code=exited, status=0/SUCCESS)
|
||
Process: 8524 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=0/SUCCESS)
|
||
Process: 8526 ExecStart=/usr/sbin/nginx (code=exited, status=0/SUCCESS)
|
||
Main PID: 8527 (nginx)
|
||
```
|
||
|
||
Видим, что nginx и работает.
|
||
|
||
Но командой **setsebool nis_enabled 1** разрешает открывать любые порты, отключаем ее
|
||
```bash
|
||
[root@fedora ~]# setsebool nis_enabled 0
|
||
```
|
||
|
||
### Способ 2
|
||
|
||
Создадим совой разрешающий модуль **nginx-custom** с помощью **audit2allow**
|
||
```bash
|
||
[root@fedora ~]# ausearch -c 'nginx' | audit2allow -M nginx-custom
|
||
******************** IMPORTANT ***********************
|
||
To make this policy package active, execute:
|
||
|
||
semodule -i nginx-custom.pp
|
||
|
||
```
|
||
|
||
Тут нам сразу дается подсказка как импортировать созданный модуль, импортируем его
|
||
```bash
|
||
[root@fedora ~]# semodule -i nginx-custom.pp
|
||
```
|
||
|
||
Перезапускаем nginx
|
||
```bash
|
||
[root@fedora ~]# systemctl restart nginx
|
||
```
|
||
Nginx перезапустился без ошибок
|
||
|
||
Данный модуль так же как и в первом случае разрашает открывать любые порты!
|
||
Удалим наш модуль
|
||
```bash
|
||
[root@fedora ~]# semodule -r nginx-custom
|
||
libsemanage.semanage_direct_remove_key: Removing last nginx-custom module (no other nginx-custom module exists at another priority).
|
||
```
|
||
|
||
### Способ 3
|
||
|
||
С помощью semanage добавим наш порт 8880 в http_port_t
|
||
|
||
```bash
|
||
[root@fedora ~]# semanage port -a -t http_port_t -p tcp 8880
|
||
```
|
||
Проверим что он там появился
|
||
```bash
|
||
[root@fedora ~]# semanage port -l | grep http_port_t
|
||
http_port_t tcp 8880, 80, 81, 443, 488, 8008, 8009, 8443, 9000
|
||
http_port_t udp 80, 443
|
||
pegasus_http_port_t tcp 5988
|
||
```
|
||
|
||
И перезапусти nginx
|
||
```bash
|
||
[root@fedora ~]# systemctl restart nginx
|
||
```
|
||
|
||
проверим какие порты слушает nginx
|
||
```bash
|
||
[root@fedora ~]# ss -tlupn | grep nginx
|
||
tcp LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=9000,fd=8),("nginx",pid=8999,fd=8))
|
||
tcp LISTEN 0 511 0.0.0.0:8880 0.0.0.0:* users:(("nginx",pid=9000,fd=9),("nginx",pid=8999,fd=9))
|
||
tcp LISTEN 0 511 [::]:80 [::]:* users:(("nginx",pid=9000,fd=10),("nginx",pid=8999,fd=10))
|
||
```
|
||
|
||
|
||
Способ 3 считаю наилучшим решением!
|
||
|
||
Все успешно!
|
||
|
||
|
||
|
||
Задание 1 успешно выполнено!
|
||
|
||
|
||
|
||
## Задание 2 Обеспечить работоспособность приложения
|
||
|
||
### Подготовка
|
||
|
||
Клонирум репозиторий
|
||
|
||
```bash
|
||
alex@ubuntu-pc:~/otus$ git clone https://github.com/mbfx/otus-linux-adm
|
||
Клонирование в «otus-linux-adm»...
|
||
remote: Enumerating objects: 558, done.
|
||
remote: Counting objects: 100% (456/456), done.
|
||
remote: Compressing objects: 100% (303/303), done.
|
||
remote: Total 558 (delta 125), reused 396 (delta 74), pack-reused 102 (from 1)
|
||
Получение объектов: 100% (558/558), 1.38 МиБ | 5.36 МиБ/с, готово.
|
||
Определение изменений: 100% (140/140), готово.
|
||
```
|
||
|
||
Переходим в каталог с заданием
|
||
```bash
|
||
alex@ubuntu-pc:~/otus$ cd otus-linux-adm/selinux_dns_problems
|
||
```
|
||
|
||
Запускам vagrant
|
||
```bash
|
||
alex@ubuntu-pc:~/otus/otus-linux-adm/selinux_dns_problems$ vagrant up
|
||
Bringing machine 'ns01' up with 'virtualbox' provider...
|
||
Bringing machine 'client' up with 'virtualbox' provider...
|
||
==> ns01: Box 'centos/7' could not be found. Attempting to find and install...
|
||
ns01: Box Provider: virtualbox
|
||
ns01: Box Version: >= 0
|
||
==> ns01: Loading metadata for box 'centos/7'
|
||
ns01: URL: https://vagrantcloud.com/api/v2/vagrant/centos/7
|
||
==> ns01: Adding box 'centos/7' (v2004.01) for provider: virtualbox
|
||
ns01: Downloading: https://vagrantcloud.com/centos/boxes/7/versions/2004.01/providers/virtualbox/unknown/vagrant.box
|
||
Progress: 73% (Rate: 10.8M/s, Estimated time remaining: 0:00:12)
|
||
...
|
||
...
|
||
|
||
TASK [install packages] ********************************************************
|
||
fatal: [ns01]: FAILED! => {"changed": false, "msg": "Failure talking to yum: Cannot find a valid baseurl for repo: base/7/x86_64"}
|
||
|
||
PLAY RECAP *********************************************************************
|
||
ns01 : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
|
||
|
||
Ansible failed to complete successfully. Any error output should be
|
||
visible above. Please fix these errors and try again.
|
||
```
|
||
|
||
Видим, что ansible завершается с ошикой **"Failure talking to yum: Cannot find a valid baseurl for repo: base/7/x86_64"**
|
||
|
||
Попровим Vagrantfile, добавив туда скрипт, который будет менять url до репозиотрия centos
|
||
|
||
```bash
|
||
# -*- mode: ruby -*-
|
||
# vi: set ft=ruby :
|
||
|
||
Vagrant.configure(2) do |config|
|
||
config.vm.box = "centos/7"
|
||
|
||
config.vm.provision "shell", inline: <<-SHELL
|
||
sudo sed -i s/mirror.centos.org/vault.centos.org/g /etc/yum.repos.d/CentOS*
|
||
sudo sed -i s/^#.*baseurl=http/baseurl=http/g /etc/yum.repos.d/CentOS*
|
||
sudo sed -i s/^mirrorlist=http/#mirrorlist=http/g /etc/yum.repos.d/CentOS*
|
||
SHELL
|
||
|
||
config.vm.provision "ansible" do |ansible|
|
||
#ansible.verbose = "vvv"
|
||
ansible.playbook = "provisioning/playbook.yml"
|
||
ansible.become = "true"
|
||
end
|
||
|
||
config.vm.provider "virtualbox" do |v|
|
||
v.memory = 256
|
||
end
|
||
|
||
config.vm.define "ns01" do |ns01|
|
||
ns01.vm.network "private_network", ip: "192.168.50.10", virtualbox__intnet: "dns"
|
||
ns01.vm.hostname = "ns01"
|
||
end
|
||
|
||
config.vm.define "client" do |client|
|
||
client.vm.network "private_network", ip: "192.168.50.15", virtualbox__intnet: "dns"
|
||
client.vm.hostname = "client"
|
||
end
|
||
|
||
end
|
||
```
|
||
|
||
|
||
Вновь запускаем Vagrant
|
||
```bash
|
||
alex@ubuntu-pc:~/otus/otus-linux-adm/selinux_dns_problems$ vagrant up
|
||
Bringing machine 'ns01' up with 'virtualbox' provider...
|
||
Bringing machine 'client' up with 'virtualbox' provider...
|
||
==> ns01: Checking if box 'centos/7' version '2004.01' is up to date...
|
||
==> ns01: Machine already provisioned. Run `vagrant provision` or use the `--provision`
|
||
==> ns01: flag to force provisioning. Provisioners marked to run always will still run.
|
||
==> client: Importing base box 'centos/7'...
|
||
==> client: Matching MAC address for NAT networking...
|
||
==> client: Checking if box 'centos/7' version '2004.01' is up to d
|
||
...
|
||
...
|
||
TASK [copy motd to the client] *************************************************
|
||
changed: [client]
|
||
|
||
TASK [copy transferkey to client] **********************************************
|
||
changed: [client]
|
||
|
||
PLAY RECAP *********************************************************************
|
||
client : ok=7 changed=5 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
|
||
|
||
```
|
||
|
||
Теперь все запустилось как нужно
|
||
|
||
Подключаемся в консоль VM **client**
|
||
```bash
|
||
alex@ubuntu-pc:~/otus/otus-linux-adm/selinux_dns_problems$ vagrant ssh client
|
||
Last login: Sun Jan 25 11:28:02 2026 from 10.0.2.2
|
||
###############################
|
||
### Welcome to the DNS lab! ###
|
||
###############################
|
||
|
||
- Use this client to test the enviroment
|
||
- with dig or nslookup. Ex:
|
||
dig @192.168.50.10 ns01.dns.lab
|
||
|
||
- nsupdate is available in the ddns.lab zone. Ex:
|
||
nsupdate -k /etc/named.zonetransfer.key
|
||
server 192.168.50.10
|
||
zone ddns.lab
|
||
update add www.ddns.lab. 60 A 192.168.50.15
|
||
send
|
||
|
||
- rndc is also available to manage the servers
|
||
rndc -c ~/rndc.conf reload
|
||
|
||
###############################
|
||
### Enjoy! ####################
|
||
###############################
|
||
[vagrant@client ~]$
|
||
```
|
||
|
||
Пытаемся обновить зону ddns.lab
|
||
```bash
|
||
[vagrant@client ~]$ nsupdate -k /etc/named.zonetransfer.key
|
||
> server 192.168.50.10
|
||
> zone ddns.lab
|
||
> update add www.ddns.lab. 60 A 192.168.50.15
|
||
> send
|
||
update failed: SERVFAIL
|
||
```
|
||
|
||
Получаем ошибку.
|
||
|
||
Подключаемся на VM ns01
|
||
```bash
|
||
alex@ubuntu-pc:~/otus/otus-linux-adm/selinux_dns_problems$ vagrant ssh ns01
|
||
Last login: Sun Jan 25 11:19:21 2026 from 10.0.2.2
|
||
[vagrant@ns01 ~]$
|
||
```
|
||
|
||
Смотрим логи selinux с помощью audit2why
|
||
```bash
|
||
[vagrant@ns01 ~]# sudo cat /var/log/audit/audit.log | audit2why
|
||
type=AVC msg=audit(1769341839.490:2068): avc: denied { create } for pid=5356 comm="isc-worker0000" name="named.ddns.lab.view1.jnl" scontext=system_u:system_r:named_t:s0 tcontext=system_u:object_r:etc_t:s0 tclass=file permissive=0
|
||
|
||
Was caused by:
|
||
Missing type enforcement (TE) allow rule.
|
||
|
||
You can use audit2allow to generate a loadable module to allow this access.
|
||
|
||
```
|
||
|
||
Видим , что файл имеет контекст etc_t а изменить мы пытаемся из конеткста named_t, из за этого selinux и не дает произвести изменения
|
||
|
||
Посмотрим, какие контесты на файлах в каталоге /etc/named
|
||
```bash
|
||
[vagrant@ns01 ~]$ sudo ls -lZ /etc/named
|
||
drw-rwx---. root named unconfined_u:object_r:etc_t:s0 dynamic
|
||
-rw-rw----. root named system_u:object_r:etc_t:s0 named.50.168.192.rev
|
||
-rw-rw----. root named system_u:object_r:etc_t:s0 named.dns.lab
|
||
-rw-rw----. root named system_u:object_r:etc_t:s0 named.dns.lab.view1
|
||
-rw-rw----. root named system_u:object_r:etc_t:s0 named.newdns.lab
|
||
```
|
||
|
||
Видим, что везде контекст etc_t.
|
||
|
||
|
||
Для сравнения посмотрим существующую зону (localhost) и её контекст:
|
||
```bash
|
||
[vagrant@ns01 ~]$ sudo ls -lZ /var/named/named.localhost
|
||
-rw-r-----. root named system_u:object_r:named_zone_t:s0 /var/named/named.localhost
|
||
|
||
```
|
||
Видим, что в данном случае, контекст named_zone_t
|
||
|
||
Изменим контекст для каталога /etc/named на named_zone_t
|
||
|
||
```bash
|
||
[vagrant@ns01 ~]$ sudo chcon -R -t named_zone_t /etc/named
|
||
```
|
||
Проверим
|
||
```bash
|
||
[vagrant@ns01 ~]$ sudo ls -lZ /etc/named
|
||
drw-rwx---. root named unconfined_u:object_r:named_zone_t:s0 dynamic
|
||
-rw-rw----. root named system_u:object_r:named_zone_t:s0 named.50.168.192.rev
|
||
-rw-rw----. root named system_u:object_r:named_zone_t:s0 named.dns.lab
|
||
-rw-rw----. root named system_u:object_r:named_zone_t:s0 named.dns.lab.view1
|
||
-rw-rw----. root named system_u:object_r:named_zone_t:s0 named.newdns.lab
|
||
```
|
||
|
||
Видим, контексты изменились, перейдем на client и попробуем обновить зону еще раз
|
||
|
||
```bash
|
||
[vagrant@client ~]$ nsupdate -k /etc/named.zonetransfer.key
|
||
> server 192.168.50.10
|
||
> zone ddns.lab
|
||
> update add www.ddns.lab. 60 A 192.168.50.15
|
||
> send
|
||
>
|
||
```
|
||
|
||
Теперь ошибок не выдается, проверим также с помощью nslookup
|
||
```bash
|
||
[vagrant@client ~]$ nslookup www.ddns.lab
|
||
Server: 192.168.50.10
|
||
Address: 192.168.50.10#53
|
||
|
||
Name: www.ddns.lab
|
||
Address: 192.168.50.15
|
||
|
||
```
|
||
|
||
|
||
Все готово! |