<?xml version="1.0" encoding="utf-8" ?>
<rss version = "2.0" xmlns:content="http://purl.org/rss/1.0/modules/content">
<channel>
<title>Блог №200 по адресу 0708:07C7</title>
<link>http://err200.net/</link>
<description />
<generator>Nouz (nouz.org)</generator>

<item><title><![CDATA[Wild Player для DivMMC]]></title>
<link>http://err200.net/notes/52/</link>
<comments>http://err200.net/notes/52/</comments>
<description><![CDATA[Немного хакнул <a href="http://budder.narod.ru/MugenGroup/wp.htm">Wild Player</a> (плеер трекерной музыки для ZX Spectrum) для работы с DivMMC. За основу взял tap-версию 0.333.<br/><br/>UPD 2020-09-04: Обновил версию - исправлено зависание если вставлено 2 SD-карты.<br/><br/>Ссылки для скачивания:<br/><a href="files/zx/wp_divmmc4.z80">wp_divmmc.z80</a><br/><a href="files/zx/wp_divmmc4.tzx">wp_divmmc.tzx</a>]]></description>
<pubDate>Sun, 19 Apr 2020 09:32:45 +0300</pubDate>
<author>Uzix</author>
</item><item><title><![CDATA[Особенность маршрутизации в Linux]]></title>
<link>http://err200.net/notes/51/</link>
<comments>http://err200.net/notes/51/</comments>
<description><![CDATA[Про rp_filter в интернете не писал только ленивый. Но вот о чём редко пишут - rp_filter начисто игнорирует маркер пакета (nfmark, он же fwmark)! Т.е. если у вас настроена policy-based-routing с использованием ip rule fwmark, то обратный маршрут rp_filter будет рассчитывать неверно, что приведёт к тихому дропу пакетов. Что делать? Я вижу пару вариантов:<ul> <li>Отключить rp_filter на интерфейсе и прописать всё что он делает руками;</li><li>Использовать TOS для маркировки пакетов. Минусы - он восьмибитный, и ip rule не умеет применять к значению маску. К тому же нужно помнить, что TOS - не метаинформация внутри ядра, а реальное поле в IP-пакете со всеми вытекающими.</li></ul>Есть также модуль iptables rpfilter. Он делает то же, что и встроенный в ядро rp_filter, но при этом его можно обвязать любыми (в рамках таблицы raw) правилами iptables. К сожалению, он доступен только для ядер >=3.3.]]></description>
<pubDate>Thu, 06 Dec 2018 17:12:36 +0300</pubDate>
<author>Uzix</author>
</item><item><title><![CDATA[CMake: указание директорий для поиска библиотек]]></title>
<link>http://err200.net/notes/50/</link>
<comments>http://err200.net/notes/50/</comments>
<description><![CDATA[При сборке ПО с использованием CMake иногда возникает необходимость указать нестандартный путь для поиска библиотек.<br/>Сделать это можно следующим образом:<pre>cmake -DPKG_CONFIG_USE_CMAKE_PREFIX_PATH=1 -DCMAKE_PREFIX_PATH=/opt/dsview/ ../</pre><br/>]]></description>
<pubDate>Wed, 18 Apr 2018 11:21:46 +0300</pubDate>
<author>Uzix</author>
</item><item><title><![CDATA[Оно работает!]]></title>
<link>http://err200.net/notes/49/</link>
<comments>http://err200.net/notes/49/</comments>
<description><![CDATA[Наконец-то спустя недели освоения ПЛИС и Verilog удалось запрограммировать и испытать текстовый VGA/RS-232 терминал.<br/>Вот как это выглядит:<br/><cut><br/><br><a href="/files/fpgaterm_screen.jpg"><img src="/image.php?width=240&image=/files/fpgaterm_screen.jpg"></a><br><br/>А вот как это выглядит со стороны ПК:<br/><br><a href="/files/fpgaterm_pc.png"><img src="/image.php?width=240&image=/files/fpgaterm_pc.png"></a><br><br/><br/><pre>Device : EP1C3T144C8<br/>Timing Models : Final<br/>Total logic elements : 412 / 2,910 ( 14 % )<br/>Total pins : 46 / 104 ( 44 % )<br/>Total virtual pins : 0<br/>Total memory bits : 20,510 / 59,904 ( 34 % )<br/>Total PLLs : 0 / 1 ( 0 % )</pre><br/><br/>ОЗУ на моей отладочной плате, к сожалению, не предусмотрено. Поэтому приходится экономить по максимуму. Например, шрифт содержит только самые основные символы и только в верхнем регистре. Но оно работает!<br/>Теперь буду прикручивать к этому процессор.<br/>]]></description>
<pubDate>Fri, 13 Apr 2018 22:07:23 +0300</pubDate>
<author>Uzix</author>
</item><item><title><![CDATA[/dev во freebsd chroot ]]></title>
<link>http://err200.net/notes/48/</link>
<comments>http://err200.net/notes/48/</comments>
<description><![CDATA[Не нашёл в интернете хорошего решения, поэтому выкладываю тут.<br/><br/>Т.к. во FreeBSD нельзя сделать просто mknod в произвольном месте фс (вернее можно, но результат работать не будет с ошибкой "operation not supported"), то для доступа к устройствам внутри chroot приходится немного шаманить - а именно монтировать devfs с нужными нам устройствами.<br/><br/>Покажу на примере php-fpm. Создаём файл /usr/local/etc/rc.conf.d/php_fpm со следующим содержимым:<br/><pre>mount_devs() {<br/>    for i in $php_fpm_chroots; do<br/>        umount "${i}/dev" 2>/dev/null || true<br/>        devfs_domount "${i}/dev" devfsrules_hide_all<br/>        devfs -m "${i}/dev" rule apply path null unhide<br/>        devfs -m "${i}/dev" rule apply path random unhide<br/>        devfs -m "${i}/dev" rule apply path urandom unhide<br/>    done<br/>}<br/><br/>start_precmd="$start_precmd && mount_devs"<br/></pre><br/>и в rc.conf дописываем:<br/><pre>php_fpm_chroots="/var/www1 /var/www2"</pre><br/>Создаём по нужным путям dev/, делаем рестарт сервиса - и после этого всё должно заработать.<br/>]]></description>
<pubDate>Thu, 02 Mar 2017 12:59:28 +0300</pubDate>
<author>Uzix</author>
</item><item><title><![CDATA[https]]></title>
<link>http://err200.net/notes/47/</link>
<comments>http://err200.net/notes/47/</comments>
<description><![CDATA[В связи с наметившейся тенденцией всяческого ущемления (понижение позиции в выдаче поисковиков, предупреждения о небезопасности в браузерах) сайтов, доступных только по http, а так же по причине необходимости повышения безопасности передаваемых данных, передо мной возникла задача внедрения https с минимальными материально-техническими затратами на внедрение и сопровождение.<br/><cut><br/>Итак, возможны несколько подходов при внедрении https.<br/><b>1.</b> Использование самоподписанных сертификатов. Этот подход хорошо подходит для небольших частных сайтов, различных админок и подобной мелочи.<br/>Плюсы такого подхода:<br/>+ Ни от кого не зависим - сертификат можно самостоятельно сделать на любой домен, на любой срок. Обычный центр сертификации по очевидным причинам не станет подписывать сертификат для внутренних доменов (*.lan и т.п.).<br/>+ Всё довольно просто - получить самоподписанный сертификат можно буквально в одну команду.<br/>Минусы:<br/>- При первом посещении сайта пользователю будет выдано предупреждение о недоверенном сертификате и необходимо будет добавить сертификат в список доверенных. <br/>Для некоторых утилит часто неясно как или вовсе невозможно это сделать.<br/><br/>howto:<br/><pre>openssl req -x509 -newkey rsa:4096 -nodes -keyout key.pem -out cert.pem -days 365<br/></pre><br/><br/><b>2.</b> Использование собственного центра сертификации. Оптимальный вариант для внутренних ресурсов организаций. К плюсам и минусам подхода №1 добавляется:<br/>+ Опять же ни от кого не зависим - сертификат можно самостоятельно сделать на любой домен, на любой срок. <br/>+ Централизованное управление выданными/отозванными сертификатами. Как бонусом - удобно мониторить истекающие сертификаты.<br/>+ Для доверия к любому внутреннему ресурсу достаточно добавить всего один сертификат на всех клиентах. При системы центрального управления конфигурациями (active directory, ansible и т.п.) сделать это крайне просто.<br/>- При компрометации сертификата центра сертификации автоматически компрометируются все серверы и клиенты, на которых он установлен. Т.к. x509 не предусматривает ограничений на выдаваемые центром сертификации сертификаты, то компрометируются в том числе и любые https соединения к любым серверам. Единственное что остаётся в безопасности - клиенты, использующие привязку к сертификату (certificate pinning).<br/>- Собственный центр сертификации относительно сложно настроить. Нельзя просто скопировать первый рецепт с serverfault - нужно понимать что и зачем делать.<br/><br/>howto:<br/>Не существует быстрого и универсального пути, но для себя я написал небольшой скрипт, обладающий минимальным функционалам по созданию ЦС, созданию и подписи ключей и сертификатов. Скрипт далеко не идеальный, но длительное время он служил мне верой и правдой.<br/><pre>#!/bin/bash -xe<br/><br/>export OPENSSL_CONF=cnf<br/><br/>a="$1"<br/>shift || true<br/>n="$1"<br/>o="$2"<br/><br/>cd "`dirname $0`"<br/>umask 0007<br/><br/>case "$a" in<br/>  gen)<br/>    test -n "$n"<br/>    openssl genrsa 2048 >private/$n<br/><br/>    cp "$OPENSSL_CONF"{,.tmp}<br/>    export OPENSSL_CONF="$OPENSSL_CONF.tmp"<br/>    echo '[ alt_names ]' >> "$OPENSSL_CONF"<br/>    cnt=1<br/>    while (( "$#" )); do<br/>        echo "DNS.$cnt = $1" >> "$OPENSSL_CONF"<br/>        (( cnt++ ))<br/>        shift<br/>    done<br/>    <br/>    openssl req -new -key private/$n -subj "/C=RU/ST=Belgorod/O=IVTBSU/OU=CA/CN=$n" >csr.$n<br/>    openssl req -text -noout &lt;csr.$n<br/>    openssl ca -batch -notext -extensions server -in csr.$n >cert/$n<br/>    rm csr.$n<br/>  ;;<br/>  genca)<br/>    mkdir ca cert private dh || true<br/>    openssl genrsa 4096 >ca/key<br/>    openssl req -new -key ca/key -subj "/C=RU/ST=Belgorod/O=IVTBSU/OU=CA/CN=ivt.su" >ca/csr<br/>    openssl x509 -req -days 10000 -in ca/csr -signkey ca/key >ca/crt<br/>    rm ca/csr<br/>    echo 100001 >ca/srl<br/>    echo 100001 >ca/crlnum<br/>    touch ca/index<br/>    openssl ca -gencrl >ca/crl<br/>  ;;<br/>  gendh)<br/>    test -r cert/$n<br/>    openssl dhparam -in cert/$n 1024 >dh/$n<br/>  ;;<br/>  revoke)<br/>    test -r cert/$n<br/>    openssl ca -revoke cert/$n<br/>    openssl ca -gencrl >ca/crl<br/>    rm cert/$n private/$n<br/>  ;;<br/>  public)<br/>    openssl rsa -in cert/$n -pubout<br/>  ;;<br/>  info)<br/>    openssl x509 -in cert/$n -text<br/>  ;;<br/>  chown)<br/>    test -n "$o"<br/>    for i in dh cert private; do<br/>      test -r "$i/$n" || continue<br/>      chmod 0400 "$i/$n"<br/>      chown $o:wheel "$i/$n"<br/>    done  <br/>  ;;<br/>  *)<br/>    echo "Usage: $0 <gen NAME [NAME2 [...]]|genca|gendh NAME|revoke NAME>"<br/>    exit 1<br/>  ;;<br/>esac<br/></pre><br/>Так же понадобится файл конфигурации openssl (cnf):<br/><pre>[ ca ]<br/>default_ca = myca<br/><br/>[ crl_ext ]<br/># issuerAltName=issuer:copy  #this would copy the issuer name to altname<br/>authorityKeyIdentifier = keyid:always<br/><br/>[ myca ]<br/>dir              = ./ca<br/>new_certs_dir    = $dir<br/>unique_subject   = no<br/>certificate      = $dir/crt<br/>database         = $dir/index<br/>private_key      = $dir/key<br/>serial           = $dir/srl<br/>default_days     = 730<br/>default_md       = sha256<br/>policy           = myca_policy<br/>x509_extensions  = myca_extensions<br/>crlnumber        = $dir/crlnum<br/>default_crl_days = 730<br/><br/>[ myca_policy ]<br/>commonName             = supplied<br/>stateOrProvinceName    = supplied<br/>countryName            = optional<br/>emailAddress           = optional<br/>organizationName       = supplied<br/>organizationalUnitName = optional<br/><br/>[ myca_extensions ]<br/>basicConstraints       = CA:false<br/>subjectKeyIdentifier   = hash<br/>authorityKeyIdentifier = keyid:always<br/>keyUsage               = digitalSignature,keyEncipherment<br/>extendedKeyUsage       = serverAuth<br/>crlDistributionPoints  = URI:http://CHANGE.ME/root.crl<br/>nsComment              = "OpenSSL Generated Certificate"<br/>subjectAltName         = @alt_names<br/><br/><br/>[ req ]<br/>default_md             = sha256<br/>distinguished_name     = req_distinguished_name<br/>#attributes            = req_attributes<br/>x509_extensions        = v3_ca<br/>req_extensions         = v3_req<br/>[ v3_req ]<br/>subjectAltName         = @alt_names<br/>[ v3_ca ]<br/>subjectKeyIdentifier   = hash<br/>authorityKeyIdentifier = keyid:always,issuer<br/>basicConstraints       = CA:true<br/><br/>[ req_distinguished_name ]<br/>countryName                  = Country?<br/>countryName_default          = RU<br/>stateOrProvinceName          = State?<br/>stateOrProvinceName_default  = Belgorod obl.<br/>localityName                 = City?<br/>localityName_default         = Belgorod<br/>0.organizationName           = Organization?<br/>0.organizationName_default   = Home<br/>commonName                   = Domain?<br/>commonName_default           = change.me<br/>emailAddress                 = Email?<br/>emailAddress_default         = ca@change.me<br/><br/>[ server ]<br/>basicConstraints       = CA:FALSE<br/>nsCertType             = server<br/>nsComment              = "OpenSSL Generated Server Certificate"<br/>subjectKeyIdentifier   = hash<br/>authorityKeyIdentifier = keyid,issuer:always<br/>extendedKeyUsage       = serverAuth<br/>keyUsage               = digitalSignature, keyEncipherment<br/>subjectAltName         = @alt_names<br/><br/>[ client ]<br/>basicConstraints       = CA:FALSE<br/>nsComment              = "OpenSSL Generated Client Certificate"<br/>subjectKeyIdentifier   = hash<br/>authorityKeyIdentifier = keyid,issuer:always<br/>extendedKeyUsage       = clientAuth<br/>keyUsage               = digitalSignature<br/></pre><br/><br/><b>3.</b> Использование публичного центра сертификации. Фактически единственный приемлемый вариант для публичных сайтов. <br/>+ Все клиенты по умолчанию будет доверять вашему сертификату.<br/>- Нужно проходить процедуру верификации для подтверждения владения доменом, при чём домен, очевидно, должен быть публичным.<br/>- Центр сертификации может накладывать собственные ограничения на параметры сертификата. Например, Let's Encrypt выдаёт сертификаты не более чем на ~3 месяца и не допускает использования widcard в доменном имени.<br/>- Большинство центров сертификации хотят денег.<br/><br/>howto:<br/>Я буду использовать let's encrypt (LE) т.к.<br/>1. Он бесплатный;<br/>2. Процедура получения и обновления сертификатов автоматизирована.<br/>Всю грязную работу будет выполнять утилита acme-tiny:<br/><pre> pkg install acme-tiny</pre><br/>Вряд ли кому-то доставит удовольствие поддерживать сертификаты для нескольких десятков доменов, особенно с учётом срока годности сертификатов LE (~3 месяца). Поэтому я набросал небольшой скрипт. Он автоматически создаёт ключи и сертификаты для указанных доменов и, при близости срока их истекания, проводит обновление.<br/>Предварительная подготовка:<br/><pre># mkdir -p /var/www/le<br/># mkdir /etc/ssl/le<br/># cd /etc/ssl/le<br/># openssl genrsa 4096 >LE.key</pre><br/>Собственно, сам скрипт:<br/><pre>#!/bin/sh -e<br/><br/>cd "$(dirname $0)"<br/><br/><br/>isok() {<br/>  name="$1"; domains="$4"<br/>  test -r "$name.key" || return 1<br/>  test -r "$name.crt" || return 1<br/>  openssl x509 -in "$name.crt" -checkend 2592000 -noout || return 1<br/>  f1="`mktemp`"; echo "$domains" |tr : '\n' |sort >"$f1"<br/>  f2="`mktemp`"; openssl x509 -in "$name.crt" -text |egrep -m1 '^ +DNS:' |sed -e 's/ *DNS://g' |tr , '\n' |sort >"$f2"<br/>  set +e<br/>  diff -q "$f1" "$f2" >/dev/null<br/>  ret=$?<br/>  set -e<br/>  rm "$f1" "$f2"<br/>  test "$ret" = 0 || return 1<br/>  return 0<br/>}<br/><br/>upd() {<br/>  name="$1"; group="$2"; service="$3"; domains="$4"<br/>  echo "Generating $name..." >&2<br/>  cnff="`mktemp`"<br/>  test -r "$name.key" || openssl genrsa 4096 >"$name.key"<br/>  cat /etc/ssl/openssl.cnf >"$cnff"<br/>  echo "$domains" | awk -vRS=: 'BEGIN{printf "[SAN]\nsubjectAltName="}notfirst==1{printf ","}{printf "DNS:"$0; notfirst=1} ' >>"$cnff"<br/>  openssl req -new -sha256 -key $name.key -subj "/" -reqexts SAN -config "$cnff" > "$name.csr"<br/>  rm "$cnff"<br/>  acme_tiny --account-key LE.key --csr "$name.csr" --acme-dir /var/www/le/ > "$name.crt"<br/>  rm "$name.csr"<br/>  curl -s https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem >> "$name.crt"<br/>  cat "$name.crt" "$name.key" >"$name.pem"<br/>  chgrp "$group" "$name.key" "$name.crt" "$name.pem"<br/>  chmod o-rwx    "$name.key" "$name.crt" "$name.pem"<br/>  test "$service" = '-' || service "$service" reload<br/>}<br/><br/>cat << EOF |grep -v -e^# -e^$ |while read i; do isok $i || upd $i; done<br/><br/># name    group    service    dns1.example.com:dns2.example.com<br/>web       www      nginx      err200.net:www.err200.net:ftp.err200.net<br/>imap      dovecot  dovecot    imap.err200.net:pop3.err200.net:pop.err200.net<br/>irc       ircd     inspircd   irc.err200.net<br/>EOF</pre><br/><br/>Добавляем в cron:<br/><pre>@monthly /etc/ssl/le/upd.sh</pre><br/><br/>Самое время настроить веб-сервер. Я сделаю это на примере nginx. Let's encrypt верифицирует домен путём загрузки через http файла со случайно сгенерированным именем, нужно это учесть.<br/>Создаём /etc/nginx/lessl.conf:<br/><pre>listen 443 ssl http2;<br/><br/>add_header Strict-Transport-Security "max-age=31536000";<br/><br/>location ^~ /.well-known/acme-challenge/ {<br/>    alias /var/www/le/;<br/>    try_files $uri =404;<br/>    auth_basic off;<br/>}</pre><br/><br/>Теперь в конфиг нужных server'ов просто пишем<br/><pre>include lessl.conf;</pre><br/>... делаем service nginx reload и запускаем скрипт. Если всё сделано правильно - скрипт отрапортует "Certificate signed!" столько раз, сколько в нём указано сертификатов.<br/>Всё, можно прописывать в server'ах:<br/><pre>ssl_certificate /etc/ssl/le/web.crt;<br/>ssl_certificate_key /etc/ssl/le/web.key;</pre><br/>... и сайт должен заработать по https.<br/><br/>При использовании реверс прокси может возникнуть проблема редиректов с https на http внутри сайта. Решается она очень просто:<br/><pre>proxy_redirect default;<br/>proxy_redirect http:// $scheme://;</pre><br/>Или для haproxy:<br/><pre>http-response replace-value Location http://(.*) https://\1 if { dst_port 443 }</pre><br/><br/>На этом всё.]]></description>
<pubDate>Wed, 01 Feb 2017 15:34:09 +0300</pubDate>
<author>Uzix</author>
</item><item><title><![CDATA[...]]></title>
<link>http://err200.net/notes/45/</link>
<comments>http://err200.net/notes/45/</comments>
<description><![CDATA[An aircraft company discovered that it was cheaper to fly its planes with less fuel on board. The planes would be lighter and use less fuel and money was saved. On rare occasions however the amount of fuel was insufficient, and the plane would crash. This problem was solved by the engineers of the company by the development of a special OOF (out-of-fuel) mechanism. In emergency cases a passenger was selected and thrown out of the plane. (When necessary, the procedure was repeated.) A large body of theory was developed and many publications were devoted to the problem of properly selecting the victim to be ejected. Should the victim be chosen at random? Or should one choose the heaviest person? Or the oldest? Should passengers pay in order not to be ejected, so that the victim would be the poorest on board? And if for example the heaviest person was chosen, should there be a special exception in case that was the pilot? Should first class passengers be exempted? Now that the OOF mechanism existed, it would be activated every now and then, and eject passengers even when there was no fuel shortage. The engineers are still studying precisely how this malfunction is caused.<p><i><a href=http://lwn.net/Articles/104179/>Источник</a></i>]]></description>
<pubDate>Thu, 10 Nov 2016 16:22:26 +0300</pubDate>
<author>Uzix</author>
</item><item><title><![CDATA[О Mikrotik]]></title>
<link>http://err200.net/notes/44/</link>
<comments>http://err200.net/notes/44/</comments>
<description><![CDATA[Не так давно я заимел в личное пользование маршрутизатор Mikrotik RB951Ui-2HnD, и в этой заметке хочу поделиться впечатлениями от работы с данным устройством.<br/><cut><br/><br/>Ну, во-первых, что сразу бросается в глаза? Это Winbox - утилита для настройки. Тысяча и одна настройка, множество менюшек и кнопочек вызывают прямо-таки щенячий восторг у искушённого человека. Более того, всё это великолепие доступно через командный интерфейс, прямо как во "взрослых" маршрутизаторах. В каком ещё домашнем устройстве можно встретить такое?<br/>Но первоначальный хайп быстро уходит, и в ходе настройки устройства под свои потребности довольно скоро понимаешь что Микротик - это не более чем красивая обёртка с довольно тусклыми возможностями.<br/><br/>Небольшая ремарка - Микротик брался на замену TP-Link'у с OpenWRT (и вечно падающим Wi-Fi, да). Соответственно, я ожидал что он сможет покрыть тот скромный функционал, который давал мне OpenWRT. Наивный...<br/><br/><br/>Итак, что не так с Микротик (исключительно ИМХО):<br/><br/>1. OpenVPN-клиент - это недоразумение. Нет UDP, нет сжатия, <strike>нет keepalive</strike>. Злые языки говорят что есть ещё ограничение на количество маршрутов, получаемое при push. Специально под Микротик мне пришлось поднимать дополнительный сервер OpenVPN со своим набором настроек.<br/><br/>2. RIP и PPTP - неработоспособная связка. Входящие пакеты есть, но Микротик их упорно игнорирует и сам ничего не рассылает. При этом OSPF работает на ура.<br/><br/>3. В DNS-сервере нет функционала по форвардингу указанных доменов на отдельные DNS-сервера (благо, решается с помощью iptables и layer7-фильтров с километровыми regex). Да и вообще, встроенный DNS-сервер (если сравнивать с dnsmasq) - недоразумение из категории "Роутер за 300".<br/><br/>4. Нет абсолютно никакой возможности вести хотя бы простейший учёт трафика своими силами (без MetaROUTER или внешних серверов).<br/><br/>5. Во многих настройках принимается только IP-адрес, либо принимается домен, который при сохранении резолвится в IP. Приходится городить скрипты, следящие за доменным именем и обновляющие настройки.<br/><br/>6. Слабая система журналирования: в info пишется слишком мало, а в debug - уже слишком много.<br/><br/>7. Велосипеды, всюду свои велосипеды. Свой скриптовый язык, свой iperf, свои реализации всех сервисов. И это неприятней чем кажется.<br/><br/>По мере накопления опыта данный список будет дополняться.<br/><br/><br/>В целом, маршрутизаторы Mikrotik обладают хорошим железом и средним ПО, способным удовлетворить нужды обыкновенной домохозяйки, но не более того.]]></description>
<pubDate>Fri, 12 Aug 2016 13:53:26 +0300</pubDate>
<author>Uzix</author>
</item><item><title><![CDATA[Применение m4 для генерации конфигурации]]></title>
<link>http://err200.net/notes/43/</link>
<comments>http://err200.net/notes/43/</comments>
<description><![CDATA[В данной заметке я хочу рассказать о существовании замечательной утилиты - макропроцессора m4.<br/><i>Заметка носит ознакомительный характер и не ставит целью описание нюансов m4 (RTFM!).</i><br/><cut><br/>Любой *nix-системный администратор сталкивался с проблемой громоздкости и избыточности конфигурационных файлов. Так, некоторое ПО (php-fpm) не поддерживает наследование секций конфигурации (хотите новый пул в php-fpm, отличающийся лишь директорией и пользователем? будьте добры скопипасьте и все остальные 9000 параметров для нового пула). Другое же ПО (nagios) - несмотря на мощные возможности наследования - имеет довольно громоздкий формат конфигурационных файлов.<br/><br/>Обычно подобные проблемы решают двумя путями: скрипты-генераторы конфигов и системы управления конфигурацией (ansible, puppet). Первый подход мне не нравится своей... неэлегантностью что-ли. О втором же подходе (до некоторой поры) можно сказать - "из пушки по воробьям".<br/><br/>Чем же может помочь m4? m4 - ПО, предназначенное для преобразования входных текстовых данных согласно некоторому набору правил (макросов). Сами макросы могут быть как предопределёнными в m4, так и определяемыми во входных данных (файле конфигурации).<br/><br/>К слову, количество "мусорных" строк в конфигурации Nagios вгоняло меня в уныние с первых дней знакомства с системой. Поэтому, узнав о существовании m4, я  решил опробовать этот инструмент именно на Nagios. И результат превзошёл все мои ожидания.<br/>Вот пример старой конфигурации:<br/><pre>define host {<br/>    use                 generic-server<br/>    host_name           my-server-1234<br/>    address             1.2.3.4<br/>}<br/><br/>define service {<br/>    use                 service-ping<br/>    host_name           my-server-1234<br/>}<br/><br/>define service {<br/>    use                 service-ssh<br/>    host_name           my-server-1234<br/>    _port               2222<br/>}<br/><br/>define service {<br/>    use                 service-tcp<br/>    host_name           my-server-1234<br/>    service_description SSH honeypot<br/>    _port               22<br/>}<br/><br/>define service {<br/>    use                 service-users<br/>    host_name           my-server-1234<br/>}<br/><br/>... и ещё около сотни строк в таком же духе<br/></pre><br/><br/>А вот новая:<br/><pre>add( my-server-1234, 1.2.3.4, (), (<br/>    ( ping ),<br/>    ( ssh, _port 2222 ),<br/>    ( tcp, service_description SSH honeypot, _port 22 ),<br/>    ( users ),<br/>    ( procs ),<br/>    ( mem ),<br/>    ( load ),<br/>    ( conns ),<br/>    ( disk ),<br/>    ( proc, service_description App servers, _warn 1:1, _crit 1:1, _proc java ),<br/>    ( filelines, service_description App users, _file /var/db/app/usersdump.txt, _pattern Nobody online, _args -v ),<br/>))</pre><br/><br/>Выгода, как мне кажется, очевидна. На минимальное изучение m4, составление макросов, и переписывание конфигурации Nagios (~100 сервисов) ушло менее одного дня. Более объёмные конфигурации можно переписывать небольшими порциями - весь текст в файле, не являющийся макросами m4, будет скопирован на выход без изменений.<br/><br/>Помимо очевидного плюса (сокращение писанины и копипасты), данный подход имеет парочку неприятных минусов:<ul><li>После редактирования конфигурации необходимо не забывать запускать m4;</li><li>Некоторые символы и слова требуют специального внимания т.к. могут быть интерпретированы в m4.</li></ul><br/>На мой взгляд, данные минусы не являются критичными, и m4 заслуживает быть добавленным в арсенал системного администратора.]]></description>
<pubDate>Sun, 05 Jun 2016 17:43:29 +0300</pubDate>
<author>Uzix</author>
</item><item><title><![CDATA[ГОСТ шифр]]></title>
<link>http://err200.net/notes/42/</link>
<comments>http://err200.net/notes/42/</comments>
<description><![CDATA[В данной статье решается задача создания защищённого соединения с сервером госзакупок с минимизацией необходимости дальнейшей поддержки решения.<br/><cut><br/>1. Ставим OpenSSL версии >= 1.0.1 (с этой версии в основном дереве исходных кодов появилась поддержка ГОСТ), её заголовочные файлы, компилятор.<br/><br/>2. По умолчанию поддержка ГОСТ выключена. Для её включения в начало файла /etc/ssl/openssl.cnf перед первой секцией прописываем:<br/><pre>openssl_conf = openssl_def<br/><br/>[openssl_def]<br/>engines = engine_section<br/><br/>[engine_section]<br/>gost = gost_section<br/><br/>[gost_section]<br/>engine_id = gost<br/>dynamic_path = /usr/lib/x86_64-linux-gnu/openssl-1.0.0/engines/libgost.so<br/>default_algorithms = ALL<br/>CRYPT_PARAMS = id-Gost28147-89-CryptoPro-A-ParamSet<br/></pre><br/><br/>3. Многие программы (в т.ч. старые версии PHP) не читают конфиг OpenSSL, поэтому их нужно патчить. Т.к. поддерживать патченный PHP довольно накладно, то будем использовать stunnel.<br/><br/>4. stunnel версии 4.55 (последней на момент написания статьи) без патчей тоже не читает конфиг OpenSSL. Распаковываем исходники, патчим их, собираем всё это:<br/><pre>wget http://cryptocom.ru/opensource/stunnel-4.55-cp2.diff<br/>mkdir -p /opt/stunnel-gost/src/<br/>cd /opt/stunnel-gost/src/<br/>tar xzvf ~/stunnel-4.55.tar.gz<br/>patch -p1 <~/stunnel-4.55-cp2.diff<br/>./configure --prefix=/opt/stunnel-gost/<br/>make install<br/></pre><br/><br/><b>UPD:</b> На момент публикации статьи файл с оригинальным патчем более недоступен по указанной ссылке. Посему выкладываю его здесь:<br/><pre>diff -Nur -X - stunnel-4.55/src/ssl.c stunnel-gost/src/ssl.c<br/>--- stunnel-4.55/src/ssl.c      2012-08-10 01:44:18.000000000 +0400<br/>+++ stunnel-gost/src/ssl.c     2015-08-19 16:01:41.000000000 +0300<br/>@@ -59,6 +59,9 @@<br/> }<br/> <br/> int ssl_configure(GLOBAL_OPTIONS *global) { /* configure global SSL settings */<br/>+    OPENSSL_config(NULL);<br/>+    OpenSSL_add_all_algorithms();<br/>+    SSLeay_add_ssl_algorithms();<br/> #ifdef USE_FIPS<br/>     if(FIPS_mode()!=global->option.fips) {<br/>         RAND_set_rand_method(NULL); /* reset RAND methods */<br/></pre><br/><br/>5. Прописываем в  /opt/stunnel-gost/etc/stunnel/stunnel.conf:<br/><pre>foreground = yes<br/>debug = 6<br/>setuid = proxy<br/>setgid = proxy<br/>pid = /tmp/stunnel.pid<br/><br/>socket = l:TCP_NODELAY=1<br/>socket = r:TCP_NODELAY=1<br/><br/>verify = 3<br/>cert = /opt/stunnel-gost/etc/stunnel/clientcert.pem<br/>key = /opt/stunnel-gost/etc/stunnel/clientprivatekey.pem<br/>CAfile = /opt/stunnel-gost/etc/stunnel/servercert.pem<br/><br/>[n1]<br/>client = yes<br/>accept  = 1443<br/>connect = int223.zakupki.gov.ru:443<br/>ciphers = GOST2001-GOST89-GOST89<br/>TIMEOUTclose = 0<br/><br/>[n2]<br/>client = yes<br/>accept  = 1444<br/>connect = intfz04.lanit.ru:443<br/>ciphers = GOST2001-GOST89-GOST89<br/>TIMEOUTclose = 0<br/></pre><br/><br/>6. Создаём init-файл для upstart (/etc/init/stunnel-gost.conf):<br/><pre>start on runlevel [2345]<br/>stop on runlevel [016]<br/>respawn<br/>respawn limit 10 5<br/>setuid root<br/>setgid root<br/>chdir /opt/stunnel-gost<br/>exec /opt/stunnel-gost/bin/stunnel /opt/stunnel-gost/etc/stunnel/stunnel.conf<br/></pre><br/><br/>Готово. Все запросы на http://127.0.0.1:1443/ будут проксироваться на https://int223.zakupki.gov.ru:443/.]]></description>
<pubDate>Tue, 17 May 2016 10:06:30 +0300</pubDate>
<author>Uzix</author>
</item>

</channel></rss>