среда, 1 октября 2025 г.

Windows: Установка Windows 11 с обоходом проверки TPM и безопасной загрузки

Если вам по определенным причинам необходимо развернуть ОС Microsoft Windows 11 на старом оборудовании или виртуальной машине без использования модуля TPM и функции безопасной загрузки, можно обойти эту преграду во время установки следующим образом.

Как только загрузится мастер установки в графическом интерфейсе, нажмите сочетание клавиш "Shift+F10": появится окошко консоли Windows. Теперь можно набрать команду "regedit" и запустить редактор реестра.

Далее добавим следующие параметры:
1. Создадим новый раздел "HKEY_LOCAL_MACHINES\SYSTEM\Setup\LabConfig".
2. В созданном разделе добавим два параметра типа "DWORD":
"BypassTPMCheck" и "BypassSecureBootCheck".
3. Установим значение данных параметров равным "1".

После изменения реестра закрываем редактор и продолжаем установку ОС Windows 11.

вторник, 30 сентября 2025 г.

Debian: Настройка для работы в домене Active Directory

Выполните следующие шаги для настройки работы в домене вашей ОС Linux Debian:

1. Предварительная настройка сети, DNS, полного и короткого имени хоста.
Убедитесь, что сервер имеет корректные сетевые настройки и может разрешать доменные имена:
ping dc.YOUR_FQDN
nslookup YOUR_FQDN


Замените в файле "/etc/hosts" имя локального домена "localdomain" на имя вашего домена YOUR_FQDN командой:
sudo sed -i 's/localdomain/YOUR_FQDN/g' /etc/hosts

2. Установка необходимых пакетов.
sudo apt update
sudo DEBIAN_FRONTEND=noninteractive apt -y install realmd \
sssd sssd-tools libnss-sss libpam-sss adcli samba-common-bin \
oddjob oddjob-mkhomedir packagekit krb5-user


3. Обнаружение домена и настройка Kerberos и realmd.
Обнаружение домена:
sudo realm discover YOUR_FQDN

Для настройки Kerberos отредактируйте файл "/etc/krb5.conf":

[libdefaults]
    default_realm = YOUR_FQDN
    dns_lookup_realm = true
    dns_lookup_kdc = true


Для настройки realmd создайте файл "/etc/realmd.conf" со следующим содержимым:

[service]
automatic-install = yes

[active-directory]
os-name = Debian
os-version = 13


Данные параметры будут отражаться в свойствах комьютерного аккаунта в Active Directory после ввода хоста в домен.

4. Предварительная настройка SSSD.
Поскольку при добавлении хоста в домен, а также при удалении из домена с помощью команды "realm join" файл "/etc/sssd/sssd.conf" будет перезаписан, лучшим вариантом будет создать новый файл конфигурации SSSD со своими параметрами.
sudo nano /etc/sssd/conf.d/10-mysettings.conf

[domain/YOUR_FQDN]
#Добавить провайдер аутентификации
auth_provider = ad
#Добавить провайдер смены пароля
chpass_provider = ad
#Режим коротких имен пользователей, при значении "false"
use_fully_qualified_names = true
#Настройка оболочки по умолчанию
default_shell = /bin/bash
#Правило формирования домашней папки
fallback_homedir = /home/%u@%d
#Добавить для игнорирования групповых политик, к которым нету доступа
ad_gpo_ignore_unreadable = true
#Добавить настройки динамического DNS
dyndns_update = true
dyndns_refresh_interval = 1800
dyndns_ttl = 1800
dyndns_update_ptr = true


Установите правильные права на файл конфигурации:
sudo chmod 600 /etc/sssd/conf.d/10-mysettings.conf

5. Присоединение к домену.
sudo realm join YOUR_FQDN
\
--membership-software=adcli \
--user=DomainAdmin


Введите пароль пользователя при запросе.

Проверка успешного присоединения:
id DomainAdmin@YOUR_FQDN

6. Настройка автоматического создания домашних каталогов.
Отредактируйте файл "/etc/pam.d/common-session":
sudo nano /etc/pam.d/common-session

Добавьте в конец файла:
session optional pam_mkhomedir.so skel=/etc/skel umask=077

7. Настройка прав доступа.

Управление доступом к консоли сервера:

Запретите вход всем доменным пользователям:
sudo realm deny --all
Разрешите вход только определенным группам:
sudo realm permit -g 'Linux_Console_Users'@YOUR_FQDN
Для групп с пробелами в названии:
sudo realm permit -g '"Domain Linux Users"'@YOUR_FQDN
Проверьте настройки:
sudo realm list

Управление доступом по SSH:

Создайте новый файл в директории "/etc/ssh/sshd_config.d":
sudo nano /etc/ssh/sshd_config.d/10-admins.conf

Добавьте параметры для ограничения доступа по группам:
AllowGroups
Linux_SSH_Users@YOUR_FQDN "Linux SSH Admins"@YOUR_FQDN

ВАЖНО!!!!
Если вы использует значение параметра "use_fully_qualified_names = false" в файле "/etc/sssd/sssd.conf", то и при настройке SSH доступа прописывайте короткое имя пользователя или группы, без названия домена, например:
AllowGroups Linux_SSH_Users "Linux SSH Admins"

Также название групп (Linux_SSH_Users и "Linux SSH Admins") и домена (YOUR_FQDN) должны быть СТРОГО В НИЖНЕМ РЕГИСТРЕ!!!

Установите правильные права на файл и перезапустите службу SSH:
sudo chmod 600 /etc/ssh/sshd_config.d/10-admins.conf
sudo systemctl restart ssh

8. Настройка прав sudo для доменных групп.
Создайте файл правил sudo:
sudo visudo -f /etc/sudoers.d/domain_admins
Всегда используйте команду "visudo", которая предотвращает сохранение конфигурации с синтаксическими ошибками.

Добавьте необходимые правила:

Полные права администратора (пример):
%Linux_Sudoers@YOUR_FQDN ALL=(ALL:ALL) ALL
Члены группы Linux_Sudoers теперь могут выполнять команды с "sudo", вводя свой пароль от учётной записи Active Directory.

Ограниченные права (пример):
%Linux_Sudoers@YOUR_FQDNALL=(root) /usr/bin/systemctl restart nginx, /usr/bin/systemctl status nginx

Для групп с пробелами в названии:
%Linux\ Admins@YOUR_FQDN ALL=(ALL:ALL) ALL

Установите права доступа на файл:
sudo chmod 440 /etc/sudoers.d/domain_admins

ВАЖНО!!!!
Если вы использует значение параметра "use_fully_qualified_names = false" в файле "/etc/sssd/sssd.conf", то и при настройке sudoers прописывайте короткое имя пользователя или группы, без названия домена, например:
%Linux_Sudoers ALL=(ALL:ALL) ALL

9. Тестирование конфигурации.
Попробуйте войти под доменной учетной записью:
ssh linux_admin@YOUR_FQDN@ip_адрес_сервера
Проверьте создание домашнего каталога:
pwd
Проверьте работу "sudo" для пользователей из разрешенных групп.
Убедитесь, что время на сервере синхронизировано с доменом (используйте NTP).
Регулярно проверяйте логи аутентификации: /var/log/auth.log.
Для диагностики проблем используйте журналы SSSD: /var/log/sssd/
Проверьте связь с контроллером домена:
klist
Проверьте возможность получение тикета Kerberos:
kinit


Вывод хоста из домена, переименование доменной машины.

Для вывода из домена вашего хоста выполните:
sudo realm leave YOUR_FQDN -v --user=DomainAdmin
При этом будут сброшены все настойки, сделаные в файле "/etc/sssd/sssd.conf".

Операция переименования для Linux сводится к следующим шагам:
1. Выводу хоста из домена.
2. Переименованию командой:
sudo hostnamectl set-hostname NEW-HOSTNAME
Также необходимо изменить имя в файле "/etc/hosts":
sudo sed -i 's/OLD-HOSTNAME/NEW-HOSTNAME/g' /etc/hosts
Перезапускаем службу:
sudo systemctl restart systemd-hostnamed
3. Повторный ввод в домен под новым именем:
sudo realm join YOUR_FQDN \
--membership-software=adcli \
--user=DomainAdmin

После ввода в домен необходимо повторно настроить доступ командой "sudo realm permit", так как файл "/etc/sssd/sssd.conf", где хранились предыдущие настройки, был сброшен службой SSSD при выходе из домена.

понедельник, 22 сентября 2025 г.

Debian: Настройка полного зеркала репозитория Debian

Создание полного зеркала репозитория Debian - задача, которая требует значительных ресурсов и надежного интернет-соединения. Полное зеркало включает в себя все пакеты, обновления, обратные порты (backports) и обновления безопасности для конкретного выпуска Debian.
Debmirror - это специализированная утилита на Perl, предназначенная для создания и поддержания зеркал репозиториев Debian и Ubuntu. В отличие от стандартных методов "rsync", она предлагает более простой и надежный способ синхронизации, особенно для выборочного зеркалирования.

Далее приведем шаги для настройки зеркала репозитория Debian 13 ("trixie") используя "Debmirror":

1. Установка Debmirror и веб-сервера Apache2:
sudo apt-get update
sudo apt-get install debmirror apache2 -y


Базовый синтаксис команды debmirror следующий:

debmirror [ОПЦИИ] /путь/к/локальному/зеркалу

Ключевые параметры debmirror:
-a, --arch : Архитектуры (например, amd64,i386);
-s, --section : Разделы репозитория (main, contrib, non-free для Debian; main, restricted, universe, multiverse для Ubuntu);
-d, --dist : Дистрибутивы (кодовые имена, например, bullseye, bookworm, trixie для Debian; focal, jammy для Ubuntu). Можно указать несколько через запятую, включая обновления (bullseye-updates, bullseye-security);
-h, --host : URL-адрес исходного зеркала (например, ftp.debian.org, archive.ubuntu.com или локальный Nexus-репозиторий);
-r, --root : Корневой путь на удаленном сервере (например, /debian для Debian, /ubuntu для Ubuntu);
-e, --method : Протокол для загрузки (http, https, ftp, rsync). http или https часто наиболее надежны.
--progress : Показывать прогресс загрузки.
--nosource : Не загружать исходные коды пакетов (значительно экономит место).
--ignore-release-gpg : Игнорировать проверку GPG-подписи Release-файлов. Используйте с осторожностью, так как это снижает безопасность.
--ignore-missing-release : Продолжать синхронизацию, даже если на сервере отсутствует Release-файл.


2. Пробная синхронизация:

Создаем место хранения репозитория на диске:
sudo mkdir -p /srv/mirror/debian
sudo mkdir -p /srv/mirror/debian-security
sudo chown -R nobody:nogroup /srv/mirror/debian
sudo chown -R nobody:nogroup /srv/mirror/debian-security



Затем выполняем команды синхронизации в качестве проверки:

Синхронизация основного репозитория Debian (trixie,trixie-updates,trixie-backports):
debmirror \
-a amd64 \
--nosource \
-s main,contrib,non-free,non-free-firmware \
-d trixie,trixie-updates,trixie-backports \
-h ftp.debian.org \
-r /debian \
-e https \
--progress \
--ignore-release-gpg \
--no-check-gpg \
--rsync-extra=none \
/srv/mirror/debian


Синхронизация патчей безопасности Debian (trixie-security):
debmirror \
-a amd64 \
--nosource \
-s main,contrib,non-free,non-free-firmware \
-d trixie-security \
-h security.debian.org \
-r /debian-security \
-e https \
--progress \
--ignore-release-gpg \
--no-check-gpg \
--rsync-extra=none \
/srv/mirror/debian-security


Если все прошло без ошибок, можно приступить к следующему шагу.


3. Настройка веб-сервера (Apache2) для доступа к локальному репозиторию:

Чтобы сделать зеркало доступным по HTTP создайте файл:
sudo nano /etc/apache2/sites-available/debian-mirror.conf

со следующим содержимым:

<VirtualHost *:80>
    ServerName your-mirror-domain.com #Замените на имя вашего сервера или IP
    DocumentRoot /srv/mirror
    <Directory "/srv/mirror">
        Options +Indexes +FollowSymLinks
        IndexOptions NameWidth=* +SuppressDescription FancyIndexing
        Require all granted
    </Directory>
    ErrorLog ${APACHE_LOG_DIR}/debian-mirror_error.log
    CustomLog ${APACHE_LOG_DIR}/debian-mirror_access.log combined
</VirtualHost>


Если необходимо добавить поддержку HTTPs:

Создайте директории для пары ключей (если они не существуют):
sudo mkdir -p /etc/ssl/private /etc/ssl/certs

Затем сгенерируйте сертификат:
sudo openssl req -x509 -nodes -days 730 -newkey rsa:2048 \ -keyout /etc/ssl/private/your-mirror.key \ -out /etc/ssl/certs/your-mirror.crt

При генерации укажите в Common Name: your-mirror-domain.com. Остальные поля можно заполнить по желанию или оставить пустыми.

Установите правильные права доступа для ключа:
sudo chmod 600 /etc/ssl/private/your-mirror.key

И создайте файл:
sudo nano /etc/apache2/sites-available/debian-mirror-ssl.conf

со следующим содержимым:

<VirtualHost *:443>
    ServerName your-mirror-domain.com #Замените на имя вашего сервера или IP
    DocumentRoot /srv/mirror
    SSLEngine on
    SSLCertificateFile /etc/ssl/certs/your-mirror.crt
    SSLCertificateKeyFile /etc/ssl/private/your-mirror.key
    <Directory "/srv/mirror">
        Options +Indexes +FollowSymLinks
        IndexOptions NameWidth=* +SuppressDescription FancyIndexing
        Require all granted
    </Directory>
    ErrorLog ${APACHE_LOG_DIR}/debian-mirror_ssl_error.log
    CustomLog ${APACHE_LOG_DIR}/debian-mirror_ssl_access.log combined
</VirtualHost>


Активируйте конфигурацию и перезапустите Apache:
sudo a2ensite debian-mirror
sudo a2ensite debian-mirror-ssl
#Для поддержки HTTPs
sudo apachectl configtest
sudo a2enmod rewrite
sudo a2enmod ssl
#Для поддержки HTTPs
sudo systemctl restart apache2


Проверьте доступность: Откройте в браузере "http://your-server-ip/debian". Должна отобразиться структура каталогов репозитория.


4. Создание скрипта для автоматизации процесса и мониторинга:

Следующий скрипт умеет помимо выполнения синхронизации нужных веток репозитория командой "debmirror" также записывать лог, отслеживать запущен ли был скрипт ранее и отправлять отчёт на email. Создайте файл:
sudo nano /usr/local/bin/update-mirror.sh

Добавьте в него текст скрипта и сделайте исполняемым:
sudo chmod +x /usr/local/bin/update-mirror.sh

#!/bin/bash

# Настройки скрипта
LOG_FILE="/var/log/mirror_update.log"
LOCK_FILE="/var/run/mirror_update.lock"
MIRROR_BASE="/srv/mirror"

# Email-уведомления
EMAIL_RECIPIENTS="admin@example.com,devops@example.com"  # Замените на реальные адреса
EMAIL_SUBJECT_PREFIX="[Mirror Update] "
SMTP_SERVER="Input_IP_of_SMTP_Server"  # Адрес SMTP-сервера
FROM_EMAIL="mirror-update@$(hostname)"  # Адрес отправителя

# Конфигурация зеркал
declare -A MIRRORS=(
    ["main"]="
        -a amd64
        --nosource
        -s main,contrib,non-free,non-free-firmware
        -d trixie,trixie-updates,trixie-backports
        -h ftp.by.debian.org
        -r /debian
        -e rsync
        --progress
        --ignore-release-gpg
        --no-check-gpg
        ${MIRROR_BASE}/debian
    "
    ["security"]="
        -a amd64
        --nosource
        -s main,contrib,non-free,non-free-firmware
        -d trixie-security
        -h ftp.by.debian.org
        -r /debian-security
        -e rsync
        --progress
        --ignore-release-gpg
        --no-check-gpg
        ${MIRROR_BASE}/debian-security
    "
)

# Функция логирования
log() {
    echo "$(date '+%Y-%m-%d %H:%M:%S'): $1" >> "$LOG_FILE"
}

# Функция отправки email через curl и SMTP
send_email() {
    local subject="$1"
    local body="$2"

    # Проверяем, установлен ли curl
    if command -v curl &> /dev/null; then
        # Формируем email в формате MIME
        local email_content=$(cat <<EOF
From: ${FROM_EMAIL}
To: ${EMAIL_RECIPIENTS}
Subject: ${EMAIL_SUBJECT_PREFIX}${subject}
Date: $(date -R)
MIME-Version: 1.0
Content-Type: text/plain; charset="utf-8"

${body}
EOF
)

        # Отправляем через SMTP используя curl
        echo "$email_content" | curl -s --url "smtp://${SMTP_SERVER}" \
            --mail-from "${FROM_EMAIL}" \
            --mail-rcpt "${EMAIL_RECIPIENTS}" \
            --upload-file - \
            --insecure

        if [ $? -eq 0 ]; then
            log "Email sent successfully: ${subject}"
        else
            log "ERROR: Failed to send email: ${subject}"
        fi
    elif command -v sendmail &> /dev/null; then
        # Альтернативный метод через sendmail
        (
            echo "Subject: ${EMAIL_SUBJECT_PREFIX}${subject}"
            echo "From: ${FROM_EMAIL}"
            echo "To: ${EMAIL_RECIPIENTS}"
            echo
            echo "${body}"
        ) | sendmail -t
    else
        log "ERROR: No email client found. Cannot send notification: $subject"
    fi
}

# Функция проверки блокировки
check_lock() {
    if [ -e "$LOCK_FILE" ]; then
        local pid=$(cat "$LOCK_FILE")
        if kill -0 "$pid" 2>/dev/null; then
            log "ERROR: Скрипт уже запущен с PID $pid"
            send_email "Script already running" "Mirror update script is already running with PID $pid. Current execution blocked."
            exit 1
        else
            log "WARNING: Обнаружен lock файл, но процесс не существует. Удаляю lock файл."
            rm -f "$LOCK_FILE"
        fi
    fi
}

# Функция создания блокировки
create_lock() {
    echo $$ > "$LOCK_FILE"
}

# Функция удаления блокировки
remove_lock() {
    rm -f "$LOCK_FILE"
}

# Функция выполнения debmirror
run_mirror() {
    local name="$1"
    local options="$2"

    log "Starting mirror update: $name"
    log "Command: debmirror $options"

    # Выполнение команды
    debmirror $options

    local exit_code=$?
    if [ $exit_code -eq 0 ]; then
        log "Update successful: $name"
        return 0
    else
        log "Update failed with exit code $exit_code: $name"
        return $exit_code
    fi
}

# Основная логика
main() {
    log "=== Starting mirror update process ==="

    # Проверяем блокировку
    check_lock

    # Создаем блокировку
    create_lock

    # Добавляем обработчик для очистки при выходе
    trap 'remove_lock; log "Script interrupted"; exit 1' INT TERM
    trap 'remove_lock' EXIT

    local overall_success=true

    for mirror_name in "${!MIRRORS[@]}"; do
        if ! run_mirror "$mirror_name" "${MIRRORS[$mirror_name]}"; then
            overall_success=false
            log "ERROR: Mirror $mirror_name failed with exit code $?"
            send_email "Update failed: $mirror_name" "Mirror update for $mirror_name failed. Check $LOG_FILE for details."
        fi
    done

    if [ "$overall_success" = true ]; then
        log "=== All mirror updates completed successfully ==="
        send_email "All updates completed" "All mirror updates completed successfully. Check $LOG_FILE for details."
    else
        log "=== Some mirror updates failed ==="
        # Уведомление об ошибках уже отправлялись для каждого конкретного сбоя
    fi
}

# Обработка ошибок
set -euo pipefail

# Запуск основной функции
main "$@"


5. Настройка ротации логов:

Создайте файл /etc/logrotate.d/update_mirror с следующим содержимым:

/var/log/mirror_update.log {
weekly
missingok
rotate 26
compress
delaycompress
notifempty
create 644 root root
dateext
dateformat -%Y-%m-%d
}


Объяснение директив:
weekly - ротация происходит раз в неделю;
missingok - пропустить ротацию, если файл отсутствует;
rotate 26 - хранить 26 архивных копий (полгода ≈ 26 недель);
compress - сжимать архивные логи с помощью gzip;
delaycompress - отложить сжатие до следующей ротации (удобно для отладки);
notifempty - не ротировать пустые файлы;
create 644 root root - создать новый лог-файл с правами 644 и владельцем root:root после ротации;
dateext - добавлять дату к имени архивного файла;
dateformat -%Y-%m-%d - формат даты в имени файла (ГГГГ-ММ-ДД).

Проверка конфигурации:
sudo logrotate -d /etc/logrotate.d/update_mirror
Ключ -d включает режим отладки, который покажет потенциальные проблемы без выполнения ротации.

Принудительная ротация для тестирования:
sudo logrotate -vf /etc/logrotate.d/update_mirror
Ключ -v включает подробный вывод, а -f принудительно запускает ротацию.


6. Настройка автоматической синхронизации через cron

Для поддержания зеркала в актуальном состоянии его необходимо регулярно синхронизировать. Рекомендуется делать это не реже 4 раз в сутки.
Создайте задание cron (sudo crontab -e):
Синхронизация каждые 6 часов (в произвольные минуты для равномерной нагрузки):
0 */6 * * * /usr/local/bin/update-mirror.sh

или синхронизация каждые сутки в 2 часа ночи:
0 2 * * * /usr/local/bin/update-mirror.sh

Не синхронизируйте зеркало точно в 3:00, 9:00, 15:00 и 21:00 UTC, так как в это время обновляются главные зеркала. Добавьте случайное смещение в несколько минут.


7. Тестирование и использование зеркала:

Протестируйте свое зеркало, настроив на другой машине sources.list:
sudo nano /etc/apt/sources.list

Добавьте строки:
deb http://your-mirror-ip-or-domain/debian/ trixie main contrib non-free non-free-firmware
deb http://your-mirror-ip-or-domain/debian/ trixie-updates main contrib non-free non-free-firmware
deb http://your-mirror-ip-or-domain/debian/ trixie-backports main contrib non-free non-free-firmware
deb http://your-mirror-ip-or-domain/debian-security/ trixie-security main contrib non-free non-free-firmware


Выполните обновление индексов пакетов:
sudo apt update
sudo apt upgrade


понедельник, 8 сентября 2025 г.

ALT Linux: Настройка VMware VM Customization Specifications для ОС ALT Linux

К сожалению, при использовании "VM Customization Specifications" при развертывании ОС ALT Linux скрипты "open-vm-toos" не могут корректно сконфигурировать такие параметры как имя хоста, сетевые настройки и т.д. для данной системы.
Чтобы решить эту проблему, применим скрипт, который возьмет на себя функционал, не корректно работающий в самих тулзах.

Выполним следующие шаги для настройки "VM Customization Specifications":

1. Подготавливаем шаблон ОС ATL Linux с установкой необходимого ПО, которое уже должно быть в комплекте с новыми хостами.
2. Обязательно устанавливаем "open-vm-tools" и проверяем, что служба "vmtoolsd" находится в автозапуске:
sudo apt-get install open-vm-tools
sudo systemctl enable vmtoolsd && sudo systemctl start vmtoolsd


3. Включаем поддержку скриптов для кастомизации:
sudo vmware-toolbox-cmd config set deployPkg enable-custom-scripts true

Для проверки текущего состояния параметра выполните:
sudo vmware-toolbox-cmd config get deployPkg enable-custom-scripts

4. Далее настраиваем "VM Customization Specifications" на vCenter Server. При настройке указываем: тип ОС - Linux, правило формирования имени хоста, часовой пояс, TCP/IP настройки и добавляем следующий скрипт:

#!/bin/bash

# Функция для преобразования маски подсети в префикс CIDR
mask2cidr() {
    local mask=$1
    local n=0
    IFS=.
    for byte in $mask; do
        case $byte in
            255) n=$((n+8));;
            254) n=$((n+7));;
            252) n=$((n+6));;
            248) n=$((n+5));;
            240) n=$((n+4));;
            224) n=$((n+3));;
            192) n=$((n+2));;
            128) n=$((n+1));;
            0);;
            *) echo 24; return 1;;
        esac
    done
    echo $n
}

# Функция определения метода управления сетью
get_network_manager() {
    local interface=$1
    local options_file="/etc/net/ifaces/$interface/options"

    # Проверяем существование файла настроек
    if [ -f "$options_file" ]; then
        local nm_controlled=$(grep -E "^NM_CONTROLLED=" "$options_file" | cut -d= -f2)
        local disabled=$(grep -E "^DISABLED=" "$options_file" | cut -d= -f2)
        local systemd_controlled=$(grep -E "^SYSTEMD_CONTROLLED=" "$options_file" | cut -d= -f2)

        if [ "$nm_controlled" = "yes" ]; then
            echo "NetworkManager"
        elif [ "$disabled" = "no" ]; then
            echo "EtcNet"
        elif [ "$systemd_controlled" = "yes" ]; then
            echo "SystemD"
        else
            echo "Unknown"
        fi
    else
        # Если файл не существует, проверяем активные сервисы
        if systemctl is-active NetworkManager >/dev/null 2>&1; then
            echo "NetworkManager"
        elif systemctl is-active systemd-networkd >/dev/null 2>&1 && \
             systemctl is-active systemd-resolved >/dev/null 2>&1; then
            echo "SystemD"
        elif systemctl is-active network >/dev/null 2>&1; then
            echo "EtcNet"
        else
            echo "Unknown"
        fi
    fi
}

# Функция настройки NetworkManager
configure_networkmanager() {
    local interface=$1
    local bootproto=$2
    local ipaddr=$3
    local netmask=$4
    local gateway=$5
    local dns_servers=$6
    local domain=$7

    # Создаем или модифицируем соединение
    if [ "$bootproto" = "static" ]; then
        local prefix_length=$(mask2cidr "$netmask")
        nmcli con add type ethernet con-name "$interface" ifname "$interface" ip4 "$ipaddr/$prefix_length" gw4 "$gateway"
        if [ -n "$dns_servers" ]; then
            nmcli con mod "$interface" ipv4.dns "$dns_servers"
        fi
        if [ -n "$domain" ]; then
            nmcli con mod "$interface" ipv4.dns-search "$domain"
        fi
    else
        nmcli con add type ethernet con-name "$interface" ifname "$interface" ipv4.method auto
    fi

    # Активируем соединение
    nmcli con up "$interface"
}

# Функция настройки EtcNet
configure_etcnet() {
    local interface=$1
    local bootproto=$2
    local ipaddr=$3
    local netmask=$4
    local gateway=$5
    local dns_servers=$6
    local domain=$7

    local iface_dir="/etc/net/ifaces/$interface"

    mkdir -p "$iface_dir"

    # Обновляем файл options в зависимости от типа настройки
    if [ -f "$iface_dir/options" ]; then
        # Обновляем существующий файл options, сохраняя другие параметры
        if [ "$bootproto" = "static" ]; then
            # Удаляем старые параметры BOOTPROTO и SYSTEMD_BOOTPROTO если есть
            sed -i '/^BOOTPROTO=/d' "$iface_dir/options"
            sed -i '/^SYSTEMD_BOOTPROTO=/d' "$iface_dir/options"
            # Добавляем новые параметры
            echo "BOOTPROTO=static" >> "$iface_dir/options"
            echo "SYSTEMD_BOOTPROTO=static" >> "$iface_dir/options"
        else
            # Удаляем старые параметры BOOTPROTO и SYSTEMD_BOOTPROTO если есть
            sed -i '/^BOOTPROTO=/d' "$iface_dir/options"
            sed -i '/^SYSTEMD_BOOTPROTO=/d' "$iface_dir/options"
            # Добавляем новые параметры
            echo "BOOTPROTO=dhcp" >> "$iface_dir/options"
            echo "SYSTEMD_BOOTPROTO=dhcp4" >> "$iface_dir/options"
        fi
    else
        # Создаем новый файл options
        if [ "$bootproto" = "static" ]; then
            cat > "$iface_dir/options" <<EOF
BOOTPROTO=static
SYSTEMD_BOOTPROTO=static
EOF
        else
            cat > "$iface_dir/options" <<EOF
BOOTPROTO=dhcp
SYSTEMD_BOOTPROTO=dhcp4
EOF
        fi
    fi

    if [ "$bootproto" = "static" ]; then
        # Записываем IP-адрес с префиксом CIDR
        PREFIX_LENGTH=$(mask2cidr "$netmask")
        if [ -z "$PREFIX_LENGTH" ]; then
            PREFIX_LENGTH=24
        fi
        echo "$ipaddr/$PREFIX_LENGTH" > "$iface_dir/ipv4address"

        # Записываем маршрут по умолчанию
        if [ -n "$gateway" ]; then
            echo "default via $gateway" > "$iface_dir/ipv4route"
        fi

        # Настраиваем DNS через resolv.conf в директории интерфейса
        if [ -n "$dns_servers" ]; then
            # Создаем resolv.conf в директории интерфейса
            echo "# Generated by network configuration script" > "$iface_dir/resolv.conf"
            if [ -n "$domain" ]; then
                echo "domain $domain" >> "$iface_dir/resolv.conf"
                echo "search $domain" >> "$iface_dir/resolv.conf"
            fi

            # Добавляем DNS-серверы
            for dns in $dns_servers; do
                echo "nameserver $dns" >> "$iface_dir/resolv.conf"
            done
        fi

        # Освобождаем DHCP-аренду для интерфейса
        if command -v /sbin/dhcpcd >/dev/null 2>&1; then
            /sbin/dhcpcd -k "$interface" 2>/dev/null || true
        fi
    else
        # Для DHCP очищаем возможные предыдущие статические настройки
        rm -f "$iface_dir/ipv4address"
        rm -f "$iface_dir/ipv4route"
        rm -f "$iface_dir/resolv.conf"

        # Файл type больше не создаем, как было указано в требованиях
    fi

    # Добавляем интерфейс в порядок обработки
    local order_file="/etc/net/ifaces.order"
    if ! grep -q "^$interface$" "$order_file" 2>/dev/null; then
        echo "$interface" >> "$order_file"
    fi

    # Перезапускаем сеть
    systemctl restart network
}

# --- Функция очистки логов и временных файлов ---
clean_system() {
    # Очистка логов (с сохранением структуры каталогов)
    find /var/log -type f -name "*.log" -exec truncate -s 0 {} \;
    find /var/log -type f -name "*.gz" -delete
    find /var/log -type f -name "*.old" -delete
    find /var/log -type f -name "lastlog" -exec rm -f {} \;

    # Очистка временных файлов
    rm -rf /tmp/*
    rm -rf /var/tmp/*

    # Очистка истории команд и пользовательских данных
    for user_home in /home/*; do
        if [[ -d "$user_home" ]]; then
            user=$(basename "$user_home")
            # Очистка bash_history и других историй
            truncate -s 0 "$user_home/.bash_history" 2>/dev/null || true
            # Очистка кэшей приложений
            rm -rf "$user_home/.cache/*" 2>/dev/null || true
        fi
    done
    # Очистка root
    truncate -s 0 /root/.bash_history 2>/dev/null || true
    rm -rf /root/.cache/* 2>/dev/null || true

    # Удаление случайных seed-файлов
    rm -f /var/lib/systemd/random-seed
}

# --- Функция удаления SSH host keys ---
reset_ssh_keys() {
    rm -f /etc/ssh/ssh_host_*
    # Ключи будут сгенерированы при следующем запуске SSH-сервера
}

if [ "$1" = "precustomization" ]; then
    # Выполняем очистку системы
    clean_system
    reset_ssh_keys

    # Проверяем и создаем директорию /etc/sysconfig/network-scripts если нужно
    if [ ! -d "/etc/sysconfig/network-scripts" ]; then
        mkdir -p /etc/sysconfig/network-scripts
    fi
    # Этап предварительной настройки
    VMCUST_DIR=$(ls -d /var/run/.vmware-imgcust* 2>/dev/null | head -n 1)
    if [ -n "$VMCUST_DIR" ]; then
        CUST_CFG_PATH="$VMCUST_DIR/cust.cfg"
        if [ -f "$CUST_CFG_PATH" ]; then
            cp "$CUST_CFG_PATH" "/root/cust.cfg"
        fi
    fi
elif [ "$1" = "postcustomization" ]; then
    # Этап пост-настройки
    if [ ! -f "/root/cust.cfg" ]; then
        exit 1
    fi

    CFG_FILE="/root/cust.cfg"

    # Парсим параметры конфигурации
    BOOTPROTO=$(awk -F' = ' '/^BOOTPROTO/ {line=$2} END{print tolower(line)}' "$CFG_FILE")
    IPADDR=$(awk -F' = ' '/^IPADDR/ {line=$2} END{print line}' "$CFG_FILE")
    NETMASK=$(awk -F' = ' '/^NETMASK/ {line=$2} END{print line}' "$CFG_FILE")
    GATEWAY=$(awk -F' = ' '/^GATEWAY/ {line=$2} END{print line}' "$CFG_FILE")
    HOSTNAME=$(awk -F' = ' '/^HOSTNAME/ {line=$2} END{print line}' "$CFG_FILE")
    DOMAIN=$(awk -F' = ' '/^DOMAINNAME/ {line=$2} END{print line}' "$CFG_FILE")
    MACADDR=$(awk -F' = ' '/^MACADDR/ {line=$2} END{print tolower(line)}' "$CFG_FILE")
    DNS_SERVERS=$(awk -F' = ' '/^NAMESERVER\|[0-9]/ {print $2}' "$CFG_FILE" | tr '\n' ' ')
    DNS_FROM_DHCP=$(awk -F' = ' '/^DNSFROMDHCP/ {line=$2} END{print tolower(line)}' "$CFG_FILE")
    TIMEZONE=$(awk -F' = ' '/^TIMEZONE/ {line=$2} END{print line}' "$CFG_FILE")
    UTC=$(awk -F' = ' '/^UTC/ {line=$2} END{print tolower(line)}' "$CFG_FILE")

    # Определяем сетевой интерфейс
    INTERFACE=$(ip -o link | awk -v mac="$MACADDR" 'tolower($0) ~ mac {gsub(":", "", $2); print $2}')
    if [ -z "$INTERFACE" ]; then
        INTERFACE=$(ip route | awk '/default/ {print $5; exit}')
    fi

    # Определяем метод управления сетью
    NET_MGR=$(get_network_manager "$INTERFACE")

    case "$NET_MGR" in
        "NetworkManager")
            configure_networkmanager "$INTERFACE" "$BOOTPROTO" "$IPADDR" "$NETMASK" "$GATEWAY" "$DNS_SERVERS" "$DOMAIN"
            ;;
        "EtcNet")
            configure_etcnet "$INTERFACE" "$BOOTPROTO" "$IPADDR" "$NETMASK" "$GATEWAY" "$DNS_SERVERS" "$DOMAIN"
            ;;
        "SystemD")
            # Существующая настройка SystemD
            rm -f /etc/systemd/network/*.network
            rm -f /etc/systemd/resolved.conf.d/*.conf

            # Создаем базовую конфигурацию для loopback-интерфейса
            cat > /etc/systemd/network/00-loopback.network <<EOF
[Match]
Name=lo

[Network]
Address=127.0.0.1/8
Address=::1/128
EOF

            # Создаем конфигурацию для основного интерфейса
            CONFIG_FILE="/etc/systemd/network/alterator-${INTERFACE}.network"

            if [ "$BOOTPROTO" = "static" ]; then
                if [ -z "$IPADDR" ] || [ -z "$NETMASK" ]; then
                    exit 1
                fi

                PREFIX_LENGTH=$(mask2cidr "$NETMASK")
                if [ -z "$PREFIX_LENGTH" ]; then
                    PREFIX_LENGTH=24
                fi

                # Создаем конфиг для статического IP с DNS
                cat > "$CONFIG_FILE" <<EOF
[Match]
Name=$INTERFACE

[Network]
Address=$IPADDR/$PREFIX_LENGTH
Gateway=$GATEWAY
EOF

                # Добавляем DNS серверы, если нужно
                if { [ "$BOOTPROTO" = "static" ] || [ "$DNS_FROM_DHCP" = "no" ]; } && [ -n "$DNS_SERVERS" ]; then
                    for dns in $DNS_SERVERS; do
                        echo "DNS=$dns" >> "$CONFIG_FILE"
                    done
                fi
            else
                # Создаем конфиг для DHCP
                cat > "$CONFIG_FILE" <<EOF
[Match]
Name=$INTERFACE

[Network]
DHCP=ipv4

[DHCPv4]
UseDomains=true
UseDNS=yes
EOF

                # Добавляем DNS серверы, если указано не использовать DNS от DHCP
                if [ "$DNS_FROM_DHCP" = "no" ] && [ -n "$DNS_SERVERS" ]; then
                    for dns in $DNS_SERVERS; do
                        echo "DNS=$dns" >> "$CONFIG_FILE"
                    done
                fi
            fi

            systemctl restart systemd-networkd
            systemctl restart systemd-resolved
            ;;
        *)
            echo "Неизвестный метод управления сетью"
            exit 1
            ;;
    esac

    # Общие настройки
    hostnamectl set-hostname "$HOSTNAME"
    sed -i "/127\.0\.1\.1/d" /etc/hosts
    echo "127.0.1.1 $HOSTNAME.$DOMAIN $HOSTNAME" >> /etc/hosts

     # Настройка часового пояса
    if [ -n "$TIMEZONE" ]; then
        timedatectl set-timezone "$TIMEZONE"
    fi

    # Настройка формата времени BIOS (UTC или локальное)
    if [ -n "$UTC" ]; then
        if [ "$UTC" = "yes" ]; then
            # Устанавливаем UTC время в BIOS
            timedatectl set-local-rtc 0
        else
            # Устанавливаем локальное время в BIOS
            timedatectl set-local-rtc 1
        fi
    fi

    # Сохраняем конфигурацию
    {
        echo "CONFIG_SOURCE=$CFG_FILE"
        echo "BOOTPROTO=$BOOTPROTO"
        echo "INTERFACE=$INTERFACE"
        echo "HOSTNAME=$HOSTNAME"
        echo "DOMAIN=$DOMAIN"
        echo "TIMEZONE=$TIMEZONE"
        echo "UTC=$UTC"
        [ -n "$DNS_FROM_DHCP" ] && echo "DNS_FROM_DHCP=$DNS_FROM_DHCP"
        [ -n "$DNS_SERVERS" ] && echo "DNS_SERVERS=\"$DNS_SERVERS\""
    }

    if [ "$BOOTPROTO" = "static" ]; then
        {
            echo "IP_ADDRESS=$IPADDR"
            echo "NETMASK=$NETMASK"
            echo "PREFIX_LENGTH=$PREFIX_LENGTH"
            [ -n "$GATEWAY" ] && echo "GATEWAY=$GATEWAY"
        }
    fi
    rm -f "/root/cust.cfg"
##############################################################################################
    # МЕСТО ДЛЯ ДОПОЛНИТЕЛЬНОЙ НАСТРОЙКИ СИСТЕМЫ
    # Здесь можно добавить команды для окончательной настройки машины:
    # - Доустановка необходимого программного обеспечения
    # - Настройка через Ansible или другие системы управления конфигурациями
    # - Выполнение пользовательских скриптов
    # - Настройка мониторинга, логирования и других сервисов
##############################################################################################
fi

Данный скрипт охватывает все возможные варианты настройки сети: EtcNet, NetworkManager, Systemd-Networkd, как со статическим IP, так и с DHCP.

среда, 18 июня 2025 г.

Windows: Активация LDAP over SSL (LDAPS) при помощи стороннего центра сертификации (CA)

Рассмотрим вариант настройки протокола LDAPS (LDAP over SSL) с использованием стороннего центра сертификации для домена mydomain.local с тремя контроллерами: DC1,DC2,DC3:

1. Создадим шаблон запроса сертификата в виде файла <имя>.inf для каждого контроллера домена. Замените <имя> на FQDN контроллера (например DC1.mydomain.local):

[Version]
Signature="$Windows NT$"

[NewRequest]
Subject = "CN=DC1.mydomain.local" ; FQDN текущего контроллера
KeySpec = 1
KeyLength = 2048
Exportable = TRUE
MachineKeySet = TRUE
SMIME = False
PrivateKeyArchive = FALSE
UserProtected = FALSE
UseExistingKeySet = FALSE
ProviderName = "Microsoft RSA SChannel Cryptographic Provider"
ProviderType = 12
RequestType = PKCS10
KeyUsage = 0xa0

[EnhancedKeyUsageExtension]
OID=1.3.6.1.5.5.7.3.1 ; Server Authentication

[Extensions]
2.5.29.17 = "{text}"
_continue_ = "dns=DC1.mydomain.local&" ; FQDN текущего
_continue_ = "dns=DC1&" ; короткое имя текущего
_continue_ = "dns=DC2.mydomain.local&" ; FQDN других контроллеров
_continue_ = "dns=DC2&"
_continue_ = "dns=DC3.mydomain.local&"
_continue_ = "dns=DC3&"
_continue_ = "dns=ldap.mydomain.local&" ; виртуальное имя для переключения
_continue_ = "dns=mydomain.local&" ; домен верхнего уровня
_continue_ = "dns=MYDOMAIN" ; NetBIOS-имя домена


Важно:
Для балансировки в раздел [Extensions] необходимо добавить FQDN домена и всех контроллеров домена, а также их NetBIOS имена. Кроме того можно дополнительно прописать отказоустойчивые DNS записи, например "ldap.mydomain.local".

Сохраните файл на каждом контроллере (например, C:\Cert\DC1.inf).

2. Сгенерируем CSR для каждого контроллера. Для этого создадим запросы на сертификаты через командную строку (на каждом контроллере):
certreq -new C:\Cert\<имя>.inf C:\Cert\<имя>.csr

3. Теперь необходимо отправить CSR в сторонний ЦС. Передайте файлы DC1.csr, DC2.csr, DC3.csr администратору внешнего ЦС и получите обратно подписанные сертификаты (DC1.cer, DC2.cer, DC3.cer или DC1.p7b, DC2.p7b, DC3.p7b) от ЦС.

4. Установим сертификаты на контроллеры домена. Для этого выполним на каждом контроллере домена команду импорта:
certreq -accept C:\Cert\<имя>.cer

Чтобы проверить установленный сертификат, откройте "mmc", добавьте оснастку "Сертификаты (локальный компьютер)". Убедитесь, что сертификат отображается в Личное → Сертификаты и имеет закрытый ключ.

5. Для завершения настройки LDAPS на контроллерах при включенном брандмауэре откройте 636 порт:
New-NetFirewallRule -DisplayName "LDAPS" -Direction Inbound -Protocol TCP -LocalPort 636 -Action Allow

6. Перезапустите службу LDAP или перезагрузите сервера:
Restart-Service NTDS -Force

7. Проверьте работу LDAPS при помощи "ldp.exe" - выполните подключение к контроллеру домена, указав порт 636 и галочку "SSL".


Отключение незашифрованного LDAP (опционально):

Откройте "Управление групповыми политиками" и выберите "Default Domain Controllers Policy".
Перейдите: "Конфигурация компьютера → Политики → Конфигурация Windows → Параметры безопасности → Контроллер домена: требование цифровой подписи для LDAP-сервера".
Установите параметр: "Требуется цифровая подпись".
Перегрузите контроллеры домена для применения изменений.

понедельник, 26 мая 2025 г.

Windows: Удаление раздела восстановления с диска

Иногда такой раздел мешает в виртуальной среде расширить системный диск с ОС Windows. Для удаления запустите консоль с повышенными привилегиями и выполните:

1. Сначала отключите среду восстановления:
reagentc /disable

2. Затем запустите:
diskpart
list volume


Обратите внимание на номер тома для раздела восстановления, запомните его.

3. Удалите раздел:
select volume N
delete volume override
exit


где N - номер вашего раздела восстановления.

В результате проделанных действий раздел восстановления будет удален, а занятое им пространство освободится.

пятница, 23 мая 2025 г.

Windows: Отключение Azure Arc Setup в Windows Server 2022 и выше

С конца 2024 года вместе с обновлениями Windows приходит новый компонент "Azure Arc Setup", предназначенный для управления Azure ресурсами. Если вы не используете данный функционал, рекомендуется его отключить. Для этого откройте консоль PowerShell с повышенными привилегиями и выполните:

Для Windows 2022:
Disable-WindowsOptionalFeature -Online -FeatureName AzureArcSetup
(Также для Windows 2022 можно отключить данную функцию через выключение компонентов в "Диспетчере серверов")

Для Windows 2025:
DISM /online /Remove-Capability /CapabilityName:AzureArcSetup~~~~

После этого необходимо будет перезагрузить хост.