воскресенье, 26 июля 2020 г.

Отключение сообщений об ошибках на стандартный ввод-вывод в net-snmp

Есть у меня один скрипт на Python, использующий привязки к библиотеке Net-SNMP. Скрипт отмечает результаты своей работы в базе данных и выводит сообщения об ошибках только при каких-то совсем уж неожиданных ошибках, например, при отсутствии связи с этой базой данных. Если же скрипт отработал шататно, он не должен выводить никаких сообщений. Поскольку сркипт регулярно запускался через планировщик задач cron, то при ошибках весь вывод скрипта отправлялся мне по почте. В общем, всё как обычно.

Раньше скрипт выполнял запросы только по протоколам SNMP первой и второй версии. Когда же в сети появились устройства, доступные только по протоколу SNMP третьей версии, скрипт начал выводить ошибки такого вида:
Authentication failed for backup
backup - это имя пользователя SNMPv3, под которым не удавалось выполнить SNMP-запросы.

Поскольку скрипт анализирует результаты запросов SNMP, то эти диагностические сообщение лишь засоряют вывод скрипта. Как оказалось, эти сообщения выводит сама библиотека Net-SNMP и я не нашёл никаких способов для того, чтобы их отключить, например, через конфигурацию /etc/snmp/snmp.conf. Чтобы отключить эти сообщения, потребуется поправить исходный текст библиотеки. Скачаем и распакуем пакет с исходными текстами net-snmp:
$ apt-get source net-snmp
Наши правки к исходному коду оформим в виде заплатки при помощи инструмента quilt, подробнее о котором я писал в заметке Использование quilt для подготовки заплат. Создадим новую заплатку:
$ quilt new removed-redundant-log-message
Добавим в будущую заплатку файл:
$ quilt add snmplib/snmpusm.c
Открываем файл snmplib/snmpusm.c в текстовом редакторе, находим и удаляем две строчки с вызовом функции snmp_log:
            snmp_log(LOG_WARNING, "Authentication failed for %s\n",
                                user->name);
В этом же файле при подобных ошибках функции snmp_log не вызываются и это единственный вызов snmp_log в этом файле. Скорее всего этот вызов функции был оставлен по ошибке, а не удалён вместе с другими подобными вызовами.

Чтобы изменения в файле snmplib/snmpusm.c попали в заплатку, обновляем заплатку:
$ quilt refresh
Можно прокомментировать сделанные в пакете изменения и изменить версию пакета:
$ dch -i
В запустившемся редакторе описываем последние изменения:
net-snmp (5.7.3+dfsg-5-stupin1) UNRELEASED; urgency=medium

  * Fixed SNMPv3 time widnow logic to work with D-Link switches
  * Removed redundant log message "Authentication failed from"

 -- Vladimir Stupin <vladimir@stupin.su>  Fri, 15 May 2020 16:01:26 +0500
Теперь можно пересобрать deb-пакеты, выполнив команду:
$ debuild -us -uc
В вышестоящем каталоге появятся готовые deb-пакеты, которые можно установить в систему командой dpkg -i или поместить в репозиторий пакетов при помощи aptly. Почитать об использовании aptly можно в другой моей заметке Создание своего репозитория Debian при помощи aptly.

После установки исправлений надоедливые сообщения об ошибках пропали.

воскресенье, 19 июля 2020 г.

Сертификат удостоверяющего центра Active Directory для веб-серверов

На работе в локальной сети имеется ряд веб-серверов, для которых понадобилось сделать поддержку протокола HTTPS. Поскольку веб-серверы находятся в локальной сети, то публичные удостоверяющие центры сертификаты для них выдать не могут. Можно было сгенерировать самоподписанные сертификаты, но тогда понадобилось бы вносить каждый сертификат в список доверенных в каждом браузере. Но есть выход получше. Т.к. компьютеры под управлением Windows в локальной сети объединены в домен Active Directory, они все должны доверять удостоверяющему центру Active Directory. Можно сгенерировать сертификаты для веб-серверов, подписать их в удостоверяющем центре Active Directory и тогда все браузеры, использующие системное хранилище сертификатов, на таких компьютерах будут автоматически доверять этим сертификатам.

Насколько я знаю, из самой популярной тройки браузеров только Firefox в конфигурации не использует системное хранилище сертификатов. Если учитывать, что большинство компьютеров в локальных сетях предприятий обычно работают под управлением Windows и включены в домен Active Directory, а большая часть пользователей используют браузеры Chrome и Internet Explorer, то таким образом можно внедрить HTTPS на веб-серверах в локальной сети максимально гладко. В случае с Firefox можно либо включить использование системного хранилища сертификатов Windows в настройках браузера, либо вручную импортировать в браузер корневой сертификат удостоверяющего центра Active Directory. Он всего один и срок его действия больше, чем у сертификатов веб-серверов.

По возможности лучше генерировать для каждого веб-сервера индивидуальный сертификат и тогда при взломе одного веб-сервера трафик остальных останется защищённым, т.к. злоумышленник не сможет использовать приватный ключ со взломанного сервера для расшифровки перехваченного трафика других веб-серверов или организации атаки посредника. Я же для экономии времени предпочёл сегенерировать один сертификат сразу для всех веб-серверов, находящихся в моей зоне ответственности. Чтобы при необходимости продлить сертификат мне не пришлось бы вспоминать значения полей из запроса на сертификат и не пропустить по невнимательности ни одного из веб-серверов, я подготовил файл конфигурации cert-web.ini такого вида:
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req

[req_distinguished_name]
countryName = RU
countryName_default = RU
stateOrProvinceName = Bashkortostan Republic
stateOrProvinceName_default = Bashkortostan Republic
localityName = Ufa
localityName_default = Ufa
organizationalUnitName = My Department
organizationalUnitName_default = My Department
commonName = My Company
commonName_default = My Company
commonName_max  = 64

[ v3_req ]
# Extensions to add to a certificate request
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = server1.domain1.tld
DNS.2 = server2.domain1.tld
DNS.3 = server3.domain1.tld
DNS.4 = server4.domain2.tld
DNS.5 = server5.domain2.tld
DNS.6 = server6.domain3.tld
В конфигурации упоминаются:
  • RU - код страны,
  • Bashkortostan Republic - административная единица внутри страны,
  • Ufa - название населённого пункта,
  • My Company - название компании,
  • My Department - название подразделения компании,
  • serverX.domainY.tld - доменные имена веб-серверов в локальной сети.
Генерируем приватный ключ:
$ openssl genrsa -out cert-web.key 2048
Генерируем запрос на сертификат в соответствии с файлом конфигурации:
$ openssl req -config cert-web.ini -new -key cert-web.key -out cert-web.csr
Запрос на сертификат из файла cert-web.csr я передал администратору домена Active Directory, который подписал его в удостоверяющем центре и вернул мне подписанный сертификат cert-web.cer в формате DER.

Полученный сертификат надо преборазовать из формата DER в формат PEM:
$ openssl x509 -inform der -in cert-web.cer -out cert-web.crt
Осталось соединить приватный ключ и сертификат в формате PEM для использования получившегося файла веб-сервером:
$ cat cert-web.key cert-web.crt > cert-web.pem
Остаётся положить получившийся один файл на веб-серверы и задействовать их использование в конфигурациях веб-серверов. Если использовать систему автоматизированного управления конфигурациями, то эта задача не займёт много времени. После освоения Ansible я стал раскладывать сертификаты на веб-серверы именно с её помощью.

Для того, чтобы получить корневой сертификат удостоверяющего центра Active Directory, нужно зайти веб-браузером на сервер с удостоверяющим центром, где можно будет найти и скачать корневой сертификат. В моём случае корневой сертификат удостоверяющего центра был доступен по ссылке вида: https://domain1.tld/certsrv/certnew.cer?ReqID=CACert&Renewal=2&Mode=inst&Enc=b64

Т.к. на веб-серверах был доступен API, который использовался на других серверах, то корневой сертификат понадобилось добавить так же и на эти серверы. В случае с Debian это можно сделать способом, описанным ниже.

Сначала устанавливаем стандартные сертификаты удостоверяющих центров, если они ещё не были установлены:
# apt-get install ca-certificates
Кладём корневой сертификат нашего удостоверяющего центра в каталог /usr/local/share/ca-certificates/, предназначенный специально для дополнительных сертификатов удостоверяющих центров.

Обновляем список корневых сертификатов, которым должна доверять библиотека openssl:
# update-ca-certificates
После этого все установленные в системе программы должны начать доверять сгенерированным нами сертификатам веб-серверов. Если этого не случилось и какая-то программа или модуль не начали доверять новым сертификатам, изучите документацию. Например, для того, чтобы модуль urllib2 для Python начал доверять сертификатам, мне понадобилось передавать библиотеке urllib2 дополнительные настройки, описанные в заметке: Проверка действительности SSL-сертификата в urllib2