rubric/modules/linuxmodules/linux_security.go
2026-04-06 11:02:36 +03:00

276 lines
12 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package linuxmodules
import (
"fmt"
"rubric/utils"
)
var SecurityModule = Module{
Key: "security",
Aliases: []string{"sec", "selinux", "firewall", "безопасность"},
Title: "Безопасность: SELinux и Firewall",
Description: "Темы 4546, 48: SELinux, firewalld, восстановление доступа",
Run: showSecurity,
}
func showSecurity() {
utils.Header("Linux — Безопасность: SELinux и Firewall")
// ─── 45. SELinux ──────────────────────────────────────────────
utils.Section("45. Принудительный контроль доступа — SELinux")
utils.Println("SELinux (Security-Enhanced Linux) — система принудительного контроля доступа.")
utils.Println("Работает поверх обычных прав Unix: даже root ограничен политикой SELinux.")
fmt.Println()
utils.Println(utils.ColorBold + "Режимы SELinux:" + utils.ColorReset)
utils.Code(`Enforcing — SELinux активен, запрещённые действия блокируются
и логируются (производственный режим)
Permissive — SELinux активен, нарушения только логируются
(не блокируются). Для отладки.
Disabled — SELinux полностью отключён (требует перезагрузки)
# Текущий режим:
getenforce
sestatus # подробная информация
# Временно изменить режим (до перезагрузки):
setenforce 0 # Enforcing → Permissive
setenforce 1 # Permissive → Enforcing
setenforce Permissive # то же самое
# Постоянно — /etc/selinux/config:
SELINUX=enforcing # enforcing / permissive / disabled
SELINUXTYPE=targeted # политика
# После изменения с/на disabled — нужна перезагрузка.
# При включении SELinux после disabled — нужна переметка файлов:
touch /.autorelabel && reboot`)
utils.Println(utils.ColorBold + "Контексты SELinux:" + utils.ColorReset)
utils.Code(`Каждый файл, процесс и порт имеет SELinux-контекст:
user:role:type:level
↓ ↓ ↓ ↓
system_u:object_r:httpd_sys_content_t:s0
Самое важное — type (тип): httpd_sys_content_t, etc_t...
# Просмотр контекстов файлов:
ls -Z /var/www/html/
ls -lZ /etc/nginx/
# Просмотр контекста процессов:
ps auxZ | grep nginx
# Просмотр контекста портов:
semanage port -l | grep http`)
utils.Println(utils.ColorBold + "Управление контекстами:" + utils.ColorReset)
utils.Code(`# Изменить контекст файла:
chcon -t httpd_sys_content_t /var/www/mysite/
chcon -R -t httpd_sys_content_t /var/www/mysite/ # рекурсивно
# Проблема: chcon не постоянен, restorecon сбросит его.
# Правильно: использовать semanage fcontext:
# Добавить постоянное правило для контекста:
semanage fcontext -a -t httpd_sys_content_t '/srv/web(/.*)?'
# Применить правила к файлам:
restorecon -Rv /srv/web/
# Восстановить контекст по умолчанию:
restorecon -Rv /var/www/html/
# Проверить ожидаемый контекст:
matchpathcon /var/www/html/index.html`)
utils.Println(utils.ColorBold + "Булевые переменные SELinux (Booleans):" + utils.ColorReset)
utils.Code(`# Booleans — включают/выключают определённые возможности:
# Просмотр всех:
getsebool -a
getsebool -a | grep httpd
# Включить/выключить (временно):
setsebool httpd_can_network_connect on
setsebool httpd_can_network_connect off
# Постоянно (после перезагрузки):
setsebool -P httpd_can_network_connect on
setsebool -P httpd_enable_homedirs on
# Полезные booleans:
httpd_can_network_connect # nginx/apache → внешняя сеть
httpd_can_network_connect_db # nginx/apache → БД
httpd_enable_homedirs # доступ к /home
samba_enable_home_dirs # Samba к /home
ssh_sysadm_login # SSH-вход для sysadmin`)
utils.Println(utils.ColorBold + "Порты и SELinux:" + utils.ColorReset)
utils.Code(`# Посмотреть разрешённые порты:
semanage port -l
semanage port -l | grep http
# Разрешить nginx слушать нестандартный порт 8888:
semanage port -a -t http_port_t -p tcp 8888
# Удалить правило порта:
semanage port -d -t http_port_t -p tcp 8888
# Изменить существующее правило:
semanage port -m -t http_port_t -p tcp 8888`)
utils.Println(utils.ColorBold + "Диагностика проблем SELinux:" + utils.ColorReset)
utils.Code(`# Логи SELinux:
/var/log/audit/audit.log # основной лог
# Поиск запретов:
ausearch -m avc -ts recent # последние запреты AVC
grep 'denied' /var/log/audit/audit.log | tail -20
# audit2why — объяснить запрет:
ausearch -m avc -ts recent | audit2why
# audit2allow — создать модуль для разрешения:
ausearch -m avc -ts recent | audit2allow -m mymodule > mymodule.te
checkmodule -M -m -o mymodule.mod mymodule.te
semodule_package -o mymodule.pp -m mymodule.mod
semodule -i mymodule.pp
# sealert — графическая диагностика (если установлен setroubleshoot):
sealert -a /var/log/audit/audit.log`)
// ─── 46. firewalld ────────────────────────────────────────────
utils.Section("46. Межсетевой экран — firewalld")
utils.Println("firewalld — динамический менеджер firewall в RHEL/Fedora/CentOS.")
utils.Println("Работает поверх nftables (или iptables).")
fmt.Println()
utils.Println(utils.ColorBold + "Зоны (Zones) — основное понятие firewalld:" + utils.ColorReset)
utils.Code(`Зона определяет уровень доверия к трафику интерфейса.
drop — всё входящее молча отбрасывается
block — входящее отклоняется с сообщением об ошибке
public — публичные сети, только явно разрешённое (по умолчанию)
external — внешние сети с маскарадингом
internal — внутренние сети, больше доверие
home — домашние сети
work — рабочие сети
dmz — демилитаризованная зона
trusted — весь трафик разрешён`)
utils.Println(utils.ColorBold + "Основные команды firewall-cmd:" + utils.ColorReset)
utils.Command("firewall-cmd --state", "работает ли firewalld")
utils.Command("systemctl status firewalld", "статус сервиса")
utils.Command("firewall-cmd --get-active-zones", "активные зоны и интерфейсы")
utils.Command("firewall-cmd --get-default-zone", "зона по умолчанию")
utils.Command("firewall-cmd --list-all", "все правила активной зоны")
utils.Command("firewall-cmd --list-all --zone=public", "правила зоны public")
fmt.Println()
utils.Println(utils.ColorBold + "Управление сервисами и портами:" + utils.ColorReset)
utils.Code(`# Разрешить сервис (временно, до перезагрузки):
firewall-cmd --add-service=http
firewall-cmd --add-service=https
firewall-cmd --add-service=ssh
# Постоянно (--permanent):
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --reload # применить permanent-правила
# Удалить сервис:
firewall-cmd --permanent --remove-service=http
# Список доступных сервисов:
firewall-cmd --get-services
# Разрешить порт напрямую:
firewall-cmd --permanent --add-port=8080/tcp
firewall-cmd --permanent --add-port=5000-5100/tcp
firewall-cmd --permanent --remove-port=8080/tcp`)
utils.Println(utils.ColorBold + "Rich rules — сложные правила:" + utils.ColorReset)
utils.Code(`# Разрешить SSH только с конкретного IP:
firewall-cmd --permanent --add-rich-rule='
rule family="ipv4"
source address="192.168.1.0/24"
service name="ssh" accept'
# Заблокировать IP:
firewall-cmd --permanent --add-rich-rule='
rule family="ipv4"
source address="10.10.10.5"
drop'
# Ограничить количество соединений (rate limiting):
firewall-cmd --permanent --add-rich-rule='
rule service name="ssh"
limit value="5/m" accept'`)
utils.Println(utils.ColorBold + "Маскарадинг (NAT):" + utils.ColorReset)
utils.Code(`# Включить маскарадинг (нужно для роутера):
firewall-cmd --permanent --zone=external --add-masquerade
# Пробросить порт:
firewall-cmd --permanent --add-forward-port=port=80:proto=tcp:toport=8080
# Внешний 80 → внутренний 8080`)
// ─── 48. Восстановление доступа ───────────────────────────────
utils.Section("48. Восстановление доступа")
utils.Println("Что делать если потеряли пароль root или доступ к системе.")
fmt.Println()
utils.Println(utils.ColorBold + "Сброс пароля root (RHEL/CentOS):" + utils.ColorReset)
utils.Code(`1. Перезагрузить систему.
2. В меню GRUB нажать 'e' на нужной записи.
3. Найти строку начинающуюся с linux или linuxefi.
4. В конце строки добавить: rd.break
5. Нажать Ctrl+X для загрузки.
# В initramfs shell:
mount -o remount,rw /sysroot # перемонтировать с правами записи
chroot /sysroot # перейти в систему
passwd root # задать новый пароль root
# Если SELinux включён:
touch /.autorelabel # переметить файлы SELinux
exit
reboot`)
utils.Println(utils.ColorBold + "Сброс пароля root (Ubuntu/Debian):" + utils.ColorReset)
utils.Code(`1. В GRUB выбрать "Advanced options".
2. Выбрать строку "(recovery mode)".
3. В меню recovery выбрать "root".
# Или: в GRUB нажать 'e', найти строку linux,
# заменить ro на rw, добавить в конец: init=/bin/bash
# В shell:
passwd root
# Если файловая система только для чтения:
mount -o remount,rw /
passwd root
sync
reboot -f`)
utils.Println(utils.ColorBold + "Восстановление из LiveCD:" + utils.ColorReset)
utils.Code(`# Загрузиться с LiveCD/LiveUSB
# Найти системный раздел:
lsblk
# Смонтировать:
mount /dev/sda2 /mnt
mount /dev/sda1 /mnt/boot # boot раздел
# Для UEFI:
mount /dev/sda1 /mnt/boot/efi
# Chroot:
mount --bind /dev /mnt/dev
mount --bind /proc /mnt/proc
mount --bind /sys /mnt/sys
chroot /mnt
# Теперь можно: passwd root, grub-install, etc.`)
utils.Footer()
}