Материалы к спецкурсу "Администрирование Linux"

ЗАНЯТИЯ март-май 2021

Предполагаемый список тем

Начальная загрузка компьютера. Загрузчик GRUB
Начальная загрузка ОС. Суперпроцесс init и его реализация systemd
Пользователи и пароли. Система PAM для гибкой настройки ограничений доступа
Настройка SUDO для административных работ
ssh как универсальный способ удаленного доступа
Шифорвание и подпись в PGP/GPG
Шифорвание и подпись X.509 (OpenSSL + ГОСТ)
Запуск задач по расписанию. Исторический crond и таймеры в systemd
Брандмауэр Iptables. Работа netfilter в ядре и написание правил
Брандмауэр Firewalld
Cвои программы в роли сетевых сервисов. Сокеты в systemd
Ведение логов. Исторический syslog и современный journal
Контейнеры в Linux ограничение ресурсов и изоляция процессов

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

Большинство дистрибутивов Linux поддерживают репозитории совместимого программного обеспечения и ту или иную систему управления процессом установки программ из репозитория - менеджер пакетов. Чаще всего менеджер пакетов делится на две составляющие. Низкоуровневая часть менеджера, управляет локальной базой установленных пакетов. Высокоуровневая часть менеджера умеет вычислять зависимости пакетов между собой, находить необходимые пакеты в репозиториях и скачивать их для локальной установки через низкоуровневую компоненту.

Название дистрибутива: cat /etc/os-release или lsb_release -a

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

Debian и его производные (в частности Ubuntu) используют связку dpkg, apt, aptitude и пакеты в формате DEB. RedHat (CentOS, SciLinux и т.д.) используют rpm, yum и пакеты в формате RPM. ArchLinux использует менеджер pacman.

Программа Alien позволяет конвертировать пакеты RPM в DEB и обратно.

К сожалению, даже использование единой системы управления пакетами не всегда обеспечивает автоматическую переносимость пакетов из дистрибутива в дистрибутив. Разные дистрибутивы могут строить различные схемы зависимостей и установка пакета от "чужого" дистрибутива может привести к конфликтам в версиях используемых библиотек.

Борьба с зависимостями в Debian

При установке kleopatra в Antix Linux выдается ошибка

$sudo apt install kleopatra
...
Some packages could not be installed. This may mean that you have
requested an impossible situation or if you are using the unstable
distribution that some required packages have not yet been created
or been moved out of Incoming.
The following information may help to resolve the situation:

The following packages have unmet dependencies:
 kleopatra : Depends: libkf5kcmutils5 (>= 5.2.0+git20141003) but it is not going to be installed
             Depends: libkf5notifications5 (>= 5.12.0) but it is not going to be installed
E: Unable to correct problems, you have held broken packages.

последовательные попытки ручной установки пакетов по цепочке приводят к

$sudo apt install libpulse-mainloop-glib0
....
The following packages have unmet dependencies:
 libpulse-mainloop-glib0 : Depends: libpulse0 (= 10.0-1+deb9u1) but 10.0-1.0nosystemd1 is to be installed

опции -f, -m, --ignore-missing не помогают

Ручная установка

apt-get download  libpulse-mainloop-glib0
sudo dpkg -i --force-all libpulse-mainloop-glib0_10.0-1+deb9u1_i386.deb
sudo vim /var/lib/dpkg/status
# Находим зависимости для libpulse-mainloop-glib0
# и удаляем libpulse0
sudo apt-get install kleopatra

Управление пакетами в Debian - dpkg

Утилита управления пакетами dpkg используется в дистрибутиве Debian, а так же в Ubuntu и многих других. Файлы пакетов имеют расширение .deb

Самые важные опции

dpkg -i mc-3.14.deb - установка пакета

dpkg -r mc - удаление пакета с сохранением файлов конфигурации

dpkg --purge mc -полное удаление пакета

dpkg -V mc - проверка целостности установленного пакета

Поисковые запросы

dpkg-query -L mc- список файлов в пакете

dpkg-query -S /etc/mc.ini - поиск пакета, которому принадлежит файл или каталог

Манипуляции с файлом .deb

dpkg-deb --contents mc-3.14.deb - просмотр содержимого

dpkg-deb -x mc-3.14.deb /tmp - извлечение файлов из архива

Управление пакетами в RHEL - rpm

Для установки, удаления и обновления программ в дистрибутивах RHEL, Fedora, Mandriva, AltLinux и некоторых других используется менеджер пакетов rpm. Менеджер пакетов rpm позволяет устанавливать, удалять, верифицировать пакеты соответствующего формата, но не имеет средств для автоматического разрешения зависимостей и поиска в репозиториях. Для автоматизации установки пакетов можно воспользоваться программой yum (Yellowdog Update Manager), которая автоматически разрешает зависимости между пакетами и подгружает необходимые файлы. При необходимости собрать пакет с программой из исходных текстов можно воспользоваться rpmbuild. Для этого необходимо подготовить пакет в формате .src.rpm, включающий исходные тексты программы и .spec файл, описывающий процесс сборки.

Структура пакета

Пакеты именуются по следующей схеме: имя-версия-сборка. Распространяются пакеты в виде файлов, в название которых добавляется .архитектура.rpm. Например, squid-2.5.STABLE8–1.FC3.1.i386.rpm расшифровывается так: программа squid, версия 2.5.STABLE8, сборка 1.FC3.1, архитектура i386 (неоптимизированное приложение под i386 совместимые процессоры). Номер сборки может включать название дистрибутива (FC3 в данном случае, а может и не включать). Архитектура noarch означает скрипты, независимые от архитектуры процессора. Файлы .src.rpm содержат исходные тексты программ и устанавливаются особым образом.

Каждый пакет содержит файлы программ, библиотек, конфигурации, документации и пр., упакованные архиватором cpio. Также пакет содержит дополнительные секции:

  • PROVIDE – предоставляемая функциональность (например, “mail server”) плюс файлы пакета;
  • REQUIRENAME – необходимые для корректной работы пакеты, файлы и т.п. (то, что требуется в REQUIRENAME, должно присутствовать в PROVIDE ранее установленных пакетов);
  • OBSOLETES – список пакетов, которые могут быть удалены т.к. их функциональность и/или файлы заменяютя данным пакетом;
  • PREIN, POSTIN – скрипты, выполняемые до установки (например, остановка обновляемого демона), и скрипты, выполняемые после установки (например, правка конфигурационных файлов под конкретную машину);
  • PREUN, POSTUN – скрипты, выполняемые при удалении;
  • SUMMARY – краткое описание пакета;
  • DESCRIPTION – подробное описание.

и т.д.

Кроме того, каждый пакет принадлежит к некоторой группе Интернет, Разработка Программ, Развлечения и т.п. Просмотреть секции rpm файла можно в mc.

В дальнейших описаниях <пакет> означает имя пакета без i386.rpm (если установлена одна версия программы, то номер версии и сборки тоже можно опустить), а <файл> означает имя файла .rpm. В качестве файла можно указывать его URL, например, http://download.fedora.redhat.com/pub/fedora/linux/core/updates/3/i386/yum-2.2.0-0.fc3.noarch.rpm

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

Вспомогательные опции: -v – подробный вывод сообщений, -h – показ индикатора прогресса установки.

rpm -ivh <файл>... – установить пакет(ы)
rpm -Uvh <файл>... – обновить пакет(ы), если не установлены – установить
rpm -Fvh <файл>... – обновить уже установленный(е) пакет(ы)
rpm -e <пакет>... – удалить пакет(ы)

Просмотр информации об установленных пакетах или файлах rpm

Вспомогательные опции: -a – все установленные пакеты, -p – информация о файле rpm (в примерах будут приведены не везде).

rpm -q <пакет>... – проверка на наличие установленного пакета и его версии
rpm -qa - список всех пакетов
rpm -qi <пакет>... – DESCRIPTION пакета
rpm -qip <файл>... – DESCRIPTION файла
rpm -qR <пакет>... – REQUIERS пакета
rpm -ql <пакет>... – список файлов пакета
rpm -qf <файл_в_файловой_системе>... – определение принадлежности произвольного файла к одному из установленных пакетов

Проверка целостности rpm пакета

Файлы, размещенные в rpm пакете, сопровождаются вычисленной контрольной суммой и, как правило, подписаны цифровой подписью сборщика пакета. После установки пакета контрольные суммы и подписи сохраняются в базе установленных пакетов. Эти вспомогательные данные позволяют выполнить несколько проверок, например, можно проверить, что пакет создан доверенным издателем и что файлы пакета не были подменены после установки.

Первая проверка очень важна при скачивании пакетов из интернета, а вторая при подозрении на взлом компьютера.

Публичные ключи для проверки подписи автоматически устанавливаются при установке из дистрибутива, а также полуавтоматически добавляются при установке rpm пакетов для подключения репозиториев yum. Файлы с ключами в CentOS устанавливаются в каталог /etc/pki/rpm-gpg/. Можно добавить ключ вручную, указав путь к локальному файлу или его url. Файл с ключем должен иметь текстовый формат 'ASCII armored'

 rpm --import PUBKEY-file

После инсталляции к ключам применимы те же команды, что и к установленным пакетам

rpm -qa gpg-pubkey* – список всех ключей
rpm -qi gpg-pubkey-db42a60e – информация (в том числе имя хозяина) о конкретном ключе
rpm -e gpg-pubkey-db42a60e – удаление ключа

Проверка файла пакета на целостность

rpm --checksig <файл>

Проверка установленного пакета на целостность

rpm --verify <пакет>

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

  • S – размер (Size)
  • M – тип файла или права доступа (Mode)
  • 5 – контрольная сумма (MD5)
  • D – мажор или минор устройства устройства (Device)
  • L – содержимое символической ссылки (Link)
  • U – владелец (User)
  • G – группа (Group)
  • T – время модификации (mTime)
  • P – капабилити (caPabilities)

Извлечение и упаковка файлов rpm пакета

Программа rpm2cpio извлекает файлы из RPM пакета в формате архива cpio. Для распаковки файлов вместе со структурой каталогов используется команда cpio с опциями -i – распаковать и -d – создать каталоги:

rpm2cpio <файл.rpm> | cpio -i -d

Если необходимо сохранить установленный пакет в файл, то можно воспользоваться программой rpmrebuild:

rpmrebuild <package>

Особые случаи

Eсли пакет уже установлен и его надо переустановить или необходимо понизить версию пакета, то можно к командам инсталяции или обновления добавить опцию --force.

Если установка или удаление пакета формально нарушает зависимости, но известно, что все будет хорошо, то используется опция --nodeps.

Менеджер пакетов Debian - apt

Менеджер пакетов Apt (Advanced Package Tool) надстроен над утилитой dpkg и предназначен для кэширования списков пакетов из локальных и сетевых репозиториев, вычисления зависимостей между пакетами и автоматизированных скачивания и установки пакетов.

Функциональность менеджера пакетов распределена между несколькими командами (apt-get, apt-cache и др.).

Информационные запросы apt-cache

apt-cache search Midnight - поиск пакета по регулярному выражению в названии или кратком описании

apt-cache show pkg - основные сведения о пакете

Обновление кэша, установка/обновление/удаление пакетов apt-get

apt-get update - обновление кэша

apt-get upgrade - обновление установленных пакетов до последней версии

apt-get install pkg - установка пакета

apt-get remove pkg - удаление пакета

Управление репозиториями

apt-cdrom add - добавить репозиторий на смонтированном CD

Менеджер пакетов RHEL - yum

Основные операции с yum

yum search <строка> – поиск текстовой строки в названиях пакетов и комментариях

yum install <пакет>... – установка пакетов и всего для них необходимого
yum install <файл.rpm> – установка из локального файла
yum upgrade <пакет>... – обновление пакетов до самой последней версии
yum downgrade <пакет-версия>... – откат обновления до определённой версии
yum remove <пакет>... – удаление пакета. Если этот пакет необходим другим, то будут удалены все

yum list z\* – список пакетов на букву z. Пакеты разбиты на установленные и доступные.
yum info <пакет> – просмотр информации о пакете
yum repolist – список всех репозиториев

yum clean – очистка кэша

Описания репозиториев для yum

Описания репозиториев находятся в каталоге /etc/yum.repos.d/ в файлах с расширением .repo.

Формат файла

#в одном файле могут быть описаны несколько репозиториев, каждый  размещается в своей секции  
[epel]  

# человекочитаемое имя. $basearch - архитектура процессора, $releasever - версия дистрибутива
name=Extra Packages for Enterprise Linux $releasever - $basearch

#местоположение репозитория; если репозиторий локальный, то url может иметь вид
#baseurl=file:///var/repos/myrepo
baseurl=http://download.fedoraproject.org/pub/epel/$releasever/$basearch

#если у проекта есть несколько зеркал, то baseurl может быть заменен на путь к списку зеркал в формате xml
#mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-6&arch=$basearch

#репозиторий можно отключить, поставив enabled=0
enabled=1

#надо ли проверять цифровую подпись пакетов и путь к файлу ключа
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6

#если мы предпочитаем получать определённые пакеты из другого репозитория,
# то можем выборочно отключить их в этом
exclude=nagios*

Подготовка локального репозитория для программы yum

  1. Скопировать rpm пакеты своего репозитория в каталог <dir>
  2. Проверить, что установлен пакет createrepo, и установить, если необходимо

         rpm -q createrepo
         sudo yum install createrepo
    
  3. Создать XML данные репозитория

          createrepo <dir>
    

Процесс загрузки Linux

Загрузка операционной системы, это многоступенчатый процесс. В различных дистрибутивах Linux процесс загрузки может несколько изменяться, но общая схема примерно одинакова и состоит из следующих стадий:

  1. В момент запуска процессор передаёт управление по определённому физическому адресу в ПЗУ. В этот момент начинается выполнение кода BIOS/UEFI. Производится инициализация оборудования и выбирается загрузочный носитель. В случае BIOS происходит считывание в ОЗУ начального загрузчика и передача управления на него. Начальный загрузчик обычно занимает один сектор на диске (MBR) и ограничен размером 384 байт ( 512 байт – сектор диска, минус 128 байт – таблица разделов). В зависимости от типа загрузочного устройства загрузочный сектор может считываться из разных мест:

    • При загрузке с дискеты или HDD загрузчик читается из первого сектора физического носителя;
    • При загрузке с CD/DVD – из первого сектора образа загрузочного диска, размещённого в структуре данных CD;
    • При сетевой загрузке – из первого сектора образа загрузочного диска, скачиваемого с сервера по протоколу tftp.

    При форматировании диска в MBR вместо загрузчика иногда пишется программа, которая пишет на экране информационный текст "No bootable device -- insert boot disk and prress any key"

1.1 Начальный загрузчик считывает в память основной загрузчик (GRUB, LiLo, NTLDR) и передаёт управление ему. Поскольку начальный загрузчик очень мал, то, как правило, в его код жестко прописывают сектора, из которых надо прочитать код основного загрузчика. На HDD это может быть пространство между MBR и первым разделом на диске (нулевая дорожка) или зарезервированное место внутри ФС (зарезервированный Inode в ext2fs). На дискете и при использовании образа диска при загрузке с CD или по сети – основной загрузчик может располагаться сразу вслед за первичным загрузчиком и занимать весь объём образа.

При загрузке через UEFI загрузчик или непосредственно ядро Linux считывается целиком из файла на системном разделе EFI с файловой системой FAT32.
  1. Загрузка ядра (vmlinuz) и вспомогательного образа диска (initrd, initramfs). Загрузчик GRUB представляет из себя мини ОС, поддерживающую все основные файловые системы. GRUB ищет конфигурационный файл, в котором прописаны пути к образу ядра и образу вспомогательного диска. При необходимости образ ядра распаковывается в ОЗУ, формируется область памяти, содержащая параметры, передаваемые из загрузчика в ядро, в том числе адрес образа вспомогательного диска.

    Ядро загружаемое через GRUB должно соответствовать соглашениям multiboot или multiboot2 . В соответствии с соглашением, образ ядра включает структуру (например в секции данных), которая начинается с магического числа и содержит информацию о желаемом положении ядра в памяти и точке на которую надо передать управление. Перед передачей управления в ядро в регистр EAX помещается ещё одно магическое число, а в регистр EBX - адрес таблицы с параметрами, подготовленными загрузчиком.

    Вспомогательный диск необходим современным Linux системам из-за модульности ядра и содержит драйверы (ATA, NFS, RAID и т.п.), необходимые для получения доступа к основной файловой системе. Внутри образа находится файловая система в формате архива cpio.

    На этом этапе создаётся процесс с pid=1, в котором происходит выполнение скрипта init, находящегося в корневом каталоге вспомогательного диска. Параметры, передаваемые ядру, фактически передаются в init, как аргументы командной строки.

    Скрипт содержит команды загрузки необходимых драйверов в виде модулей ядра, создание временных файлов устройств в каталоге /dev для доступа к этим модулям, сканирование дисковых разделов для обнаружения и инициализации RAIDов и логических томов. После инициализации логических дисков, делается попытка смонтировать корневую файловую систему, заданную параметром root=. В случае бездисковой сетевой загрузки корневой каталог подключается по NFS.

    На экран выдаются сообщения о загрузке драйверов и о поиске виртуальных томов подсистемы LVM. Этап завершается перемонтированием корневого каталога на основную файловую систему и загрузку в процесс с pid=1 основной программы /sbin/init (или её аналога).

  2. В классическом UNIX'е и старых версиях Linux (примерно до 2012 года) программа init считывает конфигурационный файл /etc/inittab, инициализирует текстовые консоли и, как правило, запускает необходимые службы с помощью набора скриптов, расположенных в каталогах /etc/init.d и /etc/rc*.d. В современных дистрибутивах Linux в файле /sbin/init находится более современная программа запуска служб. Наиболее популярной из подобных программ является systemd, который позволяют существенно сократить время этого этапа загрузки.

На экран на этом этапе выдаются строки, сообщающие о запуске служб, и информация об успешности данного процесса ([OK] или [ERR]).

Загрузка через EFI

Для загрузки через EFI к ядру Linux добавляется заголовок исполняемого файла в формате PE/COFF, что позволяет использовать EFI для загрузки. Часть ядра, связанная с этим заголовком и кодом, на который передаётся управление называется EFI Stub — заглушка для EFI. Исходный код заглушки для архитектуры x86 находится в файлах arch/x86/boot/header.S и arch/x86/boot/compressed/eboot.c.

В x86 используется bzImage, в armzImage в arm64 — неупакованное ядро.

Для загрузки ядра файл bzImage, расположенный в arch/x86/boot/bzImage, необходимо скопировать в системный раздел EFI (ESP) на диске и переименовать с расширением .efi. Без расширения загрузчик EFI откажется его выполнить. Запуск bzImage.efi из файловых систем Linux загрузчиком EFI не поддерживается. Для архитектур arm и arm64 ядро также нужно скопировать в системный раздел, но можно не переименовывать.

Аргументы ядра в командной строке EFI указываются после bzImage.efi, например:

fs0:\Linux> bzImage.efi console=ttyS0 root=/dev/sda4 initrd=\Kernels\initrd-large.img

Параметр initrd= обрабатывается в заглушке, остальные передаются в ядро. Путь к initrd записывается как абсолютный путь от корня ESP. В качестве разделителя каталогов используется обратный слеш.

Для записи строки загрузки Linux в меню EFI можно воспользоваться efibootmgr:

efibootmgr --create \
--disk /dev/sda1 \
--label 'Linux 5.9.1 i915' \ # Строка в меню загрузки
--loader '\EFI\Boot\5.9.1.efi' \ # Образ для загрузки
'initrd=\EFI\gentoo\initramfs.img' \
'root=/dev/sda1 pcie_aspm=off'

Загрузчик GRUB

GRUB (GRand Unified Boot Loader) – Великий унифицированный загрузчик. Разработан в рамках проекта GNU как образцовая реализация мультизагрузчика, способного загружать различные ОС с различных разделов одного диска или различные версии одной ОС в рамках одного раздела.

В настоящий момент под названием GRUB известны две существенно отличающиеся версии программы. Версия 0.97 – "старый" или "legacy" GRUB – используется в RHEL до версии 6 включительно. В этой статье речь именно о нём. GRUB версии > 1.0 – это почти полностью переписанный вариант программы, используемый в Ubuntu, Fedora и многих других дистрибутивах.

Поскольку в MBR есть только 384 байт для размещения загрузчика – GRUB поделен на две части stage1 и stage2. Размер stage1 равен одному сектору на диске – 512 байт. При этом реально используется только 384, а остальное зарезервировано. Stage2 – довольно крупная программа, содержащая драйверы нескольких ФС, интерпретатор командной строки и несколько вспомогательных функций. Её размер составляет примерно 124 КБ. При инсталляции GRUB компонент stage2 должен быть размещён в последовательных секторах на диске, а адрес первого сектора и количество секторов должны быть прописаны в секторе, содержащем stage1. Если носитель не позволяет разместить stage2 в фиксированных секторах, то применяется промежуточный загрузчик stage1.5, поддерживающий одну конкретную ФС и занимающий менее 16 КБ.

Список ФС, поддерживаемых stage2/1.5 (ls /boot/grub/*1_5)

  • e2fs_stage1_5
  • fat_stage1_5
  • ffs_stage1_5
  • iso9660_stage1_5
  • jfs_stage1_5
  • minix_stage1_5
  • reiserfs_stage1_5
  • ufs2_stage1_5
  • vstafs_stage1_5
  • xfs_stage1_5

Ручная правка initrd.img

Иногда хочется сделать в initrd что-то нестандартное, что не предусмотрено стандартным скриптом (mkinitrd, mkinitramfs, dracut и т.п.). В этом случае можно распаковать существующий образ, поправить его руками и снова запаковать. Формат файла - архив cpio сжатый gzip. Единственная тонкость - для cpio надо указывать опцию, задающую внутренний формат архива -H newc

mkdir initrd; cd initrd
gunzip -c /boot/initramfs-2.6.32.158.img | cpio -i --make-directories 
#внесение правок
find . | cpio -o -H newc | gzip > /boot/myinitrd.img

initramfs, как файл, мало отличается от initrd. При создании явно указывается максимальная степень сжатия.

#Упаковка (фрагмент из dracut CentOS 6)
find . |cpio -R root:root -H newc -o --quiet|  $gzip -9 > "$outfile"

В CentOS7 структура файла изменилась. В начало приклеен ещё один маленький несжатый архив cpio "early_initramfs" он же "microcode blob" (необязательный). Программа skipcpio ищет в полученном файле признак конца архива (строку "TRAILER!!!") и выдает хвост. Для сжатия можно использовать различные программы (gzip,bzip2, xz). По умолчанию используется gzip.

#Распаковка:
/usr/lib/dracut/skipcpio /boot/initramfs-3.10.0-957.el7.x86_64.img | zcat | cpio -i  --make-directories 
#Упаковка
find . |cpio -c -o |xz -z -9 -C crc32 -F xz > /boot/myinitrd.img

Внесение исправлений в initrd

Иногда возникает ситуация, при которой загрузка Linux невозможна из за неправильно собранного образа диска initrd. Возникает ситуация курицы и яйца: чтобы исправить initrd необходимо загрузить Linux, чтобы загрузить Linux нужен исправленный initrd.

В CentOS и аналогичных системах последовательность действий такова:

Загрузиться с установочного диска в режим восстановления - Rescue mode. Для этого в момент загрузки на приглашение boot: необходимо ввести linux rescue

Если всё пойдёт нормально, то корневой каталог основной системы будет смонтирован в /mnt/sysimage, загрузочный каталог в /mnt/sysimage/boot. Кроме того текущие каталоги /proc, /sys и /dev будут смонтированы в соответствующие подкаталоги /mnt/sysimage. Если это не случится, то придётся проделать эти операции вручную.

Когда все каталоги смонтированы, можно сменить корневой каталог

#если выяснится, что вы что-то забыли смонтировать, то можно выйти по ^D
chroot /mnt/sysimage

и пересобрать initrd

В CentOS 6

#копируем старый файл
cp -p /boot/initramfs-$(uname -r).img /boot/initramfs-$(uname -r).img.bak
#создаём новый
dracut -f 
#если версия ядра в основной системе отличается от версии на установочном диске, указываем её явно
dracut -f /boot/initramfs-2.6.32-358.el6.x86_64.img 2.6.32-358.el6.x86_64

В CentOS 5

#копируем старый файл
cp -p /boot/initrd-$(uname -r).img /boot/initrd-$(uname -r).img.bak
#создаём новый
mkinitrd -f -v /boot/initrd-$(uname -r).img $(uname -r)
#если версия ядра в основной системе отличается от версии на установочном диске, указываем её явно
mkinitrd -f -v /boot/initrd-2.6.18-371.el5.img 2.6.18-371.el5

Перезагрузка

cd /
sync
telinit 6

Полный пример с драйвером i2o_block (SCSI адаптер Adaptec 2010S), который не загружается автоматически. Пример выполняется в CentOS 5, поскольку в стандартном ядре CentOS 6 поддержка этого драйвера отключена.

После загрузки с CD в Rescue mode выдаётся сообщение, что Linux разделы не найдены и их надо монтировать самостоятельно.

#Загружаем драйвер
insmod i2o_block

#Проверяем, что всё сработало
lsmod
....
dmesg
...

#Создаём файлы устройств на основе информации в dmesg
mkdir /dev/i2o
mknod /dev/i2o/hda b 80 0
mknod /dev/i2o/hda1 b 80 1
mknod /dev/i2o/hda2 b 80 2

#Активируем VolumeGroup
lvm vgchange -a y

#Монтируем тома
mkdir /mnt/sysimage
mount /dev/mapper/VolGroup00-LogVol00 /mnt/sysimage
mount /dev/i2o/hda1 /mnt/sysimage/boot

#Монтируем спецкаталоги
mount --bind /proc /mnt/sysimage/proc
mount --bind /dev /mnt/sysimage/dev
mount --bind /sys /mnt/sysimage/sys

Далее по инструкции, только при создании образа диска надо указать программе mkinitrd дополнительную опцию --preload=i2o_block и отключить сервисы readahead, поскольку они приводят к зависанию драйвера i2o_block:

chkconfig early-readahead off
chkconfig later-readahead off

Загрузка Linux - SysV init

Можно посмотреть видео https://youtu.be/QlLwJhKrMGA.

В прошлый раз мы говорили о том, что происходит при загрузке Linux: вначале стартует загрузчик, он загружает ядро и развертывает временный диск в оперативной памяти, ядро запускает процесс init, init находит настоящий корневой диск, производит такой хитрый переворот - вместо временного виртуального диска на это же самое место в корневой каталог монтируется реальный диск, с этого реального дисков процесс init загружает в себя другой init, который есть на этом реальном диске. После всех этих операций UNIX переходит в состояние обычной работы.

В этой лекции я расскажу, что делает классическая программа init в сочетании со скриптами rc.d в стиле System V (Систем пять). System V - это классическая версия UNIX на которой построены коммерческие UNIX.

Судя по названию, rc.d это некий каталог. Есть такая традиция UNIX - если вся конфигурация чего-либо умещается в один файл, и он называет config, то при разбиении его на отдельные файлы, которые подключаются к основному, создают каталог с аналогичным именем и добавляют к имени .d – config.d. Буква d означает, что это директория и там лежат вспомогательные части конфигурационного файла. У формата конфигурационных файлов программы init есть две традиции: вариант System V, в котором каждая деталь конфигурации держится в отдельном файле в каталоге rc.d, и традиция BSD систем, в которой есть один файл /etc/rc, содержащий много скриптов и переменных, которые отвечают за поведение системы.

В любом случае, при старте системы у нас создается процесс с PID=1, в котором запущена программа, которая называется init. Как вы видели в прошлый раз, если программу init убить, то ядро впадает в панику и прекращает всяческую работу.

Классический System V init читает файл /etc/inittab и выполняет ряд предписаний, которые прописаны в этом файле. Inittab этот текстовый файл каждая строка которого, это, по сути дела, одна команда или какое-то правило поведения. Inittab выглядит так:

id:3:initdefault:

si::sysinit:/etc/rc.d/rc.sysinit

l3:3:wait:/etc/rc.d/rc 3

1:2345:respawn:/sbin/mingetty tty1

ca::ctrlaltdel:/sbin/shutdown -t3 -r now

Вначале строки стоит метка. В чем большой смысл этой метки я не очень понимаю. Можно считать, что это простой текст и все. Вторым пунктом стоит либо так называемый уровень загрузки, либо пустое значение. Уровень загрузки — это либо одно число от 0 до 6, либо список чисел через запятую. Дальше идет некое действие. Действия бывают следующие: wait, respawn, sysinit, ctrlaltdel. Есть и другие действия, но это самые используемые. Наконец, в конце строки написана некая команда с именем исполняемого файла и аргументов, которые этой команде надо передать.

Действие sysinit выполняется однократно при старте системы.

Действие ctrlaltdel это на самом деле не совсем действие – это обработчик сочетания клавиш control alt del. Само нажатие перехватывается ядром системы, и информация об этом пересылается в процесс init, который должен выполнить определенную команду. Например, может быть выполнена команда shutdown, которая выполнит выключение компьютера. В принципе сюда можно прописать любую другую программу, например, echo, которая после нажатия control alt del будет выдавать на все терминалы системы какое-нибудь сообщение. камина консолью так

Действие wait означает, что необходимо запустить команду, дождаться пока она закончится и только после этого продолжить обработку следующих строк. Не знаю, могут ли запускаться такие действия в параллель. Скорее всего, нет.

Действие respawn означает, что надо запустить программу и не дожидаясь ее завершения, перейти в дальнейшем действиям. Если эта программа в последующем завершится, то необходимо ее рестартовать.

Итак, есть однократное выполнение с ожиданием результатов и многократное выполнение в асинхронном режиме – запустились, дождались пока закончить, запустили слова.

Уровни загрузки — это некая условность, которая позволяет управлять загружаемыми службами. Ближайший аналог в windows – это загрузка в безопасном режиме, когда грузится только ограниченное число драйверов и стартует минимальное количество служб, загрузка с отладкой, когда каждое действие дополнительно протоколируются и обычная полноценная загрузка.

В Linux по традиции выделяется 6 вариантов загрузки. Это деление довольно условно.

0 и 6 это выключение. 0 - полное выключение электричество, а 6 - режим перезагрузки.

4 в Linux вообще пропущен

Остаются четыре уровня загрузки:

1 - однопользовательский режим. Если передать загрузчику ключевое слово single, то мы окажемся в однопользовательском режиме, где запущен только один процесса и это шелл администратора системы. Этот режим используется для восстановления системы.

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

2 - тоже текстовый режим, но без подключения сетевых дисков. Дело в том, что традиционные сетевая файловая система nfs, которая используется в UNIX, чрезвычайно устойчива к повреждениям сети. Если мы выключили файловый сервер или обрезали сетевой кабель, то сетевая файловая система nfs будет предпринимать многочисленные попытки восстановиться и эти попытки настолько длительны, что я ни разу не смог дождаться времени, когда же наконец появится сообщение об ошибке. Возможно это произойдёт через час, а может и через 6 часов. Всё это время драйвер nfs будет держать компьютер, не давая ничего сделать. Поэтому, если у нас упала сеть или файловый сервер в настройках написано, что при старте необходимо подмонтировать внешние диски, то попытка загрузится в полноценный режим приведёт к тому, что у вас все зависнет. Для этого случая и предусмотрен второй вариант загрузки - все как в третьем, только сетевые диски не подключаются. Сам сетевой адаптер работает, IP адрес назначается, интернет доступен.

5 - то же самое что и 3, но с запуском x window - графического интерфейса.

Можно считать, что между уровнями есть некоторая последовательность переходов:

режим 2 включает себя 1 + многопользовательский режим. 3 включает 2 + монтирование сетевых файловых систем. Наконец, 5 включает в себя 3 + запуск графической подсистемы. Будет ли это реализовано последовательно или нет - это проблема дистрибутива. Вообще говоря, администраторы могут самостоятельно настроить файл inittab так, чтобы эти режимы запускались последовательно, а можно сделать так чтобы все было абсолютно независимо - переключаясь в очередной режим, убираем все что было сделано на предыдущем шаге, и настраиваем все с нуля.

Рассмотрим строки реального файла. Они очень просты.

l3:3:wait:/etc/rc.d/rc 3

Запускается какая-то программа, которая должна выполнить все необходимые действия, которые ожидаются на третьем уровне. Наверно, на третьем уровне нужно настроить сетевые интерфейсы, запустить драйвер терминалов, стартовать какие-то службы. Только после того, как всё этого завершится мы сможем работать в системе. Поскольку надо дождаться завершения запуска, мы выбираем действие wait.

Программа запуска называется rc и запускается с номером уровня в качестве параметра. Сама программа init достаточно простая. Она умеет построчно читать свой файл с простым синтаксисом и стартовать новые процессы, запуская какие-то вспомогательные программы. Вся логика уровней загрузки спрятана в скрипте rc. Запустив rc с параметром 3 мы перейдем на третий уровень, с параметром 5 - на пятый.

Программа rc тоже очень простая. Это скрипт который выполняет все файлы в каталогах, соответствующих уровню загрузки, например, /etc/rc3.d/. В этих каталогах находятся исполняемые файлы, которые принимают один параметр - либо start, либо stop. Если файл запущен с параметром start, то он стартует службу, если с параметром stop, то останавливает её. Например, network start будет настраивать сетевые интерфейсы, а network stop будет переводить интерфейсы в выключенное состояние. Кроме сетевых интерфейсов есть скрипты подключения/отключение сетевых файловых систем, запуска/остановки сервисов и т.д.

Имена файлов в каталогах построенным по определенным правилам. Они начинаются либо с буквы K либо с буквы S, за которыми идет число и имя службы.

Скрипт rc просматриваем содержимого каталога rc3 и выбирает оттуда все файлы которые начинаются с буквы K (kill). Файлы упорядочиваются в порядке возрастания номера и выполняются с параметром stop. Потом те же действия выполняются с файлами на букву S (start), которые запускаются с параметром start. Вот в общем и вся процедура перехода на определенный уровень.

Можно предположить, что в каталоге /etc/rc0.d/ лежат только файлы, начинающиеся на букву K, поскольку при выключении надо все остановить, а в каталоге /etc/rc1.d/ будет один файл на буку S для запуска консоли администратора.

Для простоты программирования есть отдельный каталог /etc/init.d/, в котором лежат те же самые файлы только без буквы цифр в начале имени. На самом деле, файлы в каталогах уровней это просто символические ссылки на основные файлы. Так /etc/rc3.d/S10apache это ссылка на файл /etc/init.d/apache. Буквы и цифры в названии ссылок нужны для того, чтобы скрипт rc вызвал их в нужном порядке и с нужными аргументами.

В системах, которые построены по такому принципу, чтобы стартовать или остановить какую-либо службу в каталоге /etc/init.d/ надо найти файл который, который ей соответствует, и запустить его с параметром start или stop. Чем не нравится запускать службы именно таким способом - явно вызывая скрипты. Дело в том, что в командной строке linux замечательно работает автодополнение. С его помощью очень быстро можно ввести путь до файла запуска.

Чтобы спрятать от пользователя конкретную реализацию поверх системы скриптов и символических ссылок написаны две вспомогательные программы.

Программа chkconfig позволяет манипулировать символическими ссылками на соответствующие скрипты. Чтобы посмотреть, что стартует, а что останавливаться на каждом из уровней можно воспользоваться командой ls и выдать список скриптов в соответствующем каталоге, но проще воспользоваться командой chkconfig –list. Программа chkconfig пробегает по всем каталогам rc и выдает список того что стартует, а что останавливается на каждом уровне. Если мы хотим, чтобы при старте системы у нас что-то автоматически стартовала определенная службу мы выполняем chkconfig <имя службы> on и скрипт создает ссылку для запуска в нужном каталоге и с правильным именем. Запуск chkconfig <имя службы> off приводит к удалению ссылки для запуска и созданию ссылки для остановки. Таким образом программа chkconfig позволяет управлять списком служб, которые стартуют в момент старта системы.

Ещё одна программа - service используется для ручного запуска и остановки служб. Service это обертка, которая позволяет не обращаться напрямую к скрипту, а указать имя службы и сказать хотим мы ее стартовать или остановить. В bash, который я использую, нет автодополнения для команды service, поэтому мне проще набрать путь к скриптам.

В стартовых скриптах аргументы start и stop должны обрабатываться обязательно. Кроме того, можно придумать какие-то свои аргументы, которые будут делать что-то полезное.

В большинстве скриптов реализована опция status, которая показывает запущена служба или нет. Когда мы выполняем start, то скрипт после успешного запуска службы получает ее идентификатор PID и записывать его в определенный файл. По команде stop файл удаляется. Обычно такие файлы создаются в каталоге /var/run/. Команда status проверяет есть ли такой файл. Его нет, то сообщает, что служба не запущена. Если файл есть, то она извлекает из него идентификатор процесса и проверяет текущий список процессов. Если этот идентификатор присутствует все запущено, если программа по каким-то причинам поломалась, то статус выдаёт, что была сделана попытка запустить эту службу - файл существует, но сама служба не запущена.

Опция restart последовательно выполняет внутри скрипта две команды – сначала stop, а потом старт. Это совершенно необязательная команда - просто удобная. Наконец, есть службы, которые позволяет на ходу перечитать какие-то конфигурационные файлы. Для них добавляют команду reload, задачей которой является отправка службе сигнала о том, что конфигурация изменилась. Отдельный случай, команды save и load для сохранения конфигурации брандмауэра.

Если администратор системы вместо остановки или старта отдельных службы хочет всю систему перевести на определенный уровень, то этого можно достичь одним из двух способов. Можно вызвать прямо программу /sbin/init. Если ее вызвать с определенным числом в качестве параметра, то она выполнит все инструкцию из файла inittab, для которых прописывал соответствующий уровень. Если запустить, например, /sbin/init 1, то init найдет в своем конфигурационном файле все строчки, в которых есть уровень 1 и выполнит их. В некоторых системах команда shutdown реализована как /sbin/init 0, поскольку нулевой уровень соответствует остановке системы. В последнее время для перехода между уровнями появилась специальная программа под названием telinit, которая является ссылкой на init. Её задача – переслать процессу init сигнал о том, что администратор желает перейти на определенный уровень. telinit q сообщает init о том, что надо перечитать файл inittab. В старых системах это достигалось посылкой сигнала SIGHUP процессу с PID=1 (kill –HUP 1).

Ещё несколько строк в inittab, это запуск терминалов

1:2345:respawn:/sbin/mingetty tty1

Для того, чтобы обеспечить диалоговую доступ к системе, вы inittabе может присутствовать некоторое количество строчек такого рода. 2345 это уровни, на которых надо запускать команду, respawn означает, что программу надо перезапускать в случае завершения. Программа getty – это программа управления терминалом. Традиционно терминал в UNIX называется телетайпом, поскольку первыми терминалами были электрические пишущие машинка. Соответственно, tty это сокращение от телетайпа. Mingetty – программа, которая умеет работать с виртуальными терминалами на персональном компьютере. Она умеет настраивать драйвер терминала, а в качестве параметров получает имя устройства терминала, который надо настроить. В каталоге /dev/ есть файл устройства tty1, который соответствует первому виртуальному терминалу. Если бы у нас был модем и мы хотели бы инициализировать его момент загрузки, то могли бы вызвать getty с параметром ttyS0, который соответствует порту COM1. При инициализации модема можно было бы задать дополнительные параметры: скорость соединения 19200 бод, 7 или 8 бит в байте, четность, количество стоп-битов.

S0:2345:respawn:/sbin/getty ttyS0 19200 8 n 1

В прошлый раз я рисовал цепочку, в которой процесс вызовом fork делаются свою копию, дочерняя копия вызовом exec загружает в свою память другую программу, а после завершения сообщает об этом родительскому процессу.

Текстовые пользовательские сеансы устроены на таких цепочках: сначала init делает свою копию и запускает в ней программу mingetty. Mingetty инициализирует терминал и клавиатуру, а потом запускает в том же процессе программу login. Login выводит на экран приглашения на ввод имени и пароля и, если все прошло успешно то назначает себе привилегии пользователя и в том же процессе, затирая самого себя, запускает интерпретатор пользователя, например, bash. Когда пользователь набирает команду exit, то интерпретатор завершает жизненный путь этого процесса. Когда процесс завершается, init получает об этом сигнал. Init смотрит, что полагается делать, видит действие respawn, снова запускает программу mingetty, которая заново инициализирует терминал и все повторяется. Таким образом каждый сеанс находится внутри одного процесса. Как только мы вышли из сеанса наш процесс закончился и тотчас же запустилась программа, которая почистит за нами терминал и восстановит все настройки по умолчанию.

В файле inittab есть есть ещё одно специальное ключевое слово initdefault - уровень по умолчанию. Если через ядро init получил параметр single, то мы загрузимся на уровень 1. Если через загрузчик ничего не передали, то используется значение по умолчанию. Если после установки графической оболочки оказалось, что наш компьютер слабоват для графики, то можно установит уровень по умолчанию на 3, и после следующей перезагрузки мы попадаем на третий уровень - то есть в текстовый режим. Установили систему без графического режима, потом доустановили все пакеты для x window, поменяли уровень по умолчанию на 5 и после следующей перезагрузки попали сразу в графический режим.

В этой системе скриптов иногда хочется сделать что-то свое, например, при старте удалить все файлы в каталоге /tmp/. Для этого есть отдельный файл под названием /etc/rc.local, который запускается после всех остальных. Это просто скрипт без параметров, в который можно прописать всё, что угодно. Например, на одном из моих роутеров в момент старта системы в этом файле прописываются таблицы маршрутизации. Мне было лень искать где находятся соответствующие стандартные скрипты из дистрибутива и проще оказалось прописать команды в rc.local.

Сеть

firewalld

Список стандартных сервисов

firewall-cmd --get-services

Добавление разрешения на сервис или порт

firewall-cmd --permanent --add-service=ssh
firewall-cmd --permanent --add-port=4444/tcp

Удаление разрешения

firewall-cmd --permanent --remove-service=ssh

Список установленных разрешений

firewall-cmd --permanent --list-all

После всех установок необходимо их применить

firewall-cmd --reload

Запуск сетевых служб через systemd

Для запуска сетевой службы в стиле inetd, но через systemd необходимо создать два файла:

  1. Файл, описывающий сокет, на котором ожидается соединение;
  2. Файл, описывающий сервис - программу, которую надо запустить после подключения клиента к сокету.

В файле сокета ListenStream - указывает на протокол TCP (для UDP используется параметр ListenDatagram=). В качестве значения ListenStream может быть указан номер порта или пара IP:Port. Параметр Accept=yes указывает на то, что для каждого подключения надо стартовать отдельный экземпляр программы. Чтобы проинформировать приложение о свойствах соединения, ему передаются переменные окружения REMOTE_ADDR и REMOTE_PORT.

/etc/systemd/system/baz.socket:

[Unit]
Description=Baz Socket

[Socket]
ListenStream=127.0.0.1:9999
Accept=yes

[Install]
WantedBy=sockets.target

Имя файла сервиса должно заканчиваться на @, чтобы указать, что одновременно может быть запущено много экземпляров данной программы. В данной конфигурации стандартный ввод программы будет назначен на /dev/null, стандартный вывод будет перенаправлен в сокет, сообщения об ошибках будут сохранены в логах journald. Программа может быть написана на чем угодно. Переменным окружения VAR1 и VAR2 будут назначены значения "word1 word2" и 'word3" соответственно, текущий каталог будет изменен на /tmp, вместо %i будет подставлено имя экземпляра программы, которое также будет видно в списке запущенных сервисов между @ и .service.

/etc/systemd/system/baz@.service:

[Unit]
Description=Baz Service
Requires=baz.socket

[Service]
Type=simple
Environment="VAR1=word1 word2" VAR2=word3
ExecStart=/usr/local/baz %i
WorkingDirectory=/tmp
StandardInput=socket
StandardOutput=socket
StandardError=journal
TimeoutStopSec=5

[Install]
WantedBy=multi-user.target

/usr/local/bin/baz:

#!/bin/bash
pwd
echo ${VAR1}
echo ${VAR2}
echo $1

Ручная настройка сети в Linux

Для доступа к сетевым картам в Linux используются так называемые интерфейсы. Интерфейсы это не файлы устройств и их нет в каталоге /dev. Интерфейсы создаются динамически и не всегда связаны с сетевыми картами. Например интерфейс ppp0 - это интерфейс VPNа, организованного по протоколу PPTP, а интерфейс lo это виртуальная сетевая карта с адресом localhost (127.0.0.1). В Linux имена интерфейсов традиционно состоят из мнемонического типа интерфейса и его порядкового номера. Карты ethernet доступны через интерфейсы eth0, eth1 и т.д. В системах, использующих systemd способ именования другой - интерфейсы имеют имена вида enp2s0 (en -Ethernet, p - PCI, 2 - номер на шине) Список всех интерфейсов можно посмотреть командой ifconfig -a или ip link.

Привязка интерфейса к карте

При наличии нескольких сетевых карт возникает вопрос о порядке их нумерации. В CentOS 6 эта задача возложена на подсистему обнаружения и конфигурации устройств - udev. В системах с systemd правила именования встроены в udev, но могот быть переопределены, как написано ниже.

Конфигурационный файл переименования интерфейсов обновляется автоматически при первом обнаружении очередной сетевой карты и находится в файле /etc/udev/rules.d/70-persistent-net.rules. Файл состоит из строк такого содержания:

# PCI device 0x1af4:0x1000 (virtio-pci)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="52:54:00:29:24:1e", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"

Видно, что нумерация опирается на аппаратный (MAC) адрес карты. Если в компьютере заменить карту, то интерфейс eth0 станет недоступным, а новая карта получит имя eth1. Если есть желание вручную назначить имена картам, то можно отредактировать этот файл, выставив желаемые соответствия между MAC адресами именами интерфейсов (возможно потребуется перезагрузка).

ifcfg

Классическая утилита конфигурации сетевых интерфейсов ifcfg

#просмотр списка активных интерфейсов
ifcfg

#просмотр конфигурации конкретного интерфейса
ifcfg eth0

#просмотр списка доступных интерфейсов
ifcfg -a

#настройка ip адреса и активация интерфейса
ifconfig eth0 192.168.0.1 netmask 255.255.255.0 up 

#деактивация интерфейса
ifconfig eth0 down

route

Настройка таблицы маршрутизации route

#добавление шлюза по умолчанию
route add default gw 192.168.0.1

#добавление маршрута в локальную сеть
 route add -net 192.56.76.0 netmask 255.255.255.0 dev eth0

#добавление маршрута в удаленную сеть
route add -net 192.57.66.0 netmask 255.255.255.0 gw 192.168.0.2

#удаление маршрута
route del -net 192.57.66.0 netmask 255.255.255.0 gw 192.168.0.2

#просмотр таблицы маршрутизации
route
#или
netstat -r

ip

В современных дистрибутивах линукса на смену ifconfig и route приходит универсальная утилита ip

#просмотр списка доступных интерфейсов
ip link

#просмотр статистики по интерфейсам
ip -s link

#просмотр ip адресов
ip addr

#просмотр таблицы маршрутизации
ip route

DNS

Адреса серверов DNS и имя локального домена вписываются в файл /etc/resolv.conf

search example.com
nameserver 8.8.8.8

Ручная настройка сети в ArchLinux

Для просмотра доступных сетевых интерфейсов используется команда ip link

ArchLinux использует для настройки сети systemd/netctl. Для конфигурации используются файлы профилей, которые хранятся в /etc/netctl/. В данном каталоге есть подкаталог examples/ из которого можно копировать файлы с образцами профилей в /etc/netctl/. Например:

cp /etc/netctl/examples/ethernet-static /etc/netctl/enp1s0-work

Содержимое enp1s0-work после редактирования

Interface=enp1s0
Connection=ethernet
IP=static
Address=('10.1.10.2/24')
Gateway='10.1.10.1'
DNS=('10.1.10.1')

Базовые команды netctl

#активация профиля 
netctl start enp1s0-work

#включение автоматической активации с текущими настройками профиля при старте системы
netctl enable enp1s0-work

#обновление конфигурации автостарта после изменения настроек профиля
netctl reenable enp1s0-work

Ручная настройка сети в Ubuntu

Просмотр доступных интерфейсов - ifcfg -a

Файл конфигурации интерфейсов - /etc/network/interfaces. auto - говорит о том, что интерфейс надо конфигурировать при старте системы.

iface eth0 inet static 
address 192.168.0.1 
netmask 255.255.255.0 
gateway 192.168.0.254 
auto eth0 

iface eth1 inet dhcp
auto eth1 

После смены настроек в /etc/network/interfaces, необходимо отключить и снова включить интерфейс.

ifdown eth0
ifup eth0

Ручная настройка сети в CentOS 6

Общие настройки сети

Файл /etc/sysconfig/network используется стартовыми скриптами и содержит ключевые параметры - нужна ли сеть, нужно ли конфигурировать IP v6, имя компьютера. Сюда можно вписать шлюз по умолчанию, но CentOS 6 ориентируется на динамическое подкючение к сетям через WiFi и вписывает его в конфигурацию подходящего интерфейса.

NETWORKING=yes
NETWORKING_IPV6=no
HOSTNAME=wwww.example.com

GATEWAY=10.10.10.1

Конфигурация интерфейса

Файлы в каталоге /etc/sysconfig/network-scripts с именами вида ifcfg-eth0

Интерфейс, получающий адрес по DHCP

# динамическая конфигурация интерфейса
ONBOOT="yes"
DEVICE="eth0"
BOOTPROTO="dhcp"

Ручная конфигурация

# статическая конфигурация интерфейса
ONBOOT="yes"
DEVICE="eth1"
BOOTPROTO="static"
IPADDR=145.14.137.221
PREFIX=24
# конфигурация шлюза и DNS
GATEWAY=192.168.1.1
DEFROUTE=yes
DNS1=192.168.1.14
# NM - NetworkManager - графическая оболочка + автоматизация настроек
NM_CONTROLLED="no"

Дополнительный IP адрес на интерфейсе eth1

ONBOOT=no
DEVICE=eth1:0
BOOTPROTO=static
IPADDR=172.16.12.6
NETMASK=255.255.0.0
# следующие два параметра можно не писать
# они вычисляются из IP и маски
BROADCAST=172.16.255.255
NETWORK=172.16.0.0

Инициализация VLAN на eth1

DEVICE=eth1.72
VLAN=yes
VLAN_TRUNK_IF=eth1
BOOTPROTO=static
IPADDR=10.10.0.1
NETMASK=255.255.255.192
ONBOOT=yes

Настройка DNS

Файл /etc/resolv.conf

# мой домен, для подстановки в короткие имена
search example.com
# сервер DNS
nameserver 8.8.8.8

Ручная настройка имен хостов файл /etc/hosts

127.0.0.1               localhost.localdomain localhost ANY
::1             localhost6.localdomain6 localhost6

194.87.0.50           www.ru

Настройка брандмауэра

Файл /etc/sysconfig/system-config-firewall правила для настройки программой system-config-firewall

Файл /etc/sysconfig/iptables текущие правила, сохраненные на случай перезагрузки.

После ручного изменения правил их можно сохранить командой service iptables save

Запуск сетевых служб через xinetd

Для написания сетевой службы в Linux не обязательно уметь программировать сокеты. Сокет, с точки зрения прикладной программы, выглядит как обычный файловый дескриптор, из которого можно читать и в который можно писать любыми стандартными функциями ввода/вывода. Поэтому появляется возможность перенаправить стандартный ввод/вывод любой программы в заранее подготовленный сокет. Для такого перенаправления служит программа xinetd.

Конфигурация xinetd, как правило, разделяется на две части: значения по умолчанию – /etc/xinetd.conf и настройки для отдельных служб, по одному файлу в каталоге /etc/xinetd.d/ на службу.

Чтобы запустить свою сетевую службу, необходимо создать ещё один файл в /etc/xinetd.d/. Имя файла особого значения не имеет, но обычно выбирается по имени службы. Предположим, что служба называется mynetd, запускается от имени пользователя user1 и выполняет команду sleep 10. Служба должна ожидать TCP соединение на порту 8888.

Конфигурационный файл /etc/xinetd.d/mynetd будет выглядеть так:

service mynetd
{
    disable = no
    # Если не написать UNLISTED, то xinetd будет искать имя службы и номер порта
    # в файле /etc/services
     type = UNLISTED

    # stream = TCP, datagram = UDP
    socket_type = stream
    port = 8888
    # Можно считать, что для протокола TCP wait всегда равен 'no',
    # а для протокола UDP – всегда 'yes'
    wait = no

    user = user1
    # При считывании конфигурации файл службы должен существовать и заданный пользователь
    # должен иметь право на его выполнение
      server = /bin/sleep
      server_args = 10
}

Параметр wait интерпретируется следующим образом: если socket_type = datagram и wait = yes, то при появлении на порту данных стартует новый процесс со входом/выходом, перенаправленным в сокет. Пока этот процесс не завершится, xinetd не контролирует наличие новых данных на порту, оставляя их запущенной программе. Если поставить wait = no, то на каждую дейтаграмму будет запускаться новый процесс, разделяющий со своими предшественниками общий сокет. В такой ситуации невозможно предсказать, какой копии программы достанутся входные данные из сокета. В принципе, такой подход возможен, если обработка дейтаграммы идёт долго, а писать многопоточный сервис лень. Для TCP ситуация обратная, wait = yes имеет смысл только для многопоточных программ, иначе первый процесс захватит сокет и не отдаст его, пока программа не завершится.

Брандмауэр уровня приложений - tcpwrappers

TCP Wrappers – изначально набор вспомогательных программ 'запускалок' (tcpd, miscd и вспомогательные программы), для контроля за IP адресами клиентов, стартующих сетевые сервисы через inetd. Основная функция, управляющая проверкой правил, hosts_access(request) была в последующем выделена в отдельную библиотеку libwrap. В настоящее время эту библиотеку используют самые разнообразные сервисы, такие как xinetd, sshd, rsyncs и т.п. Полный список программ, использующих TCP Wrappers, можно получить, выполнив следующую команду:

strings -f  /usr/sbin/* /usr/local/sbin/* |  grep hosts_access

Функция hosts_access использует два конфигурационных файла /etc/hosts.allow и /etc/hosts.deny (в FreeBSD только /etc/hosts.allow), которые могут иметь классический или расширенный синтаксис.

Классический вариант

В классическом варианте вначале проверяются все правила из hosts.allow. Если хоть одно правило применимо к паре сервис-клиент, то соединение устанавливается. Затем проверяются все правила из hosts.deny. При нахождении соответствия соединение отклоняется. Если правила нет, то соединение устанавливается. Чтобы явно разрешить доступ только по правилам из hosts.allow, необходимо добавить в hosts.deny правило ALL:ALL.

Классический синтаксис описан в man странице HOSTS_ACCESS(5). Файлы состоят из строк вида

daemon_list : client_list [ : shell_command ]

где

  • daemon_list – список имён сервисов (в xinetd имена прописываются явно в конфигурации службы, для остальных программ они совпадают с именем исполняемого файла) или ключевое слово ALL;
  • client_list – список имён/адресов клиентов;
  • shell_command – вспомогательная команда, например, для логирования событий. В современном варианте это поле имеет другой формат.

Современный вариант

Файлы /etc/hosts.allow и /etc/hosts.deny эквивалентны по своему назначению. Каждое правило может содержать результат – allow или deny. Если в правиле результат не прописан явно, то он вычисляется по правилу классического варианта. Можно считать, что все правила находятся hosts.allow, а hosts.deny остается пустым. Выполняется первое найденное правило.

Синтаксис правил описан в man странице HOSTS_OPTIONS(5). Файлы состоят из строк вида

daemon_list : client_list : option [: option ...]

daemon_list, client_list полностью совместимы с классическим синтаксисом, а опции позволяют понизить привилегии, запустить дополнительную программу параллельно с сервисом или вместо него, и, наконец, принять решение allow или deny. Опции выполняются слева направо. Опция allow/deny должна стоять последней, поскольку после неё произойдёт запуск сервиса или прекращение работы.

Для запуска дополнительных программ используются две опции: spawn shell_command – запуск программы в параллельном процессе одновременно с сетевым сервисом, и twist shell_command – запуск программы в текущем процессе вместо сервиса. Командам в качестве параметров можно передать некоторую информацию о соединении. spawn не влияет на запуск основного сервиса, поэтому за ней должна следовать опция allow или deny. twist затирает текущий процесс и, соответственно, дальнейшие проверки опций. Однако, через параметры в twist можно передать имя исполняемого файла сервиса, чтобы выполнить его после дополнительных проверок.

Кроме опций запуска программ, существуют опции смены владельца, установки маски создаваемых файлов, понижение приоритета и т.п.

В конце списка правил можно добавить правило по умолчанию ALL:ALL:deny, иначе подразумевается наличие ALL:ALL:allow.

Формат списка client_list

Список состоит из полей, разделённых пробелами и/или запятыми. Список может состоять из основной части и исключений, следующих за ключевым словом EXCEPT. Возможна группировка списков и исключений с помощью круглых скобок. В списке могут присутствовать IP адреса, имена хостов, ключевые слова и шаблоны.

Ключевые слова (часть опущена):

  • ALL – все хосты
  • PARANOID – хосты, у которых цепочка преобразований IP->Имя->IP даёт адрес, отличный от исходного.

Шаблоны (часть опущена):

  • .example.org – все имена из домена
  • 192.168.1. – все IP адреса подсети
  • 192.168.132.0/255.255.254.0 – IP адреса по маске
  • /etc/deny.list – текстовый файл, состоящий из строк, содержащих списки хостов в любой описанной выше форме
  • www.*.ru - подстановка вместо звёздочки любого количества символов. Не может быть частью предыдущих шаблонов.

Подстановки при запуске внешних команд

  • %a (%A) Адрес клиента (сервера)
  • %h (%H) Имя клиента (сервера)
  • %d Имя сервиса
  • %p Идентификатор процесса (PID)

Примеры

#классический стиль
sshd : .example.com
vsftpd : 192.168. 
ALL : 192.168.1.0/255.255.255


# Разрешаем подключение из домена .example.com
# кроме station15.example.com
sshd : station15.example.com : deny
sshd : .example.com : allow
#Дополнительно запрещаем всем кроме домена *.hacker.org
sshd : ALL EXCEPT *.hacker.org:twist /bin/echo "Reject - bad host name %h"
# Фактически разрешаем *.hacker.org (остальные уже заблокированы)
# с логированием соединений в файл /tmp/sshd.connections
sshd : ALL:spawn /bin/echo "%d at %I connected from %i" > /tmp/sshd.connections: allow
# Запрещаем остальные соединения
ALL:ALL:deny

Ограничение трафика на маршрутизаторе

Ограничение трафика на маршрутизаторе делается в два этапа:
1. Классификация пакетов с помощью netfilter или фильтров iproute2
2. Создание нескольких очередей пакетов с помощью iproute2

Пакеты распределяются в зависимости от класса на несколько очередей в которых ждут своей очереди на отправку. Каждая очередь имеет ограничения на полосу пропускания, приоритет и еще некоторые параметры. При переполнения очереди пакеты соответствующего класса начинают отбрасываться.
Очереди организованы в древовидную иерархию. Каждая очередь может быть разбита на более мелкие. Корневые очереди, связанные непосредственно с «хэндлером» интерфейса имеют абсолютные ограничения по пропускной способности. Дочерние очереди могут «заимствовать» друг у друга неиспользуемую полосу пропускания.

Классификация пакетов с iptables

Первый этап выполняется с помощью программы /sbin/iptables.

Маркируем пакеты в зависимости от каких либо параметров, например по размеру, номеру порта, ip адресу. Для специфических случаев можно дописывать свои модули для netfilter. Например модуль IP2P http://www.ipp2p.org позволяет выбирать пакеты p2p сетей.

Приписываем класс пакета в соответствии с проставленными меткам

Вообще говоря, можно было бы классифицировать пакеты сразу. Например выделим входящий HTTP трафик в отдельный класс

iptables -t mangle -A POSTROUTING -o eth0 -s 0/0 --source-port 80 -j CLASSIFY --set-class 1:10

Маркировка позволяет проверять только несколько первых пакетов в соединении. Для того, чтобы не исследовать каждый пакет используется модуль CONNMARK который позволяет маркировать все пакеты принадлежащие соединению.

Пример классификации P2P трафика. Классы для различных интерфейсов определяются независимо, что позволило использовать класс 1:20 для входящего и для исходящего трафика.

iptables -t mangle -A PREROUTING -p tcp -j CONNMARK --restore-mark
iptables -t mangle -A PREROUTING -p tcp -m mark ! --mark 0 -j ACCEPT
iptables -t mangle -A PREROUTING -p tcp -m ipp2p --ipp2p -j MARK --set-mark 1
iptables -t mangle -A PREROUTING -p tcp -m mark --mark 1 -j CONNMARK --save-mark

iptables -t mangle -A POSTROUTING -o eth0 -m mark --mark 1 -j CLASSIFY --set-class 1:20
iptables -t mangle -A POSTROUTING -o eth1 -m mark --mark 1 -j CLASSIFY --set-class 1:20

Создание очередей пакетов

Этап второй выполняется с помощью /sbin/tc.

Создаем связанную с интерфейсом очередь исходящих пакетов, указываем класс по умолчанию. Создаем корневой класс, назначаем лимит. Создаем дочерние классы, указываем лимиты для них (Обязательно должен быть создан класс используемый по умолчанию).

Теперь каждый пакет попадает в свою очередь. Если очередь переполняется, пакеты отбрасываются не доходя до аппаратного уровня.
Пример: Общая пропускная способность канала 10 Мбит/с. Внешний интерфейс eth0, внутренний eth1. Ограничиваем исходящий трафик P2P сетей из предыдущего примера полосой 32 Кбит/с, входящий 256 Кбит/с.

/sbin/tc qdisc add dev eth0 root handle 1: htb default 10
/sbin/tc class add dev eth0 parent 1: classid 1:1 htb rate 10mbit
/sbin/tc class add dev eth0 parent 1:1 classid 1:10 htb rate 10mbit
/sbin/tc class add dev eth0 parent 1:1 classid 1:20 htb rate 32kbit

/sbin/tc qdisc add dev eth1 root handle 1: htb default 10
/sbin/tc class add dev eth1 parent 1: classid 1:1 htb rate 10mbit
/sbin/tc class add dev eth1 parent 1:1 classid 1:10 htb rate 10mbit
/sbin/tc class add dev eth1 parent 1:1 classid 1:20 htb rate 256kbit

Пример стартового скрипта /etc/init.d/shaper (написан не мною и не связан с примером iptables)

#!/bin/sh
# init script written by shane at knowplace dot org
# this script only creates the qdiscs and classes required for shaping, it
# does NOT create the necessary filters

INTERFACE='eth0'
rc_done=" done"
rc_failed=" failed"

return=$rc_done

TC='/sbin/tc'

tc_reset ()
{
# Reset everything to a known state (cleared)
$TC qdisc del dev $INTERFACE root 2> /dev/null > /dev/null
}

tc_status ()
{
echo "[qdisc - $INTERFACE]"
$TC -s qdisc show dev $INTERFACE
echo "------------------------"
echo
echo "[class - $INTERFACE]"
$TC -s class show dev $INTERFACE
}

tc_showfilter ()
{
echo "[filter - $INTERFACE]"
$TC -s filter show dev $INTERFACE
}

case "$1" in

start)
echo -n "Starting traffic shaping"
tc_reset
U320="$TC filter add dev $INTERFACE protocol ip parent 1:0 prio 0 u32"
#
# dev eth0 - creating qdiscs & classes
#
$TC qdisc add dev $INTERFACE root handle 1: htb default 60
$TC class add dev $INTERFACE parent 1: classid 1:1 htb rate 116kbit
$TC class add dev $INTERFACE parent 1:1 classid 1:10 htb rate 32kbit ceil 116kbit prio 0
$TC class add dev $INTERFACE parent 1:1 classid 1:20 htb rate 22kbit ceil 116kbit prio 1
$TC class add dev $INTERFACE parent 1:1 classid 1:30 htb rate 22kbit ceil 116kbit prio 2
$TC class add dev $INTERFACE parent 1:1 classid 1:40 htb rate 20kbit ceil 116kbit prio 3
$TC class add dev $INTERFACE parent 1:1 classid 1:50 htb rate 18kbit ceil 116kbit prio 4
$TC class add dev $INTERFACE parent 1:1 classid 1:60 htb rate 2kbit ceil 116kbit prio 5
$TC qdisc add dev $INTERFACE parent 1:10 handle 10: sfq perturb 10
$TC qdisc add dev $INTERFACE parent 1:20 handle 20: sfq perturb 10
$TC qdisc add dev $INTERFACE parent 1:30 handle 30: sfq perturb 10
$TC qdisc add dev $INTERFACE parent 1:40 handle 40: sfq perturb 10
$TC qdisc add dev $INTERFACE parent 1:50 handle 50: sfq perturb 10
$TC qdisc add dev $INTERFACE parent 1:60 handle 60: sfq perturb 10
tc_status
;;

stop)
echo -n "Stopping traffic shaper"
tc_reset || return=$rc_failed
echo -e "$return"
;;

restart|reload)
$0 stop && $0 start || return=$rc_failed
;;

stats|status)
tc_status
;;

filter)
tc_showfilter
;;

*)
echo "Usage: $0 {start|stop|restart|stats|filter}"
exit 1

esac
test "$return" = "$rc_done" || exit 1
##################################

Примечания.

В параметрах iptables цель CLASSIFY в iptables может использоваться только в таблице mangle и только в цепочке POSTROUTING.

В параметрах tc встречаются сокращения:
qdisc – Classful Queuing Disciplines – базовый объект связанный с сетевым интерфейсом и обеспечивающий управление очередями
htb – Hierarchical Token Bucket – имя собственное одного из планировщиков очередей пакетов в ядре Linux

Имена классов имеют вид M:N. M: эквивалентно M:0 и используется для создания общего корня очередей (хэндлера) связанного напрямую с интерфейсом.

Ведение логов

В современных системах логи ведутся через сервис journald.

Просмотр последних сообщений в логах

journalctl -e

то же, но с подробной информацией о событиях

journalctl -ex

При наличии каталога /var/log/journal - файлы журнала создаются в нем и сохраняются при перезагрузке. В противном случае журнал хранится в каталоге /run/log/journal/, который отображается в ОЗУ и теряется при перезагрузке.

Для совместимости с существующими системами journald пересылает все сообщения в классический syslogd. Этот поведение можно отключить в конфигурации /etc/systemd/journald.conf установив параметр

ForwardToSyslog=no

Полезные опции:

  • -k, --dmesg - сообщения от ядра
  • -u, --unit=UNIT - фильтр по юнитам systemd
  • -S, --since=, -U, --until= - время ОТ и ДО. Формат даты "2012-10-30 18:17:16" время можно опускать. Дополнительно есть строки "yesterday", "today"
  • -p, --priority= - важность сообщения в стиле syslog (notice,info и т.д.). Можно задавать в числовом виде: 0=emerg,..7-debug
  • SYSLOG_FACILITY= - тип сообщения в стиле syslog (authpriv,mail и т.д.), заданный числовым значением.

Числовые значения для фильтрации в стиле syslog.

Приоритет: emerg=0, alert=1, crit=2, err=3, warning=4, notice=5, info=6, debug=7

Типы сообщений: kern=0, user=1, mail=2, daemon=3, auth=4, syslog=5, lpr=6, news=7, uucp=8, cron=9, authpriv=10, ftp=11

Наблюдение за логами - logwatch

Набор скриптов Logwatch предназначен для выделения из логов наиболее значимой информации.

Структура пакета практически не зависит от используемой операционной системы и ориентирована на популярные сервисы, такие как веб-сервер apache, почтовый сервер sendmail, антивирус clamav и т.п. Благодаря этому всегда можно обновить версию Logwatch, взяв tar-архив прямо с сайта проекта http://www.logwatch.org. Тонкие отличия для системных модулей, таких как pam_unix, учтены в самих скриптах.

Основные скрипты располагаются в каталоге /usr/share/logwatch При необходимости тонких настроек или внесения изменений в скрипты, необходимо скопировать соответствующие файлы в каталог /etc/logwatch с сохранением вложенной структуры каталогов.
При загрузке logwatch вначале просматривает /etc/logwatch, а затем /usr/share/logwatch. При этом скрипты с совпадающими именами берутся только из /etc/logwatch, а переменные конфигурации, описанные в /etc/logwatch либо перекрывают описанные /usr/share/logwatch, либо, в случаях когда формируется список значений, добавляются к описанным в /usr/share/logwatch.

Если у вас выдаются избыточные безвредные сообщения, нераспознанные модулями Logwatch, то в /etc/logwatch/conf/ignore.conf можно прописать набор регулярных выражений, которые будут отфильтровывать лишние строки. При настройке этого фильтра следует соблюдать осторожность, чтобы не заблокировать оповещение о важных событиях в системе.

Ведение логов syslog

Запись логов ведётся специальным приложением syslogd или его современной версией rsyslogd. Для отправки сообщений демону используется сетевой протокол, который может использовать либо TCP/IP, либо Unix сокет /dev/log. Программист на Си может воспользоваться для записи в лог стандартной функцией syslog(3), а разработчик скриптов или обычный пользователь – утилитой logger.

Особенностью протокола syslog является доверие к клиенту, что приводит к возможности генерировать записи любого содержания в любом логе от имени любой службы (в том числе от имени ядра ОС).

Сообщение, передаваемое в syslogd, содержит класс сообщения, состоящий из категории и важности, идентификатор (имя программы) и произвольный текст. syslogd на основе класса сообщения выбирает файл для записи и сохраняет в этот файл время получения сообщения, идентификатор и текст.

Классы сообщений

По категориям: authpriv, cron, daemon, ftp, kern, lpr, mail, news, syslog, user, uucp, local0...local7

authpriv – данные могут содержать приватную информацию, например пароли при логировании процесса аутенификации. Такие данные должны сохраняться в файле, недоступном на чтение для обычных пользователей.
cron, ftp, lpr, mail, news, uucp – различные службы (в том числе устаревшие), которые генерируют большой поток сообщений. В CentOS отдельно настроены mail и cron
daemon – любая служба
user – обычный пользователь
syslog – сообщения самого syslogd
local0...local7 – отданы на усмотрение местного администратора. В CentOS local7 используется для записи сообщений во время загрузки

По важности: emerg, alert, crit, err, warning, notice, info, debug

emerg – критическая ошибка, затрагивающая всю систему (отказ диска, отключение электропитания и т.п.)
alert, crit – проблемы различной степени тяжести. Используются редко
err, warning, notice, info – диапазон, обычно используемый приложениями
debug – отладочные сообщения. Обычно нигде не сохраняются

Конфигурационные файлы syslogd/rsyslogd

В зависимости от используемого демона конфигурация может находиться в /etc/syslog.conf или /etc/rsyslog.conf. rsyslog.conf имеет более развитый синтаксис, однако правила, описывающие сортировку сообщений по категориям, имеют одинаковый формат. Эти правила состоят из строк вида:

фильтр действие

фильтр – описывает класс сообщений, для которых будет выполняться действие, и состоит из шаблонов, разделённых точкой с запятой. Каждый шаблон состоит из полей категории и важности, разделённых точкой. Фильтр выбирает те сообщения, категория и важность которых соответствуют всем шаблонам фильтра. Т.е. условия-шаблоны объединяются логическим оператором И.

Примеры фильтров:
mail.info – категория mail, важность info и выше
*.=debug – любая категория, важность – только debug
*.* – все сообщения
*.*;authpriv.none – все, кроме категории authpriv

действие – имя файла, FIFO, программы или IP адрес удаленного компьютера.

Формат записи действий:
/var/log/messages – файл
/dev/console – консоль (root'а?)
/dev/ttyS0 – последовательный порт
|/tmp/debug-log – FIFO. Удобно для отладки
@192.168.1.0 – IP адрес
* – сообщение всем залогированным пользователям

Пример из реального файла syslog.conf

# Всё  (кроме mail и cron) важности info и выше
# Прячем сведения об аутенификации пользователей!
*.info;mail.none;authpriv.none;cron.none    /var/log/messages

# authpriv в отдельный файл с ограниченным доступом
authpriv.*                                  /var/log/secure

# Все сообщения почты в отдельный файл
mail.*                                      /var/log/maillog
# то же с сообщениями от crond
cron.*                                      /var/log/cron

# Сообщения уровня emerg рассылаются всем
*.emerg                                     *

Программа logger

logger -t идентификатор -p категория.важность текст

По умолчанию logger подставляет в качестве идентификатора имя пользователя, а в качестве класса сообщения user.notice, однако любой, даже непривилегированный, пользователь может изменить эти значения с помощью соответствующих опций.

Запуск задач по расписанию - crond

Для запуска задач по расписанию в Unix традиционно используется демон crond. Эта программа при старте читает пользовательские файлы расписаний из каталога /var/spool/cron/ и общесистемное расписание, хранящееся в файле /etc/crontab и файлах, расположенных в каталоге /etc/cron.d/. Общесистемное расписание отличается от пользовательского тем, что каждая его запись содержит поле с идентификатором пользователя, от имени которого выполняется задание.

После того, как расписания загружены в оперативную память, crond ежеминутно проверяет наличие записи в расписании, соответствующей текущему времени, и, если такая найдена, запускает указанную команду от имени указанного пользователя. Вывод команды (stdout и stderr) перехватывается и отправляется по почте, указанной в расписании. По умолчанию почта при выполнении пользовательского расписания отправляется локальному пользователю, а при выполнении общесистемного расписания – root'у.

Если crond обнаруживает изменение времени mtime у файла /etc/crontab или у одного из каталогов с расписаниями, то он автоматически заново считывает все файлы расписаний.

Формат расписания

Формат общесистемного расписания

# Установка переменных окружения
name = value
#строка расписания
mm hh DD MM DW user cmd [arg...]

Формат пользовательского расписания

# отличается отсутствием поля user
mm hh DD MM DW  cmd [arg...]

mm hh DD MM DW – время выполнения в формате: минута час деньмесяца месяц деньнедели. Любое поле может быть записано следующим образом:

  • * – любое значение
  • 1-7 – интервал значений от и до
  • 0-10,20,30,40,50 – перечисление значений и интервалов
  • */10 – итерация с шагом, т.е. 0,10,20...
  • 0-10/2 – в промежутке с шагом

Месяц и день_недели задаются номером или первыми тремя буквами названия.

Переменные окружения, которые влияют на выполнение команды:

  • LOGNAME – имя пользователя (изменить нельзя)
  • HOME – домашний каталог, в котором будет запущена программа (по умолчанию из /etc/passwd)
  • SHELL – командный интерпретатор, которому будет передана на выполнение команда (по умолчанию из /etc/passwd)
  • MAILTO – почтовый адрес для отправки результата выполнения (по умолчанию локальному пользователю)

Редактирование личного расписания

crontab file – скопировать личное расписание из файла
crontab -e – запуск редактора vi для правки расписания
crontab -l – просмотреть расписание
crontab -r – удалить расписание

Пример личного расписания

   # некоторые любят интерпретатор zsh 
   SHELL=/bin/zsh
   # Отсылаем почту на внешний адрес
   MAILTO= test@example.com
   #
   # каждый день в ноль часов пять минут
   # перехватываем вывод, чтобы не приходили письма
   5 0 * * *       $HOME/bin/daily.job >> /dev/null 2>&1
   # В 14:15 первого числа каждого месяца
   15 14 1 * *     $HOME/bin/monthly
   # раз в пять минут проверяем почту
   */5 * * * *    $HOME/bin/check_mail

Одноразовое выполнение действий по расписанию – at

Для однократного запуска команды в указанное время используется демон atd, задания для которого формируются командой at. Команда вводится со стандартного ввода или читается из файла. Время задаётся в различных форматах, например 16:00 31.12.2014 или "now +3 hours" (minutes, hours, days)

echo touch /tmp/test | at 14:35 – создать файл сегодня в 14:35, а если уже поздно, то завтра в указанное время
at -f file now + 14days – прочитать команду из файла и выполнить через две недели
atq – показать все назначенные задания
atrm id – удалить задание с номером id

Сервис anacron

Сервис anacron изначально придуман для персональных компьютеров, которые могут быть выключены в тот момент, когда crond должен был запустить очередную команду. Если anacron обнаруживает, что ежедневная, еженедельная или ежемесячная команда не была выполнена, то он осуществляет её запуск. Конфигурация anacron хранится в /etc/anacrontab в формате:

period delay job-identifier command

где
period – периодичность выполнения команды в днях
delay – если за указанный период команда не выполнялась, то делается задержка delay минут и запускается команда
job-identifier – произвольная текстовая строка для записи в лог-файлы
command – выполняемая команда

Типичный файл /etc/anacrontab (run-parts – выполнить все файлы в каталоге):

 #period in days   delay in minutes   job-identifier   command
 1                                5       cron.daily   nice run-parts /etc/cron.daily
 7                               25      cron.weekly   nice run-parts /etc/cron.weekly
 @monthly                        45     cron.monthly   nice run-parts /etc/cron.monthly

В результате переноса долгопериодных действий в anacron, в CentOS 6 существенно изменилось содержание /etc/crontab

CentOS 5

/etc/crontab:

01 * * * * root run-parts /etc/cron.hourly
02 4 * * * root run-parts /etc/cron.daily
22 4 * * 0 root run-parts /etc/cron.weekly
42 4 1 * * root run-parts /etc/cron.monthly

CentOS 6

/etc/crontab в CentOS 6 пуст

/etc/cron.d/0hourly:

01 * * * * root run-parts /etc/cron.hourly

/etc/cron.hourly/0anacron вызывает anacron, который и выполняет запуск ежедневных, еженедельных и ежемесячных задач.

Имена и пароли пользователей (nss и pam)

Традиционный Unix хранил информацию о пользователях и их паролях в простой текстовой базе данных в файле /etc/passwd. База состоит из строк, соответствующих пользователям, каждая из которых состоит из полей, разделённых двоеточием

vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin

Поля слева на право: имя для входа; пароль (хэш пароля, символ-ссылка на базу паролей, символ отсутствия пароля и т.п.); числовой идентификатор пользователя UID; числовой идентификатор основной группы пользователя GID; текстовое описание пользователя в произвольной форме (называется поле GECOS, поскольку изначально хранило параметры для связи с ОС GECOS); домашний каталог пользователя (стартовый при входе в систему); программа интерпретатор команд пользователя (запускается при входе в систему).

Со временем стало понятно, что хранение хэша пароля в файле доступном для чтения всем пользователям - это неудачное решение, но на формат файла passwd и его доступность ориентировалось уже столько программ, что изменить его было нельзя не потеряв обратной совместимости. В результате, пароли были вынесены в отдельную базу, формат которой сильно отличается в разных Unix-подобных системах. В Solaris и Linux пароли хранятся в файле /etc/shadow. В FreeBSD в /etc/master.passwd. В OSF1 в специализированной базе данных.

В настоящее время файл passwd обеспечивает отображение имён пользователей в числовые идентификаторы и базовую настройку программного окружения пользователя, а база паролей вне зависимости от формата - аутенификацию пользователей. Существуют ситуации, когда важно только отображение имён (запуск локальных служб, не требующий паролей; вход по ключу в протоколе SSH) или только парольная аутенификация (почтовые серверы, хранящие почту по именам в общей БД). В некоторых случаях наоборот данных из файла passwd и пароля оказывается недостаточно. Чаще всего это процедура авторизации, например, для ограничения доступа к определённым ресурсам в определённые часы.

После того, как Unix-компьютеры начали объединяться в сети, у администраторов появилась дополнительная проблема по синхронизации паролей и числовых идентификаторов в пределах локальной сети. Общие пароли нужны для того, чтобы пользователь мог работать на любом из свободных компьютеров, а единые числовые идентификаторы нужны для удалённого доступа к файловым системах (т.к. права доступа определяются не именем пользователя, а его UIDом). Для решения проблемы были предложены протоколы репликации базы пользователей локальной сети с администраторского компьютера (Network Information Service - NIS и NIS++), а также протоколы удалённой аутенификации пользователей на основе криптографии (Kerberos).

В настоящее время существует множество решений, не использующих классические файлы: хранение учётных данных в СУБД общего назначения; доступ к учетным данным по протоколу LDAP; аутенификация с помощью смарт-карт,одноразовых паролей и биометрических средств.

В середине 1990-х для унификации всех этих средств и протоколов программисты фирмы Sun предложили вынести ключевые функций в расширяемые модульные библиотеки. Библиотека доступа к данным из файла passwd (а так же к файлам групп /etc/group, хостов /etc/hosts и некоторым другим) называется Name Service Switch (переключатель служб имён NSS), а библиотека выполняющая аутенификацию и авторизацию пользователей, а также смену паролей - Pluggable Authentication Modules (подключаемые модули аутенификации PAM). Каждая библиотека может наращиваться за счёт динамически подгружаемых модулей. Данные библиотеки доступны в Solaris, Linux, FreeBSD и некоторых других Unix-подобных ОС.

В Linux список модулей NSS можно просмотреть командой:

ls /lib/libnss.so

список модулей PAM:

ls /lib*/security

Обычно в Linux присутствуют модули NSS поставляемые в составе библиотеки glibc: files, compat, nis, nisplus, hesiod, dns. Модули PAM по умолчанию включают ряд локальных проверок: проверка пароля в файлах passwd или shadow, проверка на принадлежность к определённой группе, проверка времени суток и т.п.

Для взаимодействия с сетевыми службами, такими как сервер Active Directory, возможно, придётся доустановить дополнительные модули NSS и PAM.

Программа sudo

Программа sudo предназначена для выполнения администрирования обычными пользователями

Способ запуска
sudo программа опции

Пользователь не должен знать пароль root'a, но, в зависимости от настроек, ему может быть предложено ввести свой пароль для авторизации. Беспарольный доступ обычно используют для повышения полномочий в скриптах, например для управления через Web. Для обычных администраторов пароль желательно оставлять, чтобы злоумышленник не воспользовался их правами, когда они на 5 минут отойдут от терминала.

Конфигурационный файл /etc/sudoers рекомендуется изменять редактором /usr/sbin/visudo. Visudo запускается с правами root, создает копию /etc/sudoers, затем, используя переменную среды EDITOR, запускает любимый редактор пользователя (или vi по умолчанию), а после редактирования проверяет результат на синтаксическую правильность и, в случае успешной проверки, сохраняет.

Формат файла sudoers:

пользователь на_компьютере=(под чьим именем) список команд

поле на_компьютере нужно для того, чтобы один файл sudoers можно было простым копированием размножать на различные машины

Пример файла /etc/sudoers, который разрешает пользователю user выполнять любые действия, подтверждая свои полномочия паролем, а пользователю apache позволяет выключить компьютер не вводя пароль.

user ALL=(ALL) ALL
apache ALL=(ALL) NOPASWD:/sbin/poweroff

Шифрование (openssl,gpg)

OpenPGP/GnuPG

В 1991г в США Филом Циммерманом были опубликованы исходные текстов программы PGP (Pretty Good Privacy – замечательная приватность). Эта программа выводила на гражданский рынок самые современные на тот момент алгоритмы шифрования с ассиметричными ключами RSA, ВSA и ElGamal (расширение Diffi-Helman). На тот момент в США действовали довольно жёсткие законы в отношении экспорта криптографических программ и Фил в течении трёх лет подвергался судебному преследованию, но был оправдан, поскольку удалось убедить судей, что исходные тексты программы, это литературное произведение, попадающее под первую поправку к конституции США.

Права на программу PGP несколько раз переходили от одной компании к другой. С начала 2000-х и по настоящее время программой владеет компания Symantec, которая закрыла доступ к исходным кодам программы.

В 1997 году на основе реализации PGP v.5 была разработана группа стандартов OpenPGP. Стандарты описывает требования к алгоритмам шифрования, форматы хранения данных, взаимодействие с почтовыми программами и т.п.

В 1999 в рамках проекта GNU и при финансировании правительства Германии была разработана свободно распространяемая программа шифрования совместимая с OpenPGPGnuPG версии 1, а в 2006 году - GnuPG версии 2.

В 2014 году вышла версия GnuPG 2.1.0, которая значительно отличается от предшественников (включая версии 2.0.x) по формату файлов. Миграция с 2.0.x на 2.1.x происходит автоматически, обратное преобразование потребует ручного выполнения экспорта-импорта ключей. Кроме того, начиная с версии 2.1.0 прекращена поддержка исторического формата ключей PGP-2. Тем не менее, GnuPG всех версий совместима с классической программой PGP версии 5 и старше.

В 2017 вышла версия GnuPG 2.2.0, которая не сильно отличается о 2.1.x. До этой версии команда gpg означала GnuPG 1.x, а для новых версий GnuPG использовалась команда gpg2. Начиная с версии 2.2 во всех новых дистрибутивах команда gpg означает GnuPG 2.2 и старше.

Реализации GnuPG существуют для всех популярных ОС. Реализация GnuPG для Linux включена во все дистрибутивы, реализация GnuPG для Windows - Gpg4win, для Android OpenKeychain.

Документацию и последние версии GnuPG можно получить на http://www.gnupg.org. На русском языке подробную информацию можно получить на сайте http://www.pgpru.com.

Для интеграции PGP в почтовые программы можно воспользоваться следующими продуктами: Linux, Windows, OS X - плагин для почтового клиента Thunderbird - Enigmail; Android - K9 mail + OpenKeychain; Серверное web-приложение Roundcubemail (ver.>1.2); Gmail и т.п. - расширение для браузеров Mailvelop.

Если не вдаваться в подробности (которые очень важны, если криптография используется по назначению, а не в качестве игрушки), то процесс работы с GnuPG делится на следующие этапы:

  • Генерация ключей для подписи и шифрования, а также сертификата для отзыва ключа
  • Экспорт публичного ключа в файл, который затем передается всем желающим
  • Импорт публичных ключей полученных от партнеров в личную «связку ключей»
  • Шифрование и проверка цифровой подписи публичными ключами партнеров
  • Дешифрование и цифровая подпись документов личными секретным ключами
  • При необходимости - отзыв ключей

Выжимки из инструкции по GnuPG

На данной странице описаны базовые команды GnuPG 2.x.

Обобщённый формат вызова GnuPG:

gpg --опция ... --команда [имя ключа]

Команды указывают желаемое действие, а опции - параметры для выполнения этого действия. Опции указываются до команд. Некоторые команды переводя gpg в интерактивный режим.

В качестве имени ключа может использоваться цифровой отпечаток (fingerprint), идентификатор ключа (key ID) или e-mail владельца. В дальнейшем имя ключа будет заменяться на mykey .

Общие опции

  • --homedir /the-secret-place - каталог, в котором хранятся данные gpg. Опция имеет более высокий приоритет, чем переменная окружения GNUPGHOME. По умолчанию в Linux используется каталог ~/.gnupg, в Windows %AppData%\Roaming\gnupg
  • --output file - имя файла для сохранения результата. По умолчанию результат выдаётся на stdout
  • --armor результат выводится в текстовой кодировке (Radix64=Base64+CRC). По умолчанию - результат двоичный

Генерация новой пары ключей

gpg --gen-key

В GnuPG версии 2.1.x* и старше --gen-key предлагает ввести только имя, e-mail и пароль для секретного ключа, подставляя остальные параметры по умолчанию. Для полного диалога в этих версиях необходимо использовать команду --full-gen-key, возможно с опцией --expert, которая добавляет расширенный выбор алгоритмов шифрования.

В результате выполнения команды --gen-key генерируется два ключа: мастер-ключ, он же ключ подписи, и ключ шифрования. Оба ключа используют алгоритм шифрования rsa2048 и имеют срок жизни два года. Кроме того автоматически формируется сертификат отзыва.

В процессе создания ключа у для него будет создан длинный шестнадцатеричный цифровой отпечаток (fingerprint) который может использоваться для выбора ключа при последующих операциях.

Немного о вводимых параметрах:

  • Идентификатор владельца ключа (UID) в OpenPGP имеет формат "Полное имя (комментарий) <адрес e-mail>". Идентификатор связывает ключ с определенным человеком. Поскольку OpenPGP в значительной мере ориентирован на использование совместно электронной почтой, то основным идентификатором является e-mail, а полное имя, это лишь вспомогательный элемент.

  • Пароль для шифрования секретного ключа должен быть достаточно сложным для взлома. Утеря секретного ключа сводит на нет всю систему шифровальной защиты и потому ключ хранится на диске в зашифрованном виде. В идеальном случае ключ должен храниться на съемном носителе (флешке) в физически защищенном месте. Если злоумышленник получит доступ к файлу секретного ключа, то пароль к нему будет последней линией обороны.

Создание отзывающего сертификата

Если ключ сертификат отзыва мастер-ключа (revoсation certificate) не был создан во время генерации, то его следует создать, используя команду --gen-revoke. Если секретный ключ будет похищен или утерян, то этот сертификат может быть разослан для уведомления о том, что открытый ключ нельзя больше использовать.

gpg --output revoke.asc --gen-revoke mykey

Сертификат отзыва сохраняется в текстовой кодировке.

Добавление/удаление/отзыв идентификаторов

К одному ключу можно добавить несколько пользовательских идентификаторов (UID), например, личный и рабочий адреса электронной почты. Операция выполняется в диалоговом режиме.

gpg --edit-key mykey

В диалоговом режиме ввести команду adduid

gpg> adduid
Real Name: My work email
E-mail: my@example.com

После создания нового идентификатора следует отметить степень доверия к нему и назначить, какой UID будет основным. Команда uid помечает/снимает отметку с UIDов, к которым будет применена следующая команда

gpg> uid <number>
gpg> trust
     (5 = ultimate trust)
gpg> uid <number>
gpg> primary
gpg> save

Удаление идентификатора

gpg> uid <number>
gpg> deluid

Отзыв идентификатора

gpg> uid <number>
gpg> revuid

Экспорт открытого ключа

Перед тем как послать кому-либо открытый ключ необходимо экспортировать его командой --export:

gpg --armor --output alice.gpg --export my@example.com

Опция --armor указывает, что ключ будет сохранён в формате ASCII.

Импорт открытого ключа

После обмена ключами открытый ключ партнера может быть добавлен к связке открытых ключей при помощи команды --import:

gpg --import blake.asc

Просмотр ключей

gpg --list-keys

/home/alice/.gnupg/pubring.gpg
pub 1024R/B115BDB6 2002–05–01 Alice (test key) <alice@wonderland.uk>
pub 1024R/01A1FE63 2002–05–01 Blake (dumb) <blake@anywhere.ru>
sub 1024R/526C7F7F 2002–05–01 [expires: 2003–05–01]

Установка степени доверия к ключу

Для того, чтобы проверить достоверность ключа используется цифровой отпечаток (fingerprint) ключа. После проверки ключ заверяется подписью, для подтверждения того, что он достоверен. Ожидаемый отпечаток ключа передается через надёжный канал связи, например зачитывается владельцем по телефону.

Отпечаток ключа можно просмотреть командой --fingerprint.

gpg --fingerprint alice@wonderland.uk
pub 1024R/B115BDB6 2002–05–01 Alice (test key) <alice@wonderland.uk>
Key fingerprint = DE49 CDEF 12A3 8B7B 272B A572 C73A 9987 B115 BDB6

Или

gpg --fingerprint
/home/test/.gnupg/pubring.gpg
pub 1024R/B115BDB6 2002–05–01 Alice (test key) <alice@wonderland.uk>
Key fingerprint = DE49 CDEF 12A3 8B7B 272B A572 C73A 9987 B115 BDB6
pub 1024R/01A1FE63 2002–05–01 Blake (dumb) <blake@anywhere.ru>
Key fingerprint = 80B8 1955 7D68 FE4F D882 DAD1 D85C 124A 01A1 FE63
sub 1024R/526C7F7F 2002–05–01 [expires: 2003–05–01]

Подпись доверенного ключа

Для подписи ключа необходимо перейти в режим редактирования ключа при помощи команды --edit-key:

gpg --edit-key blake@anywhere.ru

В диалоговом режиме ввести команду sign:

gpg> sign

Подтвердить желание подписать ключ и ввести пароль секретного ключа

Указать, с какой степенью достоверности проверен ключ

gpg> trust

 Укажите, насколько Вы доверяете данному пользователю в вопросах проверки
достоверности ключей других пользователей (проверяет паспорт,
сверяет отпечатки ключей из разных источников и т.п.)
 1 = Не знаю или не буду отвечать
 2 = НЕ доверяю
 3 = Доверяю ограниченно
 4 = Полностью доверяю
 5 = Абсолютно доверяю

Выход из режима редактирования и сохранение изменений

gpg> quit

Шифрование

Для шифрования документа используется команда --encrypt. Для шифрования необходимо иметь открытые ключи предполагаемых получателей. Программа ожидает в качестве параметра имя шифруемого документа или, в случае его отсутствия, шифрует стандартный ввод. Зашифрованный результат помещается в стандартный вывод, если не указана опция --output. Для повышения защиты перед шифрованием документ дополнительно сжимается.

gpg --output message.gpg --encrypt --recipient blake@anywhere.ru message.txt

Опция --recipient может повторяться несколько раз для каждого из предполагаемых получателей и имеет в качестве аргумента идентификатор открытого ключа, которым должен быть зашифрован документ.

При шифровании документа создаётся одноразовый случайный ключ для симметричного шифрования документа, а в зашифрованный документ добавляются несколько копий этого одноразового ключа, каждая из которых зашифрована публичным ключом одного из получателей.

Дешифрование

Для расшифровки сообщения используется команда --decrypt. Зашифрованный документ может быть расшифрован только тем, чей секретный ключ соответствует одному из указанных открытых ключей. В частности, отправитель не можете расшифровать зашифрованный им документ, если он не включил свой открытый ключ в список получателей.

gpg --output message.txt --decrypt message.gpg

Для доступа к секретному ключу необходимо ввести пароль

You need a passphrase to unlock the secret key for
user: «Blake (dumb) <blake@anywhere.ru>"
1024-bit RSA key, ID 526C7F7F, created 2002–05–01 (main key ID 01A1FE63)

Enter passphrase:

Симметричное шифрование

Документы можно шифровать и без открытого ключа. Вместо этого используется симметричный алгоритм для шифрования документа. Ключ, используемый при шифровании, образуется из ключевой фразы. Для большей безопасности эта ключевая фраза не должна совпадать с той, которая используется для защиты секретного ключа. Симметричный шифр применим, когда есть возможность обменяться ключевой фразой. Для использования симметричного шифра применяется команда --symmetric.

gpg --output message.gpg --symmetric message.txt
Enter passphrase:

Цифровые подписи

Цифровая подпись удостоверяет создателя и дату создания документа. Если документ будет каким-либо образом изменен, то проверка цифровой подписи будет неудачной. При подписи документа используется закрытый ключ подписывающего, а проверяется подпись с использованием его открытого ключа.

Для подписи документов используется команда --sign.

gpg --output file.sig --sign file.bin

You need a passphrase to unlock the secret key for
user: «Alice (test key) <alice@wonderland.uk>"
1024-bit RSA key, ID B115BDB6, created 2002–05–01

Enter passphrase:

Перед подписью документ сжимается. Подписанный документ выводится в двоичном формате.

У подписанный документ можно либо просто проверить подпись, либо проверить подпись и восстановить исходный документ. Для проверки подписи используется команда --verify. Для проверки подписи и извлечения документа используется команда --decrypt.

gpg --output file.bin --decrypt file.sig
gpg: Signature made Sat May 4 19:04:21 2002 MSD using RSA key ID B115BDB6
gpg: Good signature from «Alice (test key) <alice@wonderland.uk>"

Прозрачно подписанные (сlearsigned) документы

Обычно цифровые подписи применяются для отправки электронной почты. При этом нежелательно сжимать подписываемые документы. Команда --clearsign добавляет к документу цифровую подпись в формате ASCII, не изменяя при этом сам документ.

gpg --output doc.asc --clearsign doc.txt

Можно получить подпись, хранящуюся отдельно от документа

gpg --output doc.sig --detach-sign doc.txt

Для проверки подписи необходимы и подпись, и сам документ. Для проверки используется команда --verify.

gpg --verify doc.sig doc.txt
gpg: Signature made Sat May 4 19:34:08 2002 MSD using RSA key ID B115BDB6
gpg: Good signature from «Alice (test key) <alice@wonderland.uk>"

Доверие к ключам в OpenPGP

В криптографии существует несколько моделей доверительных отношений:

  • Непосредственное доверие
  • Иерархическое доверие
  • Сеть доверия

В модели непосредственного доверия мы самостоятельно проверяем ключи партнёра не полагаясь ни на кого больше. Такая модель доверия используется в SSH, где публичные ключи сервера и клиента представляет из себя набор параметров шифрования и не содержит никакой удостоверяющей информации. Проверка ключа производится самостоятельно путём сличения его цифрового отпечатка с имеющимся в наличии (закэшированном в предыдущем сеансе или размещённого в специальном файле).

В модели иерархического доверия существуют некие изначально доверенные корневые сертификаты, принадлежащие уважаемому центру аутентификации (Central authority, CA). Данный центр подписывает сертификаты доверенных удостоверяющих центров, которые, в свою очередь, подписывают сертификаты серверов и пользователей. Каждый сертификат хранит цепочку подписей, ведущую к корневым сертификатам и позволяет, таким образом, отследить на персональную ответственность за выдачу сертификата. Корневые сертификаты распространяются некоторым надёжным способом, например, как часть дистрибутива ОС или браузера. Эта модель используется в SSL.

Модель сети доверия объединяет обе предыдущие модели. В сети доверия каждый самостоятельно проверяет достоверность чужих сертификатов, но, после проверки, может выступить в качестве удостоверяющего центра для других участников сети. В отличие от централизованной модели здесь никогда не может быть стопроцентной уверенности в подлинности сертификата, но наличие многих участников, независимо подтверждающих достоверность какого-либо сертификата, оказывается вполне достаточным для большинства практических задач.

Сеть доверия - Web of Trust

Для того, чтобы избежать MitM атаки (Man in the middle - расшифровка сообщений в канале передачи) необходимо, удостовериться в том, что публичный ключ партнёра не был подменён. Для достижения этой цели в сертификате ключа OpenPGP хранятся подписи от других участников сети доверия, подтверждающие достоверность хозяина ключа. Хочу обратить внимание, что подписывается не сам ключ, а идентификатор пользователя, привязанный к данному ключу. Так, вы можете быть уверены, что человек действительно использует один из e-mailов, привязанных к ключу, и ничего не знать про другие его e-mailы.

Уровень достоверности того, что сертификат ключа действительно выпущен своим хозяином, высчитывается по количеству подписей и уровня доверия к этим подписям. Получив от нового партнёра по переписке публичный ключ, подписанный людьми, чьи ключи помечены как доверенные, мы повышаем свою уверенность в достоверности полученного ключа.

В оригинальном PGP существовало три степени доверия к подписывающим ключ и три уровня достоверности сертификата.

Уровни доверия:

  • Полное доверие
  • Частичное доверие
  • Нет доверия

Уровни достоверности:

  • Подлинный сертификат
  • Возможно подлинный сертификат
  • Неопределённый (недостоверный) сертификата

В версии GnuPG 2.x появился уровень "Абсолютное доверие" для своих собственных сертификатов.

Чтобы сертификат считался подлинным требуется собственноручная подпись сертификата, или хотя бы одна подпись от полностью доверенного владельца ключа, или две подписи от частично доверенных владельцев ключей.

На самом нижнем уровне этой сети находится личный ключ и личная связка сертификатов. Личный ключ считается абсолютно достоверным а его хозяин (я) абсолютно доверенным. Добавляя чей-либо публичный ключ в связку можно подписать сертификат ключа своим личным ключом, что даст ему статус подлинного сертификата. При этом уровень доверия к владельцу можно установить по своему желанию.

Возможно, что вам не известен уровень доверия к ключам, использованным для подписи ключа партнёра. Тогда вам придётся искать цепочку ключей от известных доверенных ключей к проверяемому. Кроме того, существует некоторая вероятность, что подписавшие ключ люди сговорились (принадлежат к одной тайной организации) и совместно выпустили фальшивый ключ. Поэтому, чем больше людей в мире участвует в подписании ключей, тем проще найти подтверждающую цепочку и тем меньше вероятность сговора. Процедура взаимного подписания ключей при личных контактах, или подписания при абсолютной уверенности в достоверности ключей (например путём сличения цифровых отпечатков по телефону) и создаёт сеть доверия пользователей OpenPGP.

Пример локальной сети доверия можно посмотреть на странице ключей команды разработчиков Arch Linux.

Редактирование уровня доверия к хозяину ключа:

$> gpg  --edit-key DA3CE9CE6DF2C45843AB2392D5560606D3C9EE9B
...
gpg> trust
sec  rsa2048/D5560606D3C9EE9B
          создан: 2020-04-17     годен до: 2022-04-17  назначение: SC
     доверие: абсолютное    достоверность: абсолютное
ssb  rsa2048/C6FF5CA708A972CD
          создан: 2020-04-17     годен до: 2022-04-17  назначение: E
[  абсолютно ] (1). Jon Dow <user@example.com>
Укажите, насколько Вы доверяете данному пользователю в вопросах проверки
достоверности ключей других пользователей (проверяет паспорт,
сверяет отпечатки ключей из разных источников и т.п.)
 1 = Не знаю или не буду отвечать
 2 = НЕ доверяю
 3 = Доверяю ограниченно
 4 = Полностью доверяю
 5 = Абсолютно доверяю

Как проверять сертификаты

Выдержка из GnuPG FAQ Ru

  1. Встретить владельца сертификата лично.
  2. Попросить показать два документа, удостоверяющих личность.
  3. Убедившись, что человек действительно является тем, за кого он себя выдает, попросите у него отпечаток его сертификата, адрес электронной почты и адрес, по которому можно получить сертификат. (Например: Мой отпечаток 4541 BB01 8EA4 8F99 19CA 3701 2380 6BE5 D6B9 8E10, адрес my@example.com, сертификат можно взять на pool.sks-keyservers.net.)
  4. На своем собственном компьютере получите сертификат этого человека из указанного источника. Убедитесь, что адрес электронной почты, который вам дали, находится в списке адресов, записанных в сертификате. Убедитесь, что отпечаток сертификата, который вы получили, совпадает с отпечатком, который вам дали.
  5. Подпишите сертификат своим ключом gpg --edit-key [ID его сертификата] sign
  6. После подписи экспортируйте подписанный сертификат gpg --armor --output signed_cert.asc --export [ID его сертификата]
  7. Отправьте файл с подписанным сертификатом signed_cert.asc по данному вам адресу.

Следуя этой процедуре, вы сначала убеждаетесь, что говорите с нужным человеком. Сравнивая отпечаток сертификата с тем, который вам сообщили, вы убеждаетесь, что получили нужный сертификат. Еще одна проверка делается, чтобы убедиться, что данный вам адрес перечислен в сертификате. Как только это сделано, вы получаете уверенность, что связали сертификат с реальным человеком. Что и подтверждаете всему миру, подписав сертификат и вернув свежеподписанный сертификат владельцу.

Ключи OpenPGP

Термин "сертификат" в OpenPGP чаще всего используется в словосочетании "сертификат отзыва", а для структуры данных, связанной с ключом используется просто слово "ключ". На этой странице термин "сертификат" используется, для того, чтобы отличать ключи, как параметры алгоритма шифрования, от ключей, как структур данных.

Первичные ключи и подключи

Структура данных сертификата ключа в OpenPGP позволяет хранить в нём различные дополнительные поля. Подключи - это ключи, которые хранятся в сертификате другого ключа, который называют первичным или мастер-ключом.

Подключи помечаются флагами, которые определяют функциональное назначение подключа. Флаги имеют внутреннее числовое представление, а в информационных утилитах GnuPG помечаются буквами.

0x01    “C” Key Certification
0x02    “S” Sign Data
0x04    “E” Encrypt Communications
0x08    “E” Encrypt Storage
0x20    “A” Authentication

Мастер-ключ автоматически помечается флагами ключа подписи и ключа выпуска сертификатов (CS), поскольку он используется для подписывания подключей и для создания сертификатов отзыва. Отличие ключа шифрования от ключа подписи в том, что ключ подписи действует в будущем. Если его украдут, то злоумышленники смогут в будущем подписывать документы от вашего имени. Поэтому ключ подписи должен иметь ограниченный срок действия и (в случае компрометации) должен быть отозван до окончания срока, чтобы предупредить его использование злоумышленниками. Ключ шифрования действует в прошлом. Его компрометация ведёт к тому, что злоумышленники смогут расшифровать переписку, которая велась с его использованием и никакие отзывы здесь не помогут.

В GnuPG версии 2.1 и старше команда --gen-key создаёт мастер-ключ с функцией подписи и дополнительный подключ с функцией шифрования.

При создании нового подключа задаётся вопрос о его назначении:

$> gpg --edit-key jd@example.com
...
gpg> addkey
Выберите тип ключа:
   (3) DSA (только для подписи)
   (4) RSA (только для подписи)
   (5) Elgamal (только для шифрования)
   (6) RSA (только для шифрования)
  (14) Existing key from card
Ваш выбор?

Для создания ключа аутентификации необходимо запускать gpg с опцией --expert

Публичные и приватные ключи

Как и во всех системах с асимметричным шифрованием, каждый ключ в OpenPGP представлен парой из публичного и приватного ключа. Публичный используется для шифрования и проверки подписи, а приватный - для подписи и дешифровки.

Идентификаторы ключа

Для идентификации ключей используется два типа идентификации:

  • человекочитаемый, но не уникальный идентификатор пользователя (user ID, UID)
  • уникальный, но неудобный для ввода цифровой отпечаток ключа (fingerprint, key ID)

Идентификатор пользователя имеет формат: "Полное имя <адрес e-mail>". Этот идентификатор связывает ключ с определенным человеком. Очевидно, что человек, создающий много ключей, скорее всего, будет использовать для них одинаковые UIDы. К одному ключу можно привязать несколько идентификаторов пользователя, например UIDы для различных почтовых ящиков. Поиск ключа можно вести по полному тексту UID, по e-mail, по полному имени или по его подстроке.

Отпечаток ключа - это хэш SHA-1 длиной 160 бит, вычисляемый на основе открытого ключа и метки времени создания ключа. Для ввода/вывода отпечатка в интерфейсе пользователя используется шестнадцатеричная запись. Длина отпечатка - 40 шестнадцатеричных цифр, которые для удобства разбивают на 10 групп по 4 цифры.

$> gpg --fingerprint  -k
...
-----------------------
pub   rsa2048 2020-04-17 [SC] [   годен до: 2022-04-17]
      DA3C E9CE 6DF2 C458 43AB  2392 D556 0606 D3C9 EE9B
uid         [  абсолютно ] John Dow <jd@example.com>
sub   rsa2048 2020-04-17 [E] [   годен до: 2022-04-17]

В некоторых ситуациях (при использовании агента) используется ещё один идентификатор ключа - keygrip, который вычисляется как хэш публичного ключа без добавления времени создания.

$> gpg --with-keygrip -k
...
pub   rsa2048 2020-04-17 [SC] [   годен до: 2022-04-17]
      DA3CE9CE6DF2C45843AB2392D5560606D3C9EE9B
      Keygrip = 5D3F2A0BA1DCC59210761397A5CEC5E3393FB111
uid         [  абсолютно ] John Dow <jd@example.com>
sub   rsa2048 2020-04-17 [E] [   годен до: 2022-04-17]
      Keygrip = 0AF602B0376E373F4158E230D0E5E3E9F32F4619

Для экономии времени на ввод идентификатора (или его диктовку по телефону) могут использоваться младшие байты цифрового отпечатка. 16 последних шестнадцатеричных цифр отпечатка называются длинным идентификатором (long ID), а последние 8 символов - коротким идентификатором (short ID). Использование длинного и короткого идентификатора считается плохой практикой, поскольку для них легко сгенерировать коллизии - т.е. различные ключи с совпадающими укороченными ID (но с несовпадающими отпечатками).

В некоторых случаях в начале идентификатора нужно добавлять символы 0x, чтобы подчеркнуть, что это число в шестнадцатеричном виде.

Для того, чтобы не пересчитывать символы руками, команда просмотра публичных ключей --list-keys (-k) позволяет указать опцию --keyid-format, которая может принимать значения 0xLONG, LONG, 0xSHORT, SHORT.

$> gpg --keyid-format 0xSHORT --list-keys
/home/user/.gpg/pubring.kbx
-----------------------
pub   rsa2048/0xD3C9EE9B 2020-04-17 [SC] [   годен до: 2022-04-17]
      DA3CE9CE6DF2C45843AB2392D5560606D3C9EE9B
uid         [  абсолютно ] John Dow <jd@example.com>
sub   rsa2048/0x08A972CD 2020-04-17 [E] [   годен до: 2022-04-17]

Смысл создания подключей

Личный мастер-ключ должен храниться в очень безопасном месте, желательно на внешнем носителе в физически защищенном месте. Однако использовать такой ключ крайне неудобно: каждый раз, когда вам нужно что-то подписать придётся извлекать ключ из хранилища и использовать его на компьютере с надёжной антивирусной защитой, чтобы избежать перехвата расшифрованного ключа в процессе подписи.

Альтернативой является создание подключей для текущей работы. С помощью мастер-ключа подключам можно назначать небольшой срок жизни, чтобы уменьшить ущерб при их похищении. Так же с помощью мастер-ключа можно отзывать скомпрометированные ключи.

Мастер-ключ извлекается из хранилища и используется в следующих случаях:

  • когда вы подписываете чужой ключ или отзываете существующую подпись
  • когда вы создаете новый подключ
  • когда вы добавляете новый UID или помечаете существующий UID как основной
  • когда вы меняете настройки (например, с помощью setpref) для UID
  • когда вы меняете дату истечения срока действия вашего мастер-ключа или любого его подключа
  • когда вы отзываете существующий UID или подключ
  • когда вы отзываете или генерируете сертификат отзыва для ключа со всеми подключами

Время жизни ключа

Можно использовать различные стратегии устаревания:

  1. Мастер-ключ подписи с бесконечным временем жизни. В случае утери или похищения придётся оповещать всех корреспондентов об отзыве старого ключа и каким-то способом оповещать о появлении нового;
  2. Мастер-ключ с бесконечным временем и временные ключи с небольшим сроком жизни, подписанные мастер-ключом. Мастер-ключ хранится отдельно в сейфе. В случае утери временного ключа генерируется и подписывается новый, плюс рассылается сертификат отзыва. Небольшой срок действия ограничит время на взлом пароля для доступа к ключу;
  3. Одноразовые ключи со временем жизни в несколько часов или дней - по обстоятельствам.

Разные мелочи

Ошибка в GnuPG 2.x: Can’t connect to the agent: Invalid value passed to IPC возникает при выполнении команды:

gpg –-homedir . –-gen-key

Причина: Вся работа с секретными ключами идёт в GnuPG 2.x идёт через gpg-agent, который запускается в фоне при первой необходимости. В данном случае gpg-agent уже запущен и создал сокет в стандартном каталоге * ~/.gpg*

Исправление:

pkill -KILL gpg-agent
gpg-agent --homedir="$(pwd)" --daemon
gpg –-homedir --homedir="$(pwd)" –-gen-key

OpenSSl

История

В 1988 году Международный союз электросвязи (International Telecommunication Union - ITU) опубликовал рекомендации по методам аутенификации в протоколе доступа к службе каталогов (Direcrotry access protocol - DAP). Все рекомендации союза по компьютерным сетям (реализация модели ISO/OSI) маркировались буквой "X" и номером. Серия посвященная службе каталогов получила номера с X.500 и далее. Система аутенификации на основе публичных ключей и сертификатов получила название X.509. В дальнейшем, часть рекомендаций X.500 была реализована в протоколе LDAP, а фреймворк предложенный в X.509 была использована в вебе для реализации протокола SSL и связанной с ним иерархией отношений доверия (RFC 5280).

В частности, X.509 ввёл понятия:

  • сертификат пользователя (сертификат): открытые ключи пользователя вместе с другой вспомогательной информацией, подписанные с помощью секретного ключа, выдавшего его органа по сертификации;
  • центр сертификации (certification authority - CA): орган, которому пользователи доверяют создание и подпись сертификатов. Опционально центр сертификации может создавать и ключи пользователя;
  • путь сертификации: упорядоченная последовательность сертификатов объекта, которая вместе с публичным ключом начального объекта в пути, может быть использована для проверки публичного ключа конечного объекта в пути;
  • доверие: ключевая роль доверия в структуре аутентификации заключается в отношениях между объектом аутентификации и центром сертификации; аутентифицирующий должна быть уверен, что центр сертификации создаёт только действительные и надежные сертификаты.

Для реализации стандарта X.509 и связанных с ним стандартов (алгоритмы шифрования, форматы хранения даннных и т.п.) была разработана библиотека OpenSSL, которая поставляется с утилитой командной строки openssl, и позволяет выполнять все основные криптографические операции. Библиотека Openssl реализована для всех основных ОС, в том числе Linux, Windows, Mac OS, Android и т.д.

Манипуляции с сертификатами

Для корректной работы многих сервисов в современном интернете требуется наличие сертификатов. В качестве примера можно привести HTTPS, SMTP поверх TLS, OpenVPN. В зависимости от сферы применения к сертификатам предъявляются разные требования:

Веб сервер с поддержкой SSL (HTTPS). Необходим серверный сертификат подписанный официальным удостоверяющим центром, сертификат которого есть в поставке популярных браузеров.

Почтовый сервер с поддержкой SSL (SMTP поверх TLS, POP3S, IMAPS). Для SMTP обычно достаточно самоподписанного серверного сертификата. Для POP3S, IMAPS желательно иметь официальный сертификат, поскольку почтовые клиенты (например Thunderbird) выдают предупреждения о неизвестных или некорректных сертификатах.

С OpenVPN поставляется собственный удостоверяющий центр, который позволяет создавать сертификаты сервера и клиента. Сертификат этого центра генерируется локально и добавляется в файл конфигурации клиента и сервера.

LetsEncrypt

Проект LetsEncrypt направлен на массовое внедрение HTTPS в интернете. Он предоставляет бесплатный удостоверяющий центр и наборы скриптов (для разных ОС разные), которые автоматически генерируют пару ключей, создают запрос на выпуск сертификата, отправляют его в удостоверяющий центр LetsEncrypt, а затем автоматически добавляют полученный сертификат в настройки популярных веб-серверов (Apache,Nginx, IIS).

Для почтового сервера достаточно прописать путь к файлу сертификата LetsEncrypt и использовать его совместно с веб-сервером.

EasyRSA

Вместе с OpenVPN поставляется набор скриптов easyrsa (есть под Linux и Windows), которые вызывают openssl для выполнения основных манипуляций с сертификатами. В набор скриптов входят:

  • build-ca - создать приватный ключ удостоверяющего центра (CA)
  • build-key-server - создать серверный приватный ключ и сертификат, подписанный ключом CA
  • build-dh - создать серверный ключ Диффи-Хелмана
  • build-key - создать клиентский приватный ключ и сертификат, подписанный ключом CA
  • build-key-pkcs12 - создать приватный ключ, сертификат и упаковать их вместе сертификатом CA

Версии с добавлением -pass потребуют ввода пароля для шифрования приватного ключа.

В файле openssl.cnf хранятся различные параметры openssl. Многие из них ссылаются переменные окружения, поэтому реальные настройки находятся в файле vars.sh (vars.bat).

vars.sh (фрагмент)

export KEY_SIZE=1024
export CA_EXPIRE=3650
export KEY_EXPIRE=3650

# Атрибуты сертификата
# могут быть изменены в диалоговом режиме
# при создании сертификата
export KEY_COUNTRY="RU"
export KEY_PROVINCE="EKB"
export KEY_CITY="Ekaterinburg"
export KEY_ORG="IMM"
export KEY_EMAIL=""

EasyRSA в подробностях

Внутри скриптов EasyRSA находятся вызовы openssl. Следует помнить, что часть параметров, такие как тип и размер ключа, ключ CA и т.п. находятся в файлt openssl.cnf.

Создание ключа CA без сертификата

 #запрос на сертификат сроком на 10 лет
 openssl req -days 3650 -nodes -new -x509 -keyout ca.key -out ca.csr -config openssl.cnf

Создание пары ключ-сертификат клиента

 #запрос на сертификат сроком на 10 лет
 openssl req -days 3650 -nodes -new -keyout client.key -out client.csr -config openssl.cnf
 #подпись сертификата ключом CA
 openssl ca -days 3650 -out client.crt -in client.csr -config openssl.cnf

то же для сервера

 #запрос на сертификат сроком на 10 лет
 openssl req -days 3650 -nodes -new -keyout srv.key -out srv.csr -config openssl.cnf
 #подпись сертификата ключом CA
 openssl ca -days 3650 -extensions server -in srv.csr -out srv.crt -config openssl.cnf

Экспорт в формат PKCS#12

 #запрос на сертификат сроком на 10 лет
 openssl req -days 3650 -nodes -new -keyout client.key -out client.csr -config openssl.cnf
 #подпись сертификата ключом CA
 openssl ca -days 3650 -in client.csr -out client.crt -config openssl.cnf
 # конвертация пары ключ/сертификат в файл pkcs#12.
 openssl pkcs12 -export -inkeyclient.key -in client.crt -certfile ca.crt -out client.p12

Формат сертификатов

Формальное описание структур данных

Стандарт X.509 предполагает, что все структуры данных, связанные с сертификатами описываются в формате ASN.1. ASN.1 - это архитектурно-независимое представление данных, пригодное для хранения произвольных иерархических структур. На практике, структура ASN.1 кодируется в двоичное представление DER (Distinguished Encoding Rules), описанное в X.690.

Все объектов в ASN.1 имеют уникальные идентификаторы OID (Object Identifier), для которых определены базовые типы данных (числа, строки, коллекции и т.п). OID - это последовательность положительных целых чисел, однозначно идентифицирующая объект. В текстовой записи OID выглядит как десятичные числа, разделяемые точкой - 1.2.345.6.79. Структура OID описывает дерево, корень которого расположен в начале записи. При записи в человекочитаемой форме корневой OID заменяют на некую мнемоническую строку, которую продолжают числовой последовательностью. Например корневой OID ветки, описывающей объекты алгоритма RSA, выглядит так: 1.2.840.113549.1. На специализированном сайте можно выяснить, что это: {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1)}. Российский сегмент OID {iso(1) member-body(2) ru(643)} по соглашению с Росстандартом обслуживает ОАО "Инфотекс Интернет Траст". Объекты, связанные с российской криптографией, находятся в ветке 1.2.643.100 и описаны в Приказе ФСБ РФ от 27 декабря 2011 г. N 795 "Об утверждении Требований к форме квалифицированного сертификата ключа проверки электронной подписи".

Для обеспечения уникальности, те или иные OIDы регистрируются некими официальными организациями при координации ISO и ITU. К таким регистрирующим организациям относится IANA, которая выделяет OIDы, необходимые для протоколов сети Интернет (например, LDAP и SNMP). Частная организация может получить стартовый OID, и строить от него поддерево для внутреннего использования. В России регистрацией частных OID занимается ОАО "Инфотекс Интернет Траст".

Просмотр ASN.1 структуры ключа:

openssl asn1parse -in x509-key.pem

Типы сертификатов

  • RFC 5280 описывает формат сертификата X.509 (расширение файла .crt,.cer, .der, .pem) и списка отозванных сертификатов (.clr)

Кроме того, серия документов Public-Key Cryptography Standards (PKCS), созданная корпорацией RSA, описывает различные типы сертификатов X.509. Документы имеют порядковую нумерацию, записанную через #.

  • PKCS #1 (RFC 8017) описывает алгоритм RSA и формат его ключей
  • PKCS #7 (RFC 2315) описывает формат криптографического сообщения (зашифрованного и/или подписанного) (.p7b)
  • PKCS #8 (RFC 5208) описывает формат приватного ключа (.key)
  • PKCS #10 (RFC 2986 ) описывает формат запроса на сертификат (.csr)
  • PKCS #12 (RFC 7292) формат экспорта секретного ключа который вместе с сертификатом и путём сертификации ( .pfx или .p12).

Форматы хранения сертификатов

Основной формат хранения сертификатов X.509 - DER, однако для удобства пересылки по электронной почте его часто дополнительно кодируют в формат PEM (Privacy Enhanced Mail RFC 1421). PEM сам по себе довольно большой стандарт, но из взято только кодирование по алгоритму Base64 и обрамление полученного текста границами:

-----BEGIN label -----
-----END label -----

Для секретных ключей RSA (PKCS#1) используется традиционная форма label, похоже, не описанная в стандартах - RSA PRIVATE KEY.

RFC 7468 описывает форматы label для разных типов ключей и сертификатов

  • CERTIFICATE - сертификат X.509
  • PUBLIC KEY - публичный ключ X.509
  • X509 CRL - список отозванных сертификатов
  • PKCS7 - PKCS#7
  • PRIVATE KEY - PKCS#8
  • ENCRYPTED PRIVATE KEY - RFC 5958
  • CERTIFICATE REQUEST - PKCS#10

За пределами границ BEGIN и END в файл с сертификатом может быть добавлена человекочитаемая версия данных.

Конвертация форматов

Вывод в человекочитаемом формате. noout - отключение вывода в формате PEM:

openssl x509 -in certificate.cer -noout -text

Конвертация PEM -> DER и наоборот:

openssl x509 -inform pem -in certificate.pem -outform der -out certificate.cer
openssl x509 -inform der -in certificate.cer -outform pem -out certificate.pem

Создание файла PFX:

openssl pkcs12 -export -out certificate.pfx -inkey private.key -in certificate.crt -certfile CA.crt

Извлечение приватного ключа RSA из PKCS#8:

openssl pkcs8 -nocrypt -in pkcs8.pem -out pkcs1.pem

CA Bundle

CA Bundle - связка CA - это не особый формат, а просто набор открытых ключей (сертификатов) доверенных центров сертификации в формате PEM, склеенных в один текстовый файл. Формат придуман фирмой Netscape. В Linux CentOS 7 файл /etc/pki/tls/certs/ca-bundle.crt ставится с пакетом ca-certificates-2018.2.22-70. Создать CA Bundle из отдельных файлов можно стандартными средствами ОС:

cat *.pem > ca_bundle.crt

Ссылки

Статья про кроссплатформенное средство просмотра сертификатов

Шифрование/дешифрование

Краткая сводка полезных команд (исключая работу с сертификатами)

Генерация случайных данных/паролей

#сгенерировать 12 байт/16 символов в base64
openssl rand -base64 12

Хэш пароля. Первый вариант - классический DES из passwd, второй - MD5 из shadow. Если salt опустить, то будет сгенерирована случайная строка.

openssl passwd -salt 8E MySecret
openssl passwd -1 -salt sXiKzkus MySecret

Криптографический дайджест файла. В Linux можно использовать эквивалентные команды md5sum, sha1sum.

openssl dgst -md5 filename
openssl dgst -sha1 filename

(Де)Кодирование в BASE64

openssl enc -base64 < file.txt
openssl enc -base64 -in file.txt
openssl enc -base64 -in file.txt -out file.txt.enc

#Декодирование
openssl enc -base64 -d < file.txt.enc

Шифрование симметричными шифрами. Пароль можно вводить интерактивно, читать из файла или указывать в командной строке

#список алгоритмов
openssl list-cipher-commands

#шифрование
openssl enc -des -in file.txt -out file.enc
openssl enc -des -in file.txt -out file.enc -pass pass:mySillyPassword
openssl enc -des -in file.txt -out file.enc -pass file:/path/to/secret/password.txt

#шифрование + кодирование в base64
openssl enc -des -a -in file.txt -out file.asc

#дешифрование
openssl enc -d -des -a -in file.asc -out file.txt

Клиент/сервер

SSL/TLS клиент. На STDERR выводится информация о сертификате. После подключения можно вручную вводить команды соответствующего протокола. TLS доступен только для определённых протоколов.

openssl s_client -connect remote.host:443
openssl s_client -connect remote.host:25 -starttls smtp

Сохранение сертификата в файл penssl s_client -connect remote.host:443 2>&1 < /dev/null | sed -n '/-----BEGIN/,/-----END/p'

Веб сервер с корнем в текущем каталоге. По умолчанию слушает порт 4433.

 openssl s_server -accept 443 -cert mycert.pem -WWW

SSH -OpenPGP

И SSH и OpenPGP используют(могут использовать) алгоритм RSA для аутенификации/шифрования. Соответственно, пары открытый/секретный ключ могут использоваться совместно в двух программах, поскольку это просто числа, соответствующие некой формуле. Основное отличие между ключами в OpenPGP и SSH - это инфраструктура и формат хранения.

Импорт ключа SSH в GPG

Не совсем понятно, зачем это надо, поскольку публичные ключи SSH (обычно) распространяются без какой либо верификации, а сами ключи (обычно) не содержат никакой информации о владельце. Соответственно, цифровая подпись, сделанная ключом SSH, не может считаться хоть сколько-нибудь значимой, поскольку невозможно удостовериться в принадлежности открытого ключа автору подписи.

Для конвертации потребуются скрипты от monkeysphere. Процедура импорта описана ЗДЕСЬ.

Использование GPG для аутенификации в SSH

В gpg-agent встроена поддержка протокола ssh-agent. Соответственно, можно сгенерировать ключи средствами GPG и поместить их в gpg-agent, затем импортировать публичный ключ стандартным образом через ssh-add -L.

Процедура генерации ключа описана ЗДЕСЬ Примерно то же самое + использование ybkey- ССЫЛКА.

GPG4Win и putty

GPG4Win совместим с pagent. ИНСТРУКЦИИ.

Шифрование в OpenSSL ключом OpenSSH

Подготовка

Генерация ключей SSH и сохранение их в пару файлов (mykey,mykey.pub)

ssh-keygen -t rsa -b 4096 -f mykey 

Приватные ключи по умолчанию сохраняются в формате PEM PKCS#1. Ключи, созданные в "новом" формате OpenSSH (опция -o) не совместимы с другими криптографическими системами.

Формат PEM можно отличить по строкам

-----BEGIN RSA PRIVATE KEY-----
-----END RSA PRIVATE KEY-----

в файле приватного ключа. В новом формате они заменены на строки

-----BEGIN OPENSSH PRIVATE KEY-----
-----END OPENSSH PRIVATE KEY-----

Публичный ключ так же нужно сконвертировать в формат PEM PKCS#8 (Можно это будет сделать на лету в момент шифрования):

ssh-keygen -f mykey.pub -e -m pkcs8 > mykey.pkcs8.pub
#или
openssl rsa -in mykey -pubout -outform PKCS8 > mykey.pkcs8.pub

Обмениваемся публичными ключами с партнёрами. Чтобы это подчеркнуть, при шифровании я буду использовать чужой публичный ключ anotherkey.pub.

Шифрование

Генерируем одноразовый сеансовый ключ (32 байта):

openssl rand -base64 32 -out key.bin

Шифруем передаваемые данные симметричным ключом:

openssl enc -aes-256-cbc -salt -in bigdata.dat -out bigdata.dat.enc  -pass file:./key.bin

Шифруем сеансовый ключ публичным ключом в формате PKCS#8:

openssl rsautl -encrypt -pubin -inkey anotherkey.pkcs8.pub -in key.bin -out key.bin.enc
# возможна конвертация на лету
openssl rsautl -encrypt -pubin -inkey <(ssh-keygen -e -m PKCS8 -f anotherkey.pub) -in key.bin -out key.bin.enc

Удаляем одноразовый ключ:

rm key.bin

Обмен файлами

По открытому каналу пересылаем bigdata.dat.enc и key.bin.enc.

Расшифровка

Расшифровываем секретным ключом сеансовый ключ. В реальной жизни вместо специально сгенерированного ключа mykey надо будет использовать стандартный ключ ~/.ssh/id_rsa:

openssl rsautl -decrypt -inkey mykey -in key.bin.enc -out key.bin

Расшифровываем данные:

openssl enc -d -aes-256-cbc -in bigdata.dat.enc -out bigdata.dat -pass file:./key.bin

Асимметричное шифрование маленьких файлов

Для передачи файлов в несколько байт или килобайт можно сразу зашифровать их асимметричным алгоритмом.

# Encrypt openssl rsautl -encrypt -inkey <(ssh-keygen -e -m PKCS8 -f ~/.ssh/id_rsa.pub) -pubin -in small.dat -out small.dat.enc # Decrypt openssl rsautl -decrypt -inkey ~/.ssh/id_rsa -in small.dat.enc -out small.dat

SSH

В повседневной деятельности пользователя можно выделить два вида деятельности - запуск программ (возможно с перенаправлением ввода вывода) и операции с файлами. На настоящий момент самым популярным протоколом запуска программ является протокол ssh, а для передачи файлов используются построенные на его основе команды scp и sftp.

Протокол ssh использует шифрование трафика, что обеспечивает защиту от перехвата паролей и передаваемых данных.

В состав комплекса входят клиентские программы ssh - аналог telnet и rsh, scp - аналог rcp и sftp - программа внешне похожая на ftp по защищенному каналу. Несмотря на похожесть этих программ на своих предшественников, они используют другие протоколы, разработанные заново для исправления архитектурных ошибок, выявленных в их предшественниках.

Cервер OpenSSH в большинстве дистрибутивов устанавливается по умолчанию. Необходимо только подогнать настройки под свои нужды.

Конфигурационные файлы хранятся в каталоге /etc/ssh

  • /etc/ssh/sshd_config конфигурация сервера
  • /etc/ssh/ssh_config конфигурация клиента по умолчанию.

Пользователи могут изменить личные настройки в файле $HOME/.ssh/config или задать их в командной строке.

В сети постоянно работают хакерские программы пытающиеся подобрать пароли к ssh грубой силой. В первую очередь проверяется пользователь root. По этому, первый шаг в укреплении безопасности – запрет root'у подключаться по ssh. Все администраторские действия лучше всего проводить с использованием программы Sudo. Кроме того, проверяются стандартные имена служб и типичные имена пользователей, например andrew, alex, mary и т.п. Лучший способ избавиться от проблем с подбором пароля – перейти на аутенификацию с публичным ключом. После генерации пары секретный ключ, публичный ключ, публичный ключ добавляется в список доверенных в файле пользователя ~/.ssh/authorized_keys. Права на файл authorized_keys желательно выставить в rw-------.

Серверные настройки – sshd_config

#Запрет на вход с именем root
PermitRootLogin no

#Разрешение на вход только по ключам
RSAAuthentication yes
PubkeyAuthentication yes
PasswordAuthentication no

Для безопасного удаленного доступа к локальным сетевым службам и запуска программ с графическим интерфейсом добавляем

AllowTcpForwarding yes
X11Forwarding yes

Внимание: для работы X11Forwarding в CentOS необходимо установить пакет xorg-x11-xauth

Telnet, FTP

"telnet" - протокол удалённого терминала предназначенный для удалённого подключения к ОС имеющих текстовый интерфейс.

"ftp" - по сути дела сеанс telnet в рамках которого на сервере запускается специализированная диалоговая программа для работы с файлами. Для передачи содержимого каталогов и файлов устанавливается дополнительное соединение, по которому и передаётся содержимое файла.

Туннели в SSH

Протокол SSH позволяет прокладывать TCP туннели внутри защищенного соединения. Фактически это означает, что клиент и сервер SSH создают по дополнительному сокету. Один из них принимает входящие соединения, а второй соединяется с кем-то в своей сети или в интернете. Данные из одного сокета пробрасываются в другой. В зависимости от распределения ролей сокетов туннели делятся на локальные (local) и удалённые (remote) . Первые принимают входящие соединения на локальном порту и пробрасывают их на удаленный сервер, вторые принимают соединения на удаленном сервере и пробрасывают их в локальную сеть.

      ++++++++     ++++++++      
      |Клиент| SSH |Сервер|      Кто то в сети
Я --->|порт  |-----|      |----> сервера или в интернете 
      |5678  |     |      |      с портом 80      
      ++++++++     ++++++++

          ++++++++     ++++++++      
Мой комп  |Клиент| SSH |Сервер|     Кто то из сети
порт  <---|      |-----|порт  |<--- сервера  или из интернета
3389      |      |     |5678  |     подключается ко мне
          ++++++++     ++++++++

В Unix проброс локального порта 5678 на remoteserv.com:80 через ssh_host.com выглядит так:

ssh -L localhost:5678:remoteserv.com:80 ssh_host.com

После создания канала можно подключаться браузером на http://loclahost:5678. localhost: в опции -L можно опустить. Это значение по умолчанию. Если надо подключиться на порт 80 самого ssh_host.com то можно задать опцию так:

ssh -L 5678:localhost:80 ssh_host.com

Проброс удаленного порта сервера для доступа на свой компьютер удаленным рабочим столом:

ssh -R *:5678:localhost:3389 ssh_host.com

* означает, что на сервере будут задействованы все доступные сетевые интерфейсы. Если этот параметр не указать, то порт 5678 откроется на сервере ssh_host.com только по адресу 127.0.0.1

Проброс портов без запуска терминала

В командах выше кроме проброса портов на удалённой машине запускается shell и устанавливается терминальное соединение. Если терминал не нужен, то можно запустить ssh с опцией -N. В этом случае никакая команда на удаленном сервере не запустится, и, что интересно, команды w, last и т.п. не будут показывать ваш вход на сервер. Впрочем, информация об авторизации в системе останется в логах категории authpriv.

Особые случаи

Опция -A находит на локальной машине порт ssh-agent пробрасывает его на удаленную машину на случайный порт или Unix-сокет и устанавливает в сеансе ssh переменную SSH_AUTH_SOCK для дальнейшей авторизации через агента.

Опция -X находит на локальной машине порт XWindow и пробрасывает его на первый свободный порт начиная от порта 6000 (базовый порт XWindow). Переменная DISPLAY в сеансе ssh устанавливается в :<номер порта - 6000>. Так, если номер порта на сервере 6007 то DISPLAY=":7".

Опция -D addr:port превращает ваш компьютер в SOCKS прокси с выходом в интернет на стороне сервера. Как и раньше, если вы укажете только порт, то вместо адреса подставится 127.0.0.1 и ваш прокси будет доступен только на локальном компьютере. Если вместо адреса подставить *, то вашим SOCKS прокси смогут воспользоваться все компьютеры, имеющие к вам доступ по сети.

Туннели в putty

Настройка туннелей в putty находится в настройках соединения в пункте Connection -> SSH -> Tunnels. Локальный/удаленный туннель может выбираться автоматически на основе введённых данных. В нашем примере локальному туннелю соответствуют поля: Source port - 5678; Destination - remoteserv.com:80

Не забудьте после ввода данных нажать кнопку "Add".

Если вам не нужен терминал, зато нужно формировать туннель из .bat файла - воспользуйтесь программой plink. Её параметры совпадают с параметрами ssh.

Доступ к устройствам в Linux

Классическая модель доступа к драйверам

В файловой системе Unix существуют специальные объекты - файлы устройств. Как правило, они создаются в каталоге /dev, но могут сбыть созданы и в любом другом каталоге. Каждый специальный файл - это точка доступа к драйверу устройства. Если драйвер предоставляет операции чтения/записи, то файл устройства может быть открыт как обычный файл cat /dev/modem > /dev/null. Для выполнения других операций с устройством (например выдвижение лотка CDROM) требуется отправка команд драйверу через системный вызов ioctl(). Файлам устройств права доступа назначаются так же , как и обычным файлам.

ВНИМАНИЕ: сетевые карты не отображаются в файлы устройств в /dev. Все сетевые интерфейсы живут в своём пространстве имён.

Команда создания специального файла:

mknod <name> <type> <major> <minor>
  • name - имя в файловой системе,
  • type - b|c - блочный или посимвольный тип устройства,
  • major, minor - номер драйвера в таблице драйверов и номер устройства в таблице устройств, обслуживаемых этим драйвером.

Имя устройства не имеет значения для функционирования ОС и выбирается по некоторым мнемоническим правилам. Например, SCSI диск может иметь следующие имена:

  • Linux - /dev/sda1 - первый раздел (1) на первом (a) SCSI диске
  • Solaris - /dev/dsk/c0t2d0s3 - контроллер 0, устройство 2 (SCSI ID), логическое устройство 0 (LUN Logical Unit Number - обычно 0), слайс 3 (Номер раздела)
  • Solaris - /devices/pci@0,0/pci-ide@7,1/ide@0/cmdk@0,0:a - диск на контроллере ide, подключенном по шине pci

Функциональность файла устройства определяется парой чисел major/minor, которые должны соответствовать номерам в некой таблице регистрации драйверов в ядре ОС. Назначение minor, обычно, определяется логикой работы драйвера. Для согласованного назначения номера major драйверам и специальным файлам существует несколько способов :

  • Статические номера major. Разработчики драйверов регистрируются у мантейнеров ядра и получают фиксированные номера major. . Разработчики дистрибутива добавляют в поставку скрипт для создания соответствующих специальных файлов в каталоге /dev.
  • Инициализация драйвера на основе специального файла. При инициализации драйвера в ядре он просматривает каталог /dev, обнаруживает по имени свой специальный файл и читает из него major/minor.
  • Динамическое назначение major/minor. При обнаружении нового устройства ядро инициализирует драйвер и назначает ему major/minor. Специальный сервис (udev) получает через сокет уведомление о найденном устройстве (тип, шина, производитель, идентификатор) и его major/minor. На основании этой информации и набора правил генерации имён сервис, создаёт для устройства специальный файл.

Каталоги /proc и /sys

Традиционно свойства процессов и некоторые параметры ядра отображаются в Linux в каталог /proc через драйвер псевдофайловой системы procfs. Начиная с ядра 2.6 параметры ядра, связанные с драйверами устройств и файловых системам, были вынесены в каталог /sys и псевдофайловую систему sysfs.

/proc

Через файл /proc/cpuinfo можно получить информацию о физических процессорах, физических ядрах и гипертрединговых логических ядрах.

$  cat /proc/cpuinfo
...
model name      : Intel(R) Xeon(R) CPU           E5520  @ 2.27GHz
....
cpu MHz         : 1733.000
...

Через файл /proc/net/dev можно получить список сетевых интерфейсов и статистику по ним

Inter-|   Receive                                                |  Transmit
 face |bytes    packets errs drop fifo frame compressed multicast|bytes    packets errs drop fifo colls carrier compressed
eth0: 1767479002126 7440045654    0 209199 176227535     ...
lo: 809098010894 313483867    0    0    0     0          ...

/sys

Каталог содержит информацию об инициализированных устройствах, сгруппированную по разным критериям: типам устройств, шинам, диагностическим протоколам доступа и т.п. Одни и те же устройства могут быть показаны в разных каталогах через символические ссылки.

  • /sys/devices - основной каталог, на который ссылаются остальные
  • /sys/dev - классификация по type, major, minor
  • /sys/bus - классификация по шине - pci, usb, scsi и т.п.
  • /sys/block - драйверы блочных устройств.
  • /sys/class - классификация по типу устройства

Заряд батареи

cat /sys/class/power_supply/BAT0/charge_full
cat /sys/class/power_supply/BAT0/charge_full_design
cat /sys/class/power_supply/BAT0/charge_now

Альтернативный путь к тем же данным

 /proc/acpi/battery/BAT0/*

Утилиты управления устройствами

  • dmesg - сообщения ядра. Включают информацию об обнаруженных устройствах.
  • lscpu - список процессоров (ядер). Выводит информацию из /proc/cpuinfo
  • lsusb - список устройств на шине USB (/sys/bus/usb/devices)
  • lspci - список устройств на шине PCI (/sys/bus/pci/devices)
  • lsblk -список дисков, разделов, логических томов и т.п.
  • hdparm - считывание параметров жёстких дисков и управление этими параметрами.
  • smartctl - считывание параметров S.M.A.R.T. жёсткого диска. Диагностика диска.
  • dmidecode - список устройств на материнской плате, в том числе информация о BIOS и о планках памяти.

Утилиты acpi, acpitool отсутствуют в большинстве современных дистрибутивов.

MySQL

БД MySql поставляется в CentOS в виде rpm пакетов с серверной и клиентской частью, а также вспомогательных пакетов, таких как интерфейс с perl. Начиная с CentOS 7 mysql заменен на mariadb.

Установка

yum install mariadb
yum install mariadb-server
yum install mariadb-client

После установки надо установить пароль администратора

systemctl start mariadb
mysqladmin password < secret_file

Если вы забыли пароль администратора, то надо остановить My SQL и временно запустить со сброшенным контролем доступа

systemctl stop mariadb
/usr/libexec/mysqld --skip-grant-tables &

#...Меняем пароль, рестартуем обычным образом
mysql -u root mysql
>update user set Password=password('newpassword') WHERE User='root';
>flush privileges;
>exit

killall -TERM mysqld

Создание новой БД и установка прав доступа для локального пользователя user1

mysqladmin -u root -p create mydb
echo 'GRANT ALL ON mydb.* to user1@localhost IDENTIFIED BY "mypassword";' | mysql -u root -p

Сохранение резервной копии/восстановление из копии

Сохранение (требует ввода пароля)

#вариант 1
mysqldump -u user1 -p mydb > mydb.sql

#альтернативный вариант, для автоматического удаления существующих таблиц при восстановлении
mysqldump -u user1 -p --add-drop-table mydb > mydb.sql

Восстановление

#Уничтожаем старые таблицы если сохраняли по 1му варианту
mysqldump -uuser1 -pmypassword --add-drop-table --no-data mydb | grep ^DROP | mysql -uuser1 -pmypassword mydb

#Восстанавливаем из копии
mysql -u user1 -p  mydb  < mydb.sql

Конфигурационный файл my.cnf

Настройки кодировки

[mysqld]
;Для клиентов которые не указывают кодировку при установке соединения
init-connect="SET NAMES UTF8"

;Кодировка на сервере по умолчанию
character_set_server=UTF8

Кодировка cp1251 в Linux

"I18N" означает Internationalisation т.е. начинается на “I” кончается на “N”, а в середине еще 18 букв.

По умолчанию в CentOS есть файлы локализации для русского языка в кодировке “UTF8”, если нам нужна другая кодировка надо создать нужные файлы из заготовок

localedef -f CP1251 -i /usr/share/i18n/locales/ru_RU /usr/lib/locale/ru_RU.CP1251

-f CP1251 ссылка на файл соответствия кодировки и UNICODE (по умолчанию файл ищется в /usr/share/i18n/charmaps/ и сжат gzip'ом)
-i /usr/share/i18n/locales/ru_RU каталог в котором лежат описания национальных констант
/usr/lib/locale/ru_RU.CP1251 каталог в который надо положить результат (библиотека libc ищет файлы кодировок именно здесь)

осталось объявить переменную LANG

export LANG=ru_RU.CP1251

Правильные программы должны корректно сортировать русские буквы, выдавать дату в русском формате и т.д.

Почтовый сервер

Наша задача – перейти с sendmail и почтовых ящиков в формате mailbox на связку postfix+cyrus-imapd, с хранением паролей пользователей в базе MySQL и организацией виртуальных почтовых доменов.
Для удобства доступа и администрирования будем использовать web-cyradm для администрирования почтовых ящиков и squirrelmail в качестве веб-интерфейса для почты.

Cyrus IMAPD

Cyrus IMAPD – сервер, обеспечивающий доступ к почте по протоколам IMAP и POP3.

Почта не привязана к локальным пользователям системы. Почтовые ящики хранятся в своем формате в отдельном каталоге, пароли могут проверяться различными способами, которые доступны через библиотеку SASL. Можно хранить пароли в базе My SQL, в sasldb или проверять через любые PAM модули. В состав Cyrus IMAPD входят программа для локальной доставки почты.

Внимание Необходимо сменить владельца /etc/imapd.conf на cyrus и отобрать у «прочих» права на чтение
chown cyrus /etc/imapd.conf
chmod o-r /etc/imapd.conf

/etc/imapd.conf
================
configdirectory: /var/lib/imap

#Где хранятся почтовые ящики
partition-default: /var/spool/imap

#Список администраторов, которые могут управлять почтовыми ящиками.
admins: cyradm

allowplaintext: 1
sievedir: /var/lib/imap/sieve
sendmail: /usr/sbin/sendmail

#Не трогаем 8ой бит.
munge8bit: 0

#Все ящики в нижнем регистре. При подключении клиентов регистр преобразуется.
username_tolower: 1

#Дает возможность использовать имена с точками. Если стоит "0", то точка используется как разделитель в системе почтовых каталогов.
unixhierarchysep: 1

#Для повышения производительности каталог с почтовыми ящиками разбивается на подкаталоги по алфавиту
# /var/spool/imap/a/, /var/spool/imap/b/ и т.д.
hashimapspool: true

#Проверка пойдет через PAM
sasl_pwcheck_method: saslauthd
# PLAIN - способ получения пароля от клиента, только PLAIN подойдет для проверки в файлах (базе) с паролями.
sasl_mech_list: PLAIN

#Список виртуальных доменов, для которые мы держим почтовые ящики
loginrealms: mydomain1.my mydomain2.my

#Сертификаты для шифрованного соединения
tls_cert_file: /usr/share/ssl/certs/cyrus-imapd.pem
tls_key_file: /usr/share/ssl/certs/cyrus-imapd.pem
tls_ca_file: /usr/share/ssl/certs/ca-bundle.crt

# Если мы хотим проверять пароли в БД с помощью встроенных модулей sasl, можно добавить
sasl_pwcheck_method: auxprop saslauthd
sasl_auxprop_plugin: sql
sasl_sql_engine: mysql
sasl_sql_user: mailadmin
sasl_sql_passwd: mailpasswd
sasl_sql_hostnames: localhost
sasl_sql_database: maildb
sasl_sql_statement: select password from accountuser where username = '%u' and domain_name = '%r'

(см. Аутенификация SASL)

/etc/cyrus.conf
Все по умолчанию

Программа cyradm

cyradm – скрипт на Perl для управления почтовыми ящиками по протоколу IMAP. Запуск

cyradm -u cyradmin localhost

cyradm можно использовать в диалоговом режиме, либо перенаправлять ему вывод какого либо скрипта

Создание почтового ящика и установка квоты 100МБ

cm user/newuser
sq user/newuser 100000

Удаление ящика
sam user/newuser cyradm c
dm user/newuser

Восстановление индексных файлов в порушенном ящике
/usr/lib/cyrus-imapd/reconstruct user

Postfix

Переход на Postfix с sendmail в CentOS осуществляется почти автоматически.
Устанавливаем postfix
yum install postfix
Правим конфигурационные файлы в каталоге /etc/postfix, удаляем Sendmail, cтроим hash для файла aliases, стартуем Postfix и добавляем его в список загружаемых при старте демонов

vi /etc/postfix/main.cf
rpm -e sendmail
newaliases
/sbin/service postfix start
/sbin/chkconfig postfix on

Замечательные русские инструкции по настройке Postfix можно найти здесь: http://sergeysl.pnz.ru/freebsd/mailsystem.php
Данная страница посвящена решению некоторых специфических задач конфигурации.

Альтернативные программы

В CentOS используется специальный механизм выбора версии программы, имеющей несколько реализаций. К таким программам относятся почтовые серверы, принт серверы, различные варианты java. В каталоге /etc/alternatives/ сделаны символические линки на реально установленные программы например, /etc/alternatives/mta изначально является символическим линком на /usr/lib/sendmail.sendmail. При удалении Sendmail происходит замена и /etc/alternatives/mta становится символическим линком на /usr/lib/sendmail.postfix. Файл /usr/sbin/sendmail является в свою очередь линком на /etc/alternatives/mta. Т.к. Postfix обрабатывает те же опции при запуске, что и Sendmail, подмену никто не заметит. Аналогичная ситуайия с mailq, newaliases, rmail.

Борьба со спамом и вирусами

Желательно установить Greylisting, clamav, spamassasin и/или mimedefang

yum install postgrey clamav clamd spamassassin mimedefang

Чтобы установка прошла атоматически, надо подключить к списку репозиториев yum'а Dag RPM Repository ( http://dag.wieers.com/rpm/ )
Возможны некоторые проблемы с зависимостями mimedefang с sendmail. (Похоже там явно прописана зависимость от rpm-пакета sendmail).
Подключение этих программ к Postfix будет описано ниже, при описании конфигурационных файлов.

Mimdefang подключится если у нас Postfix версии 2.4

Правим права доступа

В файле /etc/sysconfig/mimedefang (Проверить)
MX_USER=postfix

chown -R postfix.postfix /var/spool/MIMEDefang

MIMEDefang ожидает что сокет clamd расположен в /var/spool/MIMEDefang/clamd.sock, причем это прошито в коде /usr/bin/mimedefang.pl. Clamd по умолчанию помещает свой сокет в /tmp/clamd.socket. Попробуем сделать линк (Проверить)

ln -s /tmp/clamd.socket /var/spool/MIMEDefang/clamd.sock

По умолчанию MIMEDefang запускает Spamassassin с конфигурационным файлом /etc/mail/sa-mimedefang.cf, а пакет spamassassin устанавливает свой конфиг в /etc/mail/spamassassin/local.cf. Чтобы не было путаницы удаляем /etc/mail/sa-mimedefang.cf, MIMEDefang переключится на /etc/mail/spamassassin/local.cf автоматически.

Для postgrey прописываем белые листы:

Пользователи которым нельзя задерживать доставку почты ни под каким видом
Файл /etc/postfix/postgrey_whitelist_recipients

abuse@
quickaccess@

Локальные сети
Файл /etc/postfix/postgrey_whitelist_clients.local

192.168.100

К сожалению маска сети не предусмотрена. Если ваша подсеть больше или меньше стандартного класса, то придется перечислять все подсети или IP адреса (может получиться до 128 строк на подсеть)

Теперь надо включить postgrey, clamd, spamassassin и mimedefang в автозапуск.
/sbin/chkconfig clamd on
/sbin/chkconfig spamassassin on
/sbin/chkconfig mimedefang on

Файл /etc/postfix/main.cf
Основной конфигурационный файл Postfix'а описывающий «политические» параметры (контроль доступа, виртуальные домены и т.п.).
Полный список параметров и их значения по умолчанию можно посмотреть в main.cf.default
Ограничения на пересылку почты
Перед первым запуском правим имя хоста. Скорее всего оно определится из hostname, но лучше подстраховаться.

myhostname = mail.my.net
myorigin = $mydomain

myorigin подменяет почтовый домен для почты отправляемой с локальной машины. Нынче многие почтовые серверы проверяют наличие MX записи для адреса отправителя. В приведенном примере MX запись для my.net скорее всего существует, а для mail.my.net не существует. Почта с локальной системы, например диагностические сообщения, без установки myorigin будет блокироваться.

Ограничения на пересылку почты определяютя так
mydestination = $myhostname, localhost.$mydomain, localhost
mynetworks = 168.100.189.0/24, 127.0.0.0/8
smtpd_recipient_restrictions =
permit_mynetworks,
reject_unauth_destination,
check_policy_service unix:postgrey/socket

Результат ограничений – разрешаем пересылку почты из локальных сетей. Из остального мира после аутенификации и прохождения greylisting'а, либо для наших пользователей из списка почтовых доменов mydestination и прохождения greylisting'а. (есть еще список виртуальных пользователей, но оних ниже).
(Неприятный вопрос, будеть ли greylisting пропускать аутенифицированных пользователей?)
Пример других ограничений http://www.opennet.ru/tips/info/813.shtml

Подключение mimedefang для Postfix версии >= 2.4. Postfix 2.3.3 параметр воспринял, но Mimedefang выдал ошибки протокола при попытке отправить письмо.
smtpd_milters = unix:/var/spool/MIMEDefang/mimedefang.sock
milter_default_action = tempfail

В этом варианте spamassassin и антивирус запустятся через MIMEDefang.

Доставка почты

Почта предназначенная для локальных пользователей может доставляться
в классический файл формата mailbox

mail_spool_directory = /var/mail

или в каталог Maildir

home_mailbox = Maildir/

или с помощью внешней программы (если надо проверять на вирусы только входящую почту, то здесь можно вставить антивирусный фильтр)

mailbox_command = /usr/bin/procmail

или по протоколу lmtp если Postfix используется в связке с Cyrus IMAPD

mailbox_transport = lmtp:unix:/var/lib/imap/socket/lmtp

Можно описать собственный транспорт в файле /etc/postfix/master.cf

Файл /etc/postfix/master.cf

Конфигурационный файл, описывающий «технические» параметры (запускаемые почтовые службы и их настройки).

Подключение spamassassin и антивируса для Postfix версии < 2.4.
Проверяем только SMTP

#smtp inet n - n - - smtpd
smtp inet n - n - - smtpd -o content_filter=avfilter:dummy
...
avfilter unix - n n - - pipe
flags=R user=clamav argv=/usr/local/sbin/avfilter.sh -f ${sender} -- ${recipient}

Файл /usr/local/sbin/avfilter.sh может быть таким

#!/bin/sh
INSPECT_DIR=/tmp #Каталог куда будут сохраняться письма для сканирования
SENDMAIL="/usr/sbin/sendmail -i"
VIRUSADMIN="root@my.net" # адрес для уведомлениий

EX_TEMPFAIL=75
EX_UNAVAILABLE=69

# строка для запуска spamassassin
FILTER_SPAMC="/usr/bin/spamc"
#FILTER_SPAMC="/usr/bin/spamc -u spamfilter -U /var/run/spamd.sock"
# строка для запуска clamav
FILTER_CLAMAV="/usr/bin/clamdscan -v --no-summary --stdout"

trap "rm -f $INSPECT_DIR/in.$$ $INSPECT_DIR/vr.$$ $INSPECT_DIR/vr1.$$" 0 1 2 3 15

# Проверка на спам
cat | $FILTER_SPAMC > $INSPECT_DIR/in.$$ || { echo Cannot save mail to file; exit $EX_TEMPFAIL; }

# Проверка на вирусы
$FILTER_CLAMAV ${INSPECT_DIR}/in.$$>$INSPECT_DIR/vr.$$

# Результат проверки
AV_RESULT=$?

case "$AV_RESULT" in
0)
# Проверено. Мин нет :)
$SENDMAIL "$@" <${INSPECT_DIR}/in.$$
exit 0
;;
1)
# Обнаружен вирус. Посылаем уведомление админу
echo "Subject: VIRUS FOUND" >> $INSPECT_DIR/vr1.$$
echo >> $INSPECT_DIR/vr1.$$
echo "************************************************" >> $INSPECT_DIR/vr1.$$
echo "* MAIL *" >> $INSPECT_DIR/vr1.$$
echo "************************************************" >> $INSPECT_DIR/vr1.$$
echo >> $INSPECT_DIR/vr1.$$
# Включаем в отчет реальные адреса релеев
grep Received $INSPECT_DIR/in.$$ >> $INSPECT_DIR/vr1.$$
echo "Mail from: $2 (may be forget)" >> $INSPECT_DIR/vr1.$$
echo "To: $4" >> $INSPECT_DIR/vr1.$$
grep Subject $INSPECT_DIR/in.$$ >> $INSPECT_DIR/vr1.$$
echo >> $INSPECT_DIR/vr1.$$
echo "************************************************" >> $INSPECT_DIR/vr1.$$
echo "* Virus(es) *" >> $INSPECT_DIR/vr1.$$
echo "************************************************" >> $INSPECT_DIR/vr1.$$
# Включаем в отчет список вирусов
cat $INSPECT_DIR/vr.$$ >> $INSPECT_DIR/vr1.$$
$SENDMAIL -f $VIRUSADMIN -r $VIRUSADMIN -F "Antivirus" $VIRUSADMIN < $INSPECT_DIR/vr1.$$
exit 0
;;
*)
# Произошла ошибка в работе антивируса. Сообщим об ошибке админу
echo "Subject: ANTIVIRUS FAILED" >> $INSPECT_DIR/vr1.$$
echo >> $INSPECT_DIR/vr1.$$
echo "************************************************" >> $INSPECT_DIR/vr1.$$
echo "* Antivirus Failed with next problem *" >> $INSPECT_DIR/vr1.$$
echo "************************************************" >> $INSPECT_DIR/vr1.$$
case "$AV_RESULT" in
40)
echo "* Unknown option passed. *" >> $INSPECT_DIR/vr1.$$
;;
50)
echo "* Database initialization error. *" >> $INSPECT_DIR/vr1.$$
;;
52)
echo "* Not supported file type. *" >> $INSPECT_DIR/vr1.$$
;;
53)
echo "* Can't open directory. *" >> $INSPECT_DIR/vr1.$$
;;
54)
echo "* Can't open file. (ofm) *" >> $INSPECT_DIR/vr1.$$
;;
55)
echo "* Error reading file. (ofm) *" >> $INSPECT_DIR/vr1.$$
;;
56)
echo "* Can't stat input file / directory. *" >> $INSPECT_DIR/vr1.$$
;;
57)
echo "* Can't get absolute path name of current *" >> $INSPECT_DIR/vr1.$$
echo "* working directory. *" >> $INSPECT_DIR/vr1.$$
;;
58)
echo "* I/O error, please check your filesystem. *" >> $INSPECT_DIR/vr1.$$
;;
59)
echo "* Can't get information about current user *" >> $INSPECT_DIR/vr1.$$
echo "* from /etc/passwd. *" >> $INSPECT_DIR/vr1.$$
;;
60)
echo "* Can't get information about user *" >> $INSPECT_DIR/vr1.$$
echo "* clamav (default name) from /etc/passwd. *" >> $INSPECT_DIR/vr1.$$
;;
61)
echo "* Can't fork. *" >> $INSPECT_DIR/vr1.$$
;;
63)
echo "* Can't create temporary files/directories *" >> $INSPECT_DIR/vr1.$$
echo "* (check permissions). *" >> $INSPECT_DIR/vr1.$$
;;
64)
echo "* Can't write to temporary directory (please *" >> $INSPECT_DIR/vr1.$$
echo "* specify another one). *" >> $INSPECT_DIR/vr1.$$
;;
70)
echo "* Can't allocate and clear memory (calloc). *" >> $INSPECT_DIR/vr1.$$
;;
71)
echo "* Can't allocate memory (malloc). *" >> $INSPECT_DIR/vr1.$$
;;
*)
echo "Unknown error $AV_RESULT" >> $INSPECT_DIR/vr1.$$
;;
esac
echo "************************************************" >> $INSPECT_DIR/vr1.$$
$SENDMAIL -f $VIRADMIN -r $VIRADMIN -F "Antivirus" "$VIRADMIN" < $INSPECT_DIR/vr1.$$
exit $EX_TEMPFAIL
;;
esac
exit 0

Виртуальные домены

В Postfix используются несколько способов задания имен локальных почтовых ящиков.
1. Имена пользователей зарегистрированных в системе. Т.е. в файле /etc/passwd
2. Имена перечисленные в файле /etc/aliases
3. Почтовые ящики перечисленные в файле /etc/postfix/virtual
4.Имена, определяемые локальной программой доставки

В зависимости от подсистемы обслуживающей почтовые ящики, имена из virtual могут отображаться, а могут и не отображаться на имена пользователей из файла passwd.

Основное идеологическое отличие между /etc/aliases и /etc/postfix/virtual в том, что aliases предназначены для локальных имен (например postmaster->root->adminuser или root->root@remote.com), а файл virtual предназначен для отображения имен пользователей различных почтовых доменов, обслуживаемых данным сервером, в имена локальных или удаленных почтовых ящиков (например user@virtual.net ->user_virtual_net).
Другими словами aliases нужны для корректной доставки почты на компьютере не являющемся выделенным почтовым сервером, а virtual это средство для развертывания почтовой системы массового обслуживания.
Если используются оба файла, то вначале для определения маршрута доставки почты используется virtual, а затем, если почта должна быть доставлена в локальный почтовый ящик, aliases.

Squirrelmail

Squirrelmail - веб интерфейс к IMAP серверу/

После инсталляции размещается в /usr/share/squirrelmail, в /etc/httpd/conf.d создается конфигурация для виртуального каталога /webmail, в /etc/squirrelmail/ помещаются файлы config.php и config_local.php

Файл config.php редактируется скриптом /usr/share/squirrelmail/config/conf.pl Настройки сводятся к выбору языка и типа IMAP сервера.

Внимание! Для cyrus-imapd надо в /etc/squirrelmail/config_local.php прописать $default_folder_prefix= 'INBOX/';

Для включения ssl желательно дописать в /etc/httpd/conf.d/squirrelmail.conf

<Directory /usr/share/squirrelmail>
SSLOptions +StrictRequire
SSLRequireSSL
SSLRequire %{HTTP_HOST} eq "mail.mydomain.my"
ErrorDocument 403 https://mail.mydomain.my/webmail
</Directory>

mailman

Дистрибутив CentOS 7

Удалить письма из архива

Сначала чистим почтовый архив, потом регенерируем веб-архив, стирая старый

mutt -f  /var/lib/mailman/archives/private/mylist.mbox/mylist.mbox
/usr/lib/mailman/bin/arch --wipe mylist

Управление списком рассылки из командной строки

Программа управления списками рассылки mailman написана на Python 2 и имеет хорошо задокументированное API.

Для тех, кто не хочет программировать на python, существует несколько готовых скриптов для управления списками рассылки. В CentOS 7 они находятся в каталоге /usr/lib/mailman/bin/.

Базовые команды

Создание списка newlist [listname [listadmin-addr [admin-password]]] Если часть параметров пропущена, то она будет запрошена в интерактивном режиме.

Добавление участников рассылки add_members -r infile listname Где файл infile состоит из строк вида:

jdoe@example.com
<jdoe@example.com>
John Doe <jdoe@example.com>
"John D. Doe" <jdoe@example.com>
jdoe@example.com (John Doe)

Просмотр списка участников list_members listname. С полными именами (не дружит с Unicode) list_members -f listname

Смена административного пароля на списки рассылки change_pw. Опция -a позволяет установить один пароль на все списки, -l list1 -l list2... позволяет перечислить списки. Пароль генерируется автоматически, но его можно задать явно опцией -p pass.

Удаление списка рассылки (БЕЗ ЗАПРОСА ПОДТВЕРЖДЕНИЯ) rmlist -a listname. Опция -a указывает, что надо удалить архив сообщений.

Изменение параметров списка рассылки

Сохранение в файл основных параметров списка (без информации об участниках) config_list -o listname.conf listname. Формат вывода - программа на python, которая может быть подана на вход config_list -i listname.conf listname

Просмотр всех параметров списка dumpdb /var/lib/mailman/lists/<listname>/config.pck

Изменение параметров списка (В том числе массовое добавление полных имён участников рассылки) config_list -i infile listname. В файле infile должна находиться программа на python, в которой присваиваются значения переменным, имена которых совпадают с именами атрибутов списка рассылки. Имена переменных не совпадающих с атрибутами игнорируются. Можно присваивать значения непосредственно атрибутам объекта списка рассылки mlist, но при этом можно нарушить внутреннюю непротиворечивость конфигурации.

Примеры файлов для config_list

Отключение ежемесячного напоминания о паролях

echo send_reminders=0 > remunders0.conf
config_list -i remunders0.conf sample_list

Для добавления участникам полных имен надо найти в выдаче dumpdb /var/lib/mailman/lists/sample_list/config.pck подходящие атрибуты:

    'members': {   'student1@example.com': 0,
                   'student2@example.com': 0},
...
    'usernames': {   'student1@example.com': u'\u041f\u0435\u0440\u0432\u044b\u0439 \u0441\u0442\u0443\u0434\u0435\u043d\u0442',
                     'student2@example.com': u''},

Видно, что полные имена хранятся в формате unicode. Так, полное имя student1@example.com - "Первый студент". Можно написать присваивание какому-либо элементу массива usernames и сохранить его в файле infile:

mlist.usernames['student2@example.com'] =  u'Second Student'

Команда config_list -i infile sample_list изменит полное имя для участника student2@example.com

Аутенификация SASL (cyrus-sasl)

SASL – Simple Authentication and Security Layer, это метод аутенификации пользователя для встраивания в сетевые протоколы основанные на соединении. Ниже описана конфигурация одной из реализаций механизма - cysrus-sasl версии 2.

В cysrus-sasl существует два основных способа аутенификации: auxprop - через библиотеку, слинкованную с приложением и saslauthd - по особому протоколу через сервер аутенификации saslauthd.

auxprop позволяет проводить аутенификацию в базе данных SQL (mysql, sqlite), файле BeklyDB или в LDAP. Список вариантов проверки saslauthd можно узнать командой

# saslauthd -v
saslauthd 2.1.26
authentication mechanisms: getpwent kerberos5 pam rimap shadow ldap httpform

Один экземпляр saslauthd может использовать только один механизм аутенификации.

Не стоит использовать auxprop совместно с БД, поскольку существующая реализация требует хранить пароли БД открытым текстом. Более гибким способом является связка saslauthd + pam + pam_mysql.

Поддержка SASL включена, в частности, postfix и в cyrus-imapd. Опции SASL для cyrus-imapd прописываются в файл /etc/imapd.conf, для postfix в CentOS 7 - в файле /etc/sasl2/smtpd.conf (/usr/[local/]lib[64]/sasl2/smtpd.conf в других дистрибутивах).

Пример конфигурации с хранением незашифрованных паролей в mysql

Файл конфигурации cyrus-imapd /etc/imapd.conf

#Для отладки взаимодействия с SQL сервером (печать sql-запросов)
sasl_log_level: 5
#Для логирования необходимо вставить в конфигурацию `rsyslogd` строку
#*.=debug /var/log/debug

#Механизм запроса пароля. В данном случае в виде открытого текста.
sasl_mech_list: PLAIN

#Механизм доступа к SASL
sasl_pwcheck_method: auxprop

#Плагин, используемый через auxprop
#Сами плагины лежат в /usr/[local/]lib[64]/sasl2/
sasl_auxprop_plugin: sql

#Опции для sql плагина
# mysql - тип сервера (еще есть sqlite)
sasl_sql_engine: mysql
# Доступ к базе
sasl_sql_user: mailadmin
sasl_sql_passwd: mailpassword
sasl_sql_hostnames: localhost
sasl_sql_database: mail

# Запрос должен извлечь пароль в виде текста для пользователя %u@%r (%r - realm)
# По умолчанию вместо %r подставляется имя хоста, на котором запущен cyrus-imapd
sasl_sql_statement: select password from accountuser where username = '%u' and domain_name = '%r'

Пример использования saslauthd с postfix

Файл конфигурации postfix - /etc/postfix/main.cf

# Сервер, который будет делать проверку
smtpd_sasl_path = smtpd

smtpd_sasl_auth_enable = yes

Файл /etc/sysconfig/saslauthd содержит опции для запуска saslauthd, в том числе, используемый механизм проверки.

MECH=pam

Файл настроек sasl для демона smtpd /etc/sasl2/smtpd.conf

pwcheck_method: saslauthd
mech_list: PLAIN

Файл настроек PAM для службы smtp /etc/pam.d/smtp Приложения передают в saslauthd имя сервиса. postfix передаёт строку smtp.

#%PAM-1.0
auth required pam_mysql.so config_file=/etc/security/pam_mysql.conf [where=smtpauth=1]
account required pam_mysql.so config_file=/etc/security/pam_mysql.conf [where=smtpauth=1]

БД

В дальнейшем считаем, что в БД создана база mail, доступ к ней разрешен пользователю mailadmin с паролем mailpassword. В администраторы cyrus-imapd внесен пользователь cyradmin.
Web-cyradm предпологает следующую структуру данных для хранения паролей:

CREATE TABLE accountuser (
username varchar(255) binary NOT NULL default '',
password varchar(30) binary NOT NULL default '',
prefix varchar(50) NOT NULL default '',
domain_name varchar(255) NOT NULL default '',
UNIQUE KEY username (username)
) TYPE=MyISAM;

Миграция с Mailbox на CyrusIMAP

Перенос почтовых ящиков

Скрипт для создания пустых почтовых ящиков на основе информации в /etc/passwd

#!/usr/bin/perl -w
#
# Written by Wil Cooley <wcooley@nakedape.cc>, 25 April 2002.
#
# This script is copyright (C) 2002 by Wil Cooley and
# licensed under the GNU GPL <http://www.gnu.org//licenses/gpl.txt>
#
# Usage: migrate-pw-to-cyrus2.pl
#
# Purpose: Creates empty Cyrus mailboxes.
#
# Input: None.
#
# Notes: Set the default quota below. I used a default
# of 100MB more as a failsafe than a restriction.
#
# $Id: migrate-pw-to-cyrus2.pl,v 1.1 2002/04/26 00:56:09 wcooley Exp $
###
my $adminuser = "cyradmin" ;
my $server = "localhost" ;
my $quota = 100*1024 ; # 100MB
my $user_uid_start = 500 ;
my $err = 0 ;
my ($user,$p,$uid) ;

use Cyrus::IMAP::Admin;

$imapcon = Cyrus::IMAP::Admin->new($server) || die "Unable to connect to $server";

unless ($imapcon) {
die "Error creating IMAP connection object\n" ;
}

$imapcon->authenticate(-user => $adminuser, -mechanism => "LOGIN") ;

if ($imapcon->error) {
die $imapcon->error ;
}

print "\n" ;

setpwent() ;

while (($user,$p,$uid) = getpwent) {
if ($uid >= $user_uid_start) {
unless ($imapcon->list("user.$user")) {
$imapcon->create("user.$user") ;
if ($imapcon->error) {
print "ERROR: ", $imapcon->error, "\n" ;
next;
} ;
$imapcon->setquota("user.$user", "STORAGE", $quota) ;
if ($imapcon->error) {
print "ERROR: ", $imapcon->error, "\n";
next;
} ;
print "Created mailbox user.$user [$uid]\n" ;
}
}
}
endpwent() ;

Перенос содержимого почтовых ящиков с помощью formail и cyrus deliver

# Script to import mbox-format mailboxes to Cyrus folders
# Requires formail (from procmail)
#
# Note: As this runs cyrdeliver directly, you'll need to be
# a member of the mail group for it to work.
#
# Use this script at your own risk! I'm not responsible if
# it trashes your mail system :)
#
# By Michael-John Turner <mj@debian.org>
#

USER=$1
MAILBOX=$2
CYRUSFOLDER=$3
#CYRDELIVER=/usr/sbin/cyrdeliver
CYRDELIVER=/usr/lib/cyrus-imapd/deliver
FORMAIL=/usr/bin/formail

if ! [ -x "$FORMAIL" ]; then
echo ""
echo "formail (from procmail) is required to run this script"
echo ""
exit 1
fi

if [ "$USER" = "" ]; then
echo ""
echo "syntax: $0 user [mbox] [cyrus folder]"
echo ""
echo "If no mbox is specified, the user and mbox name are taken to be the same"
echo "If no cyrus folder is specified, the INBOX is used"
echo ""
exit 2
fi

if [ "$MAILBOX" == "" ]; then
MAILBOX=$USER
fi

if [ "$CYRUSFOLDER" == "" ]; then
echo "Adding mailbox '$MAILBOX' to Cyrus INBOX of user '$USER'..."
$FORMAIL -I "From " -s $CYRDELIVER $USER < $MAILBOX
else
echo "Adding mailbox '$MAILBOX' to Cyrus folder '$CYRUSFOLDER' of user '$USER'..."
$FORMAIL -I "From " -s $CYRDELIVER -m $CYRUSFOLDER $USER < $MAILBOX
fi

Перенос паролей

При миграции возникает желание убрать записи почтовых пользователей из /etc/passwd и перейти на хранение паролей в MySQL, LDAP или где нибудь еще. Прямого пути нет!

В качестве обходного пути можно попытаться использовать PAM-modules Сергея Позднякова http://puszcza.gnu.org.ua/software/pam-modules/

Устанавливаем pam_fshadow из указанного пакета. Копируем записи почтовых пользователей из файла /etc/shadow (/etc/master.passwd во FreeBSD) в новое место, например в /etc/mail/shadow. Пишем настройки PAM для сервисов pop, imap и, возможно, sieve.

auth sufficient pam_fshadow.so sysconfdir=/etc/mail nopass
account sufficient pam_fshadow.so sysconfdir=/etc/mail nopass

Дополнительно настраиваем SASL для проверки в MySQL. Вариант с pam_mysql менее интересен, т.к. не поддерживает виртуальные домены.

auth sufficient pam_fshadow.so sysconfdir=/etc/mail nopass
auth sufficient pam_mysql.so config_file=/etc/pam_mysql.conf
auth sufficient pam_fshadow.so sysconfdir=/etc/mail nopass
account sufficient pam_mysql.so config_file=/etc/pam_mysql.conf

Пример /etc/pam_mysql.conf
users.host=localhost;
users.database=maildb;
users.db_user=mailadmin;
users.db_passwd=mailpassword;
users.table=accountuser;
users.user_column=username;
users.password_column=password;
users.password_crypt=plain;
users.disconnect_every_operation=true;
verbose=0;
log.enabled=1;
log.table=logins;
log.message_column=message;
log.pid_column=pid;
log.user_column=username;
log.host_column=machineip;
log.time_column=logintime;

Русские буквы в почтовых ящиках IMAP

В соответствие с RFC2060 национальные символы в именах почтовых ящиков на сервере должны кодироваться в модифицированную кодировку UTF7. Отличия от оригинальной UTF7 связаны с особым значением символа '+' в некоторых почтовых системах и символа '/' в роли разделителя имён каталогов в Unix.

Алгоритм кодирования имён папок: Текст -> UTF7; & -> &-; / -> ,; + -> &

Декодирование:

echo '.&BB4EQgQ,BEAEMAQyBDsENQQ9BD0ESwQ1-' \
| sed 's/&\([^-]\)/+\1/g;s/&-/&/g;s/,/\//g' \
| iconv -f UTF7 -t UTF8

.Отправленные

Использование программы mail (mailx)

Автоматическая отправка почты

echo test | mail -s test user@example.com

Отправка вложенного файла

uuencode filename ./filename | mail -s "test with file" user@example.com

Дополнительные опции при отправке

-s - Subject:
-c - Cc:
-b - BCc:
-r - From:

Редактирование почтового ящика с помощью mutt

Открыть IMAP/mailbox/Maildir

mutt -f imaps://mail.example.com/
mutt -f file.mbox

или

MAIL='/home/user/Maildir' mutt -f file.mbox

Удалить письма с определенных доменов (From:)

Shift D ~f@example.com

Удалить письма со словом SPAM в поле Subject:

Shift D ~sSPAM

Удалить все письма (два варианта)

Shift D ~s.*
Shift D ~A

Восстановить удаленное письмо с номером 1234 1234<CR>u

Команды

Список писем

Cmd Description
j,k next, previous message
1234 go to mail number 1234
= first message
* last message
d delete
D~pattern delete by pattern
u undelete
U~pattern undelete by pattern
m new message
f forward
r reply
s save message to file
v view attachment
$ delete all marked messages
x discard changes and quit
q quit

Чтение письма

Cmd Description
j,k next, previous message
d delete
u undelete
m new message
f forward
r reply
s save message to file
i return to main menu

Отправка письма

Cmd Description
t To:
s Subject:
c CC:
b BCC:
a attach file
q abort sending message
y send

Шаблоны поиска

Шаблон Описание
~A все (all)
~N новые (new)
~O старые(old)
~R прочитанные (read)
~U непрочитанные (unread)
~bEXPR поиск в теле (body) письма
~sEXPR поиск в поле Subject
~fEXPR поиск в поле From:
~tEXPR поиск в поле To:
~d [MIN]-[MAX] дата отправки Date между MIN и MAX. Дата в формате DD/MM/YY[YY] или выражение вида >, <, = число дней (d), недель (w), месяцев (m), лет (y). Например 01/01/2019 или >3m

Проверка синтаксиса конфигурационных файлов

После правок конфигурационного файла, желательно проверить его синтаксис.

Named (BIND)

Просто проверка конфигурации

named-checkconf /etc/named.conf

Проверка конфигурации в chroot

named-checkconf -t /var/named/chroot /etc/named.conf

Samba

testparm

Postfix

postconf

Apache

apachectl configtest

Squid

squid -k parse

Nginx

nginx -t

тест + дамп

nginx -T

Сервер Apache

Установка и настройка веб сервера Apache

В разных дистрибутивах пакет содержащий apache может называться httpd (CentOS), apache (Arch Linux), apache2 (Debian/Ubuntu). Кроме основного пакета может потребоваться установка дополнительных модулей, например mod_ssl.

http.conf

Для установки apache используется один выделенный каталог с подкаталогами (ссылками на подкаталоги) с конфигурацией, модулями и логами. В CentOS базовый каталог /etc/httpd/. Дальнейшие ссылки на файлы даются именно для CentOS.

Основной конфигурационный файл /etc/httpd/conf/httpd.conf. В каталоге /etc/httpd/conf.d/ могут храниться дополнительные конфигурационные файлы. Они имеют ту же структуру что и httpd.conf и включаются в основной файл директивой Include.

Внимание В некоторых дистрибутивах Include /etc/httpd/conf.d/ стоит в первой половине httpd.conf до объявления виртуального сервера. По этому, если вы хотите хранить в отдельных файлах конфигурацию виртуальных серверов, то создайте новый каталог, например /etc/httpd/virtual, а в конец httpd.conf вставьте Include /etc/httpd/virtual/*.conf

Структура httpd.conf проста

#Комментарий
ГлобальныйПараметр значение
<Секция значение>
    ЛокальныйПараметр значение
</Секция>

Все, что не попало внутрь секций, влияет на глобальные настройки сервера, секции определяют специфические настройки каталогов, виртуальных серверов и модулей apache.

PHP

Установка PHP

В CentOS устанавливаем rpm пакеты

yum install php-common php-cli php

Если посмотреть список установленных файлов, то видно, что php устанавливает модуль для Apache /usr/lib/httpd/modules/libphp7.so, а php-cli — интерпретатор /usr/bin/php

Модуль для Apache требует внесения изменений в конфигурацию apache. В CentOS это делается при инсталляции пакета путем добавления файла /etc/httpd/conf.d/php.conf. Примерное содержимое файла

<FilesMatch \.(php|phar)$>
   SetHandler application/x-httpd-php
</FilesMatch>
DirectoryIndex index.php

Модули в PHP

Интерпретатор php позволяет подключать дополнительные модули, которые расширяют набор доступных в языке функций. Модули могут быть статически скомпилированы в интерпретатор либо подключаться динамически. Из популярных можно упомянуть php-mysql для связи с БД My SQL, php-gd – библиотека обработки изображений, php-mbstring – работа с Unicode.

В CentOS модули можно доустанавливать в соответствии с потребностями

yum install php-mysql

В соответствии с идеологией CentOS конфигурация php для модуля сохраняется в каталоге /etc/php.d/ и содержит строку подключения модуля:

extension=mysql.so

После установки модуля, веб сервер надо перегрузить.

Конфигурационный файл PHP

Общий для всех конфигурационный файл находится в /etc/php.ini

В инструкции по php перечислены параметры, которые можно (PHP_INI_ALL, PHP_INI_PERDIR) и которые нельзя (PHP_INI_SYSTEM) изменить на уровне каталога.

Начиная с версии PHP 5.3.0 в каталоге можно помещать локальный файл настроек .user.ini

Также установки «под себя» можно сделать в файле .htaccess строками подобными следующим

php_value upload_max_filesize 32M
php_value post_max_size 64M

Или в тексте самой программы

<?php
ini_set('memory_limit', '128M');
ini_set('max_input_time', '300');
ini_set('max_execution_time', '300'); // 5 minuites
?>

php_info.php

Простейшая, но очень полезная программа на php. Выдает всю информацию о конфигурации apache и php

<?php
print phpinfo();
?>

Пример подключения к MySQL

<?php
$host='localhost'; $user="user1"; $pass='123';
//Знак @  нужен, чтобы погасить выдачу возможных ошибок подключения на веб страницу
$connection = @mysql_connect($host, $user, $pass, TRUE, 2);
//Установка кодировки для обмена данными в mysql версии > 4.1.0
mysql_query('SET NAMES "utf8"', $connection);
$query ="SELECT * FROM table";
$result = mysql_query($query);
if( $result )
{
   while( $array=mysql_fetch_array($result, MYSQL_ASSOC) );
   print_r($array);
}
?>

httpd.conf Apache 2.2

Секции

Секции определяют права доступа к каталогам, файлам, виртуальным серверам и модулям apache Секции могут быть вложены друг в друга файл в каталог, каталог в виртуальный сервер, модуль в виртуальный сервер (это не проверено)

В списке виртуальных серверов может присутствовать <VirtualHost *:80> который будет использоваться если к apache пришел запрос с отсутствующим (по ip) или несконфигурированным именем сервера.

<VirtualHost dummy-host.example.com:80>
    ServerAdmin webmaster@dummy-host.example.com
    DocumentRoot /www/docs/dummy-host.example.com
    ServerName dummy-host.example.com
    ErrorLog logs/dummy-host.example.com-error_log
    CustomLog logs/dummy-host.example.com-access_log common
</VirtualHost>

Допустимые опции каталога Indexes Includes, FollowSymLinks, SymLinksifOwnerMatch, ExecCGI, MultiViews, а также All или None.

<Directory "/var/www/html">
#
#Разрешаем просмотр каталогов в которых нет файла index.html
#Разрешаем использование символических ссылок
    Options Indexes FollowSymLinks
#Запрещаем задание прав на доступ в .htaccess
    AllowOverride None
#Разрешаем доступ всем
    Order allow,deny
    Allow from all
</Directory>



#Запрещаем доступ к файлам .htaccess, .htpasswd и т.п.
<Files ~ "^\.ht">
    Order allow,deny
    Deny from all
</Files>


Включаем прокси, но ограничиваем доступ к нему доменом **example.com**

<IfModule mod_proxy.c>
    ProxyRequests On
    <Proxy *>
        Order deny,allow
        Deny from all
        Allow from .example.com
    </Proxy>
</IfModule>

Файлы .htaccess

В файлах .htaccess можно переопределить права доступа к каталогу (и его подкаталогам), если в httpd.conf для него указано AllowOverride All (All это по максимуму, возможно, что разрешено будет переопределять только часть настроек). По сути дела .htaccess это секция <Directory ...>...</Directory> вынесенная в отдельный файл и лишенная обрамляющих конструкций. Если права меняются в httpd.conf, то серверу надо послать сигнал обновления конфигурации. Изменения в .htaccess вступают в действие мгновенно.

Если вы используете Apache совместно с PHP, то в .htaccess можно вынести некоторые параметры PHP необходимые для работы скриптов в данном конкретном каталоге. Например:

php_value include_path '.:/var/www/phplib:'
php_value default_charset 'windows-1251'

Правильный порядок Allow, Deny

В директивах определяющих доступ к каталогу правила Deny и Allow можно писать в любом порядке. Реальный порядок их применения определяется директивой Order. При запоминании порядка важно уяснить, что эти правила не описывают группы адресов как в некоторых других программах (например в Squid), а последовательно применяются к каждому конкретному адресу

**Order Deny,Allow** - по умолчанию всем разрешено, т.е. если нет запрещающего правила **Deny**, то клиент допускается.  

Если какое то правило Deny запрещает доступ, то дополнительно проводится проверка в правилах Allow, и при наличии подходящего правила клиенту все таки разрешается доступ. Т.е. мы пишем глобальное правило Deny, а потом формулируем для него исключения в Allow

**Order Allow,Deny** - по умолчанию всем запрещено. 

Если какое то правило Allow разрешает доступ, то дополнительно проводится проверка в правилах Deny и при наличии соответствующего запрета клиента отфутболивают. Т.е. мы пишем глобальное правило Allow, а потом формулируем для него исключения в Deny

Примеры

#Никому нельзя (например в каталоге с библиотеками PHP)
Order Deny,Allow
Deny from all

#Только с apache.org
Order Deny,Allow
Deny from all
Allow from apache.org

#Только с apache.org кроме foo.apache.org
Order Allow,Deny
Allow from apache.org
Deny from foo.apache.org

httpd.conf Apache 2.4

Доступ по IP

<RequireAny>
  Require all denied
  Require ip 192.168.1.14
  Require ip 10.0.12.4
<RequireAny>
<RequireAll>
  Require all granted
  Require no ip 192.168.1.14
  Require no ip 10.0.12.4
<RequireAll>

Показ списка файлов в каталоге

DirectoryIndex disabled
Options Indexes
IndexOptions NameWidth=*

Файловый сервер Samba

Файлы конфигурации
/etc/samba/smb.conf – основная конфигурация
/etc/samba/smbusers – отображение имен сетевых пользователей на учетные записи UNIX
/etc/samba/lmhosts – отображение имен файловых серверов на ip адреса

/etc/samba/smbpasswd – файл с паролями, как правило вручную не меняется, имя можно поменять в smb.conf

Утилиты
smbpasswd – смена пароля пользователя, добавление учетной записи пользователя или компьютера в файл smbpasswd
testparm – проверка корректности smb.conf
testprns – проверка конфигурации сетевых принтеров
smbstatus – информация о подключенных клиентах
smbclient – утилита командной строки для подключения к серверу
nmblookup – просмотр зарегистрированнных имен NETBIOS

Файл /etc/samba/smb.conf состоит из секций имена которых выделяются квадратными скобками.
Секция [global] определяет общие настройки, [homes] доступ к домашним каталогам, остальные определяют прочие сетевые ресурсы раздаваемые этим сервером

[global]
#имя рабочей группы или домена
workgroup = IMM
#Сетевое имя компьютера, по умолчанию совпадает с hostname
netbios name = SERVER1

# Сохранять ли регистр букв
preserve case = yes
# А для "досовских" имен
short preserve case = no
# Если преобразуем ДОСовские имена, то как
default case = lower

case sensitive = no

[homes]
comment = Home Directories
browseable = no
writable = yes

[sampleshare]
path = /share
comment = Тестовый сетевой ресурс
guest ok = yes
browseable = yes
writable = no
write list = @admin
force create mode = 0664
force directory mode = 0775

Поддержка русских букв в именах файлов

Для того, чтобы русские имена файлов записанных на сервер через Samba нормально выводились в Дinux необходимо добавить в глобальную секцию smb.conf
dos charset=866
unix charset= UTF8

Группы пользователей

В Samba 3.0 появилась возможность произвольного отображения Unix'овских групп пользователей в любые группы домена. Для этого используется команда net.

Просмотр соответствий
net groupmap list

Создание собственной группы
groupadd mygroup
net groupmap add ntgroup="My group" unixgroup=mygroup type=d

Установка соответствий
net groupmap modify ntgroup="Users" unixgroup=public

Пример из книги John H. Terpstra “Samba-3 by Example”. Вторая часть примера мне кажется сомнительной. Из /etc/group понадерганы служебные группы, добавлены нестандартные public и ntadmin. Принцип сопоставления в половине случаев непонятен.

# Map Windows Domain Groups to UNIX groups
net groupmap modify ntgroup="Domain Admins" unixgroup=root
net groupmap modify ntgroup="Domain Users" unixgroup=users
net groupmap modify ntgroup="Domain Guests" unixgroup=nobody

ЗАНЯТИЯ март-апрель 2020 года

В связи с эпидемией коранвируса отменяются очные занятия 23, 30 марта и 6 апреля

Здесь будет выкладываться информация на материалы для самостоятельного изучения и ссылки на записи лекций в youtube.

Напоминаю, что у нас есть тестовая учетная запись s0222 на сервере umt.imm.uran.ru Пароль к учётке сброшен в случайное значение, так что доступ только по ключу. Кто не был на занятии 18 марта - могут прислать публичный ключ мне на почту.


2020.03.23

Практические занятия по использованию scp и sftp. Отчетность - правильные команды для каждого из заданий в виде письма на мой e-mail.

Под windows используются утилиты:

  • pagent для хранения секретного ключа
  • psftp для изучения команд sftp
  • pscp для автоматизации копирования файлов в bat файлах
  • winscp или плагин netbox в Far commander для обмена файлами с сервером в графическом режиме

Под Linux

  • ssh-agent
  • sftp
  • scp
  • возможно, подключение по sftp из файлового менеджера (в зависимости от установленной графической среды)

SCP

  1. Надо скопировать тестовый файл со своего компьютера в каталог /tmp на сервере по scp;
  2. Скопировать файл на сервере из каталога /tmp в домашний каталог на том же сервере.
  3. Скопировать файл из домашнего каталога на сервере к себе на компьютер.
  4. Скопировать со своего компьютера в домашний каталог на сервере, какой нибудь каталог с файлами и подкаталогами.
  5. Скопировать файл на своём компьютере под другим именем или в другой каталог.

Указание - scp работает как cp, но если в имени файла есть двоеточие, то всё что левее - это user@server, а правее имя файла на сервере. Если не указан абсолютный путь к файлу на сервере, то путь считается от домашнего каталога. Для копирования каталога надо будет указать опцию

SFTP

  1. Используя SFTP как shell, подключиться к серверу и отобрать у группы и остальных права на тестовые файлы.
  2. Постирать копии файлов, которые были созданы при тренировках с scp.

Дополнительно

Оценить права доступа к файлам, полученном при копировании по scp и sftp. В частности, проверить сохраняются ли права при копировании из Unix в Unix. Попробовать создать файлы с русскими именами.


2020.03.30

Практически опробовать ssh-туннели.

Литература: моя методичка, более развёрнутое описание на хабре.

Задания:

  1. Запустить графическую задачу на сервере umt.imm.uran.ru (например firefox или matlab). В Linux использовать штатные средства, в Windows putty + X-server Xming (https://sourceforge.net/projects/xming/) Прислать скриншот.

  2. Организовать туннель с localhost:8080 на 2ip.ru:443 без терминального сеанса. Зайти на 2ip.ru через туннель браузером. Задокументировать на скриншоте URL в браузере, строку с IP в окне и отдельно время включения туннеля. Проблема в том, что по IP адресу находится виртуальный сервер. Поэтому вам:

а) придётся вписать в файл hosts строчку

127.0.0.1 2ip.ru

б) в браузере заходить по адресу https://2ip.ru:8080.

в) если ваша версия windows позволяет подключение удаленным рабочим столом, то можно попробовать пробросить свой порт 3389 на большой порт на сервере и попробовать подключиться через интернет, но это на свой страх и риск.


2020.04.20

Ключи шифрования подписи в GnuPG

Прочитать историю создания программы GnuPG

Установить себе версию GnuPG 2.2 или 2.1 - почему, описано в истории.

Прочитать описание структуры ключей и описание базовых команд. Сгенерировать мастер-ключ, подключ ключ шифрования и подключ подписи со сроком действия до июня 2020 года.

Прочитать про сеть доверия. Оценить для себя, нужен ли настоящий доверенный ключ подписи в будущем или мы пока играем в шифрование на учебных примерах.

Если идея иметь свой ключ понравилась, то запаролить мастер-ключ сложным паролем, сделать его резервную копию (пока нет в методичке), и опубликовать публичный ключ на сервере ключей (тоже нет в методичке). Потом мы подпишем ключи друг другу.

Если мы делаем учебный пример, то просто переслать мне публичные ключи , ссобщив их ID и e-mail через telegram. Я в свою очередь пришлю свой ключ для последующих обменов зашифрованными файлами.

Все непонятности перспрашивать у меня в телеграм или по e-mail, чтобы я правил методичку.

Секретная доставка пароля с помощью GnuPG

Создать текстовый файл с просьбой сообщить данные учебной почтовой записи в домене uran.ru. Подписать его и прислать мне. Получить от меня зашифрованный и подписанный файл с именем и паролем для входа на сервер. Можно сделать это в командной строке или воспользоваться оболочкой (Kleopatra).

Далее воспользоваться одной из доступных почтовых программ на выбор (список см. здесь) импортировать свой подключ и для подписи и мои публичные ключи в соответствующую программу и прислать подписанное и зашифрованное письмо.