Настройка сетевой инфраструктуры на ALT Linux
Справочник по настройке маршрутизации, VLAN, GRE-туннелей, NAT, динамической маршрутизации (OSPF), DHCP и DNS на ALT Linux. Каждый раздел содержит краткое пояснение и пример готовой конфигурации для соответствующего узла сети.
Адреса, маски подсетей, имена интерфейсов и доменные имена в примерах относятся к учебному стенду. При настройке подставляйте значения своей схемы.
Содержание
1-й этап. Настройка узлов сети: маршрутизаторы и серверы
Ниже — учебный вариант (домен linux-skills.irpo, VLAN 110/120/888, пользователи net_mgr / srv_user). В официальном задании ДЭ значения другие, меняются только переменные в блоках «0. Подготовка переменных»: домен au-team.irpo; VLAN 100 (HQ-SRV, сеть не более 32 адресов → /27), VLAN 200 (HQ-CLI, не более 16 → /28), VLAN 999 (управление, не более 8 → /29); сеть в сторону BR-SRV не более 16 адресов (/28); стык BR-FW—BR-RTR с минимальной маской (/30); GRE из 10.10.10.0/24 с минимальной маской (10.10.10.0/30); ISP: 172.16.1.0/28 к HQ-RTR и 172.16.2.0/28 к BR-RTR; net_admin / P@ssw0rd на маршрутизаторах; sshuser с UID 2027, порт SSH 2027, пароль P@ssw0rd; пароль OSPF P@ssw0rd (MD5); записи DNS: docker.au-team.irpo → интерфейс ISP к HQ-RTR, web.au-team.irpo → интерфейс ISP к BR-RTR; PTR обязательны для hq-srv и br-srv.
Граничный маршрутизатор
Граничный маршрутизатор на стыке с внешней сетью: получает адрес от вышестоящего провайдера и выполняет трансляцию адресов (NAT) для внутренних подсетей.
0. Подготовка переменных
Экспортируйте переменные среды перед выполнением команд настройки узла:
int_internet="enp7s1" int_hq_rtr="enp7s2" int_br_rtr="enp7s3" ip_hq_rtr="172.20.1.1" mask_hq_rtr="28" ip_br_rtr="172.20.2.1" mask_br_rtr="28"
I. Идентификация хоста и времени
Имя хоста идентифицирует узел в сети. Вызов exec bash в конце раздела нужен, чтобы новое имя сразу отобразилось в приглашении (после него переменные придётся объявить заново).
hostnamectl hostname isp timedatectl set-timezone Europe/Moscow
II. Включение маршрутизации (IP Forwarding)
Параметр ядра net.ipv4.ip_forward включает пересылку IPv4-пакетов.
cd /etc/net/ sed -i 's/net.ipv4.ip_forward = 0/net.ipv4.ip_forward = 1/g' sysctl.conf
III. Подготовка шаблонов интерфейсов
Копирование каталогов etcnet для создания конфигураций новых интерфейсов на основе шаблона.
cd ifaces/ \cp -R $int_internet $int_hq_rtr \cp -R $int_hq_rtr $int_br_rtr
IV. Настройка режимов BOOTPROTO и IPv4-адресов
Конфигурирование статических адресов и DHCP-клиента на интерфейсах.
cat << EOF > /etc/net/ifaces/$int_internet/options BOOTPROTO=dhcp TYPE=eth CONFIG_WIRELESS=no SYSTEMD_BOOTPROTO=dhcp4 CONFIG_IPv4=yes DISABLED=no NM_CONTROLLED=no SYSTEMD_CONTROLLED=no EOF cat << EOF > /etc/net/ifaces/$int_hq_rtr/options BOOTPROTO=static TYPE=eth CONFIG_WIRELESS=no SYSTEMD_BOOTPROTO=static CONFIG_IPv4=yes DISABLED=no NM_CONTROLLED=no SYSTEMD_CONTROLLED=no EOF cat << EOF > /etc/net/ifaces/$int_br_rtr/options BOOTPROTO=static TYPE=eth CONFIG_WIRELESS=no SYSTEMD_BOOTPROTO=static CONFIG_IPv4=yes DISABLED=no NM_CONTROLLED=no SYSTEMD_CONTROLLED=no EOF echo "$ip_hq_rtr/$mask_hq_rtr" > $int_hq_rtr/ipv4address echo "$ip_br_rtr/$mask_br_rtr" > $int_br_rtr/ipv4address systemctl restart network
enp7s1 > DHCP (uplink к провайдеру)
enp7s2, enp7s3 > static (downlink к роутерам площадок)
V. Скачивание nano, iptables
apt-get update && apt-get install -y nano apt-get install -y iptables
VI. Применение сетевых настроек и NAT
systemctl restart network iptables -t nat -A POSTROUTING -o $int_internet -j MASQUERADE iptables-save -f /etc/sysconfig/iptables systemctl enable --now iptables.service exec bash
Маршрутизатор площадки A
Маршрутизатор площадки A: терминирует VLAN пользователей и серверов, поднимает GRE-туннель до второй площадки, распространяет маршруты по OSPF и выдаёт адреса по DHCP.
0. Подготовка переменных
domain="linux-skills.irpo" username="net_mgr" userpassword="Mgr@P@ss88" int_name_default_gateway="enp7s1" int_name_vlan_slave="enp7s2" int_name_vlan_hq_srv="enp7s2.110" int_name_vlan_hq_cli="enp7s2.120" int_name_vlan_remote="enp7s2.888" ip_isp="172.20.1.2" mask_isp="28" ip_gateway="172.20.1.1" # Адреса самого HQ-RTR в VLAN (шлюзы для HQ-SRV и HQ-CLI) ip_vlan_hq_srv="192.168.110.1" mask_hq_srv="26" vlan_id_hq_srv="110" ip_vlan_hq_cli="192.168.120.1" mask_hq_cli="24" vlan_hq_cli="120" ip_remote="192.168.88.1" mask_remote="28" vlan_remote="888" # Сервер HQ-SRV (DNS для площадки) ip_hq_srv="192.168.110.2" ip_br_rtr="172.20.2.2" dhcp_subnet="192.168.120.0" dhcp_netmask="255.255.255.0" dhcp_ip_range_start="192.168.120.2" dhcp_ip_range_end="192.168.120.12"
I. Идентификация хоста и времени
hostnamectl hostname hq-rtr.$domain timedatectl set-timezone Europe/Moscow
II. Включение маршрутизации (IP Forwarding)
cd /etc/net/ sed -i 's/net.ipv4.ip_forward = 0/net.ipv4.ip_forward = 1/g' sysctl.conf
III. Подготовка шаблонов интерфейсов
cd ifaces/ \cp -R $int_name_default_gateway $int_name_vlan_slave \cp -R $int_name_default_gateway $int_name_vlan_hq_srv \cp -R $int_name_default_gateway $int_name_vlan_hq_cli \cp -R $int_name_default_gateway $int_name_vlan_remote \cp -R $int_name_default_gateway gre10
IV. Настройка IPv4-адресов и маршрутов
cat << EOF > /etc/net/ifaces/$int_name_default_gateway/options BOOTPROTO=static TYPE=eth CONFIG_WIRELESS=no SYSTEMD_BOOTPROTO=static CONFIG_IPv4=yes DISABLED=no NM_CONTROLLED=no SYSTEMD_CONTROLLED=no EOF cat << EOF > /etc/net/ifaces/$int_name_vlan_hq_srv/options BOOTPROTO=static TYPE=eth CONFIG_WIRELESS=no SYSTEMD_BOOTPROTO=static CONFIG_IPv4=yes DISABLED=no NM_CONTROLLED=no SYSTEMD_CONTROLLED=no EOF cat << EOF > /etc/net/ifaces/$int_name_vlan_hq_cli/options BOOTPROTO=static TYPE=eth CONFIG_WIRELESS=no SYSTEMD_BOOTPROTO=static CONFIG_IPv4=yes DISABLED=no NM_CONTROLLED=no SYSTEMD_CONTROLLED=no EOF cat << EOF > /etc/net/ifaces/$int_name_vlan_remote/options BOOTPROTO=static TYPE=eth CONFIG_WIRELESS=no SYSTEMD_BOOTPROTO=static CONFIG_IPv4=yes DISABLED=no NM_CONTROLLED=no SYSTEMD_CONTROLLED=no EOF cat << EOF > /etc/net/ifaces/gre10/options BOOTPROTO=static SYSTEMD_BOOTPROTO=static TYPE=iptun TUNTYPE=gre CONFIG_WIRELESS=no CONFIG_IPv4=yes DISABLED=no NM_CONTROLLED=no SYSTEMD_CONTROLLED=no TUNLOCAL=$ip_isp TUNREMOTE=$ip_br_rtr TUNTTL=32 TUNOPTIONS='ttl 32' EOF echo "$ip_isp/$mask_isp" > $int_name_default_gateway/ipv4address echo "default via $ip_gateway" > $int_name_default_gateway/ipv4route echo "$ip_vlan_hq_srv/$mask_hq_srv" > $int_name_vlan_hq_srv/ipv4address echo "$ip_vlan_hq_cli/$mask_hq_cli" > $int_name_vlan_hq_cli/ipv4address echo "$ip_remote/$mask_remote" > $int_name_vlan_remote/ipv4address echo "10.0.0.1/30" > gre10/ipv4address
V. Настройка VLAN-интерфейсов
echo "HOST=$int_name_vlan_slave" >> $int_name_vlan_hq_srv/options echo "HOST=$int_name_vlan_slave" >> $int_name_vlan_hq_cli/options echo "HOST=$int_name_vlan_slave" >> $int_name_vlan_remote/options echo "VID=$vlan_id_hq_srv" >> $int_name_vlan_hq_srv/options echo "VID=$vlan_hq_cli" >> $int_name_vlan_hq_cli/options echo "VID=$vlan_remote" >> $int_name_vlan_remote/options sed -i 's/TYPE=eth/TYPE=vlan/g' $int_name_vlan_hq_srv/options sed -i 's/TYPE=eth/TYPE=vlan/g' $int_name_vlan_hq_cli/options sed -i 's/TYPE=eth/TYPE=vlan/g' $int_name_vlan_remote/options echo "nameserver 77.88.8.8" > /etc/resolv.conf echo "nameserver 77.88.8.8" > /etc/net/ifaces/$int_name_default_gateway/resolv.conf
VI. Применяем сетевые настройки
systemctl restart network
VII. Установка и настройка динамической маршрутизации (FRR / OSPF), nano и iptables
apt-get update apt-get install -y frr apt-get install -y dhcp-server apt-get install -y sudo apt-get install -y nano apt-get install -y iptables sed -i 's/ospfd=no/ospfd=yes/g' /etc/frr/daemons systemctl enable --now frr
VIII. Создание пользователей
useradd -m $username echo "$username:$userpassword" | chpasswd usermod -aG wheel $username echo "$username ALL=(ALL:ALL) NOPASSWD: ALL" >> /etc/sudoers
IX. Настройка NAT
iptables -t nat -A POSTROUTING -o $int_name_default_gateway -j MASQUERADE iptables-save -f /etc/sysconfig/iptables systemctl enable --now iptables.service
X. Настройка DNS-резолвера
cat << EOF > /etc/resolv.conf nameserver $ip_hq_srv search $domain domain $domain EOF cat << EOF > /etc/net/ifaces/$int_name_default_gateway/resolv.conf nameserver $ip_hq_srv search $domain domain $domain EOF
XI. Конфигурация OSPF через vtysh
vtysh — отдельная оболочка, переменные bash в ней не работают: все значения вписываются буквально. Если команда no ip ospf passive не принимается (старый FRR), используйте вместо неё no passive-interface gre10 внутри router ospf.
vtysh conf t interface gre10 ip ospf network point-to-point ip ospf message-digest-key 1 md5 Mgr@P@ss88 ip ospf authentication message-digest no ip ospf passive exit ! router ospf passive-interface default network 10.0.0.0/30 area 0 network 192.168.88.0/28 area 0 network 192.168.110.0/26 area 0 network 192.168.120.0/24 area 0 exit exit wr exit
XII. Настройка DHCP-сервера
Шлюз — адрес HQ-RTR в VLAN клиентов; сам он в диапазон выдачи не входит (диапазон начинается со следующего адреса).
cat << EOF > /etc/dhcp/dhcpd.conf
ddns-update-style none;
subnet $dhcp_subnet netmask $dhcp_netmask {
option routers $ip_vlan_hq_cli;
option subnet-mask $dhcp_netmask;
option domain-name "$domain";
option domain-name-servers $ip_hq_srv;
range dynamic-bootp $dhcp_ip_range_start $dhcp_ip_range_end;
default-lease-time 21600;
max-lease-time 43200;
}
EOF
echo "DHCPDARGS=$int_name_vlan_hq_cli" > /etc/sysconfig/dhcpd
systemctl enable --now dhcpd
systemctl status dhcpd
exec bash
Межсетевой экран площадки B (BR-FW)
Отдельный узел на ALT Linux между BR-RTR и локальной сетью площадки: разделяет FW-NET и BR-NET, маршрутизирует транзит и участвует в OSPF со стороны маршрутизатора.
0. Подготовка переменных
Объявите переменные в сессии этого узла перед выполнением остальных команд. Они живут только в текущей оболочке: после bash, su, exit или переподключения по SSH объявите их заново — проверить можно командой echo с именем любой переменной.
# Домен и часовой пояс (те же, что на остальных узлах 1-го этапа) domain="linux-skills.irpo" tz="Europe/Moscow" # Интерфейсы — уточните имена командой: ip -br a int_to_rtr="enp7s1" int_to_srv="enp7s2" # FW-NET — стык с BR-RTR, минимальная маска: /30 = ровно два адреса узлов ip_fw_to_rtr="192.168.3.2" ip_rtr_to_fw="192.168.3.1" mask_p2p="30" net_p2p="192.168.3.0/30" # BR-NET — локальная сеть площадки B (не более 16 адресов) ip_fw_to_srv="192.168.4.1" mask_br="28" net_br="192.168.4.0/28" ip_br_srv="192.168.4.2" # DNS — в этой роли выступает сервер площадки A ip_hq_srv="192.168.110.2" # OSPF ospf_router_id="77.7.7.7"
I. Очистка клонированной машины (если разворачиваете из копии)
Выполняйте только на копии, не на доноре. Стираются сетевые настройки, конфигурация маршрутизации, правила фильтрации и идентификаторы, которые не должны совпадать у двух машин.
# Службы, доставшиеся от донора systemctl disable --now frr dhcpd nftables 2>/dev/null || true systemctl disable --now iptables.service 2>/dev/null || true # Правила фильтрации и трансляции iptables -F; iptables -X iptables -t nat -F; iptables -t nat -X iptables -t mangle -F; iptables -t mangle -X iptables -P INPUT ACCEPT; iptables -P FORWARD ACCEPT; iptables -P OUTPUT \ ACCEPT \rm -f /etc/sysconfig/iptables /etc/nftables.conf # Конфигурация маршрутизации \rm -f /etc/frr/frr.conf /etc/frr/zebra.conf /etc/frr/ospfd.conf \ /etc/frr/ripd.conf sed -i 's/^\([a-z0-9]*\)=yes/\1=no/' /etc/frr/daemons 2>/dev/null || true # Описания интерфейсов etcnet, кроме служебных cd /etc/net/ifaces for d in *; do case "$d" in lo|default|unknown) continue ;; esac \rm -rf "$d" done cd / # Резолвер и арендованные адреса \rm -f /etc/resolv.conf \rm -rf /var/lib/dhcp/dhcpd/state/* 2>/dev/null || true # Идентификаторы, которые обязаны различаться \rm -f /etc/machine-id && systemd-machine-id-setup \rm -f /etc/openssh/ssh_host_* /etc/ssh/ssh_host_* 2>/dev/null || true ssh-keygen -A \rm -f /root/.ssh/known_hosts \rm -f /etc/udev/rules.d/70-persistent-net.rules # Журналы и история : > /root/.bash_history journalctl --rotate && journalctl --vacuum-time=1s reboot
II. Имя хоста и часовой пояс
hostnamectl set-hostname br-fw.$domain timedatectl set-timezone $tz ip -br a
III. Настройка интерфейсов
Стык с маршрутизатором — /30: в такой подсети ровно два адреса узлов и оба назначаются (/28 дал бы 14 адресов и не был бы «минимально возможной маской»). Маршрут по умолчанию ведёт на маршрутизатор. Файл резолвера пишется и в каталог интерфейса: etcnet при перезапуске сети подставляет оттуда свою копию.
mkdir -p /etc/net/ifaces/$int_to_rtr /etc/net/ifaces/$int_to_srv cat <<EOF > /etc/net/ifaces/$int_to_rtr/options TYPE=eth DISABLED=no BOOTPROTO=static SYSTEMD_BOOTPROTO=static CONFIG_IPV4=yes NM_CONTROLLED=no SYSTEMD_CONTROLLED=no EOF echo "$ip_fw_to_rtr/$mask_p2p" > /etc/net/ifaces/$int_to_rtr/ipv4address echo "default via $ip_rtr_to_fw" > /etc/net/ifaces/$int_to_rtr/ipv4route cat <<EOF > /etc/net/ifaces/$int_to_srv/options TYPE=eth DISABLED=no BOOTPROTO=static SYSTEMD_BOOTPROTO=static CONFIG_IPV4=yes NM_CONTROLLED=no SYSTEMD_CONTROLLED=no EOF echo "$ip_fw_to_srv/$mask_br" > /etc/net/ifaces/$int_to_srv/ipv4address # Временный резолвер — нужен для apt-get на следующем шаге echo "nameserver 77.88.8.8" > /etc/resolv.conf echo "nameserver 77.88.8.8" > /etc/net/ifaces/$int_to_rtr/resolv.conf systemctl restart network ip -4 -br a
IV. Настройка DNS-резолвера
Файл пишется дважды намеренно: etcnet при перезапуске сети подставляет свою копию из каталога интерфейса и затирает корневой /etc/resolv.conf.
apt-get update apt-get install -y iptables apt-get install -y frr cat <<EOF > /etc/resolv.conf search $domain nameserver $ip_hq_srv EOF cat <<EOF > /etc/net/ifaces/$int_to_rtr/resolv.conf search $domain nameserver $ip_hq_srv EOF systemctl restart network cat /etc/resolv.conf
V. Включение маршрутизации (IP Forwarding)
Параметр задаётся в двух местах намеренно: etcnet применяет собственный sysctl.conf при каждом перезапуске сети и может вернуть значение обратно.
cat <<EOF > /etc/sysctl.d/99-router.conf net.ipv4.ip_forward = 1 EOF sed -i -E 's/^#?net.ipv4.ip_forward.*/net.ipv4.ip_forward = 1/' \ /etc/net/sysctl.conf sysctl --system sysctl net.ipv4.ip_forward
VI. Политика фильтрации (без NAT)
NAT на BR-FW не нужен и вреден: сеть BR-NET анонсируется по OSPF, а маскарад скрыл бы реальные адреса BR-SRV от площадки A (Ansible, домен). По заданию динамическая трансляция настраивается только на HQ-RTR и BR-RTR. Здесь достаточно разрешающей политики транзита и сохранения правил.
iptables -P FORWARD ACCEPT iptables-save -f /etc/sysconfig/iptables systemctl enable --now iptables.service
VII. Установка и запуск FRR
Демон ospfd по умолчанию выключен; без zebra маршруты не попадают в ядро.
sed -i 's/^zebra=no/zebra=yes/' /etc/frr/daemons sed -i 's/^ospfd=no/ospfd=yes/' /etc/frr/daemons systemctl enable --now frr systemctl is-active frr
VIII. Конфигурация OSPF
Соседство поднимается только на интерфейсе к маршрутизатору: остальные объявлены пассивными. Сеть в сторону сервера анонсируется, но соседей там не ищет. Внутри vtysh переменные bash не работают, но здесь команды передаются через heredoc без кавычек у EOF — подстановку делает bash ещё до запуска vtysh, поэтому переменные можно использовать. Со стороны BR-RTR интерфейс к BR-FW тоже должен быть не пассивным и его сеть объявлена в OSPF (см. раздел BR-RTR), иначе соседство не поднимется.
vtysh <<EOF configure terminal interface $int_to_rtr no ip ospf passive exit router ospf ospf router-id $ospf_router_id passive-interface default network $net_p2p area 0 network $net_br area 0 exit end write memory EOF vtysh -c 'show running-config' | head -20
IX. Проверка
Соседство поднимется только после настройки BR-RTR — до этого список соседей пуст, и это не ошибка. Состояние Full означает, что смежность установлена. Если пусто — смотрите, поднят ли интерфейс, совпадают ли area и маска на обоих концах.
ip -4 -br a ip route sysctl net.ipv4.ip_forward vtysh -c 'show ip ospf neighbor' vtysh -c 'show ip route ospf' ping -c2 $ip_rtr_to_fw ping -c2 $ip_br_srv getent ahostsv4 hq-srv.$domain
Маршрутизатор площадки B
Маршрутизатор площадки B: подключается к площадке A через GRE-туннель и обменивается маршрутами по OSPF. Внутренний интерфейс смотрит на BR-FW (стык /30, см. раздел межсетевого экрана); сеть BR-SRV приходит по OSPF от BR-FW, поэтому на стыке с BR-FW OSPF не пассивный и без MD5 (на BR-FW аутентификация по заданию не требуется).
0. Подготовка переменных
domain="linux-skills.irpo" username="net_mgr" userpassword="Mgr@P@ss88" int_name_default_gateway="enp7s1" int_name_br_fw="enp7s2" ip_isp="172.20.2.2" mask_isp="28" ip_gateway="172.20.2.1" # Стык с BR-FW — те же значения, что ip_rtr_to_fw / net_p2p в разделе BR-FW ip_to_br_fw="192.168.3.1" mask_to_br_fw="30" ip_hq_srv="192.168.110.2" ip_hq_rtr="172.20.1.2"
I. Идентификация хоста и времени
hostnamectl hostname br-rtr.$domain timedatectl set-timezone Europe/Moscow
II. Включение маршрутизации (IP Forwarding)
cd /etc/net/ sed -i 's/net.ipv4.ip_forward = 0/net.ipv4.ip_forward = 1/g' sysctl.conf cd ifaces/
III. Подготовка шаблонов интерфейсов
\cp -R $int_name_default_gateway $int_name_br_fw \cp -R $int_name_default_gateway gre10
IV. Настройка IPv4-адресов и маршрутов
cat << EOF > /etc/net/ifaces/$int_name_default_gateway/options BOOTPROTO=static TYPE=eth CONFIG_WIRELESS=no SYSTEMD_BOOTPROTO=static CONFIG_IPv4=yes DISABLED=no NM_CONTROLLED=no SYSTEMD_CONTROLLED=no EOF cat << EOF > /etc/net/ifaces/$int_name_br_fw/options BOOTPROTO=static TYPE=eth CONFIG_WIRELESS=no SYSTEMD_BOOTPROTO=static CONFIG_IPv4=yes DISABLED=no NM_CONTROLLED=no SYSTEMD_CONTROLLED=no EOF cat << EOF > /etc/net/ifaces/gre10/options BOOTPROTO=static SYSTEMD_BOOTPROTO=static TYPE=iptun TUNTYPE=gre CONFIG_WIRELESS=no CONFIG_IPv4=yes DISABLED=no NM_CONTROLLED=no SYSTEMD_CONTROLLED=no TUNLOCAL=$ip_isp TUNREMOTE=$ip_hq_rtr TUNTTL=32 TUNOPTIONS='ttl 32' EOF echo "$ip_isp/$mask_isp" > $int_name_default_gateway/ipv4address echo "default via $ip_gateway" > $int_name_default_gateway/ipv4route echo "$ip_to_br_fw/$mask_to_br_fw" > $int_name_br_fw/ipv4address echo "10.0.0.2/30" > gre10/ipv4address
V. Настраиваем временный DNS-резолвер
echo "nameserver 77.88.8.8" > /etc/resolv.conf echo "nameserver 77.88.8.8" > /etc/net/ifaces/$int_name_default_gateway/resolv.conf
VI. Установка и настройка динамической маршрутизации (FRR / OSPF), nano и iptables
systemctl restart network apt-get update apt-get install -y frr apt-get install -y sudo apt-get install -y nano apt-get install -y iptables sed -i 's/ospfd=no/ospfd=yes/g' /etc/frr/daemons systemctl enable --now frr
VII. Создание пользователей
useradd -m $username echo "$username:$userpassword" | chpasswd usermod -aG wheel $username echo "$username ALL=(ALL:ALL) NOPASSWD: ALL" >> /etc/sudoers
VIII. Настройка DNS-резолвера
cat << EOF > /etc/resolv.conf nameserver $ip_hq_srv search $domain domain $domain EOF cat << EOF > /etc/net/ifaces/$int_name_default_gateway/resolv.conf nameserver $ip_hq_srv search $domain domain $domain EOF
IX. Настройка NAT
iptables -t nat -A POSTROUTING -o $int_name_default_gateway -j MASQUERADE iptables-save -f /etc/sysconfig/iptables systemctl enable --now iptables.service
X. Применяем сетевые настройки
systemctl restart network
XI. Конфигурация OSPF через vtysh
Внутри vtysh переменные bash не работают — все значения вписаны буквально. Имя интерфейса к BR-FW — из переменной int_name_br_fw.
vtysh conf t interface gre10 ip ospf network point-to-point ip ospf message-digest-key 1 md5 Mgr@P@ss88 ip ospf authentication message-digest no ip ospf passive exit interface enp7s2 no ip ospf passive exit ! router ospf passive-interface default network 10.0.0.0/30 area 0 network 192.168.3.0/30 area 0 exit exit wr exit exec bash
Сервер площадки A
Сервер площадки A: выполняет роль внутреннего DNS-сервера (dnsmasq) для домена сети и настроен на защищённый SSH-доступ.
0. Подготовка переменных
ssh_username="srv_user" ssh_uid="2200" ssh_userpassword="Srv@P@ss456" ssh_port="2030" int_to_hq_rtr="enp7s1" ip_to_hq_rtr="192.168.110.2" mask_hq_srv="26" ip_default_gateway="192.168.110.1" domain="linux-skills.irpo" # Публикуемые имена на ISP по таблице задания: docker → интерфейс ISP к HQ-RTR, # web → интерфейс ISP к BR-RTR (легко перепутать — сверяйтесь с таблицей DNS) name_isp_hq="docker" ip_isp_hq="172.20.1.1" name_isp_br="web" ip_isp_br="172.20.2.1" # HQ-RTR (адрес в VLAN серверов = ip_default_gateway) ip_hq_rtr_to_isp="172.20.1.2" ip_hq_rtr_to_hq_cli="192.168.120.1" ip_hq_rtr_to_remote="192.168.88.1" ip_hq_cli="192.168.120.2" # BR-RTR, BR-FW, BR-SRV — значения из разделов маршрутизатора и межсетевого экрана площадки B ip_br_rtr_isp="172.20.2.2" ip_br_rtr_fw="192.168.3.1" ip_br_fw_rtr="192.168.3.2" ip_br_fw_srv="192.168.4.1" ip_br_srv="192.168.4.2"
I. Идентификация хоста и времени
hostnamectl hostname hq-srv.$domain timedatectl set-timezone Europe/Moscow
II. Настройка сетевого интерфейса и DNS-резолвера
cd /etc/net/ifaces/ cat << EOF > /etc/net/ifaces/$int_to_hq_rtr/options BOOTPROTO=static TYPE=eth CONFIG_WIRELESS=no SYSTEMD_BOOTPROTO=static CONFIG_IPv4=yes DISABLED=no NM_CONTROLLED=no SYSTEMD_CONTROLLED=no EOF echo "$ip_to_hq_rtr/$mask_hq_srv" > $int_to_hq_rtr/ipv4address echo "default via $ip_default_gateway" > $int_to_hq_rtr/ipv4route echo "nameserver 77.88.8.8" > /etc/resolv.conf echo "nameserver 77.88.8.8" > /etc/net/ifaces/$int_to_hq_rtr/resolv.conf systemctl restart network
III. Установка + создание всего конфига dnsmasq
apt-get update apt-get install -y sudo apt-get install -y nano apt-get install -y openssh-server apt-get install -y dnsmasq apt-get install -y iptables cat << EOF > /etc/dnsmasq.conf no-hosts no-resolv server=77.88.8.8 cache-size=1000 no-negcache interface=* domain=$domain local=/$domain/ host-record=$name_isp_hq.$domain,$ip_isp_hq host-record=$name_isp_br.$domain,$ip_isp_br host-record=hq-rtr.$domain,$ip_hq_rtr_to_isp host-record=hq-rtr.$domain,$ip_default_gateway host-record=hq-rtr.$domain,$ip_hq_rtr_to_hq_cli host-record=hq-rtr.$domain,$ip_hq_rtr_to_remote host-record=hq-srv.$domain,$ip_to_hq_rtr host-record=hq-cli.$domain,$ip_hq_cli host-record=br-rtr.$domain,$ip_br_rtr_isp host-record=br-rtr.$domain,$ip_br_rtr_fw host-record=br-fw.$domain,$ip_br_fw_rtr host-record=br-fw.$domain,$ip_br_fw_srv host-record=br-srv.$domain,$ip_br_srv EOF dnsmasq --test
IV. Настройка безопасного SSH-доступа
useradd $ssh_username -m -u $ssh_uid echo "$ssh_username:$ssh_userpassword" | chpasswd gpasswd -a $ssh_username wheel echo "$ssh_username ALL=(ALL:ALL) NOPASSWD: ALL" >> /etc/sudoers cat << EOF >> /etc/openssh/sshd_config port $ssh_port MaxAuthTries 2 AllowUsers $ssh_username Banner /etc/openssh/banner EOF cat << EOF > /etc/openssh/banner ................................ ... Authorized access only ... ................................ EOF sshd -t systemctl enable --now sshd systemctl restart sshd
V (опционально). Поиск конфликтных процессов, использующих 53 порт
ss -tlpn | grep :53
VI. Добавляем службу в автозапуск
systemctl enable --now dnsmasq.service
VII (опционально). Убиваем процесс, который использует 53 порт
kill <PID из вывода ss>
VIII. Смотрим статус службы dnsmasq
systemctl status dnsmasq
IX. Синхронизация часового пояса (доп. проверка)
timedatectl set-timezone Europe/Moscow timedatectl exec bash
Сервер площадки B
Сервер площадки B: базовая сетевая настройка и защищённый SSH-доступ.
0. Подготовка переменных
domain="linux-skills.irpo" ssh_username="srv_user" ssh_uid="2200" ssh_userpassword="Srv@P@ss456" ssh_port="2030" # Сеть BR-NET и шлюз — те же, что net_br / ip_fw_to_srv в разделе BR-FW int_br_srv="enp7s1" ip_br_srv="192.168.4.2" mask_br_srv="28" ip_default_gateway="192.168.4.1" ip_hq_srv="192.168.110.2"
I. Идентификация хоста и времени
hostnamectl hostname br-srv.$domain timedatectl set-timezone Europe/Moscow
II. Настройка сетевого интерфейса и DNS-резолвера
cd /etc/net/ifaces/ cat << EOF > /etc/net/ifaces/$int_br_srv/options BOOTPROTO=static TYPE=eth CONFIG_WIRELESS=no SYSTEMD_BOOTPROTO=static CONFIG_IPv4=yes DISABLED=no NM_CONTROLLED=no SYSTEMD_CONTROLLED=no EOF echo "$ip_br_srv/$mask_br_srv" > $int_br_srv/ipv4address echo "default via $ip_default_gateway" > $int_br_srv/ipv4route cat << EOF > /etc/resolv.conf nameserver $ip_hq_srv search $domain domain $domain EOF cat << EOF > /etc/net/ifaces/$int_br_srv/resolv.conf nameserver $ip_hq_srv search $domain domain $domain EOF systemctl restart network
III. Настройка безопасного SSH-доступа
useradd $ssh_username -m -u $ssh_uid echo "$ssh_username:$ssh_userpassword" | chpasswd gpasswd -a $ssh_username wheel echo "$ssh_username ALL=(ALL:ALL) NOPASSWD: ALL" >> /etc/sudoers cat << EOF >> /etc/openssh/sshd_config port $ssh_port MaxAuthTries 2 AllowUsers $ssh_username Banner /etc/openssh/banner EOF cat << EOF > /etc/openssh/banner ................................ ... Authorized access only ... ................................ EOF sshd -t systemctl enable --now sshd systemctl restart sshd exec bash
1-й этап. Диагностика и проверка конфигурации
Блок 0. Сквозной smoke-тест и MTU
Базовая проверка доступности узлов от самой дальней точки (br-srv) до целевых серверов строго по IP. Тест MTU ловит «чёрные дыры» фрагментации в GRE-туннеле.
# Последовательный пинг от br-srv (самая дальняя точка): ping -c2 192.168.4.1 # свой шлюз (br-fw) ping -c2 192.168.3.1 # br-rtr со стороны br-fw ping -c2 10.0.0.1 # дальний конец туннеля (hq-rtr) ping -c2 192.168.110.1 # шлюз серверной VLAN на HQ ping -c2 192.168.110.2 # hq-srv — цель # Проверка MTU через туннель (GRE съедает 24 байта: MTU gre10 = 1476): ping -M do -s 1448 -c2 192.168.110.2 # 1448+28=1476 — ДОЛЖНО пройти ping -M do -s 1472 -c2 192.168.110.2 # 1472+28=1500 — ДОЛЖНО НЕ пройти (Frag needed)
Блок 1. Граничный маршрутизатор (ISP) — NAT и форвардинг
ip -br a # enp7s1 — адрес от DHCP; enp7s2 172.20.1.1/28; enp7s3 172.20.2.1/28; все UP iptables -t nat -nvL POSTROUTING # MASQUERADE на out enp7s1, счётчики растут cat /proc/sys/net/ipv4/ip_forward # 1 (в рантайме) grep ip_forward /etc/net/sysctl.conf # = 1, без # (постоянность!)
Блок 2. Маршрутизатор площадки A (hq-rtr) — VLAN
cat /etc/net/ifaces/enp7s2.110/options cat /etc/net/ifaces/enp7s2.110/ipv4address cat /etc/net/ifaces/enp7s2.120/options cat /etc/net/ifaces/enp7s2.120/ipv4address cat /etc/net/ifaces/enp7s2.888/options cat /etc/net/ifaces/enp7s2.888/ipv4address
Блок 3. Маршрутизатор площадки B (br-rtr) — GRE и OSPF
cat /etc/net/ifaces/gre10/options cat /etc/net/ifaces/gre10/ipv4address vtysh -c "show ip route ospf"
Блок 4. DHCP-сервер (hq-rtr, VLAN 120)
dhcpd -t # Проверка синтаксиса dhcpd.conf systemctl status dhcpd # active (running) grep DHCPDARGS /etc/sysconfig/dhcpd # DHCPDARGS=enp7s2.120 (привязка к VLAN!) journalctl -u dhcpd --no-pager -n 30 # DHCPDISCOVER/OFFER/ACK при запросах
Блок 5. DNS-сервер (hq-srv) — dnsmasq
dnsmasq --test # Проверка синтаксиса dnsmasq.conf systemctl status dnsmasq # active (running) ss -tulpn | grep :53 # dnsmasq слушает 53 (udp и tcp) # Прямые записи домена: nslookup hq-rtr.linux-skills.irpo 127.0.0.1 # 192.168.110.1 (и остальные адреса hq-rtr) nslookup br-srv.linux-skills.irpo 127.0.0.1 # 192.168.4.2 nslookup hq-cli.linux-skills.irpo 127.0.0.1 # 192.168.120.2 # Обратные записи (PTR обязательны для hq-srv и br-srv): nslookup 192.168.110.2 127.0.0.1 # hq-srv.linux-skills.irpo nslookup 192.168.4.2 127.0.0.1 # br-srv.linux-skills.irpo # Форвардинг наружу: nslookup ya.ru 127.0.0.1 # пересылка на 77.88.8.8 работает
Блок 6. SSH и безопасность (Hardening)
sshd -t # Проверка синтаксиса sshd_config grep -E "^port|MaxAuthTries|AllowUsers|Banner" /etc/openssh/sshd_config # Ожидаемо: port 2030 / MaxAuthTries 2 / AllowUsers srv_user / Banner /etc/openssh/banner systemctl status sshd # active ss -tlpn | grep 2030 # слушает 2030 # Тест входа с клиента: ssh -p 2030 srv_user@192.168.110.2 # должен показать баннер и запросить пароль
Блок 7. Сквозные «грабли» и постоянность настроек
# MSS-клампинг (ловит "зависание" TCP при работающем пинге) iptables -t mangle -nvL FORWARD | grep TCPMSS # Проверка синтаксиса сохранённых правил iptables (перед загрузкой/рестартом) iptables-restore --test < /etc/sysconfig/iptables # Постоянность форвардинга на всех роутерах grep ip_forward /etc/net/sysctl.conf # = 1, без # # Постоянность resolv.conf на роутерах (защита от затирания etcnet) ls /etc/net/ifaces/enp7s1/resolv.conf # должен существовать # Reverse Path Filtering sysctl net.ipv4.conf.all.rp_filter # 0 или 2 — ок; 1 (strict) может резать асимметрию
НАСТРОЙКА RIP (запасной вариант вместо OSPF, без скачивания пакетов)
В FRR нет отдельных юнитов zebra/ripd — демон включается в /etc/frr/daemons, после чего перезапускается служба frr. Сети впишите свои (пример для hq-rtr).
sed -i 's/ripd=no/ripd=yes/' /etc/frr/daemons systemctl enable --now frr systemctl restart frr vtysh configure terminal router rip version 2 network 10.0.0.0/30 network 192.168.110.0/26 network 192.168.120.0/24 network 192.168.88.0/28 passive-interface default no passive-interface gre10 exit exit write memory exit
ОСНОВНЫЕ ПАРАМЕТРЫ
доменное имя - linux-skills.irpo доменное имя isp (hq-rtr) - web доменное имя isp (br-rtr) - docker сеть hq-rtr - 172.20.1.0/28 сеть br-rtr - 172.20.2.0/28 в сторону hq-srv (vlan 110) 192.168.110.0/26 в сторону hq-cli (vlan 120) 192.168.120.0/24 в сторону просто vlan (vlan 888) 192.168.88.0/28 GRE hq-rtr — br-rtr 10.0.0.0/30 стык br-rtr — br-fw 192.168.3.0/30 в сторону br-srv (за br-fw) 192.168.4.0/28 пользователь rtr - net_mgr пароль rtr - Mgr@P@ss88 пользователь ssh - srv_user uid пользователя ssh - 2200 пароль ssh - Srv@P@ss456 порт ssh - 2030
2-й этап. Организация сетевого администрирования
Контроллер домена Samba, файловое хранилище RAID0 и NFS, служба точного времени, Ansible, контейнеризованное приложение, веб-сервер с базой данных и статическая трансляция портов.
ISP — служба точного времени
ISP выступает сервером времени для обеих площадок и объявляет себя как stratum 5.
0. Подготовка переменных
Объявите переменные в сессии этого узла перед выполнением остальных команд. Они живут только в текущей оболочке: после bash, su, exit или переподключения по SSH объявите их заново — проверить можно командой echo с именем любой переменной.
# Служба точного времени ntp_upstream="pool.ntp.org" ntp_stratum="5"
I. Установка и настройка chrony
Директива local stratum позволяет раздавать время даже при недоступности вышестоящего источника.
apt-get update && apt-get install -y chrony apt-get install -y iptables cat <<EOF > /etc/chrony.conf server $ntp_upstream iburst prefer minstratum 4 local stratum $ntp_stratum allow 0.0.0.0/0 EOF systemctl enable --now chronyd systemctl restart chronyd
II. Проверка источников
chronyc sources -v chronyc tracking
HQ-RTR — статическая трансляция портов
Публикация веб-приложения и SSH сервера HQ-SRV на внешнем адресе маршрутизатора.
0. Подготовка переменных
Объявите переменные в сессии этого узла перед выполнением остальных команд. Они живут только в текущей оболочке: после bash, su, exit или переподключения по SSH объявите их заново — проверить можно командой echo с именем любой переменной.
# Внешний адрес самого маршрутизатора ip_hq_rtr="172.16.1.10" # Публикуемый узел ip_hq_srv="192.168.1.10" # Порты app_port="8080" web_port="80" ssh_port="2027" # Маршрут до локальной сети площадки B через GRE net_br="192.168.4.0/28" ip_gre_br="192.168.5.2" int_gre="gre1"
I. Установка пакетов
apt-get update && apt-get install -y iptables apt-get install -y openssh-server # SSH для Ansible с BR-SRV (порт 22, пользователь net_admin) systemctl enable --now sshd ss -tlpn | grep sshd
II. Маршрут до локальной сети площадки B
Сеть за межсетевым экраном достижима через GRE-туннель. ip route replace не падает, если маршрут уже есть; запись в ipv4route сохраняет его после перезагрузки.
ip route replace $net_br via $ip_gre_br rt=/etc/net/ifaces/$int_gre/ipv4route grep -qs "^$net_br via $ip_gre_br" $rt \ || echo "$net_br via $ip_gre_br" >> $rt ip route | grep "$net_br"
III. Проброс портов на HQ-SRV
Цепочка PREROUTING подменяет адрес назначения до маршрутизации: обращение на внешний адрес маршрутизатора уходит внутрь сети.
# -C проверяет, есть ли правило — повторный запуск блока не создаст дубликатов for p in "$app_port $ip_hq_srv:$web_port" "$ssh_port $ip_hq_srv:$ssh_port"; do set -- $p iptables -t nat -C PREROUTING -d $ip_hq_rtr -p tcp --dport $1 -j DNAT --to-destination $2 2>/dev/null || \ iptables -t nat -A PREROUTING -d $ip_hq_rtr -p tcp --dport $1 -j DNAT --to-destination $2 done
IV. Разрешение транзита
Нужно, если политика цепочки FORWARD не ACCEPT. Правило пропускает уже отслеженные соединения и новые обращения к опубликованным портам.
iptables -C FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT 2>/dev/null || \ iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -C FORWARD -d $ip_hq_srv -p tcp -m multiport --dports $web_port,$ssh_port -j ACCEPT 2>/dev/null || \ iptables -A FORWARD -d $ip_hq_srv -p tcp -m multiport --dports $web_port,$ssh_port -j ACCEPT
V. Сохранение правил
Без записи в /etc/sysconfig/iptables правила исчезнут после перезагрузки.
iptables-save -f /etc/sysconfig/iptables systemctl enable --now iptables.service
VI. Проверка
iptables -t nat -nvL PREROUTING
BR-RTR — клиент NTP и статическая трансляция портов
Синхронизация времени с ISP и публикация контейнеризованного приложения BR-SRV.
0. Подготовка переменных
Объявите переменные в сессии этого узла перед выполнением остальных команд. Они живут только в текущей оболочке: после bash, su, exit или переподключения по SSH объявите их заново — проверить можно командой echo с именем любой переменной.
# Внешний адрес самого маршрутизатора ip_br_rtr="172.16.2.10" # Публикуемый узел ip_br_srv="192.168.4.2" # Служба точного времени ip_ntp_br="172.16.2.1" # Порты app_port="8080" ssh_port="2027" # Маршрут до локальной сети площадки B через межсетевой экран (стык /30) net_br="192.168.4.0/28" ip_fw_to_rtr="192.168.3.2" ip_to_fw="192.168.3.1" mask_br_rtr_to_fw="30" int_to_fw="enp7s2"
I. Клиент службы точного времени
echo "$ip_to_fw/$mask_br_rtr_to_fw" > /etc/net/ifaces/$int_to_fw/ipv4address systemctl restart network apt-get update && apt-get install -y chrony apt-get install -y iptables apt-get install -y openssh-server # SSH для Ansible с BR-SRV (порт 22, пользователь net_admin) systemctl enable --now sshd ss -tlpn | grep sshd grep -q "^server $ip_ntp_br " /etc/chrony.conf || echo \ "server $ip_ntp_br iburst" >> /etc/chrony.conf systemctl enable --now chronyd systemctl restart chronyd chronyc sources -v
II. Маршрут до локальной сети площадки B
Сеть сервера лежит за межсетевым экраном. Статический маршрут передаётся в OSPF через redistribute static — так о нём узнает и площадка A.
ip route replace $net_br via $ip_fw_to_rtr rt=/etc/net/ifaces/$int_to_fw/ipv4route grep -qs "^$net_br via $ip_fw_to_rtr" $rt \ || echo "$net_br via $ip_fw_to_rtr" >> $rt ping -c 2 $ip_br_srv vtysh <<EOF configure terminal router ospf redistribute static exit end write memory EOF
III. Проброс портов на BR-SRV
Контейнеризованное приложение и SSH публикуются на внешнем адресе маршрутизатора без смены номеров портов.
# -C проверяет, есть ли правило — повторный запуск блока не создаст дубликатов for p in "$app_port $ip_br_srv:$app_port" "$ssh_port $ip_br_srv:$ssh_port"; do set -- $p iptables -t nat -C PREROUTING -d $ip_br_rtr -p tcp --dport $1 -j DNAT --to-destination $2 2>/dev/null || \ iptables -t nat -A PREROUTING -d $ip_br_rtr -p tcp --dport $1 -j DNAT --to-destination $2 done
IV. Разрешение транзита
iptables -C FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT 2>/dev/null || \ iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -C FORWARD -d $ip_br_srv -p tcp -m multiport --dports $app_port,$ssh_port -j ACCEPT 2>/dev/null || \ iptables -A FORWARD -d $ip_br_srv -p tcp -m multiport --dports $app_port,$ssh_port -j ACCEPT
V. Сохранение правил
iptables-save -f /etc/sysconfig/iptables systemctl enable --now iptables.service
VI. Проверка
iptables -t nat -nvL PREROUTING
HQ-SRV — RAID0, NFS, Apache и MariaDB
Файловое хранилище из двух дисков, сетевой ресурс для рабочей станции и веб-приложение с базой данных.
0. Подготовка переменных
Объявите переменные в сессии этого узла перед выполнением остальных команд. Они живут только в текущей оболочке: после bash, su, exit или переподключения по SSH объявите их заново — проверить можно командой echo с именем любой переменной.
# Служба точного времени ip_ntp_hq="172.16.1.1" # Файловое хранилище raid_dev="/dev/md0" raid_disk1="/dev/sdb" raid_disk2="/dev/sdc" raid_mount="/raid" nfs_share="/raid/nfs" net_hq_cli="192.168.2.0/28" # База данных веб-приложения db_name="webdb" db_user="web" db_password="P@ssw0rd"
I. Установка пакетов и синхронизация времени
# Версию PHP уточните: apt-cache search apache2-mod_php apt-get update && apt-get install -y mdadm apt-get install -y nfs-server apt-get install -y nfs-utils apt-get install -y apache2 apt-get install -y apache2-mod_php8.2 apt-get install -y php8.2-mysqli apt-get install -y mariadb-server apt-get install -y chrony apt-get install -y iptables apt-get install -y openssh-server # SSH для Ansible с BR-SRV: порт 2027, как в задании (в готовом 1-м модуле может стоять другой) grep -q "^Port $ssh_port\$" /etc/openssh/sshd_config || \ sed -i "s/^#\?Port .*/Port $ssh_port/" /etc/openssh/sshd_config sshd -t && systemctl enable --now sshd && systemctl restart sshd ss -tlpn | grep sshd grep -q "^server $ip_ntp_hq " /etc/chrony.conf || echo \ "server $ip_ntp_hq iburst" >> /etc/chrony.conf systemctl enable --now chronyd systemctl restart chronyd
II. Сборка массива RAID0
Уровень 0 объединяет ёмкость обоих дисков без избыточности; запись в mdadm.conf нужна, чтобы массив собирался после перезагрузки.
mdadm --create $raid_dev --level=0 --raid-devices=2 $raid_disk1 $raid_disk2 mdadm --detail --scan --verbose >> /etc/mdadm.conf mkfs.ext4 -F $raid_dev mkdir -p $raid_mount grep -q "^$raid_dev " /etc/fstab || echo \ "$raid_dev $raid_mount ext4 defaults 0 0" >> /etc/fstab mount -av cat /proc/mdstat
III. Настройка сетевого ресурса NFS
Экспорт ограничен подсетью рабочей станции.
mkdir -p $nfs_share chmod 0777 $nfs_share cat <<EOF > /etc/exports $nfs_share $net_hq_cli(rw,no_root_squash) EOF systemctl enable --now nfs-server exportfs -rav
IV. Развёртывание веб-приложения
Файлы берутся с подключённого установочного образа с дополнительными материалами.
mount /dev/sr0 /mnt 2>/dev/null || true \cp -f /mnt/web/index.php /var/www/html/ \cp -f /mnt/web/logo.png /var/www/html/ \rm -f /var/www/html/index.html # Учётные данные БД в index.php должны совпадать с db_name / db_user / db_password grep -n -i -E "host|user|pass|dbname|database" /var/www/html/index.php | head nano /var/www/html/index.php
V. Запуск MariaDB и создание базы
Первый запуск инициализирует каталог данных: команда systemctl возвращает управление раньше, чем сервер поднимет сокет, поэтому следующий блок должен дождаться готовности. ALTER USER стоит отдельной строкой потому, что CREATE USER IF NOT EXISTS у существующего пользователя молча оставляет старый пароль.
systemctl enable --now mariadb for i in $(seq 30); do mariadb -e "SELECT 1" >/dev/null 2>&1 && break sleep 1 done mariadb -e "SELECT VERSION();" mariadb <<EOF CREATE DATABASE IF NOT EXISTS $db_name; CREATE USER IF NOT EXISTS '$db_user'@'localhost'; ALTER USER '$db_user'@'localhost' IDENTIFIED BY '$db_password'; GRANT ALL PRIVILEGES ON $db_name.* TO '$db_user'@'localhost'; FLUSH PRIVILEGES; EOF mariadb -e "SHOW GRANTS FOR '$db_user'@'localhost';"
VI. Импорт дампа
Кодировку дампа определяем, а не угадываем: безусловный iconv превращает обычный ASCII-файл в нечитаемые символы, причём без ошибки — и импорт падает на первой строке.
\cp -f /mnt/web/dump.sql /root/dump.sql file -b --mime-encoding /root/dump.sql if file -b --mime-encoding /root/dump.sql | grep -q utf-16; then iconv -f UTF-16 -t UTF-8 /root/dump.sql -o /root/dump_ready.sql else \cp -f /root/dump.sql /root/dump_ready.sql fi head -1 /root/dump_ready.sql mariadb $db_name < /root/dump_ready.sql mariadb -e "USE $db_name; SHOW TABLES;"
VII. Запуск веб-сервера
Проверка под учётной записью приложения важнее проверки под root: именно этим путём пойдёт index.php.
systemctl enable --now httpd2
systemctl is-active httpd2
mariadb -u $db_user -p"$db_password" $db_name -e "SHOW TABLES;"
curl -s -o /dev/null -w "%{http_code}\n" http://localhost/
BR-SRV — Samba DC, Ansible и Docker
Контроллер домена, узел управления конфигурацией и хост контейнеризованного приложения.
0. Подготовка переменных
Объявите переменные в сессии этого узла перед выполнением остальных команд. Они живут только в текущей оболочке: после bash, su, exit или переподключения по SSH объявите их заново — проверить можно командой echo с именем любой переменной.
# Домен realm="AU-TEAM.IRPO" netbios="AU-TEAM" admin_password="P@ssw0rd" # Доменная группа и пользователи domain_group="hq" domain_user_prefix="hquser" domain_user_count="5" domain_user_password="P@ssw0rd" # Узлы для инвентаря Ansible ip_hq_srv="192.168.1.10" ip_hq_cli="192.168.2.10" ip_hq_rtr="172.16.1.10" ip_br_rtr="172.16.2.10" # Доступ к узлам (на серверах SSH на порту 2027 по заданию 1-го этапа) ssh_user="sshuser" ssh_password="P@ssw0rd" ssh_port="2027" cli_user="user" cli_password="resu" # Служба точного времени ip_ntp_br="172.16.2.1" # Контейнеризованное приложение app_dir="/opt/testapp"
I. Установка пакетов
apt-get update && apt-get install -y task-samba-dc apt-get install -y ansible apt-get install -y sshpass apt-get install -y python3-module-pip apt-get install -y docker-engine apt-get install -y docker-compose-v2 apt-get install -y chrony apt-get install -y iptables
II. Развёртывание контроллера домена
Проверка перед provision защищает от повторного развёртывания уже поднятого домена.
if ! samba-tool domain info 127.0.0.1 >/dev/null 2>&1; then
\rm -f /etc/samba/smb.conf
\rm -rf /var/lib/samba /var/cache/samba
mkdir -p /var/lib/samba/sysvol
samba-tool domain provision --realm=$realm --domain=$netbios \
--server-role=dc --dns-backend=SAMBA_INTERNAL \
--option="dns forwarder=$ip_hq_srv" \
--adminpass="$admin_password"
fi
\cp -f /var/lib/samba/private/krb5.conf /etc/krb5.conf
systemctl enable --now samba
III. Политика паролей и блокировки
Опция сброса счётчика называется --reset-account-lockout-after: варианта со словом counter в samba-tool нет. Вывод show показывает применённые значения.
samba-tool domain passwordsettings set --min-pwd-length=8 samba-tool domain passwordsettings set --account-lockout-threshold=5 samba-tool domain passwordsettings set --account-lockout-duration=30 samba-tool domain passwordsettings set --reset-account-lockout-after=30 samba-tool domain passwordsettings show
IV. Создание группы и пользователей
samba-tool group add $domain_group 2>/dev/null || true
for i in $(seq 1 $domain_user_count); do
samba-tool user add $domain_user_prefix$i "$domain_user_password" \
2>/dev/null || true
samba-tool user setexpiry $domain_user_prefix$i --noexpiry
samba-tool group addmembers $domain_group $domain_user_prefix$i
done
samba-tool group listmembers $domain_group
V. Настройка Ansible
host_key_checking отключается, иначе первый запуск падает на запросе подтверждения ключа. Вход по паролю обеспечивает sshpass из репозитория — дополнительных транспортов ставить не нужно. На HQ-RTR, BR-RTR и HQ-CLI должен быть запущен sshd на порту 22 (systemctl enable --now sshd), на HQ-SRV — на порту 2027 из 1-го этапа.
mkdir -p /etc/ansible cat <<EOF > /etc/ansible/hosts [servers] HQ-SRV ansible_host=$ip_hq_srv [clients] HQ-CLI ansible_host=$ip_hq_cli [routers] HQ-RTR ansible_host=$ip_hq_rtr BR-RTR ansible_host=$ip_br_rtr [servers:vars] ansible_user=$ssh_user ansible_password=$ssh_password ansible_port=$ssh_port [clients:vars] ansible_user=$cli_user ansible_password=$cli_password [routers:vars] ansible_user=net_admin ansible_password=$admin_password [all:vars] ansible_python_interpreter=/usr/bin/python3 EOF cat <<EOF > /etc/ansible/ansible.cfg [defaults] inventory = /etc/ansible/hosts host_key_checking = False EOF # На hq-cli, hq-rtr и br-rtr предварительно: systemctl enable --now sshd cd /etc/ansible && ansible all -m ping
VI. Синхронизация времени
grep -q "^server $ip_ntp_br " /etc/chrony.conf || echo \ "server $ip_ntp_br iburst" >> /etc/chrony.conf systemctl enable --now chronyd systemctl restart chronyd
VII. Развёртывание testapp в Docker
Образы загружаются из архивов на установочном образе. По заданию используется готовый compose.yaml с образа: перед запуском проверьте в нём имена образов (должны совпадать с выводом docker images), что учётные данные БД у сервиса db и у приложения одинаковые и что приложение публикуется на 8080. Свой файл ниже — запасной вариант, если на образе compose.yaml нет.
systemctl enable --now docker.service
mount /dev/sr0 /mnt 2>/dev/null || true
docker load < /mnt/docker/site_latest.tar
docker load < /mnt/docker/mariadb_latest.tar
docker images # тег mariadb может быть 10.11, а не latest — в compose должен быть именно он, иначе docker полезет в интернет
# Где на образе compose-файл (имя и каталог могут отличаться)
compose_src=$(find /mnt -iname '*compose*.y*ml' | head -1)
echo "compose=$compose_src"
mkdir -p $app_dir
\cp -f "$compose_src" $app_dir/compose.yaml
cat $app_dir/compose.yaml
cd $app_dir && docker compose -f compose.yaml up -d
docker ps
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8080/
VII-б (запасной). Собственный compose.yaml
Только если файла на образе нет. Интернета до docker hub нет, поэтому имена образов в compose должны точно совпадать с docker images — для этого загруженной mariadb добавляется тег latest. Кавычки у EOF обязательны — символы $ в пароле bash трогать не должен (путь поэтому задаём cd). Переменные окружения приложения должны совпадать с настройками db.
mdb_tag=$(docker images mariadb --format '{{.Tag}}' | head -1)
docker tag mariadb:$mdb_tag mariadb:latest
docker images
mkdir -p $app_dir && cd $app_dir
cat <<'EOF' > compose.yaml
services:
db:
image: mariadb:latest
container_name: testapp_db
restart: unless-stopped
environment:
MARIADB_DATABASE: db
MARIADB_USER: web
MARIADB_PASSWORD: P@ssw0rd
MARIADB_RANDOM_ROOT_PASSWORD: "yes"
volumes:
- db_data:/var/lib/mysql
networks:
- testapp_net
site:
image: site:latest
container_name: testapp_site
restart: unless-stopped
depends_on:
- db
environment:
DB_TYPE: maria
DB_HOST: db
DB_NAME: db
DB_PORT: "3306"
DB_USER: web
DB_PASS: P@ssw0rd
ports:
- "8080:8000" # снаружи 8080, внутри контейнера uvicorn слушает 8000 (см. docker logs)
networks:
- testapp_net
volumes:
db_data:
networks:
testapp_net:
EOF
cd $app_dir && docker compose -f compose.yaml up -d
docker ps
HQ-CLI — ввод в домен, NFS и браузер
Рабочая станция вводится в домен, монтирует сетевой ресурс и получает ограниченные права sudo для доменной группы.
0. Подготовка переменных
Объявите переменные в сессии этого узла перед выполнением остальных команд. Они живут только в текущей оболочке: после bash, su, exit или переподключения по SSH объявите их заново — проверить можно командой echo с именем любой переменной.
# Домен domain="au-team.irpo" netbios="AU-TEAM" admin_password="P@ssw0rd" # Адреса узлов ip_br_srv="192.168.4.2" ip_hq_srv="192.168.1.10" ip_ntp_hq="172.16.1.1" # Доменная группа и пользователи domain_group="hq" domain_user_prefix="hquser" # Сетевой ресурс nfs_share="/raid/nfs" nfs_mount="/mnt/nfs"
I. Переключение резолвера на контроллер домена
Ввод в домен требует, чтобы DNS отвечал контроллер — BR-SRV (он пересылает остальные запросы на HQ-SRV). Адрес HQ-CLI получает по DHCP, поэтому файл пишется и в каталог интерфейса — иначе etcnet перезапишет его значениями от DHCP.
int_cli=$(ip -br link | awk '$1!="lo"{print $1; exit}')
cat <<EOF > /etc/resolv.conf
search $domain
nameserver $ip_br_srv
EOF
cat <<EOF > /etc/net/ifaces/$int_cli/resolv.conf
search $domain
nameserver $ip_br_srv
EOF
host -t SRV _ldap._tcp.$domain
II. Установка пакетов и синхронизация времени
Расхождение часов с контроллером домена ломает Kerberos, поэтому chrony ставится до ввода в домен.
apt-get update && apt-get install -y task-auth-ad-sssd apt-get install -y libnss-role apt-get install -y nfs-utils apt-get install -y nfs-clients apt-get install -y yandex-browser-stable apt-get install -y chrony apt-get install -y iptables apt-get install -y openssh-server # SSH для Ansible с BR-SRV (порт 22, локальный пользователь user) systemctl enable --now sshd ss -tlpn | grep sshd grep -q "^server $ip_ntp_hq " /etc/chrony.conf || echo \ "server $ip_ntp_hq iburst" >> /etc/chrony.conf systemctl enable --now chronyd systemctl restart chronyd
III. Ввод в домен
После ввода проверьте, что доменные учётные записи разрешаются командой id.
system-auth write ad $domain $(hostname -s) $netbios 'administrator' \
"$admin_password"
id ${domain_user_prefix}1@$domain
IV. Ограниченные права sudo для доменной группы
Членам группы разрешены только перечисленные в Cmnd_Alias команды. Группу нельзя добавлять в wheel (roleadd hq wheel) — это дало бы полный sudo. Пути к командам берём с самой машины. Проверка visudo обязательна: ошибка в sudoers лишает доступа всех.
control sudo public
cat <<EOF > /etc/sudoers.d/$domain_group
Cmnd_Alias HQ_LIMITED = $(command -v cat), $(command -v grep), $(command -v id)
%$domain_group ALL=(ALL:ALL) HQ_LIMITED
EOF
chmod 440 /etc/sudoers.d/$domain_group
visudo -c
# Проверка под доменным пользователем: sudo id — работает, sudo ls — отказ
su - ${domain_user_prefix}1@$domain -c 'sudo -l'
V. Автомонтирование сетевого ресурса
mkdir -p $nfs_mount grep -q "$ip_hq_srv:$nfs_share" /etc/fstab || echo \ "$ip_hq_srv:$nfs_share $nfs_mount nfs defaults,_netdev 0 0" >> /etc/fstab mount -av df -h $nfs_mount
2-й этап. Диагностика и проверка конфигурации
Значения указаны буквально — блоки можно запускать в новой сессии без объявления переменных. В комментарии — ожидаемый результат.
Блок 1. ISP — chrony-сервер
systemctl is-active chronyd # active chronyc tracking | grep -E 'Stratum|Leap' # Stratum : 5, Leap status : Normal chronyc clients # в списке HQ-SRV, HQ-CLI, BR-RTR, BR-SRV после их настройки grep -E '^(local|allow)' /etc/chrony.conf # local stratum 5; allow на 172.16.x и внутренние сети
Блок 2. Клиенты chrony — HQ-SRV, HQ-CLI, BR-RTR, BR-SRV
chronyc sources -v | tail -3 # строка с ^* — источник ISP выбран, stratum 5 chronyc tracking | grep -E 'Reference|Stratum' # Reference ID = адрес ISP, Stratum : 6 timedatectl | grep -E 'synchronized|Time zone' # System clock synchronized: yes
Блок 3. HQ-RTR и BR-RTR — трансляция портов
# HQ-RTR
iptables -t nat -nvL PREROUTING # DNAT tcp dpt:2027 → 192.168.1.10:2027, dpt:80 → 192.168.1.10:80
iptables -nvL FORWARD | grep 192.168.1.10 # ACCEPT на 2027 и 80
# BR-RTR
iptables -t nat -nvL PREROUTING # DNAT dpt:2027 → 192.168.4.2:2027, dpt:8080 → 192.168.4.2:8080
iptables -nvL FORWARD | grep 192.168.4.2
# С ISP — сквозная проверка проброса
ssh -p 2027 sshuser@172.16.1.10 hostname # hq-srv
ssh -p 2027 sshuser@172.16.2.10 hostname # br-srv
curl -s -o /dev/null -w "%{http_code}\n" http://172.16.1.10/ # 200 (Apache HQ-SRV)
curl -s -o /dev/null -w "%{http_code}\n" http://172.16.2.10:8080/ # 200 (testapp BR-SRV)
Блок 4. HQ-SRV — RAID0, NFS, Apache, MariaDB
cat /proc/mdstat # md0 : active raid0 — 2 диска, [UU] mdadm --detail /dev/md0 | grep -E 'Level|State|Devices' lsblk -f | grep -A1 md0 # ext4 findmnt /raid # смонтирован /dev/md0 grep md0 /etc/fstab /etc/mdadm.conf # запись в fstab и ARRAY в mdadm.conf (постоянность) exportfs -v # /raid/nfs 192.168.2.0/28(rw,...,no_root_squash) systemctl is-active nfs-server # active showmount -e localhost systemctl is-active httpd2 mariadb # active active curl -s http://localhost/ | head -5 # страница отвечает mysql -e 'SELECT VERSION();' # версия MariaDB
Блок 5. BR-SRV — Samba DC, Ansible, Docker
systemctl is-active samba # active
samba-tool domain level show # Domain and forest function level
samba-tool user list # hquser1..hquser5 (+ administrator)
samba-tool group listmembers hq # hquser1..hquser5
samba-tool domain passwordsettings show | grep -E 'Minimum password length|lockout threshold' # 8 и 5
host -t SRV _ldap._tcp.au-team.irpo # br-srv.au-team.irpo
cd /etc/ansible && ansible all -m ping # 4 узла: HQ-SRV, HQ-CLI, HQ-RTR, BR-RTR — "ping": "pong"
ansible-inventory --graph
docker ps # testapp_site 0.0.0.0:8080->8000/tcp, testapp_db — Up
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8080/ # 200 (HEAD/-I приложение не умеет)
Блок 6. HQ-CLI — домен, sudo, NFS
system-auth status # ad / домен au-team.irpo id hquser1@au-team.irpo # uid/gid из домена, группа hq su - hquser1@au-team.irpo -c 'sudo -l' # разрешены только /bin/cat, /bin/grep, /usr/bin/id su - hquser1@au-team.irpo -c 'sudo id' # работает su - hquser1@au-team.irpo -c 'sudo ls /' # отказ — не в списке findmnt /mnt/nfs # 192.168.1.10:/raid/nfs, rw grep nfs /etc/fstab # запись есть (автомонтирование) touch /mnt/nfs/test && rm -f /mnt/nfs/test # запись работает ip -br a | grep enp7s1 # адрес из 192.168.2.0/28 от DHCP HQ-RTR
3-й этап. Эксплуатация объектов сетевой инфраструктуры
Импорт пользователей в домен, обратный прокси с веб-аутентификацией, собственный центр сертификации и HTTPS, мониторинг atop, печать через CUPS, инвентаризация средствами Ansible, защита SSH через fail2ban и резервное копирование.
BR-SRV — импорт пользователей и инвентаризация
Массовое создание доменных учётных записей из CSV и сбор сведений об узлах площадки HQ средствами Ansible.
0. Подготовка переменных
Объявите переменные в сессии этого узла перед выполнением остальных команд. Они живут только в текущей оболочке: после bash, su, exit или переподключения по SSH объявите их заново — проверить можно командой echo с именем любой переменной.
# Домен — из него собирается базовый DN domain="au-team.irpo" # Кодировка выгрузки, если она не UTF-8 csv_encoding="CP1251" # Рабочий каталог Ansible ansible_dir="/etc/ansible"
I. Подготовка файла пользователей
Кодировку определяем, а не угадываем. Русский текст из Windows утилита file часто называет ISO-8859, хотя на деле это CP1251 — поэтому для не-UTF-8 файла берётся csv_encoding. Счётчик кириллических строк в конце показывает, получилась ли читаемая кириллица.
mount /dev/sr0 /mnt 2>/dev/null || true
ls -la /mnt/
# По заданию скрипт import.sh и users.csv лежат в корне образа — сначала пробуем их
csv_src=$(find /mnt -maxdepth 1 -iname 'users.csv' | head -1)
imp_src=$(find /mnt -maxdepth 1 -iname 'import.sh' | head -1)
echo "csv=$csv_src import=$imp_src"
\cp -f "$csv_src" /root/Users.csv
file -b --mime-encoding /root/Users.csv
case "$(file -b --mime-encoding /root/Users.csv)" in
utf-8|us-ascii)
iconv -f UTF-8 -t UTF-8//IGNORE /root/Users.csv > /root/Users_fixed.csv ;;
*)
iconv -f $csv_encoding -t UTF-8 /root/Users.csv > /root/Users_fixed.csv ;;
esac
head -3 /root/Users_fixed.csv
grep -cP '[а-яА-Я]' /root/Users_fixed.csv
II. Скрипт импорта
Сначала — штатный import.sh с образа (прочитайте его: обычно он ждёт путь к CSV аргументом или рядом с собой). Собственный скрипт ниже — запасной вариант, если штатный падает; порядок колонок в read сверьте с заголовком CSV (head -1). Одинарные кавычки в heredoc обязательны: внутри скрипта используются собственные переменные. Первая строка файла — заголовок, tail -n +2 её пропускает; иначе из заголовка получится лишнее подразделение с именем OU.
systemctl enable --now samba
systemctl is-active samba
# Вариант 1 (по заданию): штатный скрипт с образа
\cp -f "$imp_src" /root/import_iso.sh
\cp -f /root/Users_fixed.csv /root/users.csv
cat /root/import_iso.sh
bash /root/import_iso.sh /root/users.csv
samba-tool user list
# Вариант 2 (запасной): собственный скрипт
head -1 /root/Users_fixed.csv
cat <<'EOF' > /root/import.sh
#!/bin/bash
while IFS=';' \
read -r first last role phone ou street zip city country pass; do
[ -z "$first" ] && continue
username="${first:0:1}${last}"
username=$(printf '%s' "$username" | tr '[:upper:]' '[:lower:]')
samba-tool user create "$username" "$pass" \
--given-name="$first" --surname="$last" \
--job-title="$role" --telephone-number="$phone" || true
if [ -n "$ou" ]; then
samba-tool ou create "OU=$ou" 2>/dev/null || true
samba-tool user move "$username" "OU=$ou" 2>/dev/null || true
fi
done < <(tail -n +2 /root/Users_fixed.csv)
EOF
chmod +x /root/import.sh
bash /root/import.sh
samba-tool user list
III. Удаление лишнего подразделения (если импорт уже запускался без пропуска заголовка)
Базовый DN собирается из имени домена: au-team.irpo превращается в DC=au-team,DC=irpo.
base_dn="DC=${domain//./,DC=}"
echo "$base_dn"
samba-tool ou delete "OU=OU,$base_dn" 2>/dev/null || true
samba-tool ou list
IV. Плейбук инвентаризации
delegate_to: localhost сохраняет результат на управляющем узле, а не на опрашиваемой машине.
mkdir -p $ansible_dir/PC-INFO
# По заданию плейбук лежит на образе в каталоге playbook — сначала берём его
mount /dev/sr0 /mnt 2>/dev/null || true
ls -l /mnt/playbook/ && \cp -f /mnt/playbook/*.yml $ansible_dir/
# Запасной вариант, если на образе плейбука нет
cat <<'EOF' > /etc/ansible/get_hostname_address.yml
- name: Inventory HQ workstations
hosts: HQ-SRV,HQ-CLI
gather_facts: true
tasks:
- name: Save hostname and IP
copy:
dest: /etc/ansible/PC-INFO/{{ ansible_hostname }}.yml
content: |
Hostname: {{ ansible_hostname }}
IP_Address: {{ ansible_default_ipv4.address }}
delegate_to: localhost
EOF
cd $ansible_dir && ansible-playbook get_hostname_address.yml
ls -l $ansible_dir/PC-INFO/
HQ-SRV — центр сертификации, atop, CUPS, fail2ban
Собственный удостоверяющий центр на отечественных алгоритмах, непрерывный мониторинг, виртуальный PDF-принтер и блокировка перебора SSH.
0. Подготовка переменных
Объявите переменные в сессии этого узла перед выполнением остальных команд. Они живут только в текущей оболочке: после bash, su, exit или переподключения по SSH объявите их заново — проверить можно командой echo с именем любой переменной.
# Домен и публикуемые имена
domain="au-team.irpo"
web_fqdn="web.$domain"
docker_fqdn="docker.$domain"
# Центр сертификации
ca_dir="/root/ca"
ca_cn="Internal-CA"
ca_days="3650"
cert_days="30"
# Куда класть копии для забора по scp под sshuser (root по ssh не пускает AllowUsers)
ssh_user="sshuser"
ca_pub_dir="/home/sshuser/ca"
# Мониторинг (7 минут = 420 с)
atop_interval="420"
# Печать
printer_name="Cups-PDF"
cups_port="631"
# Защита SSH
ssh_port="2027"
f2b_maxretry="3"
f2b_bantime="1m"
# Кибер Бэкап (дистрибутив — CD-ROM с меткой CyberBackup_Linux_Installer: на HQ-SRV sr1, на HQ-CLI sr0;
# монтируем не в /mnt — там может быть Additional.iso)
cb_mnt="/media/cb"
cb_port="9877"
cb_dev=$(lsblk -rno NAME,LABEL | awk '/CyberBackup/{print "/dev/"$1}' | head -1)
echo "cb_dev=$cb_dev"
mkdir -p $cb_mnt; mountpoint -q $cb_mnt || mount $cb_dev $cb_mnt
cb_installer=$(find $cb_mnt -maxdepth 2 -type f | head -1)
echo "installer=$cb_installer"
I. Установка пакетов
apt-get update && apt-get install -y openssl apt-get install -y openssl-gost-engine apt-get install -y atop apt-get install -y cups apt-get install -y cups-pdf apt-get install -y fail2ban apt-get install -y iptables control openssl-gost enabled
II. Подключение движка ГОСТ в OpenSSL
Без движка openssl не знает алгоритмов gost2012 и не сможет ни выпустить ключ, ни поднять TLS. В ALT движок ставится пакетом и включается командой control; ручная правка openssl.cnf ломает конфигурацию.
# В ALT движок подключается штатным openssl.cnf, но по умолчанию выключен — # включает его control; вручную openssl.cnf не править control openssl-gost enabled control openssl-gost # enabled openssl engine gost # (gost) Reference implementation of GOST engine openssl list -public-key-algorithms | grep -i gost # gost2012_256 и др. — без этого TLS с ГОСТ не поднимется openssl ciphers | tr ':' '\n' | grep -i gost # GOST2012-GOST8912-GOST8912
III. Создание корневого сертификата
mkdir -p $ca_dir && cd $ca_dir openssl genpkey -algorithm gost2012_256 -pkeyopt paramset:TCB -out ca.key openssl req -new -x509 -md_gost12_256 -days $ca_days -key ca.key -out ca.crt \ -subj "/CN=$ca_cn" openssl x509 -in ca.crt -noout -subject -dates
IV. Выпуск сертификатов веб-серверов
Срок действия — 30 дней согласно заданию. Без subjectAltName современный браузер не примет сертификат даже при доверенном CA (ERR_CERT_COMMON_NAME_INVALID). Подпись ГОСТ-ключом требует явного дайджеста. Копии кладутся в домашний каталог sshuser — оттуда их забирают ISP и HQ-CLI по scp.
cd $ca_dir
for NAME in $web_fqdn $docker_fqdn; do
openssl genpkey -algorithm gost2012_256 -pkeyopt paramset:A -out $NAME.key
openssl req -new -md_gost12_256 -key $NAME.key -out $NAME.csr -subj \
"/CN=$NAME"
printf 'subjectAltName=DNS:%s\nextendedKeyUsage=serverAuth\n' $NAME > $NAME.ext
openssl x509 -req -md_gost12_256 -in $NAME.csr -CA ca.crt -CAkey ca.key \
-CAcreateserial -extfile $NAME.ext -out $NAME.crt -days $cert_days
openssl x509 -in $NAME.crt -noout -subject -dates -ext subjectAltName
done
mkdir -p $ca_pub_dir
\cp -f $ca_dir/ca.crt $ca_dir/*.crt $ca_dir/*.key $ca_pub_dir/
chown -R $ssh_user: $ca_pub_dir
chmod 700 $ca_pub_dir
ls -l $ca_dir $ca_pub_dir
V. Настройка мониторинга atop
Интервал читается из файла окружения юнита (на ALT — /etc/sysconfig/atop, в других сборках /etc/default/atop); drop-in дублирует значение на случай, если юнит берёт переменную напрямую. Проверка — в командной строке процесса должно быть 420.
for f in /etc/sysconfig/atop /etc/default/atop; do [ -f $f ] && sed -i "s/^LOGINTERVAL=.*/LOGINTERVAL=$atop_interval/" $f grep -qs "^LOGINTERVAL=" $f || echo "LOGINTERVAL=$atop_interval" >> $f done mkdir -p /etc/systemd/system/atop.service.d cat <<EOF > /etc/systemd/system/atop.service.d/interval.conf [Service] Environment=LOGINTERVAL=$atop_interval EOF systemctl daemon-reload systemctl enable --now atop systemctl restart atop systemctl status atop --no-pager ps -o args= -C atop
VI. Публикация PDF-принтера через CUPS
Служба переводится с прослушивания localhost на сетевой порт, разрешает доступ к разделам управления, затем создаётся и публикуется (расшаривается) сам принтер: пакет cups-pdf даёт только бэкенд cups-pdf:/ и PPD, очередь нужно добавить самому.
sed -i "s/^Listen localhost:$cups_port/Port $cups_port/" /etc/cups/cupsd.conf
grep -q "^Port $cups_port\$" /etc/cups/cupsd.conf || echo "Port $cups_port" \
>> /etc/cups/cupsd.conf
grep -q "^ Allow all" /etc/cups/cupsd.conf || {
sed -i '/<Location \/>/a\ Allow all' /etc/cups/cupsd.conf
sed -i '/<Location \/admin>/a\ Allow all' /etc/cups/cupsd.conf
sed -i '/<Location \/admin\/conf>/a\ Allow all' /etc/cups/cupsd.conf
}
systemctl enable --now cups
systemctl restart cups
ppd=$(find /usr/share/ppd /usr/share/cups/model -iname 'CUPS-PDF*.ppd' | head -1)
lpadmin -p $printer_name -E -v cups-pdf:/ -P "$ppd" -o printer-is-shared=true
cupsctl --share-printers --remote-admin --remote-any
lpstat -p $printer_name -l
# Пробная печать: PDF появится в /var/spool/cups-pdf/root/ (или ~/PDF)
echo test | lp -d $printer_name
VII. Журналирование попыток входа
В базовой установке rsyslog нет, и /var/log/auth.log не создаётся. fail2ban теперь читает журнал systemd, так что этот файл нужен уже не ему, а для ручного разбора входов.
apt-get install -y rsyslog systemctl enable --now rsyslog grep -q '^SyslogFacility AUTHPRIV' /etc/openssh/sshd_config || echo \ 'SyslogFacility AUTHPRIV' >> /etc/openssh/sshd_config grep -q '^LogLevel INFO' /etc/openssh/sshd_config || echo 'LogLevel INFO' >> \ /etc/openssh/sshd_config grep -q '^authpriv.*' /etc/rsyslog.conf || echo \ 'authpriv.* /var/log/auth.log' >> /etc/rsyslog.conf systemctl restart rsyslog sshd
VIII. Настройка fail2ban
Бэкенд systemd читает попытки входа прямо из журнала — файл лога не нужен. Для этого fail2ban требует модуль Python для systemd; на ALT пакет называется python3-module-systemd, запасной вариант — для других сборок.
apt-get install -y python3-module-systemd || apt-get install -y python3-systemd
python3 -c "import systemd.journal; print('ok')"
cat <<EOF > /etc/fail2ban/jail.d/sshd-hardening.conf
[sshd]
enabled = true
port = $ssh_port
backend = systemd
maxretry = $f2b_maxretry
bantime = $f2b_bantime
EOF
systemctl enable --now fail2ban
systemctl restart fail2ban
systemctl status fail2ban --no-pager
fail2ban-client status sshd
IX. Кибер Бэкап 18 — сервер управления и агент
Дистрибутив — один исполняемый файл (на стенде — cyberbackup_17.4.36200.x86_64; 17.4 допускается заданием как аналог); на стенде он подключён к ВМ отдельным CD-ROM. Установщик графический (ncurses): на HQ-SRV отмечаем «Сервер управления» и «Агент для Linux», регистрацию агента делаем на этот же сервер. Агенту нужен модуль SnapAPI, для сборки — заголовки текущего ядра. Веб-консоль поднимается на порту 9877.
# Установщик найден в пункте 0 (переменная cb_installer); если пусто — lsblk | grep rom echo "installer=$cb_installer"; ls -la $cb_mnt # Заголовки ядра для сборки модуля snapapi (имя пакета должно совпадать с uname -r) uname -r apt-get install -y kernel-headers-modules-$(uname -r | sed 's/^[0-9.]*-//; s/-alt.*$//') # напр. std-def apt-get install -y gcc apt-get install -y make apt-get install -y perl # Файл на диске уже исполняемый (~1,8 ГБ) — запускаем прямо с него, копировать не нужно $cb_installer # В мастере (Component Selection): оставить [*] Management Server и [*] Agent for Linux, # снять Bootable Media Builder, остальное пусто → Next. Путь по умолчанию; # регистрация агента — локальный сервер (HQ-SRV), порт 9877, учётная запись root; # на вопрос о сборке модуля SnapAPI — согласиться. ss -tlpn | grep -E ":$cb_port|:7780" systemctl list-units --no-pager | grep -i -E 'acronis|cyber|cb_'
X. Веб-консоль Кибер Бэкапа: подразделение и администратор
Дальше — только в браузере (с HQ-CLI): консоль https://192.168.1.10:9877. Первый вход — root системы. По заданию нужны подразделение irpo и пользователь irpoadmin с правами администратора этого подразделения.
1. https://192.168.1.10:9877 → вход root / пароль root HQ-SRV. 2. Настройки → Подразделения (Организация) → Добавить подразделение → имя: irpo. 3. Настройки → Учётные записи → Добавить учётную запись: имя irpoadmin, пароль P@ssw0rd, роль «Администратор», подразделение irpo. 4. Выйти, войти как irpoadmin / P@ssw0rd — убедиться, что вход работает.
ISP — обратный прокси, web-аутентификация и HTTPS
Публикация обоих приложений по доменным именам с базовой аутентификацией на веб-сайте и шифрованием по отечественным алгоритмам.
0. Подготовка переменных
Объявите переменные в сессии этого узла перед выполнением остальных команд. Они живут только в текущей оболочке: после bash, su, exit или переподключения по SSH объявите их заново — проверить можно командой echo с именем любой переменной.
# Домен и публикуемые имена domain="au-team.irpo" web_fqdn="web.$domain" docker_fqdn="docker.$domain" # Узлы, на которые проксируем ip_hq_rtr="172.16.1.10" ip_br_rtr="172.16.2.10" app_port="8080" # Откуда забрать сертификаты: HQ-SRV через проброс 2027 на HQ-RTR (2-й этап), # под sshuser — root по ssh на сервер не пускает AllowUsers ssh_user="sshuser" ssh_port="2027" ca_pub_dir="/home/sshuser/ca" # Веб-аутентификация web_auth_user="WEB" web_auth_password="P@ssw0rd"
I. Установка пакетов и файла паролей
apt-get update && apt-get install -y nginx apt-get install -y openssl apt-get install -y openssl-gost-engine apt-get install -y iptables apt-get install -y apache2-htpasswd || apt-get install -y apache2 htpasswd -bc /etc/nginx/.htpasswd $web_auth_user "$web_auth_password" cat /etc/nginx/.htpasswd
II. Копирование сертификатов с центра сертификации
Сертификаты и ключи выпускаются на HQ-SRV (см. предыдущий раздел, шаг IV кладёт копии в домашний каталог sshuser). Внутренняя сеть с ISP не маршрутируется, поэтому идём на внешний адрес HQ-RTR: проброс порта 2027 из 2-го этапа приводит на HQ-SRV.
for NAME in $web_fqdn $docker_fqdn; do scp -P $ssh_port $ssh_user@$ip_hq_rtr:$ca_pub_dir/$NAME.crt /etc/nginx/ scp -P $ssh_port $ssh_user@$ip_hq_rtr:$ca_pub_dir/$NAME.key /etc/nginx/ done chmod 600 /etc/nginx/*.key ls -l /etc/nginx/*.crt /etc/nginx/*.key
III. Конфигурация обратного прокси
Переменные nginx экранированы обратным слэшем — иначе оболочка подставит вместо них пустые значения ещё на этапе записи файла, и прокси потеряет заголовки.
cat <<EOF > /etc/nginx/sites-available.d/default.conf
server {
listen 80;
server_name $web_fqdn;
return 301 https://\$host\$request_uri;
}
server {
listen 80;
server_name $docker_fqdn;
return 301 https://\$host\$request_uri;
}
server {
listen 443 ssl;
server_name $web_fqdn;
ssl_certificate /etc/nginx/$web_fqdn.crt;
ssl_certificate_key /etc/nginx/$web_fqdn.key;
ssl_ciphers GOST2012-GOST8912-GOST8912;
ssl_protocols TLSv1.2;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://$ip_hq_rtr:$app_port;
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
auth_basic "Authorized access";
auth_basic_user_file /etc/nginx/.htpasswd;
}
}
server {
listen 443 ssl;
server_name $docker_fqdn;
ssl_certificate /etc/nginx/$docker_fqdn.crt;
ssl_certificate_key /etc/nginx/$docker_fqdn.key;
ssl_ciphers GOST2012-GOST8912-GOST8912;
ssl_protocols TLSv1.2;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://$ip_br_rtr:$app_port;
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
}
}
EOF
ln -sf /etc/nginx/sites-available.d/default.conf \
/etc/nginx/sites-enabled.d/default.conf
IV. Подключение движка ГОСТ в OpenSSL
Без движка openssl не знает алгоритмов gost2012 и не сможет ни выпустить ключ, ни поднять TLS. В ALT движок ставится пакетом и включается командой control; ручная правка openssl.cnf ломает конфигурацию.
# В ALT движок подключается штатным openssl.cnf, но по умолчанию выключен — # включает его control; вручную openssl.cnf не править control openssl-gost enabled control openssl-gost # enabled openssl engine gost # (gost) Reference implementation of GOST engine openssl list -public-key-algorithms | grep -i gost # gost2012_256 и др. — без этого TLS с ГОСТ не поднимется openssl ciphers | tr ':' '\n' | grep -i gost # GOST2012-GOST8912-GOST8912
V. Включение движка ГОСТ и запуск
Если nginx -t не принимает ssl_engine или браузер на HQ-CLI не умеет ГОСТ-TLS (ERR_SSL_VERSION_OR_CIPHER_MISMATCH), отечественные алгоритмы по заданию лишь «рекомендуются»: выпустите на HQ-SRV ключи RSA (openssl genrsa 2048 вместо genpkey, -sha256 вместо -md_gost12_256), уберите строки ssl_ciphers и ssl_engine — остальное без изменений.
grep -q '^ssl_engine gost;' /etc/nginx/nginx.conf || sed -i \
'/^events {/i ssl_engine gost;' /etc/nginx/nginx.conf
nginx -t
systemctl enable --now nginx
systemctl reload nginx
curl -k -u $web_auth_user:$web_auth_password -s -o /dev/null -w "%{http_code}\n" \
--resolve $web_fqdn:443:127.0.0.1 https://$web_fqdn/
HQ-CLI — доверие к CA, принтер и узел хранения
Рабочая станция входит в домен, принимает корневой сертификат, подключает сетевой принтер и готовит каталог для резервных копий.
0. Подготовка переменных
Объявите переменные в сессии этого узла перед выполнением остальных команд. Они живут только в текущей оболочке: после bash, su, exit или переподключения по SSH объявите их заново — проверить можно командой echo с именем любой переменной.
# Домен и контроллер домена
domain="au-team.irpo"
netbios="AU-TEAM"
admin_password="P@ssw0rd"
ip_br_srv="192.168.4.2"
cli_name="hq-cli"
int_cli="enp7s1"
# Доступ к серверу площадки A (root по ssh не пускает AllowUsers — идём под sshuser)
ssh_port="2027"
ssh_user="sshuser"
# Центр сертификации
ip_hq_srv="192.168.1.10"
ca_pub_dir="/home/sshuser/ca"
ca_cn="Internal-CA"
# Печать
printer_name="Cups-PDF"
cups_port="631"
# Узел хранения резервных копий
backup_dir="/backup"
# Кибер Бэкап (дистрибутив — CD-ROM с меткой CyberBackup_Linux_Installer: на HQ-SRV sr1, на HQ-CLI sr0;
# монтируем не в /mnt — там может быть Additional.iso)
cb_mnt="/media/cb"
cb_port="9877"
cb_dev=$(lsblk -rno NAME,LABEL | awk '/CyberBackup/{print "/dev/"$1}' | head -1)
echo "cb_dev=$cb_dev"
mkdir -p $cb_mnt; mountpoint -q $cb_mnt || mount $cb_dev $cb_mnt
cb_installer=$(find $cb_mnt -maxdepth 2 -type f | head -1)
echo "installer=$cb_installer"
I. Резолвер на контроллер домена и ввод в домен
Для ввода в домен DNS должен отвечать контроллер. Файл пишется и в каталог интерфейса: etcnet при перезапуске сети подставляет оттуда свою копию. Проверка SRV-записи идёт после перезапуска — так видно итоговое состояние.
cat <<EOF > /etc/resolv.conf search $domain nameserver $ip_br_srv EOF cat <<EOF > /etc/net/ifaces/$int_cli/resolv.conf search $domain nameserver $ip_br_srv EOF systemctl restart network cat /etc/resolv.conf host -t SRV _ldap._tcp.$domain # Если машина уже в домене со 2-го этапа — шаг пропустить (проверка: system-auth status) system-auth write ad $domain $cli_name $netbios 'administrator' "$admin_password" # Импортированные пользователи должны разрешаться (имя — из samba-tool user list на BR-SRV) id administrator@$domain
II. Установка корневого сертификата в доверенные
Без этого шага браузер будет ругаться на сертификаты web и docker. SSH на сервере слушает нестандартный порт, поэтому -P.
apt-get update && apt-get install -y openssl-gost-engine
apt-get install -y cups
apt-get install -y iptables
apt-get install -y admc
apt-get install -y krb5-kinit
control openssl-gost enabled
mkdir -p /etc/pki/ca-trust/source/anchors
scp -P $ssh_port $ssh_user@$ip_hq_srv:$ca_pub_dir/ca.crt \
/etc/pki/ca-trust/source/anchors/
update-ca-trust
trust list | grep -A2 "$ca_cn"
# Браузеру системного хранилища мало: добавляем CA в NSS-базу пользователя, под которым открывается браузер
apt-get install -y nss-utils || apt-get install -y libnss-tools
for home in /home/*; do
u=$(basename $home)
su - $u -c "mkdir -p ~/.pki/nssdb && certutil -d sql:~/.pki/nssdb -N --empty-password 2>/dev/null; \
certutil -d sql:~/.pki/nssdb -A -t 'C,,' -n '$ca_cn' \
-i /etc/pki/ca-trust/source/anchors/ca.crt"
done
curl -s -o /dev/null -w "%{http_code}\n" https://docker.$domain/
III. Подключение сетевого принтера
lpadmin -p $printer_name -E -v \ ipp://$ip_hq_srv:$cups_port/printers/$printer_name -m everywhere lpoptions -d $printer_name lpstat -p $printer_name
IV. Кибер Бэкап: агент и узел хранения на HQ-CLI
По заданию на HQ-CLI ставится агент с функциями узла хранилища и регистрируется на сервере управления HQ-SRV (раздел HQ-SRV, шаг IX должен быть уже выполнен). В мастере установки отмечаем «Агент для Linux» и «Узел хранения»; при регистрации указываем адрес сервера управления 192.168.1.10 и учётную запись irpoadmin (или root HQ-SRV).
mkdir -p $backup_dir chmod 0770 $backup_dir # Установщик найден в пункте 0 (переменная cb_installer); если пусто — lsblk | grep rom echo "installer=$cb_installer"; ls -la $cb_mnt uname -r apt-get install -y kernel-headers-modules-$(uname -r | sed 's/^[0-9.]*-//; s/-alt.*$//') # напр. std-def apt-get install -y gcc apt-get install -y make apt-get install -y perl # Файл на диске уже исполняемый (~1,8 ГБ) — запускаем прямо с него, копировать не нужно $cb_installer # В мастере (Component Selection): [*] Agent for Linux + [*] Storage Node, остальное снять; # сервер управления: $ip_hq_srv, порт $cb_port, учётная запись irpoadmin / P@ssw0rd. systemctl list-units --no-pager | grep -i -E 'acronis|cyber|cb_'
V. Веб-консоль: хранилище, план и запуск копирования
Остальное — в консоли https://192.168.1.10:9877 под irpoadmin. Проверка результата — файлы архива в /backup на HQ-CLI и статус «Успешно» в разделе Действия.
1. Настройки → Узлы хранения: убедиться, что HQ-CLI появился как узел хранения. 2. Резервные копии (Хранилища) → Добавить хранилище → Узел хранения HQ-CLI → путь /backup → сохранить (имя, например, backup-hq-cli). 3. Устройства → Все устройства → HQ-SRV → Резервное копирование → Создать план: Что копировать: Файлы/папки → /etc (со всеми поддиректориями); Куда: хранилище backup-hq-cli на узле HQ-CLI; Расписание — любое (или отключить), имя плана, например, etc-hq-srv → Создать. 4. В плане нажать «Запустить сейчас», дождаться статуса «Успешно» в разделе Действия. # Проверка на HQ-CLI: ls -la /backup du -sh /backup
3-й этап. Диагностика и проверка конфигурации
Блок 1. BR-SRV — импорт пользователей и инвентаризация
samba-tool user list | wc -l # число пользователей выросло на количество строк Users.csv samba-tool user show $(samba-tool user list | grep -v -i admin | head -1) | grep -E 'sAMAccountName|givenName' ls -l /etc/ansible/ # плейбук *.yml из Additional.iso ls -l /etc/ansible/PC-INFO/ # по файлу .yml на узел cat /etc/ansible/PC-INFO/*.yml # имя и адрес узла в каждом
Блок 2. HQ-SRV — CA, сертификаты, atop, CUPS, fail2ban
control openssl-gost # enabled openssl engine gost # (gost) Reference implementation of GOST engine openssl x509 -in /root/ca/ca.crt -noout -subject -dates # CN=Internal-CA (или свой), 30 дней for n in web docker; do openssl x509 -in /root/ca/$n.au-team.irpo.crt -noout -subject -dates -ext subjectAltName; done openssl verify -CAfile /root/ca/ca.crt /root/ca/web.au-team.irpo.crt # OK ls -l /home/sshuser/ca/ # копии для ISP и HQ-CLI systemctl is-active atop # active grep -s '^LOGINTERVAL' /etc/sysconfig/atop /etc/default/atop # 420 ps -o args= -C atop # в строке запуска интервал 420 ls -l /var/log/atop/ # журнал atop_YYYYMMDD systemctl is-active cups # active lpstat -p -d # Cups-PDF idle, принтер по умолчанию ss -tlpn | grep 631 # слушает на 0.0.0.0/адресе сервера, не только 127.0.0.1 systemctl is-active fail2ban # active fail2ban-client status sshd # Port 2027, maxretry 3, bantime 60 fail2ban-client get sshd bantime # 60 fail2ban-client get sshd maxretry # 3
Блок 3. ISP — обратный прокси, web-аутентификация, HTTPS/ГОСТ
control openssl-gost # enabled
openssl ciphers | tr ':' '\n' | grep -i gost # GOST2012-GOST8912-GOST8912
nginx -t # syntax is ok / test is successful
systemctl is-active nginx # active
ls -l /etc/nginx/*.au-team.irpo.* # web/docker .crt и .key
cat /etc/nginx/.htpasswd # WEB:$apr1$...
# без пароля — 401, с паролем — 200
curl -k -s -o /dev/null -w "%{http_code}\n" --resolve web.au-team.irpo:443:127.0.0.1 https://web.au-team.irpo/
curl -k -u WEB:P@ssw0rd -s -o /dev/null -w "%{http_code}\n" --resolve web.au-team.irpo:443:127.0.0.1 https://web.au-team.irpo/
curl -k -s -o /dev/null -w "%{http_code}\n" --resolve docker.au-team.irpo:443:127.0.0.1 https://docker.au-team.irpo/ # 200
openssl s_client -connect 127.0.0.1:443 -servername web.au-team.irpo </dev/null 2>/dev/null | grep -E 'Cipher|subject' # шифр GOST, CN web
Блок 4. HQ-CLI — доверие к CA, принтер, Кибер Бэкап
ls -l /etc/pki/ca-trust/source/anchors/ca.crt
trust list | grep -i -A2 'Internal-CA' # CA в системном хранилище
curl -s -o /dev/null -w "%{http_code}\n" --resolve web.au-team.irpo:443:172.16.2.1 -u WEB:P@ssw0rd https://web.au-team.irpo/ # 200 без -k (адрес ISP со стороны BR)
lpstat -p Cups-PDF -d # принтер подключён, по умолчанию
echo test | lp -d Cups-PDF # задание ушло, PDF появится на HQ-SRV в /var/spool/cups-pdf/…
systemctl list-units --no-pager | grep -i -E 'acronis|cyber' # службы агента и узла хранения active
ls -la /backup # каталоги архивов после первого запуска плана
du -sh /backup
# В веб-консоли https://192.168.1.10:9877 (irpoadmin): Settings → Storage nodes — hq-cli;
# Backup storage — хранилище /backup; Plans — план /etc для HQ-SRV; Activities — статус «Успешно».