воскресенье, 9 октября 2016 г.

Хакинг TV Motion Detector VG

Эта заметка может показаться необычной, потому что не укладывается в формат моего блога. Блог посвящён в основном Debian и родственным системам, а сейчас я собираюсь рассказать о программе для Windows. Впрочем, прецеденты заметок про Windows в моём блоге имеются. Написать эту заметку я решил во-первых потому, что моё решение небольшой проблемы может пригодиться кому-то ещё, а во-вторых - потому что способ решения проблемы показался мне довольно интересным. По крайней мере до этого я подобным способом проблемы ещё никогда не решал.

Для начала несколько слов о самой программе. Программа предназначена для мониторинга аналоговых телеканалов и, насколько я могу судить, довольно популярна у операторов кабельного телевидения. Программа поочерёдно переключает каналы на ТВ-тюнере и проверяет, есть ли на канале звук, двигается ли изображение. Программа умеет вызывать другие программы в случае если проблема была только что обнаружена, обнаружена повторно или произошло восстановление вещания. Подробнее о TV Motion Detector VG можно почитать на официальном сайте. Ещё один немаловажный момент - программа бесплатная. Пусть это будет ещё одним аргументом в пользу того, что эта заметка написана не за деньги и не является скрытой рекламой :)

TV Motion Detector VG использует файл scanfreq.txt со списком частот каналов и файл channels.sqlite со списком каналов в таблице channels, журналом событий в таблице log и списком запланированных задач в таблице scheduler. Имеется база данных, в которой инженеры головной станции поддерживают актуальный список каналов с их номерами, частотами и названиями. Специальная самописная программа запрашивает список каналов из базы данных, наполняемой инженерами головной станции, формирует эти два файла и через Zabbix API создаёт нужные элементы данных и триггеры для каждого канала. В сформированном файле channels.sqlite в таблице scheduler создаются записи, которые предписывают каждый час вызывать bat-файл, который завершает TV Motion Detector VG, вызывает программу, обновляющую Zabbix и эти два файла, а потом запускает TV Motion Detector VG снова. В таблице channels из файла channels.sqlite для каждого канала указываются скрипты, которые надо вызывать в случае проблем на канале, в случае продолжающихся проблем и в случае восстановления канала. В качестве таких скриптов используется утилита zabbix_sender. Программа TV Motion Detector VG прописана в автозагрузку Windows. В Zabbix кроме состояния каналов контролируется ещё и момент, когда в последний раз приходили данные от TV Motion Detector VG. Таким образом получаем практически полностью автономно работающую систему из трёх звеньев - базы каналов, TV Motion Detector VG и Zabbix.

Ручное вмешательство бывает нужно, если компьютер с TV Motion Detector VG был перезагружен. В этом случае в Zabbix срабатывает триггер о том, что давно не поступали данные из TV Motion Detector VG. Дежурный инженер заходит на компьютер с Windows по RDP, TV Motion Detector VG автоматически запускается, а дежурный инженер отсоединяется от сеанса. Дальше всё продолжает работать.

Бывает, что требуется ручное вмешательство другого рода. Если в частотном плане появляются новые частоты или пропадают старые, то TV Motion Detector VG (или драйвер ТВ-тюнера) сходит с ума и реально настраивается не на те каналы, которые соответствуют частоте канала в таблице channels из файла channels.sqlite. В таком случае помогает простое лечение - нажать кнопку Scan, дождаться окончания сканирования, после чего можно обновить файлы channels.sqlite, scanfreq.txt и запустить TV Motion Detector VG снова.

Вмешательства такого рода требуются довольно редко. А вот следующий недостаток изрядно подрывает всю кропотливо выстроенную систему.


Если приглядеться, то в нижней строчке под списком каналов программы можно увидеть текст "count: 50". Дело в том, что после перезапуска программа считает, что есть только 50 каналов. Только по ним она и проходится циклически, оставляя за пределами контроля ещё 11 каналов. Если вручную потянуть линейку прокрутки в списке каналов до конца, то программа отображает остальные каналы и после этого уже начинает проходиться циклически по каждому из 61 каналов. Но, напомню, программа в описанной выше схеме перезапускается каждый час. Поэтому ручное вмешательство не годится.

Первым делом я подумал, что программа при запуске выполняет SQL-запрос на получение списка каналов с ограничением LIMIT 50. Я открыл EXE-файл в шестнадцатеричном редакторе и нашёл все запросы SELECT. Был среди них такой запрос "SELECT COUNT(inc) as countinc, MAX(number) as maxnumber FROM channels;". Я проверил, что он возвращает и убедился, что обнаруживается ровно 61 канал.

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

Снова попробовал поискать что-нибудь в шестнадцатеричном редакторе. Естественно, таких мест оказалось довольно много. Не знаю, что натолкнуло меня на мысль попробовать ArtMoney, потому что изначально было ясно, что даже если я и найду эти счётчики в оперативной памяти, то как потом мне найти и исправить их в файле EXE? Если они не хранятся в секции .BSS или подобной ей, то найти нужные константы в ассемблерном коде будет непросто. Да и даже если они хранятся в такой секции - у меня нет опыта правки EXE-файлов. Всё же решил для любопытства найти этот счётчик при помощи ArtMoney.

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

Потом я сделал перерыв на обед. Пока шёл в столовую, подумал что свойства компонентов на форме могут оказаться прописаны в ресурсах Windows, вшитых в EXE-файл. Когда вернулся с обеда, решил проверить это предположение. В прошлом я доставал из EXE- и DLL-файлов встроенные в них пиктограммы, курсоры и картинки с помощью программы ResEdit. Скачал программу с официальной страницы. Из всех ресурсов наиболее многообещающим выглядел ресурс с именем TFORMMAIN. Но ResEdit отображал этот ресурс как блок двоичных данных.

Интересующий меня ресурс начинался с сигнатуры TPF0. Я поискал в интернете и понял, что это формы Delphi. В проекте Delphi у файлов этих форм бывает расширение DFM. Решил поискать, чем можно открыть такой файл на просмотр и редактирование. Вышел на программу ResourceHacker, которую можно скачать на странице разработчика - Ангуса Джонсона. Скачал программу и открыл интересующий меня ресурс на просмотр и редактирование. Стал изучать, какие компоненты присутствуют на форме и какие их свойства можно было бы поправить.

В процессе изучения, сопровождавшегося поиском в интернете, понял, что программа для доступа к SQLite использует компоненты AnyDAC Дмитрия Арефьева. К сожалению, документацию на AnyDAC найти в Интернете мне не удалось. Дело в том, что AnyDAC была продана фирме Embarcadero и превратилась в FireDAC. Удалось найти документацию только на библиотеку FireDAC. Оставалась слабая надежда на то, что библиотека изменилась не очень сильно и опции из FireDAC подойдут для AnyDAC.

В результате изучения документации, примеров кода, чтения форумов удалось составить примерное понимание того, как взаимодействуют между собой компоненты AnyDAC. Насколько я понял, AnyDAC на уровне интерфейсов компонентов совместима или очень похожа на наборы компонентов, аналогичных по функциям: BDE и ADO.

Верное направление для поисков было нащупано в ветке форума на www.sql.ru, где обсуждался FireDAC. Список всех возможных значений нашёлся в статье документации FireDAC.Stan.Option.TFDFetchOptions.RecordCountMode. На каком-то этапе я попробовал вставить в описание объекта ADTableChannels после 1738 строчки декомпилированного ресурса TFORMMAIN свойство FetchOptions.RecordCountMode = cmTotal:

Затем скомпилировал изменения нажав на зелёный треугольник и перезаписал файл EXE. Когда запустил программу, то увидел в строчке count вожделенное значение 61. Оставалось убедиться, что после 50 канала программа переключится на 51 канал и дойдёт до конца списка. Всё сработало, как надо:

В этот момент я испытал облегчение, радость и удивление от того, что поиски и эксперименты в конечном итоге привели к успеху. С одной стороны, я не надеялся на успех. Уж слишком были призрачными надежды на него. У читателей этого блога может сложиться впечатление, что все задачи, которые я перед собой ставлю, в конечном итоге завершаются успешно. Однако это не всегда бывает так. Иногда эксперименты заходят в тупик и очередная задача так и остаётся нерешённой. Раз нет решения, то и писать не о чем. С другой стороны, пока голова не перестала генерировать новые предположения и пока они все не проверены, остаётся надежда на успех. В этот раз мне повезло :)

P.S. Несколько замечаний о законности описанной выше модификации программы.
УК РФ, Статья 272. Неправомерный доступ к компьютерной информации.

(в ред. Федерального закона от 07.12.2011 N 420-ФЗ)

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

наказывается штрафом в размере до двухсот тысяч рублей или в размере заработной платы или иного дохода осужденного за период до восемнадцати месяцев, либо исправительными работами на срок до одного года, либо ограничением свободы на срок до двух лет, либо принудительными работами на срок до двух лет, либо лишением свободы на тот же срок.
Источник - сайт компании "КонсультантПлюс". УК РФ, Статья 272. Неправомерный доступ к компьютерной информации

Однако, в комментариях к УК РФ имеются следующие оговорки:
1. Модификация информации - внесение изменений в компьютерную информацию (в том числе изменение её параметров) без согласия её законного обладателя. Действующим законодатесльством разрешены следующие виды легальной модификации программ, баз данных лицами, правомерно владеющими этой информацией: а) модификация в виде исправления явных ошибок; б) модификация в виде внесения изменений в программы, базы данных для их функционирования на технических средствах пользователя; в) модификация в виде частной декомпиляции программы для достижения способности к взаимодействию с другими программами.
Источник - книга "Комментарий к Уголовному кодексу Российской Федерации (постатейный), Том 2" под редакцией Бриллиантова А.В. Глава 28. Преступления в сфере компьютерной информации. Статья 272. Неправомерный доступ к компьютерной информации

Ещё один источник - сайт адвокатского бюро "Домкины и партнёры". Методические рекомендации по осуществлению прокурорского надзора за исполнением законов при расследовании преступлений в сфере компьютерной информации

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

воскресенье, 2 октября 2016 г.

Настройка ipfw во FreeBSD

Некоторое время назад наводил порядок в фаерволлах на серверах FreeBSD, доставшихся в наследство от прошлых системных администраторов. Захотелось сразу продумать фаерволл таким образом, чтобы потом в нём было легко ориентироваться и было очевидно, как в него добавить новое правило. Использовался фаерволл ipfw и его таблицы. Я решил не менять фаерволл на ipf или pf, а просто последовательно преобразовывать имеющиеся правила в понятную структуру, пока меня не устроит конечный результат. Результатом и хочу поделиться, как одним из примеров того, как можно организовать фаерволл.

Включение фаерволла

В файле /etc/rc.conf должны быть две строчки, предписывающие включить фаерволл и использовать правила из файла /etc/firewall.conf:
firewall_enable="YES"
firewall_script="/etc/firewall.conf"
Написание правил

Теперь приведу упрощённый пример файла /etc/firewall.conf:
fw='/sbin/ipfw -q'
${fw} -f flush

${fw} add pass all from any to any via lo0
${fw} add deny all from any to 127.0.0.0/8
${fw} add deny all from 127.0.0.0/8 to any
${fw} add check-state
${fw} add allow ip from me to any keep-state

########## ping ##########
${fw} add allow icmp from any to me in via em0 keep-state

########## ssh ##########
table_ssh=100
${fw} table $table_ssh flush
${fw} add allow tcp from "table($table_ssh)" to me 22 in via em0 keep-state

# lan gateway
${fw} table $table_ssh add 192.168.0.1
# office computers
${fw} table $table_ssh add 192.168.0.128/25

#########################################
${fw} add deny ip from any to any
Фаерволл разрешает серверу устанавливать любые исходящие подключения. Любому внешнему сетевому узлу разрешается выполнять ICMP-запросы (среди которых могут быть не только запросы Ping). Последнее правило запрещает любой входящий трафик, который не разрешён явным образом.

В начале файла есть команда, которая очищает текущий список правил фаерволла:
${fw} -f flush
При очистке списка правил таблицы остаются нетронутыми. Поэтому внутри каждого блока, разрешающего доступ к определённому сервису на сервере, выполняется очистка соответствующей таблицы:
${fw} table $table_ssh flush
После очистки таблицы в списке правил фаерволла создаётся необходимое правило, а затем наполняется таблица, связанная с этим правилом.

Наибольший интерес представляет блок, разрешающий подключения по SSH и продолжающийся вплоть до последнего правила. Чтобы разрешить доступ к ещё одному сервису, можно скопировать блок, переименовать переменную, хранящую номер таблицы, поменять сам номер таблицы. Затем нужно заменить имя таблицы в последующих строчках, отредактировать само правило и изменить список разрешённых IP-адресов и сетей, которые будут добавлены в таблицу. Например, можно добавить блок, разрешающий доступ по HTTP:
########## http ##########
table_http=110
${fw} table $table_http flush
${fw} add allow tcp from "table($table_http)" to me 80 in via em0 keep-state

# office computers
${fw} table $table_http add 192.168.0.128/25
# zabbix server
${fw} table $table_http add 192.168.0.2
Применение правил

Как видно, всё очень просто. Для применения изменений нужно выполнить всего одну команду:
# /etc/rc.d/ipfw restart
Будьте внимательны, не допускайте ошибок в файле - иначе он может выполниться не до конца и можно потерять удалённый доступ к серверу. Советую первыми в список включать правила для SSH - тогда они будут отрабатывать раньше, чем интерпретатор дойдёт до строки с ошибкой и отбросит весь остаток файла. Вероятность того, что правила SSH будут применены при ошибках в других более часто редактируемых правилах, будет выше. А ещё лучше перед применением отредактированного файла изменить значение переменной fw с этого:
fw='/sbin/ipfw -q'
На вот это:
fw='/sbin/ipfw -q -n'
Команды не будут выполняться реально, будет только проверен их синтаксис. Если сообщений об ошибках не получено, то можно вернуть значение fw на исходное и снова выполнить команду, уже для реального применения изменений.

Вид правил в системе

Ещё одно достоинство этого фаерволла - он получается простым, т.к. в самом фаерволле есть всего несколько правил. Для наглядности приведу реальный список правил в фаерволле на одном из серверов:
# ipfw list
00100 allow ip from any to any via lo0
00200 deny ip from any to 127.0.0.0/8
00300 deny ip from 127.0.0.0/8 to any
00400 check-state
00500 allow ip from me to any keep-state
00600 allow icmp from any to me in via em0 keep-state
00700 allow tcp from table(110) to me dst-port 3306 in via em0 keep-state
00800 allow tcp from table(111) to me dst-port 10054 in via em0 keep-state
00900 allow tcp from table(112) to me dst-port 80 in via em0 keep-state
01000 allow tcp from table(116) to me dst-port 22 in via em0 keep-state
01100 allow udp from table(117) to me dst-port 69 in via em0 keep-state
01200 allow tcp from table(118) to me dst-port 48048 in via vlan32 keep-state
01300 allow udp from table(119) to me dst-port 162 in via em0
01400 deny ip from any to any
65535 deny ip from any to any
Трудно запутаться в семи существенных правилах, не так ли?

Второе достоинство фаерволла - он достаточно быстр, т.к. сравнение IP-адресов клиентов происходит с использованием таблиц, а не при помощи отдельных правил, которые просматриваются последовательно. Посмотреть текущее содержимое любой из таблиц тоже довольно просто:
# ipfw table 118 list
10.1.206.0/24 0
10.1.217.0/24 0
Динамически обновляемые таблицы

Если нужно сделать так, чтобы IP-адреса и сети в таблицу добавлялись динамически, каким-нибудь внешним скриптом, то достаточно не вписывать команды, очищающие таблицу и добавляющие в неё какие-то правила. Например, вот так:
########## tftp ##########
table_tftp=120
${fw} add allow tcp from "table($table_tftp)" to me 69 in via em0 keep-state
Таким образом, при применении изменённых правил, динамически добавленные в таблицу адреса не исчезнут из таблицы.

Динамические правила

Поскольку мы настроили фаерволл с поддержкой состояний, то правила для обратного трафика будут добавляться в него динамически. Таким образом, нужно следить за тем, чтобы список динамических правил не переполнялся. Контролировать текущее количество динамических правил в списке и их максимальное возможное количество можно при помощи утилиты sysctl:
# sysctl net.inet.ip.fw.dyn_count
net.inet.ip.fw.dyn_count: 656
# sysctl net.inet.ip.fw.dyn_max
net.inet.ip.fw.dyn_max: 8192
Если значение первого счётчика будет близко подбираться к значению второго, то максимальное количество динамических правил можно увеличить при помощи sysctl:
# sysctl -w net.inet.ip.fw.dyn_max=16384
И чтобы это значение восстанавливалось при перезагрузке, нужно прописать его в файл /etc/sysctl.conf:
net.inet.ip.fw.dyn_max=16384

воскресенье, 25 сентября 2016 г.

Стандарт SNMPv3 и суровая действительность USM_TIME_WINDOW

В прошлой статье Zabbix и проблемы с опросом по SNMPv3 при дублировании EngineID я описал решение первой проблемы, возникшей при внедрении SNMP третьей версии. После этого я столкнулся с ещё одной проблемой, которую исправлял в два подхода.

D-Link не соблюдает стандарт RFC3414

Дело в том, что даже после исправления EngineID на всех коммутаторах, на некоторых коммутаторах проблема повторялась. После перезагрузки коммутатора, Zabbix считал коммутатор недоступным по SNMP. Если разбираться глубже, с помощью приведённых в прошлой заметке OID'ов, то оказывается, что на коммутаторе после перезагрузки значение EngineBoots остаётся прежним или даже уменьшается! Первым делом были проверены версии прошивок - возможно эта проблема уже была исправлена и надо только обновить прошивку. Но оказалось, что прошивки на проблемных коммутаторах были самые свежие. Поискал в интернете, сталкивался ли кто-нибудь с подобной проблемой, и нашёл аж три темы, в которых открытым текстом утверждается, что эта проблема известна производителю и исправлять он её не собирается:
Поразмыслив, я решил, что можно было бы отключить проверку монотонности возрастания EngineBoots. В конце концов, лучше использовать SNMP третьей версии без защиты от повторного воспроизведения запросов, но зато с более безопасной аутентификацией и с защитой информации от подслушивания, чем вернуться к использованию SNMP второй или первой версии и передавать по сети в открытом виде и строку сообщества и сами запросы и ответы. Решено - будем править библиотеку.

Подготовка к пересборке Net-SNMP

Для начала отредактируем файл /etc/apt/sources.list и добавим строчки с репозиториями deb-src с исходными текстами:
deb http://mirror.ufanet.ru/debian/ wheezy main contrib non-free
deb http://mirror.ufanet.ru/debian/ wheezy-updates main contrib non-free
deb http://mirror.ufanet.ru/debian/ wheezy-proposed-updates main contrib non-free
deb http://mirror.ufanet.ru/debian-security wheezy/updates main contrib non-free

deb-src http://mirror.ufanet.ru/debian/ wheezy main contrib non-free
deb-src http://mirror.ufanet.ru/debian/ wheezy-updates main contrib non-free
deb-src http://mirror.ufanet.ru/debian/ wheezy-proposed-updates main contrib non-free
deb-src http://mirror.ufanet.ru/debian-security wheezy/updates main contrib non-free
Обновим список доступных пакетов, чтобы можно было скачать из вновь подключенных репозиториев пакеты с исходными текстами:
# apt-get update
Скачаем и распакуем исходные тексты, а затем перейдём в каталог с распакованными исходными текстами:
$ apt-get source snmp
$ cd net-snmp-5.4.3~dfsg/
Описание исправлений, внесённых в Net-SNMP

Поиск показал, что константа USM_TIME_WINDOW со значением 150 используется только в файле snmplib/snmpusm.c. Первым делом я нашёл строчку, в которой проверяется, что значение EngineBoots должно быть больше или равно значению из кэша:
if (theirBoots == ENGINEBOOT_MAX || theirBoots > boots_uint) {
Если значение EngineBoots не изменилось, то используются значение EngineTime, сохранённое в кэше. Если значение стало больше, то новые значения EngineBoots и EngineTime сохраняются в кэш. Если значение уменьшилось, то запрос завершается ошибкой SNMPERR_USM_NOTINTIMEWINDOW.

Это строчку я исправил следующим образом:
if (theirBoots == ENGINEBOOT_MAX) {
То есть при любом изменении значения EngineBoots новое значение будет сохранено в кэш для дальнейшего использования.

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

Детальное изучение проблемы показало, что при перезагрузке значение EngineBoots у них не изменилось, зато EngineTime становилось меньше прошлого, т.к. отсчёт времени после перезагрузки начинался с нуля. В этом случае вступал в силу другой фрагмент кода, который при равенстве полученного значения EngineBoots и имеющегося в кэше проверяет соответствие времени. Если время из ответа больше расчётного, то библиотека запоминает новое значение времени в кэше и принимает ответ. Если время из ответа отстаёт от расчётного менее чем на 150 секунд, то такой ответ тоже принимается. Если же время из ответа отстаёт от расчётного более чем на 150 секунд, то ответ отбрасывается, а запрос завершается всё той же ошибкой SNMPERR_USM_NOTINTIMEWINDOW. Этот фрагмент кода выглядит следующим образом:
/*
 * Boots is ok, see if the boots is the same but the time
 * is old.
 */
if (theirBoots == boots_uint && time_uint < theirLastTime) {
        if (time_difference > USM_TIME_WINDOW) {
                DEBUGMSGTL(("usm", "%s\n", "Message too old."));
                *error = SNMPERR_USM_NOTINTIMEWINDOW;
                return -1;
        }
        else {              /* Old, but acceptable */
                *error = SNMPERR_SUCCESS;
                return 0;
        }
}
Его я исправил следующим образом:
/*
 * Boots is ok, see if the boots is the same but the time
 * is acceptable old.
 */
if (theirBoots == boots_uint && time_uint < theirLastTime && time_difference < USM_TIME_WINDOW) {
        *error = SNMPERR_SUCCESS;
        return 0;
}
Снова собрал пакет, установил его в систему и перезапустил Zabbix. Через несколько дней стало понятно, что это исправление помогло и опрос по SNMP третьей версии теперь продолжает работать даже после перезагрузок коммутаторов, когда значение EngineBoots не меняется или меняется в меньшую сторону. Был достигнут неприятный компромисс, на который пришлось пойти ради общего увеличения безопасности системы.

Сборка исправленных пакетов Net-SNMP

Теперь уже, когда в деталях раскрыта подноготная исправлений, опишу до конца процесс сборки пакета.

Скачиваем и устанавливаем пакеты, которые используются в процессе сборки Net-SNMP:
# apt-get build-dep snmp
Скачиваем патч:
$ wget http://stupin.su/files/netsnmp543_snmpv3.diff
Тут же, если вы используете библиотеку Net-SNMP из Python, можно скачать ещё один патч, описанный в заметке Исправление Python-прослойки библиотеки Net-SNMP:
$ wget http://stupin.su/files/netsnmp543_python_client.diff
Теперь перейдём в каталог с исходными текстами и наложим наши патчи:
# cd net-snmp-5.4.3~dfsg/
# patch -Np0 --ignore-whitespace < netsnmp543_snmpv3.diff
# patch -Np0 --ignore-whitespace < netsnmp543_python_client.diff
Добавим наши патчи в будущий пакет:
# dpkg-source --commit
Укажем имя патча snmpv3-python_client. В окне редактирования информации о патче введём что-нибудь подобное следующему (вплоть до двух нижних строчек, с которых начинается сам текст патча):
Description: Fixed Python bindings and SNMPv3 time window logic
Author: Vladimir Stupin <vladimir@stupin.su>
Last-Update: <2016-09-06>
--- net-snmp-5.4.3~dfsg.orig/python/netsnmp/client_intf.c
+++ net-snmp-5.4.3~dfsg/python/netsnmp/client_intf.c
Теперь отметим изменения, внесённые в пакет:
# dch -i
В окне редактирования введём информацию о нашей версии пакета:
net-snmp (5.4.3~dfsg-2.8+deb7u2) UNRELEASED; urgency=low

* Fixed Python bindings for IPv4 parameter in SET-requests
* Fixed SNMPv3 time window logic

-- Vladimir Stupin <vladimir@stupin.su>  Tue, 06 Sep 2016 16:01:20 +0500
Осталось собрать пакеты:
# dpkg-buildpackage -us -uc -rfakeroot
Теперь можно установить необходимые пакеты в систему:
# cd ..
# dpkg -i libsnmp-base_5.4.3~dfsg-2.8+deb7u2_amd64.deb
# dpkg -i libsnmp15_5.4.3~dfsg-2.8+deb7u2_amd64.deb
# dpkg -i snmp_5.4.3~dfsg-2.8+deb7u2_amd64.deb
# dpkg -i libsnmp-python_5.4.3~dfsg-2.8+deb7u2_amd64.deb
Python и SNMPv3 в Net-SNMP

Двух пересборок пакетов, на самом деле, оказалось недостаточно. Дело в том, что модуль netsnmp для Python не работает с SNMP третьей версии. Как оказалось, при попытке выполнить из программы на Python запроса SNMP с настройками третьей версии, библиотека "молчит" - в сеть не уходит ни единый пакет. В то же время я вспомнил, что на одном из серверов под управлением FreeBSD всё работало превосходно. Сразу же в глаза бросилось различие в версиях Net-SNMP во FreeBSD на том сервере и на сервере под управлением Debian Wheezy. Во FreeBSD был установлен Net-SNMP версии 5.7.2, а в Debian - 5.4.3. Чтобы проверить свои предположения о том, что этот функционал был исправлен в версии 5.7.2, я воспользовался Net-SNMP из Debian Jessie. Набросал небольшую тестовую программку на Python, запустил - всё отработало на ура.

После этого я заменил в файле /etc/apt/sources.list репозитории deb-src с релиза Wheezy на релиз Jessie и повторил проделанные выше операции, получив таким образом пропатченный бэкпорт Net-SNMP из Jessie для Wheezy. Дело, однако, этим не ограничилось. В бэкпорте вместо библиотеки libsnmp15 была библиотека libsnmp30, а пакет libsnmp-python был переименован в python-netsnmp. К библиотеке libsnmp15 были привязаны Zabbix и PHP5. Пришлось пересобрать и их, в том числе с использованием моих патчей Zabbix, описанных в заметке Установка и настройка Zabbix 2.2.0 в Debian Wheezy.

Патчи, адаптированные для Net-SNMP версии 5.7.2.1 из Jessie, можно взять по следующим ссылкам:
Мне невероятно "везёт" с программами, которыми я пользуюсь. Или просто я слишком часто стал заходить на никем ещё не топтанные дорожки?