<?xml version="1.0"?>
<rss version="2.0"><channel><title>Linux Latest Topics</title><link>https://it4it.club/forum/4-linux/</link><description>Linux Latest Topics</description><language>en</language><item><title>&#x412;&#x438;&#x434;&#x435;&#x43E;&#x43D;&#x430;&#x431;&#x43B;&#x44E;&#x434;&#x435;&#x43D;&#x438;&#x435; &#x43D;&#x430; &#x43E;&#x441;&#x43D;&#x43E;&#x432;&#x435; &#x43F;&#x430;&#x43A;&#x435;&#x442;&#x430; Motion</title><link>https://it4it.club/topic/48-videonablyudenie-na-osnove-paketa-motion/</link><description><![CDATA[
<p>
	Всем доброго времени суток.
</p>

<p>
	Как всегда начнем с предыстории. Необходимо было реализовать видеонаблюдение за помещением, естественно с нулевым бюджетом, а как иначе. В наличие имелся сервер с Linux на борту и домашняя usb web камера. За основу был взят программный пакет Motion. В принципе ничего сложного в настройке нет, правим пару строк в конфиге и вуаля. Писать было ни о чем. 
</p>

<p>
	На днях обновил Ubuntu до версии 16.04.1 LTS и заодно, решено было обновить часть пакетов, в том числе Motion, и переделать систему видеонаблюдения. От usb камеры давно было решено отказаться, и ей на смену пришла дешевая IP камера (поддерживающая MJPEG поток) купленная на распродаже.
</p>

<p>
	<img alt="cam1.JPG" class="ipsImage ipsImage_thumbnailed" data-fileid="369" data-unique="ho21p8wir" src="https://it4it.club/uploads/monthly_2016_10/cam1.JPG.e7f69b1ce99a85f39db5f717adf451de.JPG" style="width: 408px; height: auto;"><img alt="cam2.JPG" class="ipsImage ipsImage_thumbnailed" data-fileid="370" data-unique="1vm9vvb0m" src="https://it4it.club/uploads/monthly_2016_10/cam2.JPG.ee612adced166eda8a288fba3d00b420.JPG" style="width: 408px; height: auto;">
</p>

<p>
	<span style="font-size:16px;"><strong>Отразим все на "бумаге"</strong></span>
</p>

<p>
	<span style="color:#008000;"><strong>Имеется</strong></span>:
</p>

<ul>
	<li>
		Сервер Linux Ubuntu 16.04.1 LTS
	</li>
	<li>
		Пакет Motion 3.2.12
	</li>
	<li>
		IP камера <u>с поддержкой MJPEG</u>
	</li>
</ul>

<p>
	<span style="color:#008000;"><strong>Требуется</strong></span>:
</p>

<ul>
	<li>
		Писать только видео (никаких фото и таймлапсов)
	</li>
	<li>
		Писать только по движению
	</li>
	<li>
		Оповещать об обнаружении движения
	</li>
	<li>
		Транслировать поток в реальном времени с сервера
	</li>
</ul>

<p>
	В Ubuntu установка пакетов проста до безобразия
</p>

<pre class="ipsCode prettyprint lang-css prettyprinted" id="ips_uid_4362_9">
<span class="pln">apt</span><span class="pun">-</span><span class="kwd">get</span><span class="pln"> update </span><span class="pun">&amp;&amp;</span><span class="pln"> apt</span><span class="pun">-</span><span class="kwd">get</span><span class="pln"> install motion</span></pre>

<p>
	По завершении установки переходим в каталог с файлом конфигурации
</p>

<pre class="ipsCode prettyprint lang-css prettyprinted" id="ips_uid_4362_7">
<span class="pln">cd </span><span class="pun">/</span><span class="pln">etc</span><span class="pun">/</span><span class="pln">motion
nano motion</span><span class="pun">.</span><span class="pln">conf</span></pre>

<p>
	Сразу разберемся с порядком действий т.к понимая, что сейчас будем делать, мы сможем настроить эту программу вне зависимости от её версии и версии операционной системы на которой она установлена.
</p>

<p>
	Сам Motion может работать одновременно с несколькими потоками (камерами для обывателя), неважно будь то IP камеры, USB камеры или иные устройства захвата видео. Да хоть все вперемешку. Самое главное, что если мы используем IP камеры, то они должны поддерживать MJPEG поток. Никакого RTSP (Real Time Streaming Protocol) Motion не поддерживает.
</p>

<p>
	Файл конфигурации motion.conf представляет из себя набор основных настроек программы и настройки для первого потока. Все последующие потоки можно конфигурировать в файлах thread1.conf, thread2.conf ... thread9.conf (по умолчанию они отсутствуют) и подключать в конце файла motion.conf
</p>

<p>
	Лично я предпочитаю основные настройки и настройки по умолчанию хранить в основном файле конфигурации, а настройки самих камер вынести во внешние файлы thread, по одному файлу на каждую камеру. Таким образом, не будет никакой путаницы если например камера №2 выйдет из строя и её понадобится заменить на не типичную камеру.
</p>

<p>
	Основные настройки представлены в двух секциях
</p>

<pre class="ipsCode" id="ips_uid_4362_15">
############################################################
# Daemon
############################################################

# Запуск в фоновом режиме (default: off)
daemon on

# Файл для хранения идентификатора процесса (default: not defined)
process_id_file /var/run/motion/motion.pid
</pre>

<pre class="ipsCode" id="ips_uid_4362_13">
############################################################
# Basic Setup Mode
############################################################

# Запускать в Setup-Mode, отключает режим демона. (default: off)
setup_mode off

# Путь до файла с логами. (default: not defined)
logfile /var/log/motion/motion.log

# Уровель лог сообщений [1..9] (EMR, ALR, CRT, ERR, WRN, NTC, INF, DBG, ALL). (default: 6 / NTC)
log_level 6

# Фильтр лог сообщений по типу (COR, STR, ENC, NET, DBL, EVT, TRK, VID, ALL). (default: ALL)
log_type all
</pre>

<p>
	Тут нас интересует только запуск программы в фоновом режиме, остальные настройки можно оставить без изменения.
</p>

<p>
	Далее идет секция настройки первого потока
</p>

<pre class="ipsCode" id="ips_uid_4362_17">
###########################################################
# Capture device options
############################################################

# Videodevice to be used for capturing  (default /dev/video0)
# for FreeBSD default is /dev/bktr0
;videodevice /dev/video0

...</pre>

<p>
	Закомментируем все настройки в этой секции, в этом файле они нам не нужны.
</p>

<p>
	Далее большинство настроек мы оставим без изменения, а поправим только некоторые. Эти настройки будут общие для всех потоков.
</p>

<p>
	Отключаем создание снимков при обнаружении движения. Можно указать один из режимов (first, best, center) и тогда мы будем получать по одному снимку на одно видео. Это может пригодиться в том случае, если вы собираетесь организовывать WEB доступ к архиву видеозаписей.
</p>

<pre class="ipsCode" id="ips_uid_4362_19">
############################################################
# Image File Output
############################################################

# Output 'normal' pictures when motion is detected (default: on)
# Valid values: on, off, first, best, center
# When set to 'first', only the first picture of an event is saved.
# Picture with most motion of an event is saved when set to 'best'.
# Picture with motion nearest center of picture is saved when set to 'center'.
# Can be used as preview shot for the corresponding movie.
output_pictures off
</pre>

<p>
	Отключаем стриминг по умолчанию
</p>

<pre class="ipsCode" id="ips_uid_4362_31">
############################################################
# Live Stream Server
############################################################

# The mini-http server listens to this port for requests (default: 0 = disabled)
stream_port 0
</pre>

<p>
	Отключаем встроенный web сервер
</p>

<pre class="ipsCode" id="ips_uid_4362_26">
############################################################
# HTTP Based Control
############################################################

# TCP/IP port for the http server to listen on (default: 0 = disabled)
webcontrol_port 0</pre>

<p>
	В самом конце основного файла конфигурации motion.conf имеется секция для подключения дополнительных потоков. По умолчанию файл motion.conf соответствовал файлу thread0.conf, но мы это доблестно исправили выше. Теперь нам необходимо включить в файл конфигурации файлы с настройками для работы с нашими камерами. Мы рассмотрим на примере конфигурации одной камеры, раскомментируем thread1.conf
</p>

<pre class="ipsCode" id="ips_uid_4362_28">
##############################################################
# Thread config files - One for each camera.
# Except if only one camera - You only need this config file.
# If you have more than one camera you MUST define one thread
# config file for each camera in addition to this config file.
##############################################################

# Remember: If you have more than one camera you must have one
# thread file for each camera. E.g. 2 cameras requires 3 files:
# This motion.conf file AND thread1.conf and thread2.conf.
# Only put the options that are unique to each camera in the
# thread config files.
thread /etc/motion/thread1.conf
; thread /etc/motion/thread2.conf
; thread /etc/motion/thread3.conf
; thread /etc/motion/thread4.conf
</pre>

<p>
	 
</p>

<p>
	<span style="color:#008000;"><strong>Создадим файл thread1.conf</strong></span>
</p>

<pre class="ipsCode" id="ips_uid_4362_33">
cd /etc/motion &amp;&amp; touch thread1.conf &amp;&amp; nano thread1.conf
</pre>

<p>
	Первым делом вам необходимо узнать:
</p>

<ul>
	<li>
		адрес MJPEG потока вашей камеры
	</li>
	<li>
		разрешение камеры (обычно для дешевых камер это 640х480)
	</li>
	<li>
		частоту кадров (у дешевых камер обычно не более 20)
	</li>
</ul>

<pre class="ipsCode" id="ips_uid_4362_35">
# Разрешение картинки
width 640
height 480

# Частота кадров
framerate 20
</pre>

<p>
	Укажем настройки для доступа к видео потоку. В моем случае камеры находятся в отдельной физической сети, и доступ к потоку по логину и паролю не требуется (только для доступа к настройкам камер).
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4362_37">
<span class="pln"># Сетевой адрес для захвата изображения с камеры (mjpeg поток)
netcam_url http://10.10.1.101/mjpeg.cgi

# Логин и пароль к видео потоку (only if required). Default: not defined
; netcam_userpass admin:password</span></pre>

<p>
	Укажем подпись для камеры, это поможет быстро идентификации её местоположение (можно использовать символ перевода каретки)
</p>

<pre class="ipsCode" id="ips_uid_4362_40">
# Подпись к камере (название камеры)
text_left CAMERA 1\nSH-21 STORAGE
</pre>

<p>
	Укажем путь до места хранения видео фрагментов (лучше создать каталог заранее)
</p>

<pre class="ipsCode" id="ips_uid_4362_42">
# Путь до места сохранения видео\фото
target_dir /media/share/motion/cam1
</pre>

<p>
	Включаем детектор движения
</p>

<pre class="ipsCode" id="ips_uid_4362_44">
# Количество изменившихся пикселей для триггера обнаружения движения
threshold 2000
</pre>

<p>
	У меня камера стоит под потолком, рядом со стеной с большим количеством окон. Ну и естественно окна смотрят на солнечную сторону, а это значит, что открывается прекрасный вид на быстро плывущие облака отбрасывающие тень на здание, а во время летней грозы помещение может освещаться завораживающими вспышка молний. И это все можно будет посмотреть на видео, если не добавить следующие параметры. Можно поэкспериментировать и добиться приемлемого результата для вас
</p>

<pre class="ipsCode" id="ips_uid_9774_5">
# Не реагировать на резкое изменение яркости (0 - отключено, 0-100% от общего числа пикселей)
lightswitch 60

# Минимальное число кадров, в которых фиксируется движение для взведения триггера тревоги
minimum_motion_frames 5</pre>

<p>
	Добавляем мертвую зону. Она позволит не создавать кучу мусора в папке с видео
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4362_48">
<span class="pln"># Количество секунд (мертвая зона) после окончания движения, в течении которых отключен детектор
event_gap 10</span></pre>

<p>
	Для наглядности можно добавить рамку вокруг движущегося объекта. Также рекомендую включить эти параметры на время, пока проходит настройка и обкатка системы
</p>

<pre class="ipsCode" id="ips_uid_4362_50">
# Рисуем рамку вокруг движущегося объекта
locate_motion_mode on

# Стиль рамки вокруг движущегося объекта
locate_motion_style redbox
</pre>

<p>
	Также для настройки я использую отображение количество изменившихся пикселей. Это очень помогает отрегулировать уровень тревоги т.к камера может быть на разном ударении от наблюдаемой зоны и следовательно чем дальше, тем меньше пикселей будет занимать движущийся вдали объект
</p>

<pre class="ipsCode" id="ips_uid_4362_52">
# Показывать количество изменившихся пикселей (используем для настройки threshold)
text_changes on
</pre>

<p>
	Включаем возможность стримить с сервера все происходящее на данной камере
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4362_56">
<span class="pln"># Настройки потока вещания (порт\качество\частота кадров\доступ только с 172.0.0.1\ограничение потока)
stream_port 8081
stream_quality 70
stream_maxrate 20
stream_localhost off
stream_limit 0</span></pre>

<p>
	Можно (и нужно, если установлен stream_localhost off) требовать авторизацию при доступе к потоку с этой камеры из вне
</p>

<pre class="ipsCode" id="ips_uid_4362_59">
# Требовать авторизацию для доступа к потоку вещания
stream_auth_method 1
stream_authentication admin:12345678</pre>

<p>
	В принципе этого уже достаточно для организации работы системы и на этом этапе можно сохранить файл. Но в моем случае требуется организовать внешнюю систему оповещения. Благо Motion умеет вызывать внешние программы и передавать им различные параметры. 
</p>

<p>
	Так как первая камера у меня захватывает не все помещение, а только ту его часть, где находится входная дверь, то мне куда более важно быть в курсе, когда движение началось именно в той части комнаты. И соблюдать режим тишины, когда объект движется от камеры.
</p>

<p>
	При вызове внешнего скрипта ему можно передать следующие параметры
</p>

<div class="ipsSpoiler" data-ipsspoiler="">
	<div class="ipsSpoiler_header">
		<span>Скрытый текст</span>
	</div>

	<div class="ipsSpoiler_contents">
		<pre class="ipsCode" id="ips_uid_4362_62">

%Y = year
%m = month
%d = date
%H = hour
%M = minute
%S = second,

%v = event
%q = frame number
%t = thread (camera) number
%D = changed pixels
%N = noise level

%i and %J = width and height of motion area
%K and %L = X and Y coordinates of motion center

%C = value defined by text_event
%f = filename with full path
%n = number indicating filetype

# Both %f and %n are only defined for on_picture_save,
# on_movie_start and on_movie_end
# Quotation marks round string are allowed.</pre>

		<p>
			 
		</p>
	</div>
</div>

<p>
	Добавим строку вызова внешнего исполняемого файла с передачей ему параметрами - номер камеры и координаты центра начала движения
</p>

<pre class="ipsCode" id="ips_uid_4362_64">
# При обнаружении движения запускать внешний скрипт
on_event_start /etc/motion/zone_alarm.sh %t %K %L</pre>

<p>
	Содержимое zone_alarm.sh
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4362_69">
<span class="com">#!/bin/bash</span><span class="pln">

CAM</span><span class="pun">=</span><span class="str">"$1"</span><span class="pln">
X</span><span class="pun">=</span><span class="str">"$2"</span><span class="pln">
Y</span><span class="pun">=</span><span class="str">"$3"</span><span class="pln">

</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">((</span><span class="str">"$CAM"</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="str">"1"</span><span class="pun">))</span><span class="pln">
then
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">((</span><span class="str">"$X"</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="str">"320"</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="str">"$Y"</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="str">"240"</span><span class="pun">))</span><span class="pln">
        then
                beep </span><span class="pun">-</span><span class="pln">f </span><span class="lit">4000</span><span class="pln"> </span><span class="pun">-</span><span class="pln">l </span><span class="lit">200</span><span class="pln"> </span><span class="pun">-</span><span class="pln">n </span><span class="pun">-</span><span class="pln">f </span><span class="lit">4000</span><span class="pln"> </span><span class="pun">-</span><span class="pln">l </span><span class="lit">200</span><span class="pln"> </span><span class="pun">-</span><span class="pln">n </span><span class="pun">-</span><span class="pln">f </span><span class="lit">4000</span><span class="pln"> </span><span class="pun">-</span><span class="pln">l </span><span class="lit">200</span><span class="pln"> </span><span class="pun">-</span><span class="pln">n </span><span class="pun">-</span><span class="pln">f </span><span class="lit">4000</span><span class="pln"> </span><span class="pun">-</span><span class="pln">l </span><span class="lit">200</span><span class="pln"> </span><span class="pun">-</span><span class="pln">n </span><span class="pun">-</span><span class="pln">f </span><span class="lit">4000</span><span class="pln"> </span><span class="pun">-</span><span class="pln">l </span><span class="lit">200</span><span class="pln">
        fi
fi</span></pre>

<p>
	В данном случае происходит звуковое оповещение на самом сервере с помощью утилиты beep, по умолчанию её может и не быть
</p>

<pre class="ipsCode" id="ips_uid_4362_71">
apt-get install beep</pre>

<p>
	Также можно сигнализировать об обнаружении движения на удаленную станцию или на мобильное устройство. Очень актуально если камера наблюдает за помещением, в котором не бывает и не должно бывать людей. Например, склад.
</p>

<p>
	Необходимо разрешить Motion работать в режиме демона, для этого правим файл <strong>/etc/default/motion</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1932_7">
<span class="com"># set to 'yes' to enable the motion daemon</span><span class="pln">
start_motion_daemon</span><span class="pun">=</span><span class="pln">yes</span></pre>

<p>
	Проверяем работу
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4096_5">
<span class="pun">/</span><span class="pln">etc</span><span class="pun">/</span><span class="pln">init</span><span class="pun">.</span><span class="pln">d</span><span class="pun">/</span><span class="pln">motion start</span></pre>

<p>
	<strong style="color: rgb(0, 128, 0);">Что мы имеем на выходе</strong>
</p>

<p>
	<img alt="cam6.png" class="ipsImage ipsImage_thumbnailed" data-fileid="373" data-unique="ncu1w5i1n" src="https://it4it.club/uploads/monthly_2016_10/cam6.png.f29c78ffb101b12997fff5ecee0874e3.png" style="width: 408px; height: auto;"><img alt="cam7.png" class="ipsImage ipsImage_thumbnailed" data-fileid="374" data-unique="x7q14x6t1" src="https://it4it.club/uploads/monthly_2016_10/cam7.png.51fd758f6e62bfd1ec8f841c49f57d72.png" style="width: 408px; height: auto;">
</p>

<p>
	<img alt="cam4.JPG" class="ipsImage ipsImage_thumbnailed" data-fileid="371" data-unique="8o1quqy7q" src="https://it4it.club/uploads/monthly_2016_10/cam4.JPG.5edaca6c0898ed25ac69277346e7d19e.JPG">
</p>

<p>
	Все прекрасно работает, но остается вопрос переполнения жесткого диска. Чтобы этот счастливый момент никогда не настал, стоит автоматизировать удаление устаревших видеозаписей. В этом нам поможет планировщик CRON.
</p>

<pre class="ipsCode" id="ips_uid_4362_73">
crontab -e</pre>

<p>
	И добавим запись, которая будет выполняться ежедневно в 23:30 и искать файлы формата .avi в указанном нами каталоге и если найденный файл существует более 14 суток, то он удаляется. Естественно если камера стоит в проходном месте, то стоит уменьшить время жизни видео.
</p>

<pre class="ipsCode" id="ips_uid_4362_75">
30 23 * * * find /media/share/motion/ -name '*.avi' -mtime +14 -exec rm {} \;</pre>

<p>
	На этом настройка завершена.
</p>

<p>
	<strong>PS</strong>: в файле motion.conf можно найти еще очень много интересных параметров!
</p>
]]></description><guid isPermaLink="false">48</guid><pubDate>Wed, 12 Oct 2016 12:57:35 +0000</pubDate></item><item><title>&#x423;&#x447;&#x438;&#x43C;&#x441;&#x44F; &#x43F;&#x435;&#x440;&#x435;&#x441;&#x44B;&#x43B;&#x430;&#x442;&#x44C; &#x434;&#x430;&#x43D;&#x43D;&#x44B;&#x435; &#x441; MQTT &#x431;&#x440;&#x43E;&#x43A;&#x435;&#x440;&#x430; &#x432; &#x431;&#x430;&#x437;&#x443; &#x434;&#x430;&#x43D;&#x43D;&#x44B;&#x445; MySQL</title><link>https://it4it.club/topic/72-uchimsya-peresylat-dannye-s-mqtt-brokera-v-bazu-dannyh-mysql/</link><description><![CDATA[
<p>
	Доброе время суток.
</p>

<p>
	Сегодня пойдет речь о том, как переправлять данные с <strong>MQTT</strong> брокера в базу данных <strong>MySQL</strong>. Транспортировать будем как сами адреса, так и значения всех топиков, на которые оформлена подписка. Данную задачу нельзя назвать распространенной, но все же, она имеет место быть и может пригодиться в том случае, если данные востребованы в системах не способных работать с <strong>MQTT</strong> протоколом самостоятельно или брокер находится в изолированной системе, а данные востребованы, например, в GUI за её приделами.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="720" href="https://it4it.club/uploads/monthly_2017_11/mqtt_to_mysql_by_it4it_club.png.54bbf00022299beecd7de472808cbcf6.png" rel=""><img alt="mqtt_to_mysql_by_it4it.club.png" class="ipsImage ipsImage_thumbnailed" data-fileid="720" data-unique="z1s0agvu8" src="https://it4it.club/uploads/monthly_2017_11/mqtt_to_mysql_by_it4it_club.thumb.png.fc824a3f5bf541148b47bb29032c5767.png"></a>
</p>

<p>
	Для осуществления задуманного нам потребуется самостоятельный процесс, который сыграет роль транспортного узла между <strong>MQTT</strong> брокером и базой данный <strong>MySQL</strong>. А значит, его придется где-то держать. В моем случае, это сервер под управлением операционной системой <strong>Linux Ubuntu 16.04.3</strong> и дальнейшее описание будет под неё, но для других ОС действия аналогичные.
</p>

<p>
	Сам демон будет написан на <strong>Python</strong> и для его работы нам потребуется:
</p>

<ol>
<li>
		python3
	</li>
	<li>
		python-pip
	</li>
	<li>
		python-dev
	</li>
	<li>
		libmysqlclient-dev
	</li>
	<li>
		библиотека paho-mqtt для python <a href="https://pypi.python.org/pypi/paho-mqtt" rel="external nofollow">https://pypi.python.org/pypi/paho-mqtt</a>
	</li>
	<li>
		библиотека mysqlclient для python <a href="https://github.com/PyMySQL/mysqlclient-python" rel="external nofollow">https://github.com/PyMySQL/mysqlclient-python</a>
	</li>
</ol>
<p>
	<strong>Но начнем мы, в первую очередь, с подготовки базы данных.</strong>
</p>

<p>
	На плечи <strong>MySQL</strong> ляжет не только хранение, но и частичная обработка данных. Для этих целей нам потребуется отдельная база, хранимая процедура и функция с реализацией небольшой логики, и пользователь с ограниченными правами под чьим именем мы будем обращаться к ним. В конце поста, кроме самого демона, будет опубликован <span style="color:#27ae60;"><strong>.sql</strong></span> файл, который достаточно просто импортировать, например с помощью стандартный средств базы данных
</p>

<pre class="ipsCode" id="ips_uid_3645_9">
mysql -uroot -p</pre>

<p>
	Вводим пароль администратора MySQL и импортируем наш .sql файл, но прежде, дочитайте статью до конца, возможно, Вы захотите внести свои изменения.
</p>

<pre class="ipsCode" id="ips_uid_3645_13">
mysql&gt; source /media/mqttMySqlClient.sql</pre>

<p>
	После этого будет получен следующий результат:
</p>

<ol>
<li>
		Создана база (схема) с именем <span style="color:null;"><strong>mqtt</strong></span>
	</li>
	<li>
		Пользователь с именем <strong>mqtt-agent</strong> и паролем <strong>p@$$w0rd</strong> имеющий возможность подключаться с внешних адресов
	</li>
	<li>
		Пользователю будут назначены ограниченные права (только <span style="color:#27ae60;"><strong>EXECUTE</strong></span>) в этой схеме
	</li>
	<li>
		Будет добавлена процедура <span style="color:#27ae60;"><strong>update_topic</strong></span>, на которую ляжет задача добавления и обновления данных
	</li>
	<li>
		Будет добавлена функция <span style="color:#27ae60;"><strong>get_topic</strong></span> для упрощения поиска данных
	</li>
</ol>
<p>
	На тот случай, если Вы захотите внести изменения или создать все ручками, рассмотрим содержимое sql файла.
</p>

<p>
	Если схема <strong>mqtt</strong> не существует, она будет создана
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_3645_17" style="">
<span class="pln">CREATE DATABASE IF NOT EXISTS </span><span class="str">`mqtt`</span><span class="pun">;</span></pre>

<p>
	Аналогичным образом будет создан пользователь <strong>mqtt-agent</strong>. Если необходимо конкретизировать, с какого адреса будет производиться подключение под этим пользователем, то замените <span style="color:#27ae60;"><strong>%</strong></span> на доменное имя или ip адрес хоста. Если планируется использовать демона на том же сервере где установлен <strong>MySQL</strong>, замените <span style="color:#27ae60;"><strong>%</strong></span> на <span style="color:#27ae60;"><strong>localhost</strong></span>. Также разрешено не более 2 активных подключений, измените это значение на необходимое Вам.
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_3645_19" style="">
<span class="pln">CREATE USER IF NOT EXISTS </span><span class="str">'mqtt-agent'</span><span class="pun">@</span><span class="str">'%'</span><span class="pln"> IDENTIFIED BY </span><span class="str">'p@$$w0rd'</span><span class="pln"> WITH MAX_USER_CONNECTIONS </span><span class="lit">2</span><span class="pun">;</span></pre>

<p>
	Пользователю будут выставлены ограниченные права. Ему будет разрешено пользоваться только хранимыми процедурами и функциями. Никакие самостоятельные запросы выполнять нельзя.
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_3645_21" style="">
<span class="pln">GRANT EXECUTE ON </span><span class="str">`mqtt`</span><span class="pun">.*</span><span class="pln"> TO </span><span class="str">'mqtt-agent'</span><span class="pun">@</span><span class="str">'%'</span><span class="pun">;</span></pre>

<p>
	Переходим к работе с самой схемой
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_3645_24" style="">
<span class="pln">USE </span><span class="str">`mqtt`</span><span class="pun">;</span></pre>

<p>
	Будет создана таблица topics со следующей структурой.
</p>

<ul>
<li>
		<strong>md5</strong> - содержит уникальный одноименный хеш полученный из полного адреса топика. Именно по этому ключу и будет производиться поиск данных. Почему именно по нему, а не по самому имени? Дело в том, что <strong>md5</strong> хеш имеет фиксированную, заранее известную, длину, что нельзя сказать о имени топика. Именно это ограничение не позволит сделать имя топика первичным ключом и явно идентифицировать данные в таблице.
	</li>
	<li>
		<strong>time</strong> - содержит UNIX время добавления/обновления данных по конкретному топику (по умолчанию <strong>GMT+0</strong>)
	</li>
	<li>
		<strong>topic</strong> - адрес топика. В контексте, упомянутого ранее, поля <strong>md5</strong>, не несет для нас никакой смысловой нагрузки.
	</li>
	<li>
		<strong>value</strong> - данные опубликованные в топике.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_5682_9" style="">
<span class="pln">DROP TABLE IF EXISTS </span><span class="str">`topics`</span><span class="pun">;</span><span class="pln">
CREATE TABLE </span><span class="str">`topics`</span><span class="pln"> </span><span class="pun">(</span><span class="pln">
  </span><span class="str">`md5`</span><span class="pln"> varchar</span><span class="pun">(</span><span class="lit">32</span><span class="pun">)</span><span class="pln"> NOT NULL</span><span class="pun">,</span><span class="pln">
  </span><span class="str">`time`</span><span class="pln"> bigint</span><span class="pun">(</span><span class="lit">20</span><span class="pun">)</span><span class="pln"> DEFAULT NULL</span><span class="pun">,</span><span class="pln">
  </span><span class="str">`topic`</span><span class="pln"> text</span><span class="pun">,</span><span class="pln">
  </span><span class="str">`value`</span><span class="pln"> text</span><span class="pun">,</span><span class="pln">
  PRIMARY KEY </span><span class="pun">(</span><span class="str">`md5`</span><span class="pun">)</span><span class="pln">
</span><span class="pun">)</span><span class="pln"> ENGINE</span><span class="pun">=</span><span class="typ">InnoDB</span><span class="pln"> DEFAULT CHARSET</span><span class="pun">=</span><span class="pln">utf8</span><span class="pun">;</span></pre>

<p>
	Теперь необходимо создать хранимые процедуры и функции, но сделать это будет невозможно из-за присутствие в их синтаксисе разделителя совпадающего с концом данных в sql запросе - "<span style="color:#27ae60;"><strong>;</strong></span>" Чтобы избежать этот неловкий момент, изменяем разделить на произвольный.
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_3645_28" style="">
<span class="pln">DELIMITER $$</span></pre>

<p>
	Создает процедуру <span style="color:#27ae60;"><strong>update_topic</strong></span>. Она принимает в качестве входных параметров два значения, адрес топика и опубликованные данные. Оба параметра являются текстовыми. Процедура, вычисляет <strong>md5</strong> хеш из адреса топика и уже по нему производит поиск записи в таблице. Если запись не будет найдена, она будет создана, в противном случае данные в поле value будут обновлены. Данная процедура должна ускорить работу демона и избавить его от задержек, которые были бы неминуемы при выполнении этих же запросов на стороне клиента.
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_3645_30" style="">
<span class="pln">DROP PROCEDURE IF EXISTS </span><span class="str">`update_topic`</span><span class="pln">$$
CREATE DEFINER</span><span class="pun">=</span><span class="pln">CURRENT_USER</span><span class="pun">()</span><span class="pln"> PROCEDURE </span><span class="str">`update_topic`</span><span class="pun">(</span><span class="pln">topic text</span><span class="pun">,</span><span class="pln"> value text</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">BEGIN</span><span class="pln">
	declare nMD5 varchar</span><span class="pun">(</span><span class="lit">32</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">default</span><span class="pln"> md5</span><span class="pun">(</span><span class="pln">topic</span><span class="pun">);</span><span class="pln">
	declare NUM bit</span><span class="pun">;</span><span class="pln">
	declare uTime bigint</span><span class="pun">(</span><span class="lit">20</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">default</span><span class="pln"> UNIX_TIMESTAMP</span><span class="pun">();</span><span class="pln">

	SELECT COUNT</span><span class="pun">(</span><span class="pln">t</span><span class="pun">.</span><span class="pln">md5</span><span class="pun">)</span><span class="pln"> INTO NUM FROM topics t WHERE t</span><span class="pun">.</span><span class="pln">md5 </span><span class="pun">=</span><span class="pln"> nMD5</span><span class="pun">;</span><span class="pln">
	</span><span class="kwd">if</span><span class="pln"> NUM </span><span class="pun">&lt;&gt;</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="kwd">then</span><span class="pln">
		INSERT INTO topics VALUES</span><span class="pun">(</span><span class="pln">nMD5</span><span class="pun">,</span><span class="pln"> uTime</span><span class="pun">,</span><span class="pln"> topic</span><span class="pun">,</span><span class="pln"> value</span><span class="pun">);</span><span class="pln">
	</span><span class="kwd">else</span><span class="pln">
		UPDATE topics t SET t</span><span class="pun">.</span><span class="pln">time </span><span class="pun">=</span><span class="pln"> uTime</span><span class="pun">,</span><span class="pln"> t</span><span class="pun">.</span><span class="pln">value </span><span class="pun">=</span><span class="pln"> value WHERE t</span><span class="pun">.</span><span class="pln">md5 </span><span class="pun">=</span><span class="pln"> nMD5</span><span class="pun">;</span><span class="pln">
	</span><span class="kwd">end</span><span class="pln"> </span><span class="kwd">if</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">END</span><span class="pln">$$</span></pre>

<p>
	Также будет добавлена функция <span style="color:#27ae60;"><strong>get_topic</strong></span>. Она необходима для запроса данных от имени созданного ранее пользователя и ограничений, наложенных на него. Функция принимает адрес топика в текстовом виде, производит вычисление <strong>md5</strong> хеша и основываясь на его совпадении с имеющимися записями выводит значение поля value искомого топика.
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_3645_38" style="">
<span class="pln">DROP FUNCTION IF EXISTS </span><span class="str">`get_topic`</span><span class="pln">$$
CREATE DEFINER</span><span class="pun">=</span><span class="pln">CURRENT_USER</span><span class="pun">()</span><span class="pln"> FUNCTION </span><span class="str">`get_topic`</span><span class="pln"> </span><span class="pun">(</span><span class="pln">topic text</span><span class="pun">)</span><span class="pln">
RETURNS text
</span><span class="kwd">BEGIN</span><span class="pln">
	declare hMD5 varchar</span><span class="pun">(</span><span class="lit">32</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">default</span><span class="pln"> md5</span><span class="pun">(</span><span class="pln">topic</span><span class="pun">);</span><span class="pln">
	declare topicValue text</span><span class="pun">;</span><span class="pln">
	SELECT t</span><span class="pun">.</span><span class="pln">value INTO topicValue FROM topics t WHERE t</span><span class="pun">.</span><span class="pln">md5 </span><span class="pun">=</span><span class="pln"> hMD5</span><span class="pun">;</span><span class="pln">
RETURN topicValue</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">END</span><span class="pln">$$</span></pre>

<p>
	И в завершении всего, будет восстановлено стандартное значение разделителя.
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_3645_40" style="">
<span class="pln">DELIMITER </span><span class="pun">;</span></pre>

<p>
	На этом разбор sql файла можно считать законченным. Он не содержит каких-либо сложным манипуляций и должен быть понятен. Все эти операции можно выполнить руками, но я совету воспользоваться импортом, как и было описано ранее.
</p>

<p>
	<strong>Переходим к демону</strong>
</p>

<p>
	В первую очередь устанавливаем необходимые пакеты.
</p>

<pre class="ipsCode" id="ips_uid_4238_5">
sudo apt-get install python3 python-pip python-dev libmysqlclient-dev</pre>

<p>
	Устанавливаем недостающие библиотеки для Python
</p>

<pre class="ipsCode" id="ips_uid_4238_7">
pip install paho-mqtt mysqlclient</pre>

<p>
	Добавим пользователя из-под которого будет запускаться демон
</p>

<pre class="ipsCode" id="ips_uid_5843_6">
sudo useradd --shell /usr/sbin/nologin --system mqtt-agent</pre>

<p>
	Выставляем все необходимые права (каталог /media как пример)
</p>

<pre class="ipsCode" id="ips_uid_3645_54">
sudo chown mqtt-agent:mqtt-agent /media/mqttMySqlClient.py
sudo chmod 0700 /media/mqttMySqlClient.py</pre>

<p>
	Добавляем демона в автозагрузку через планировщик задач и от имени созданного пользователя
</p>

<pre class="ipsCode" id="ips_uid_3645_56">
sudo crontab -u mqtt-agent -e</pre>

<p>
	Добавляем в конец следующую запись
</p>

<pre class="ipsCode" id="ips_uid_3645_58">
@reboot /media/mqttMySqlClient.py start</pre>

<p>
	Запускаем демона от имени все того же пользователя
</p>

<pre class="ipsCode" id="ips_uid_3645_60">
sudo -u mqtt-agent /media/mqttMySqlClient.py start</pre>

<p>
	Это основное, что требуется сделать на сервере для организации работы демона.
</p>

<p>
	<strong>Переходим к разбору настроек программы</strong>
</p>

<p>
	Т.к изначально за основу была взята концепция другого демона из ветки <strong><a href="https://it4it.club/topic/62-obuchaem-zabbix-rabotat-s-mqtt-protokolom/?tab=comments#comment-485" rel="">Zabbix</a></strong>, то конфигурация перекочевала оттуда и аналогично разбита на несколько секций.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3645_62" style="">
<span class="str">""" Настройки MQTT """</span><span class="pln">
mqtt_server </span><span class="pun">=</span><span class="pln"> </span><span class="str">"mqtt.it4it.club"</span><span class="pln">
mqtt_port </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1883</span><span class="pln">
mqtt_login </span><span class="pun">=</span><span class="pln"> </span><span class="str">""</span><span class="pln">
mqtt_password </span><span class="pun">=</span><span class="pln"> </span><span class="str">""</span><span class="pln">
mqtt_client_id </span><span class="pun">=</span><span class="pln"> </span><span class="str">"mqttMySqlClient"</span></pre>

<p>
	Настройки подключения к брокеру. Все должно быть интуитивно понятным. Помните, что при совпадении идентификаторов клиентов, они начнут конкурировать за подключение и по очереди терять связь. Не допускайте их совпадений.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3645_64" style="">
<span class="str">""" Список топиков для подписки """</span><span class="pln">
subscribe </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="str">'$SYS/#'</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'#'</span><span class="pun">,</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	Список топиков для подписки указывается через запятую и в кавычках.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3645_66" style="">
<span class="str">""" Настройки MySQL """</span><span class="pln">
mysql_host </span><span class="pun">=</span><span class="pln"> </span><span class="str">"127.0.0.1"</span><span class="pln">
mysql_port </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3306</span><span class="pln">
mysql_user </span><span class="pun">=</span><span class="pln"> </span><span class="str">"mqtt-agent"</span><span class="pln">
mysql_passwd </span><span class="pun">=</span><span class="pln"> </span><span class="str">"p@$$w0rd"</span><span class="pln">
mysql_schema </span><span class="pun">=</span><span class="pln"> </span><span class="str">"mqtt"</span><span class="pln">
mysql_log_file </span><span class="pun">=</span><span class="pln"> </span><span class="str">"/var/log/mqttMySqlClient.log"</span></pre>

<p>
	Настройки подключения с MySQL серверу также не должны вызывать вопросов.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3645_68" style="">
<span class="str">""" Настройки общие """</span><span class="pln">
pid_file </span><span class="pun">=</span><span class="pln"> </span><span class="str">"/tmp/mqttMySqlClient.pid"</span></pre>

<p>
	Последний параметр указывает на размещение .pid файла демона.
</p>

<p>
	Команды управления классические
</p>

<ul>
<li>
		<strong>start</strong> - запуск в режиме демона
	</li>
	<li>
		<strong>stop</strong> - остановка в режиме демона
	</li>
	<li>
		<strong>restart</strong> - перезапуск в режиме демона
	</li>
	<li>
		<strong>window</strong> - запуск в оконном режиме, также позволяет запускать процесс в операционных системах Windows
	</li>
</ul>
<p>
	После запуска, демон пытается установить связь с MQTT брокером и пока это не произойдет, связь с MySQL сервером устанавливаться не будет. Если во время работы, связь с брокером будет потеряна то в принудительном порядке, будет разорвано соединение с базой данных. Таким образом, по активным сессиям MySQL сервера можно судить о наличии связи у демона с брокером. Во время простоя, а в нашем случае, это отсутствие потока данных от брокера, для проверки связи с сервером базы данных будет использована процедура эмуляции ping для MySQL сервера. Она представляет из себя простую арифметическую задачу на сложение не приводящей к работе с данными в базе. Операция выполняется крайне быстро и её удачное выполнение сигнализирует клиенту о наличии связи с базой, а базе об активности клиента. В связи с этим, периодическая активность клиента при отсутствие данных от брокера, является показателем нормальной работы.
</p>

<p>
	<strong>И на последок</strong>
</p>

<p>
	Если вы хотите произвести выборку из таблицы под именем пользователя используемым по умолчанию и с его ограничениями. Необходимо воспользоваться функцией get_topic с указанием полного адреса, интересующего топика.
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_3645_70" style="">
<span class="kwd">select</span><span class="pln"> mqtt</span><span class="pun">.</span><span class="pln">get_topic</span><span class="pun">(</span><span class="str">'$SYS/broker/version'</span><span class="pun">);</span></pre>

<p>
	В ответ мы получим
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_3645_74" style="">
<span class="pun">+---------------------------------------+</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> mqtt</span><span class="pun">.</span><span class="pln">get_topic</span><span class="pun">(</span><span class="str">'$SYS/broker/version'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">|</span><span class="pln">
</span><span class="pun">+---------------------------------------+</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> mosquitto version </span><span class="lit">1.4</span><span class="pun">.</span><span class="lit">8</span><span class="pln">               </span><span class="pun">|</span><span class="pln">
</span><span class="pun">+---------------------------------------+</span><span class="pln">
</span><span class="lit">1</span><span class="pln"> row </span><span class="kwd">in</span><span class="pln"> </span><span class="kwd">set</span><span class="pln"> </span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="lit">00</span><span class="pln"> sec</span><span class="pun">)</span></pre>

<p>
	На этом пока все.
</p>

<p>
	Файлы проекта: 
</p>
<iframe allowfullscreen="" class="ipsEmbed_finishedLoading" data-controller="core.front.core.autosizeiframe" data-embedcontent="" data-embedid="embed2718559287" scrolling="no" src="https://it4it.club/files/file/4-demon-dlya-tranzita-dannyh-ot-mqtt-brokera-v-subd-mysql/?do=embed" style="overflow: hidden; height: 396px; max-width: 502px;"></iframe>

<p>
	<u>PS: Это тестовая версия демона и возможно она будет претерпевать некоторые изменения.</u>
</p>

<p>
	 
</p>
]]></description><guid isPermaLink="false">72</guid><pubDate>Mon, 20 Nov 2017 13:34:26 +0000</pubDate></item><item><title>&#x421;&#x43E;&#x437;&#x434;&#x430;&#x43D;&#x438;&#x435; &#x441;&#x430;&#x43C;&#x43E;&#x43F;&#x43E;&#x434;&#x43F;&#x438;&#x441;&#x430;&#x43D;&#x43D;&#x43E;&#x433;&#x43E; SSL &#x441;&#x435;&#x440;&#x442;&#x438;&#x444;&#x438;&#x43A;&#x430;&#x442;&#x430; &#x434;&#x43B;&#x44F; Apache &#x43F;&#x43E;&#x434; Ubuntu</title><link>https://it4it.club/topic/69-sozdanie-samopodpisannogo-ssl-sertifikata-dlya-apache-pod-ubuntu/</link><description><![CDATA[
<p>
	Заметка о создании само подписанного сертификата для <strong>Apache</strong> под <strong>Linux Ubuntu</strong> сроком на <strong>100</strong> лет.
</p>

<p>
	Само подписанный сертификат "не есть плохо", учитывая, что со своими задачами он справляется также хорошо, как и его платные братья. Конечно, если использовать его в публичных проектах, то доверие пользователей к ресурсу начинает катастрофически падать, но если речь идет о внутренних ресурсах, организованных для небольшой группы лиц, то это решение выглядит очень аппетитно.
</p>

<p>
	Выбираем самый короткий путь, логинимся на сервере под пользователем root
</p>

<p>
	Создаем сертификат сроком на <strong>100</strong> лет. Почему на такой долгий? Да потому, что через год никто не вспомнит о том, что его надо пересоздать, да и важность ресурса далеко не банковского уровня.
</p>

<pre class="ipsCode prettyprint lang-perl prettyprinted" id="ips_uid_2230_9" style="">
<span class="pln">openssl req </span><span class="pun">-</span><span class="pln">x509 </span><span class="pun">-</span><span class="pln">nodes </span><span class="pun">-</span><span class="pln">days </span><span class="lit">36500</span><span class="pln"> </span><span class="pun">-</span><span class="pln">newkey rsa</span><span class="pun">:</span><span class="lit">1024</span><span class="pln"> </span><span class="pun">-</span><span class="pln">keyout </span><span class="pun">/</span><span class="pln">etc</span><span class="pun">/</span><span class="pln">ssl</span><span class="pun">/</span><span class="pln">private</span><span class="pun">/</span><span class="pln">apache</span><span class="pun">.</span><span class="pln">key </span><span class="pun">-</span><span class="pln">out </span><span class="pun">/</span><span class="pln">etc</span><span class="pun">/</span><span class="pln">ssl</span><span class="pun">/</span><span class="pln">certs</span><span class="pun">/</span><span class="pln">apache</span><span class="pun">.</span><span class="pln">pem</span></pre>

<p>
	Таким образом, сертификат стандарта <strong>X509</strong> и сроком на <strong>100</strong> лет будет записан в файл <em><span style="color:#27ae60;"><strong>/etc/ssl/private/apache.key</strong></span></em>, а его <strong>1024</strong> битный ключ в файл <span style="color:#27ae60;"><em><strong>/etc/ssl/certs/apache.pem</strong></em></span>
</p>

<p>
	В процессе создания сертификата будут сыпаться различные вопросы от утилиты, можно пропускать все (прожимаем <em><strong>&lt;ENTER&gt;</strong></em>), кроме имени домена для которого этот сертификат и предназначается. Отметим, что пароль к сертификату запрашиваться не будет, об этом мы позаботились с помощью параметра <strong>-nodes</strong>. Да и пароль нам и не нужен, в противном случае его придется вводить при каждом запуске <strong>Apache</strong>.
</p>

<p>
	Теперь необходимо поправить ssl профиль для Apache.
</p>

<pre class="ipsCode prettyprint lang-perl prettyprinted" id="ips_uid_2230_14" style="">
<span class="pln">nano </span><span class="pun">/</span><span class="pln">etc</span><span class="pun">/</span><span class="pln">apache2</span><span class="pun">/</span><span class="pln">sites</span><span class="pun">-</span><span class="pln">available</span><span class="pun">/</span><span class="pln">default</span><span class="pun">-</span><span class="pln">ssl</span><span class="pun">.</span><span class="pln">conf</span></pre>

<p>
	Нам необходимо отключить поддержку <span style="color:#e74c3c;"><em><strong>SSLv2</strong></em></span> и <span style="color:#e74c3c;"><em><strong>SSLv3</strong></em></span> из-за проблем с безопасностью. Добавляем, а если он уже есть, то правим следующий параметр
</p>

<pre class="ipsCode prettyprint lang-perl prettyprinted" id="ips_uid_2230_18" style="">
<span class="typ">SSLProtocol</span><span class="pln"> all </span><span class="pun">-</span><span class="typ">SSLv2</span><span class="pln"> </span><span class="pun">-</span><span class="typ">SSLv3</span></pre>

<p>
	Указываем откуда подтянуть сертификат с ключом и сохраняем профиль
</p>

<pre class="ipsCode prettyprint lang-perl prettyprinted" id="ips_uid_2230_21" style="">
<span class="typ">SSLCertificateFile</span><span class="pln"> </span><span class="pun">/</span><span class="pln">etc</span><span class="pun">/</span><span class="pln">ssl</span><span class="pun">/</span><span class="pln">certs</span><span class="pun">/</span><span class="pln">apache</span><span class="pun">.</span><span class="pln">pem
</span><span class="typ">SSLCertificateKeyFile</span><span class="pln"> </span><span class="pun">/</span><span class="pln">etc</span><span class="pun">/</span><span class="pln">ssl</span><span class="pun">/</span><span class="pln">private</span><span class="pun">/</span><span class="pln">apache</span><span class="pun">.</span><span class="pln">key</span></pre>

<p>
	Выбираемся обратно в консоль и подключаем модуль <strong>SSL</strong> к <strong>Apache</strong>, а заодно подключаем наш обновленный профиль
</p>

<pre class="ipsCode prettyprint lang-perl prettyprinted" id="ips_uid_2230_23" style="">
<span class="pln">a2enmod ssl
a2ensite default</span><span class="pun">-</span><span class="pln">ssl</span><span class="pun">.</span><span class="pln">conf</span></pre>

<p>
	Финалом торжества станет перезапуск сервера
</p>

<pre class="ipsCode prettyprint lang-perl prettyprinted" id="ips_uid_2230_25" style="">
<span class="str">/etc/</span><span class="pln">init</span><span class="pun">.</span><span class="pln">d</span><span class="pun">/</span><span class="pln">apache2 restart</span></pre>

<p>
	Если понадобится принудительно перенаправлять потребителей трафика с <span style="color:#e74c3c;"><em><strong>http</strong></em></span> на <span style="color:#27ae60;"><em><strong>https</strong></em></span> протокол, то самым простым способом будет использование mod_rewrite
</p>

<pre class="ipsCode prettyprint lang-perl prettyprinted" id="ips_uid_2230_27" style="">
<span class="pln">a2enmod rewrite
</span><span class="pun">/</span><span class="pln">etc</span><span class="pun">/</span><span class="pln">init</span><span class="pun">.</span><span class="pln">d</span><span class="pun">/</span><span class="pln">apache2 restart</span></pre>

<p>
	После идем в нужный каталог Apache и создаем там конфигурационный файл <strong>.htaccess</strong> со следующим содержимым
</p>

<pre class="ipsCode prettyprint lang-perl prettyprinted" id="ips_uid_2230_31" style="">
<span class="typ">RewriteEngine</span><span class="pln"> </span><span class="typ">On</span><span class="pln">
</span><span class="typ">RewriteCond</span><span class="pln"> </span><span class="pun">%{</span><span class="pln">SERVER_PORT</span><span class="pun">}</span><span class="pln"> </span><span class="pun">!^</span><span class="lit">443</span><span class="pln">$
</span><span class="typ">RewriteRule</span><span class="pln"> </span><span class="pun">.*</span><span class="pln"> https</span><span class="pun">://%{</span><span class="pln">SERVER_NAME</span><span class="pun">}%{</span><span class="pln">REQUEST_URI</span><span class="pun">}</span><span class="pln"> </span><span class="pun">[</span><span class="pln">R</span><span class="pun">,</span><span class="pln">L</span><span class="pun">]</span></pre>

<p>
	Если не отрабатывает ни одно из правил, описанных в .htaccess, то вероятнее всего, в конфигурации Apache стоит запрет на его чтение. Идем в файл конфигурации
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8841_5" style="">
<span class="pln">nano </span><span class="pun">/</span><span class="pln">etc</span><span class="pun">/</span><span class="pln">apache2</span><span class="pun">/</span><span class="pln">apache2</span><span class="pun">.</span><span class="pln">conf</span></pre>

<p>
	Ищем описание настроек безопасности для корневого каталога Вашего web сервера
</p>

<pre class="ipsCode" id="ips_uid_8841_7">
&lt;Directory /var/www/&gt;
        Options Indexes FollowSymLinks
        AllowOverride None
        Require all granted
&lt;/Directory&gt;</pre>

<p>
	И разрешаем всем описанным в фале .htaccess директивам отмену ранее установленных правил доступа
</p>

<pre class="ipsCode" id="ips_uid_8841_9">
AllowOverride All</pre>

<p>
	И снова перезапускаем Apache.
</p>

<p>
	Не забудьте обновить сертификат после окончания срока его действия, если здоровье еще будет позволять. <img alt="^_^" data-emoticon="1" height="20" src="https://it4it.club/uploads/emoticons/happy.png" srcset="https://it4it.club/uploads/emoticons/happy@2x.png 2x" title="^_^" width="20"></p>
]]></description><guid isPermaLink="false">69</guid><pubDate>Fri, 01 Sep 2017 12:24:16 +0000</pubDate></item><item><title>&#x41E;&#x433;&#x440;&#x430;&#x43D;&#x438;&#x447;&#x435;&#x43D;&#x438;&#x435; &#x441;&#x435;&#x442;&#x435;&#x432;&#x43E;&#x433;&#x43E; &#x434;&#x43E;&#x441;&#x442;&#x443;&#x43F;&#x430; &#x43A; &#x441;&#x435;&#x440;&#x432;&#x435;&#x440;&#x443; &#x441; &#x43F;&#x43E;&#x43C;&#x43E;&#x449;&#x44C;&#x44E; hosts.allow &#x438; hosts.deny</title><link>https://it4it.club/topic/10-%D0%BE%D0%B3%D1%80%D0%B0%D0%BD%D0%B8%D1%87%D0%B5%D0%BD%D0%B8%D0%B5-%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE-%D0%B4%D0%BE%D1%81%D1%82%D1%83%D0%BF%D0%B0-%D0%BA-%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80%D1%83-%D1%81-%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E-hostsallow-%D0%B8-hostsdeny/</link><description><![CDATA[
<p>Необходимо ограничить доступ к TFTP серверу на который сохраняются различные конфигурационные файлы. В моем случае на сервер ходят только маршрутизаторы со статическими ip адресами. Следовательно доступ органическим существам необходимо строго-настрого запретить.</p><p>В Linux имеются два замечательных файла, названия которых говорят сами за себя:</p><ol><li>/etc/hosts.allow</li><li>/etc/hosts.deny</li></ol><p>Синтаксис файлов:</p><pre class="ipsCode prettyprint">&lt;служба или ALL&gt;: &lt;IP, имя хоста или подсеть&gt;</pre><p><span style="line-height:22.3999996185303px;">Я использую демона </span><span style="line-height:22.3999996185303px;">tftpd для организации TFTP сервера.</span></p><p>Идем в /etc/hosts.allow и добавляем в конец файла секцию описывающую каким хостам разрешено работать с демоном:</p><pre class="ipsCode prettyprint"># ---------------------------------------------------------------------------
# TFTP
# ---------------------------------------------------------------------------

# router 1
in.tftpd: 10.10.10.1
# router 2
in.tftpd: 10.10.10.2
# router 3
in.tftpd: 10.10.10.3
# router 4
in.tftpd: 10.10.10.4</pre><p>Теперь идем в /etc/hosts.deny и добавляем секцию в которой красуется короткая и лаконичная запись "<u>ты кто такой давай до свидания</u>":</p><pre class="ipsCode prettyprint"># ---------------------------------------------------------------------------
# TFTP
# ---------------------------------------------------------------------------

in.tftpd: ALL</pre><p>Естественно Вы можете указать любую службу: smtp, http, mysqld, sshd ...</p><p><strong>Spawn</strong></p><p>Позволяет выполнить код при наступление определенного события соответствующего правилам описанным выше.</p><p>Добавим логирование событий чтобы знать о всех неудачных попытках подключения к TFTP серверу. Модифицируем <span style="line-height:22.3999996185303px;">/etc/hosts.deny</span></p><pre class="ipsCode prettyprint"># ---------------------------------------------------------------------------
# TFTP
# ---------------------------------------------------------------------------

in.tftpd: ALL : spawn /bin/echo $(/bin/date +"%%d-%%m-%%y %%T") отказано в доступе %h&gt;&gt;/var/log/tftp.access.log</pre><p>Можно использовать следующие макросы:</p><ol><li><strong>%a  </strong>Адрес клиента</li><li><strong>%A</strong>  Адрес сервера</li><li><strong>%c</strong>  Информация о клиенте: user@host, user@address, имя хоста или просто адрес</li><li><strong>%d</strong>  Имя демона/процесса</li><li><strong>%h</strong>  Имя хоста клиента или адрес, если имя хоста недоступно</li><li><strong>%H</strong>  Имя хоста сервера или адрес, если имя хоста недоступно</li><li><strong>%n</strong>  Имя хоста клиента (либо 'unknown' или 'paranoid')</li><li><strong>%N</strong>  Имя хоста сервера (либо 'unknown' или 'paranoid')</li><li><strong>%p  </strong>Идентификатор процесса (PID)</li><li><strong>%s  </strong>Информация о сервере: daemon@host, daemon@address или просто имя демона</li><li><strong>%u  </strong>Имя пользователя клиента (или 'unknown')</li><li><strong>%%  </strong>Одиночный символ '%'</li></ol><p>Теперь мы будем знать о всех неудачных попытках подключения к TFTP серверу.</p><p>Полученный в итоге файл можно скормить Zabbix'у и сигнализировать при его изменении администратору сервера!</p>
]]></description><guid isPermaLink="false">10</guid><pubDate>Mon, 17 Aug 2015 10:53:22 +0000</pubDate></item><item><title>&#x417;&#x430;&#x43C;&#x435;&#x442;&#x43A;&#x438; &#x43F;&#x43E; SNMP</title><link>https://it4it.club/topic/12-%D0%B7%D0%B0%D0%BC%D0%B5%D1%82%D0%BA%D0%B8-%D0%BF%D0%BE-snmp/</link><description><![CDATA[
<p>Думаю, учитывая тот факт, что данная запись позиционируется как шпаргалка, начинать с заурядных вступлений с описанием, что такое SNMP бессмысленно. Основное можно прочитать на <a rel="external nofollow" href="https://ru.wikipedia.org/wiki/SNMP">wikipedia</a></p><p>В моем случае SNMP протокол используется для мониторинга различного оборудования Ubuntu Server'ом. </p><p><strong>В Debian установка выглядит весьма тривиально</strong></p><pre class="ipsCode prettyprint">sudo apt-get install snmp</pre><p><strong>Если необходим еще и демон, то</strong></p><pre class="ipsCode prettyprint">sudo apt-get install snmp snmpd</pre><p>В пакет snmp также входит всем известная утилита snmpwalk</p><p><strong>файлы конфигурации (из названия понятно за что отвечает каждый из них)</strong></p><ol><li>/etc/snmp/snmp.conf</li><li>/etc/snmp/snmpd.conf</li><li>/etc/snmp/snmptrapd.conf</li></ol><p>По умолчанию, после установки, snmpwalk может работать только с цифровыми именами, что может вызвать неудобство для восприятия человека.</p><pre class="ipsCode prettyprint">snmpwalk -v 2c -c public 127.0.0.1 iso.3.6.1.2.1.1.3.0</pre><p>Если заглянуть в <span style="line-height:22.3999996185303px;">snmp</span><span style="line-height:22.3999996185303px;">.conf, то там красуется печальный, но вполне обоснованный заголовок</span></p><pre class="ipsCode prettyprint"># As the snmp packages come without MIB files due to license reasons, loading
# of MIBs is disabled by default. If you added the MIBs you can reenable
# loading them by commenting out the following line.</pre><p>Что нам требуется, то и загружаем самостоятельно в каталог <span style="color:#008000;"><strong>/usr/share/mibs</strong></span>, с последующим занесением имени базы в данный файл.</p><p>Можно установить дополнительный пакет который, по нашему требованию, будет закачивать различные MIB'ы.</p><pre class="ipsCode prettyprint"> sudo apt-get install snmp-mibs-downloader</pre><p>Для обновления списка баз используем</p><pre class="ipsCode prettyprint"> sudo /usr/bin/download-mibs</pre><p>Выглядит это следующим образом</p><blockquote class="ipsStyle_spoiler" data-ipsspoiler=""><pre class="ipsCode prettyprint">Downloading documents and extracting MIB files.
This will take some minutes.

In case this process fails, it can always be repeated later by executing
/usr/bin/download-mibs again.

RFC1155-SMI: 119 lines.
RFC1213-MIB: 2613 lines.
NOTE: SMUX: ignored.
SMUX-MIB: 158 lines.
CLNS-MIB: 1294 lines.
RFC1381-MIB: 1007 lines.
RFC1382-MIB: 2627 lines.
RFC1414-MIB: 131 lines.
SNMPv2-PARTY-MIB: 1410 lines.
SNMPv2-M2M-MIB: 807 lines.
MIOX25-MIB: 708 lines.
PPP-LCP-MIB: 764 lines.
PPP-SEC-MIB: 289 lines.
PPP-IP-NCP-MIB: 203 lines.
PPP-BRIDGE-NCP-MIB: 429 lines.
FDDI-SMT73-MIB: 2126 lines.
TOKEN-RING-RMON-MIB: 2302 lines.
SOURCE-ROUTING-MIB: 450 lines.
DECNET-PHIV-MIB: 3030 lines.
DSA-MIB: 642 lines.
DPI20-MIB: 47 lines.
IBM-6611-APPN-MIB: 5112 lines.
DNS-SERVER-MIB: 1078 lines.
DNS-RESOLVER-MIB: 1196 lines.
UPS-MIB: 1899 lines.
CHARACTER-MIB: 646 lines.
RS-232-MIB: 788 lines.
PARALLEL-MIB: 286 lines.
SNA-NAU-MIB: 2765 lines.
SIP-MIB: 1099 lines.
Modem-MIB: 1340 lines.
...
</pre><p> </p></blockquote><p>После данной процедуры каталог /usr/share/mibs будет под завязку полон.</p><p>В файле конфигурации можно указать какие MIB'ы использовать просто перечислив их</p><blockquote class="ipsStyle_spoiler" data-ipsspoiler=""><div> </div><div><pre class="ipsCode prettyprint" style="line-height:22.3999996185303px;">mibs :SNMPv2-MIB:IP-MIB:IF-MIB:UPS-MIB</pre><p style="line-height:22.3999996185303px;">или для использования всех, указать</p><pre class="ipsCode prettyprint" style="line-height:22.3999996185303px;">mibs :ALL
</pre></div><p> </p></blockquote><p>Теперь можно использовать иерархическое пространство в запросах. </p><pre class="ipsCode prettyprint">snmpwalk -v 2c -c public 127.0.0.1 SNMPv2-MIB::sysUpTime.0</pre><p>На мой взгляд, в каталоге <span style="line-height:22.3999996185303px;"><span style="color:#008000;"><strong>/usr/share/mibs</strong></span> </span>стоит держать только те MIB'ы которые необходимы для работы. Можно создавать собственные базы или использовать те, что предоставляет изготовитель используемого Вами оборудования.</p><p>Что касается демона snmpd, то по умолчанию он обслуживает только кольцевой ip со стандартным <u>community public</u>. Раскомментируем следующую строку для доступа через любой сетевой интерфейс или укажем явно необходимый адрес.</p><pre class="ipsCode prettyprint">agentAddress udp:161,udp6:[::1]:161</pre><p>Для изменения/добавления community смотрим в ветку ACCESS CONTROL.</p><p><strong>Формат записи</strong></p><pre class="ipsCode prettyprint">[[rocommunity[6]]|[rwcommunity[6]] [community name] [source [OID | -V VIEW [CONTEXT]]]</pre><ol><li>rocommunity - доступ на чтение</li><li>rwcommunity - полный доступ</li></ol><pre class="ipsCode prettyprint">rocommunity secret1 192.168.1.10
rwcommunity secret2 192.168.1.10
rocommunity secret3 192.168.1.11 .1.3.6.1.2.1.1.3.0</pre><p>Все изменения применяются только после перезапуска демона</p><pre class="ipsCode prettyprint">service snmpd restart</pre><p>Подробное описание можно найти тут <a rel="external nofollow" href="http://www.net-snmp.org/docs/man/snmpd.conf.html">http://www.net-snmp.org/docs/man/snmpd.conf.html</a></p><p><strong>PS:</strong> об остальных возможностях поговорим позже.</p>
]]></description><guid isPermaLink="false">12</guid><pubDate>Thu, 20 Aug 2015 10:46:41 +0000</pubDate></item></channel></rss>
