суббота, 31 мая 2014 г.

HTTPS is evil

HTTPS зло. Это утверждает Брюс Шнайер и я с ним полностью согласен.

Знаете, что может быть хуже реальной опасности? Иллюзия безопасности.

За последние 20 лет SSL/HTTPS прошел большой путь от чисто академической разработки до повсеместного применения. 

Теперь хомяки видят в адресной строке браузера замочек и успокаиваются - "АНБ но пасаран, хацкеры но пасаран":


Вы так думаете, золотые мои? Вы правда думаете, что ваши данные в полной безопасности?

У меня для вас очень плохие новости, мои мохнатые друзья.

Вы не в безопасности. Это вам лишь кажется.

Позвольте вам кое-что объяснить языком телепередач.

Вы знаете, как это устроено и работает?

Да, ваше соединение чем-то зашифровано. 

Неким шифром, качество которого вам лично неизвестно и проверить которое лично вы не в состоянии.

Да, ваше соединение кем-то удостоверено. 

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

И мы как бы верим, правда? Нам же надо верить во что-то, пусть даже в бога?

Ошибочка, мои золотые.

Хотя несимметричная криптография, лежащая в основе SSL/HTTPS является довольно сносной защитой, и даже позволяет с приличной степенью надежности выполнять аутентификацию, проблема не в ней, а в том, как она используется.

Принцип этого использования следующий.

Алиса хочет приватно писать Бобу. Но она лично с ним не знакома. Однако оба, Алиса и Боб, знают (или думают, что знают) - некоего Джона, который является адвокатом-юристом-нотариусом. И который готов - за скромную плату - удостоверить личности Алисы и Боба друг другу.

Мало того, этот Джон готов - мамой клянусь, что я честный адвокат! - запечатать письма Алисы и Боба друг другу своей печатью, гарантирующей - мамой клянусь! - неприкосновенность переписки Алисы и Боба третьим лицам:

-Ребята, - говорит Джон - благодаря моим личным связям с Теми, Кому Надо, я могу гарантировать, что письма с моей печатью не будут вскрываться, когда правительственные или прочие агенты будут грабить корованы^Wофициально досматривать почтальонов.

Еще не смешно, нет?

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

Ну так вот. Именно так оно и работает.

Сомневаетесь? Посмотрите, какая самая читаемая статья в этом блоге:



Это означает, что любопытных мальчуганов Хочу-Все-Знать-И-Чтобы-Жертва-Ничего-Не-Узнала даже не рожают - их просто мечут, как икру.

И, самое веселое - технология это вполне себе позволяет.

Перевожу на язык телепередач - КТО УГОДНО в вашем офисе или в вашем провайдере интернет может стоять посредине, расшифровывать ваш зашифрованный трафик, читать его, снова зашифровывать - в обеих направлениях - и ВЫ НИЧЕГО ДАЖЕ НЕ УЗНАЕТЕ.

Знаете, в чем проблема? Говоря умными словами - если в секретной переписке есть третье лицо - там может быть и четвертое, и пятое, и сколько угодно еще.

Перефразируя известную немецкую поговорку - "Что знают трое - то знает и свинья".

Нет, все это прикрыто самыми благими душевными порывами - борьба с международным терроризмом, итд. итп.

Только вот с правом на охрану частной жизни это не имеет ничего общего. Как я сказал в предыдущей статье, because we can.

Итак, есть Алиса, есть Боб, есть Джон.

Алиса и Боб передают свои ключи от переписки Джону, Джон удостоверяет их подписями и печатями. И Алиса с Бобом пребывают в блаженном неведении, что их переписка в надежных руках.

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

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

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

Какую программу вы - лично вы - используете чаще всего? Бьюсь об заклад - это браузер.

Браузеры поднимают хай, если получают самоподписной сертификат SSL. Все. До единого. "Небезопасно! Валим отсюда! Та сторона не удостоверена Мамой-Клянусь-Джоном!"

А теперь слушайте сюда, мои золотые.

Брюс еще 20 лет назад сказал (вольный перевод) - "Только если Алиса и Боб ЛИЧНО обменялись своими ключами к переписке, зная друг друга ЛИЧНО, и ЛИЧНО удостоверили ключи друг друга - лишь в этом случае они могут быть уверены в конфиденциальности и аутентичности своей переписки".

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

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

В этой ситуации каждый выпустивший такой сертификат сам себе Джон и вы можете принять сертификат или отказаться от него. Вы решаете. Не адвокат Джон из Нотариальной Конторы Имени DigiNotar или Национального Удостоверяющего Центра Республики Гурундувайю.

Намек ясен?

Потому что есть огромные (и обоснованные!) сомнения в надежности третьей заочно доверяемой стороны - кем бы она ни была, хоть собственным правительством! (особенно если это правительство!)

Хотите хоть какой-то приватности и защиты - ничего лучше PGP (использующей, кстати говоря, точно ту же технологию, что и SSL - однако подчиненную совершенно иной парадигме) по сей день не придумали.

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

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

Которые есть у всякого человека. Если он не полный идиот. И живет не в мире эльфов.

PS. А вы, господа правоохранители - хорош уже получать везде и всюду читерские преимущества. Учитесь работать в рамках конституционных прав граждан. Потому что в вашей честности и чистоте помыслов мы сомневаемся. А также потому, что ни из каких законов не должно быть исключений . Ни для кого. Раз уж это законы. А конституция - основной закон.

Я понятно выражаюсь?

среда, 28 мая 2014 г.

Because we can

Вот кто бы сомневался, что приснопамятный пакет так называемых законов, принятых бешеным принтером в стахановском темпе, будут использовать на всю катушку

Because we can. 

Если ружье есть, и висит на стене, из него обязательно надо стрелять.

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

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

Только Кванмён. Только хардкор.

вторник, 27 мая 2014 г.

Solaris: Resource capping

После пересборки Squid 2.7 в полностью 64-битном режиме я столкнулся с тем, что памяти стало как-то неуютно не хватать. Более того - стал появляться свопинг. На машине, где его прежде не было. Кроме чисто символического.


Это само по себе достаточно неприятное явление, кроме того, на сервере стоит ZFS (с ограничением ARC до номинального 1 Гб). И провоцирует эпизодический IO.

Изучение вопроса напомнило вот об этом: http://wiki.squid-cache.org/SquidFaq/SquidMemory

Однако еще более тщательное изучение показало, что речь идет не об утечках памяти. А о склонности сквида выползать за границы cache_memory. Особенно с учетом дочерних процессов - AIO, редиректоров итп. Это вовсе не вся память, которую использует Squid.

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


Обратите внимание: cache_mem и memory_pool_limit вы можете скорректировать по своей необходимости (в зависимости от вашего объема доступной физической памяти на сервере).

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

Первое действие - собрать Squid с dlmalloc, причем сама библиотека должна собираться thread aware:


'--enable-dlmalloc' 'CFLAGS=-DMSPACES -DUSE_LOCKS'


Кроме того, у нас есть rcapd. Зададим необходимые параметры и запустим службу:

root @ ktulhu / # rcapadm -c 95 -E

Получаем следующую конфигурацию:



95% в случае RCAP означает, что реальный resource capping начнется лишь при заполнении физической памяти на 95% (документация rcapd совершенно четко объясняет работу службы). Значение по умолчанию - 0, что означает "capping всегда действует, если заданы ограничения".

Кроме этого, необходимо явно задать ограничения пользователю/группе/процессу с помощью /etc/project:

/etc/project не редактируется руками, для его модификации используются команды projadd/projmod/projdel. В нашем случае используется команда:

projadd -n -c "Squid processes" -U squid -G squid -p 100 -K rcap.max-rss=1500MB user.squid


Для того, чтобы ограничение начало работать, необходимо обеспечить запуск процессов контролируемого пользователя посредством команды newtask:


Так как процессы нашего пользователя управляются SMF, модифицируем контролирующий скрипт (управляющий метод):



Как видно из скрипта, в случае, если запись в /etc/project создана, процесс будет запущен посредством newtask с использованием созданного проекта и его ресурсных ограничений, которые и будет контролировать rcapd.

Чтобы убедиться, что все сделано правильно и rcapd работает (а также для мониторинга rcap), используется штатная утилита rcapstat:


Вызванная без параметров, она будет использовать установки rcap из /etc/rcap.conf:


и будет выполняться непрерывно до нажатия Ctrl+C.

Stripped/non-stripped ELF

Я ничего не буду говорить :) Просто оставлю это здесь:



понедельник, 19 мая 2014 г.

Аналог which в CMD.EXE

В *NIX-подобных системах есть очень удобная штука поиска программ с полным путем в PATH - which. 

Как это ни забавно, нечто подобное присутствует и в Windows:

C:\Windows\System32\where.exe

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

В юниксах это делается тривиально:

ECHO=`which echo`

А теперь, внимание - вопрос.

Как то же самое проделать в CMD? ;)

Да, я знаю, гугл приводит в кучу намеков. Но где работоспособное решение? ;)

Вот оно:

rem Check dig installed
for /f "delims=" %%a in ('where dig') do @set dig=%%a
if /I "%dig%"=="" echo Dig not found. If installed, add path to PATH environment variable. & exit 1
echo Dig found: %dig%

echo Warming up cache by MRU domains...
rem %dig% -f my_domains 1>nul 2>nul
rem echo Done.


Мы ищем программу (в нашем случае dig) в путях PATH, если находим - то присваиваем ее одноименной переменной, которую затем и вызываем.

Скажете, нафиг так сложно?

Первое. Попробуйте получить то же самое иным путем. ;)

Второе. А если программа стоит в директории с пробелом, например, C:\Program Files (x86)? ;)

Так надо. :) Это универсально и это - работает. В отличие от всех прочих частичных решений.

пятница, 9 мая 2014 г.

Munin: Processes memory monitoring plugin

Мне тут потребовалось мониторить память процессов определенных по списку. В Solaris.

Я очень уважаю Munin. Это отличная и настраиваемая штука под большинство систем. Для тех, кто не боится скриптов. Он даже есть в Opencsw.

Однако входящий в состав multips_memory не работает на Solaris. Никак.

Пришлось провести поиски контрибьюторских плагинов. Я нашел много хлама - но ничего рабочего.

Пришлось писать самостоятельно. Попутно выяснилось, что GNU ps и ps большинства юниксов - это две огромные разницы.

В финале каторжных интеллектуальных трудов родился плагин, работающий под большинством *NIX.


#!/bin/bash
#
# (c) 2010, Rodrigo Sieiro
# Based on the 'du_multidirs' plugin, written by Christian Kujau
# Modified for Solaris by Y.Voinov (c) 2014
# Will be work on most *nix, not only Linux.
#
# Note 1: Processes will search by comm column of ps utility.
# So, if you need monitor single process, set it up in config as
# full command line (grep uses).
# Note 2: We use bash. With born script got an error.
#
# Configure it by using the processes env var,and
# mode - set to rss or vsz (for vsize)
#
# [proc_mem]
# env.processes munin-node httpd sbin/squid squidguard unbound
# env.mode vsz
#

. $MUNIN_LIBDIR/plugins/plugin.sh

if [ "$1" = "autoconf" ]; then
echo yes
exit 0
fi

# Defaults if no configuration
processes=${processes:="munin-node"}
mode=${mode:="rss"}


if [ "$1" = "config" ]; then
echo 'graph_title Memory usage by process'
echo 'graph_args --base 1024 -l 0'
echo 'graph_vlabel Bytes'
echo 'graph_category processes'
echo 'graph_info This graph shows the memory usage of several processes'

for proc in $processes; do
echo "$proc.label $proc"
done
exit 0
fi

for proc in $processes; do
echo "$proc.value " `ps -eo $mode,comm | grep $proc | grep -v grep | awk 'BEGIN { sum = 0 } NR >= 1 { sum += $1 }; END { print sum * 1024 }'`
done

Скрипт простейший. Для его работы также пришлось исправить plugins.sh - в нем отсутствовал заголовок !#/bin/bash, кроме того, мне не удалось заставить все это работать на Борне - пришлось оставить шеллом Баш.

Скачать плагин, для не желающих копипастить, можно отсюда: proc_mem.

Для него требуется конфигурация в plugins.conf:

[proc_mem]
env.processes httpd sbin/squid squidGuard squidclamav clamd unbound tor
env.mode vsz


Список процессов (надо задавать уникальное выражение для имени процесса, поскольку для поиска используется grep) и режим мониторинга - rss либо vsz (vsize), по умолчанию используется rss. Для Solaris 10 надо задавать vsize - проверяется посредством процессных утилит системы, размер rss менее точно показывает реальную память процессов. Данный плагин написан максимально универсально и будет работать практически на всех *NIX-системах, в которых установлен Bash.

Вуаля:


Пользуйтесь.

вторник, 6 мая 2014 г.

Windows 7 + Unbound + dnscrypt

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

Как ни странно, аналогичный (хотя и меньший) выигрыш можно получить и на домашнем интернете (кэширующие персональные прокси перестали развиваться после 2006-2008 года).

Однако, если вы посмотрите на среднестатистичекую веб-страницу, то увидите кучу ссылок, каждая из которых при загрузке резловится. Есть ли разница, откуда берутся DNS-ответы? Есть. Выиграть можно до нескольких секунд при загрузке каждой страницы, если брать данные из уже прогретого кэша локального рекурсора. Особенно заметен эффект на WiFi и 3G/GPRS подключениях. Даже субьективно скорость загрузки выше.

Итак, возьмем Unbound для Windows. Скомбинировать его можно как с любыми публичными или провайдерскими DNS в качестве форвардеров, так и с нашим любимым dnscrypt.

Сразу оговорюсь - версия Unbound для Windows не имеет в своем составе утилиты unbound-control-setup (это скрипт), и для конфигурирования управления вам придется выполнять эту команду и брать результирующие файлы с *NIX-системы. Либо воспользоваться переписанной мной версией юниксового скрипта (unbound-control-setup.cmd).

Замечание. Данная версия unbound-control-setup требует установленного OpenSSL Win32/Win64, путь к бинарникам openssl должен быть добавлен в переменную окружения PATH пользователя или компьютера.

Кроме того, написание config-файла несколько отличается (я бы сказал, существенно отличается) по допустимым опциям и их значениям на Windows и *NIX.

Установим Unbound. рекомендую сразу же открыть консоль с правами администратора - она понадобится.

Откроем редактор и начинаем править конфигурационный файл (скачать его можно отсюда). Кстати, лежит он, в отличие от *NIX, в директории программы (то бишь в C:\Program Filex (x86)\Unbound на 64-битных системах и в CL\Program Files\Unbound в 32-битных).


# Unbound configuration file on windows.
# See example.conf for more settings and syntax


server:
# verbosity level 0-4 of logging
verbosity: 0

# if you want to log to a file use
#logfile: "C:\unbound.log"

# on Windows, this setting makes reports go into the Application log
# found in ControlPanels - System tasks - Logs 
use-syslog: yes
num-threads: 2
cache-min-ttl: 86400

do-not-query-localhost: no
prefetch: yes
minimal-responses: yes

include: "C:\Program Files (x86)\Unbound\unbound_ad_servers" 

# Remote control config section. 
remote-control:
# Enable remote control with unbound-control(8) here.
# set up the keys and certificates with unbound-control-setup.
control-enable: yes

# what interfaces are listened to for remote control.
# give 0.0.0.0 and ::0 to listen to all interfaces.
control-interface: 127.0.0.1
# control-interface: ::1

# port number for remote control operations.
control-port: 8953

# unbound server key file.
server-key-file: "C:\Program Files (x86)\Unbound\unbound_server.key"

# unbound server certificate file.
server-cert-file: "C:\Program Files (x86)\Unbound\unbound_server.pem"

# unbound-control key file.
control-key-file: "C:\Program Files (x86)\Unbound\unbound_control.key"

# unbound-control certificate file.
control-cert-file: "C:\Program Files (x86)\Unbound\unbound_control.pem"

forward-zone:
name: "."
# forward-addr: 127.0.0.1@5553
forward-addr: 8.8.4.4@53
forward-addr: 8.8.8.8@53

server: auto-trust-anchor-file: "C:\Program Files (x86)\Unbound\root.key"

И не забудьте перезапустить сервис unbound:


и включить в качестве сервера DNS локальный хост:



Некоторые пояснения.

Параметр num-threads определяется вами по количеству ядер процессора - ну или по количеству желаемых тредов. Минимальный TTL для максимального выигрыша от применения рекурсора ставим в наибольшее возможное значение - т.е. сутки. Секцию remote-control включаем только если у вас есть созданные сертификаты для управления, в противном случае закомментируйте ее целиком. Список unbound_ad_servers нужно предварительно создать скриптом, который я приведу ниже и, желательно, задание обновления этого списка (вызовом скрипта) забить в Планировщик заданий с интервалом хотя бы в 1 неделю.

Скрипт обновления ad-серверов (Windows-версия):


@Echo off
rem Convert the Yoyo.org anti-ad server listing
rem into an unbound dns spoof redirection list.
rem Written by Y.Voinov (c) 2014

rem Note: Wget required!

rem Variables
set prefix="C:\Program Files (x86)"
set dst_dir=%prefix%\Unbound
set work_dir=%TEMP%
set list_addr="http://pgl.yoyo.org/adservers/serverlist.php?hostformat=nohtml&showintro=1&startdate%5Bday%5D=&startdate%5Bmonth%5D=&startdate%5Byear%5D="

rem Check Wget installed
for /f "delims=" %%a in ('where wget') do @set wget=%%a
if /I "%wget%"=="" echo Wget not found. If installed, add path to PATH environment variable. & exit 1
echo Wget found: %wget%

%wget% -O %work_dir%\yoyo_ad_servers %list_addr%

del /Q /F /S %dst_dir%\unbound_ad_servers

for /F "eol=; tokens=*" %%a in (%work_dir%\yoyo_ad_servers) do (
echo local-zone: %%a redirect>>%dst_dir%\unbound_ad_servers
echo local-data: "%%a A 127.0.0.1">>%dst_dir%\unbound_ad_servers
)

echo Done.
rem  then add an include line to your unbound.conf pointing to the full path of
rem  the unbound_ad_servers file:
rem
rem   include: $dst_dir/unbound_ad_servers
rem



Написан на основе своего юниксового варианта от calomel.org. Требует установленного GNU Wget и может потребовать модификации переменной prefix в зависимости от разрядности вашей Windows.

Настоятельно советую поставить его в автоматически выполняемое задание:


Дело в следующем. Это очень хороший список ad-серверов, включающий в себя не только зарубежные сайты и сети, но также и почти всю рекламу Рунета. Чем хорош такой метод блокирования - вы не грузите данных с этих сайтов. Совсем. Сильно экономя трафик. Что, может быть, и пофигу на проволочном или оптическом безлимите, но совершенно не безразлично на WiFi или, тем более, на 3G/GPRS - где трафик стоит денег.

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

Вам может пригодиться скрипт сохранения на диске и последующей загрузки кэша, как и на *NIX.

Вот он:

@echo off
rem --------------------------------------------------------------
rem -- DNS cache save/load script
rem --
rem -- Version 1.0
rem -- By Yuri Voinov (c) 2014
rem --------------------------------------------------------------

rem Variables
set prefix="C:\Program Files (x86)"
set program_path=%prefix%\Unbound
set uc=%program_path%\unbound-control.exe
set fname="unbound_cache.dmp"

rem Check Unbound installed
if exist %uc% goto start
echo Unbound control not found. Exiting...
exit 1

:start

set arg=%1

if /I "%arg%" == "-h" goto help

if "%arg%" == "" (
echo Loading cache from %program_path%\%fname%
type %program_path%\%fname%|%uc% load_cache
goto end
)

if /I "%arg%" == "-s" (
echo Saving cache to %program_path%\%fname%
%uc% dump_cache>%program_path%\%fname%
echo ok
goto end
)

if /I "%arg%" == "-l" (
echo Loading cache from %program_path%\%fname%
type %program_path%\%fname%|%uc% load_cache
goto end
)

if /I "%arg%" == "-r" (
echo Saving cache to %program_path%\%fname%
%uc% dump_cache>%program_path%\%fname%
echo ok
echo Loading cache from %program_path%\%fname%
type %program_path%\%fname%|%uc% load_cache
goto end
)

:help
echo Usage: unbound_cache.cmd [-s] or [-l] or [-r] or [-h]
echo.
echo l - Load - default mode. Warming up Unbound DNS cache from saved file. cache-ttl must be high value.
echo s - Save - save Unbound DNS cache contents to plain file with domain names.
echo r - Reload - reloadind new cache entries and refresh existing cache
echo h - this screen.
echo Note: Run without any arguments will be in default mode.
echo       Also, unbound-control must be configured.
exit 1

:end

Как и предыдущий скрипт, он требует возможной корректировки переменной prefix и требует, чтобы был сконфигурирован unbound-control.

Соответственно, перед рестартом Unbound вы можете сохранить кэш на диске, а после оного загрузить его обратно. :)

Вернемся к конфигурационному файлу.

Самая важная его часть, пожалуй - это секция форвардеров.

В простейшем случае можете навести ее на GoogleDNS или OpenDNS и наслаждаться. Но во многих случаях может оказаться практично поженить его также с dnscrypt.

Вам потребуется dnscrypt для Win32. Его надо распаковать, скажем, в C:\Program Files и установить сервис:


Одно маленькое замечание. Dnscrypt для Windows конфигурируется через регистри. Рег-файл для установки нужных нам параметров (шаблон, вы можете подправить его по своим надобностям, параметры описаны здесь) вот:

Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\dnscrypt-proxy\Parameters]
"ProviderKey"="B735:1140:206F:225D:3E2B:D822:D7FD:691E:A1C3:3CC8:D666:8D0C:BE04:BFAB:CA43:FB79"
"ProviderName"="2.dnscrypt-cert.opendns.com"
"ResolverAddress"="208.67.220.220:443"
;"ResolverName"="opendns"
;"ResolverList"="C:\Program Files (x86)\dnscrypt-proxy-win32\dnscrypt-resolvers.csv"
"LocalAddress"="127.0.0.1:5553"
"TCPOnly"=dword:00000000
"MaxActiveRequests"=dword:00000200


Параметры приведены для текущей версии dnscrypt Win32 - 1.3.3. Параметры для версии 1.4.0 (еще не вышла на момент написания статьи) закомментированы. Обратите внимание, что dnscrypt будет слушать запросы на порту 5553.

Загрузите этот рег-файл и перезапустите dnscrypt:


Можете убедиться при помощь telnet, что слушается именно порт 5553.

Теперь можете раскомментировать строку 

# forward-addr: 127.0.0.1@5553

в конфигурации unbound, перезапустить его и получать удовольствие.;)

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

Важное замечание. "Интернет дома" от Beeline очень не любит, когда Unbound стоит на машине, устанавливающей VPN-соединение на провайдера и раздающей интернет. Я не копал глубоко, но полагаю, что это как-то связано с механизмом аутентификации VPN-провайдера, требующего собственных DNS. Это, конечно, обидно - потому что выигрыш был бы наибольший именно в случае кэширования DNS на раздающей интернет машине, однако решить данную проблему пока не удалось.

Однако вам никто не мешает поставить Unbound на другие машины домашней сети.

UPDATE Скрипты приняли в дерево исходников Unbound. Со следующей версии будут в составе дистрибутива.

воскресенье, 4 мая 2014 г.

Squid + SquidGuard: Блокирование TLD

Не знаю, как вам - а лично мне до смерти надоело ежедневно плодящиеся в домене .tv сайтцы с онлайновым видео руками заносить в бан-лист и отсылать урлы немцам для включения в бан-лист webtv.

Решил я забанить их кардинально и накрыть медным тазом весь TLD (Top Level Domain) .tv . Ибо нефиг на работе смотреть фильмы, работать надо. Дома и за свои деньги - что угодно, хоть в гамаке на лыжах. А тут - не надо. 

Все бы, казалось, просто. Напиши регулярку вида \.tv$, добавь ее в expressions в SquidGuard - и вуаля. 

Фиг вам, изба индейская.

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

Гугл-фу не принесло традиционных результатов, поэтому пришлось медитировать. 

Удалось намедитировать два способа.

Способ первый, грубиянский.

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

# Block top level domains
acl block_tld dstdom_regex \.(tv|xxx)$
http_access deny block_tld

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

Способ второй, правильный.

Вы-таки будете смеяться. Но забанить домен первого уровня в SquidGuard не просто - а очень просто.

Надо просто тупо написать в одной из баз по вашему выбору:


причем в файле domains. Не надо добавлять домены в expressions или urls - работать не будет. Добавьте их в domains. Скомпилируйте базы заново, перезапустите сквид - и привет, Verboten!


Можете добавить туда и другие домены первого уровня и перебанить к чертовой матери половину интернета. :)))))))

PS. Коллеги подсказывают - не забудьте забанить urlshorteners, а то будут обходить блок при помощи goo.gl. ;)

четверг, 1 мая 2014 г.

Cisco DNS Proxy + Unbound + dnscrypt

Я уже писал, как вынужден был в подобной связке использовать BIND. Однако, полугодовая эксплуатация показала некоторые недостатки использования BINDа.

Первый. BIND работает по правилам, не позволяя переопределять TTL записей. Что приводит, при нерегулярной нагрузке, к быстрому вымораживанию кэша. Т.е. достаточно пары неактивных выходных - и в понедельник кэш ледяной, как ад японцев.

Второй. Сборка BIND от OpenCSW неожиданно оказалась склонна к внезапному и полному размораживанию кэша (т.е. он прекращал кэширование, полностью опустошал кэш и без перезапуска отказывался кэшировать вообще).

Благо, к этому времени поспела новая версия Unbound - 1.4.22, в которой баги были пофиксены и она стала пригодной к применению. Практически сразу же появилась сборка на OpenCSW.

Так как на Windows Unbound показал превосходные результаты в качестве кэша и рекурсора, развернем его вместо BIND на нашей связке.

Опустим как самоочевидные шаги по установке пакета с OpenCSW.

Перейдем непосредственно к конфигурации.

Конфигурационный файл в /etc/opt/csw/unbound заменим на собственный:

#Use this to include other text into the file.
#include: "otherfile.conf"

# The server clause sets the main parameters.
server:
# whitespace is not necessary, but looks cleaner.

# verbosity number, 0 is least verbose. 1 is default.
verbosity: 1

# print statistics to the log (for every thread) every N seconds.
# Set to "" or 0 to disable. Default is disabled.
# statistics-interval: 0

# enable cumulative statistics, without clearing them after printing.
# statistics-cumulative: no

# enable extended statistics (query types, answer codes, status)
# printed from unbound-control. default off, because of speed.
extended-statistics: yes

# number of threads to create. 1 disables threading.
num-threads: 4

# specify the interfaces to answer queries from by ip-address.
# The default is to listen to localhost (127.0.0.1 and ::1).
# specify 0.0.0.0 and ::0 to bind to all available interfaces.
# specify every interface[@port] on a new 'interface:' labelled line.
# The listen interfaces are not changed on reload, only on restart.
# interface: 192.0.2.153
# interface: 192.0.2.154
# interface: 192.0.2.154@5003
# interface: 2001:DB8::5
interface: 127.0.0.1@53
interface: 192.168.200.3@53

# enable this feature to copy the source address of queries to reply.
# Socket options are not supported on all platforms. experimental.
# interface-automatic: no

# port to answer queries from
# port: 53

# specify the interfaces to send outgoing queries to authoritative
# server from by ip-address. If none, the default (all) interface
# is used. Specify every interface on a 'outgoing-interface:' line.
# outgoing-interface: 192.0.2.153
# outgoing-interface: 2001:DB8::5
# outgoing-interface: 2001:DB8::6

# number of ports to allocate per thread, determines the size of the
# port range that can be open simultaneously. About double the
# num-queries-per-thread, or, use as many as the OS will allow you.
# outgoing-range: 4096
outgoing-range: 206

# permit unbound to use this port number or port range for
# making outgoing queries, using an outgoing interface.
# outgoing-port-permit: 32768

# deny unbound the use this of port number or port range for
# making outgoing queries, using an outgoing interface.
# Use this to make sure unbound does not grab a UDP port that some
# other server on this computer needs. The default is to avoid
# IANA-assigned port numbers.
# If multiple outgoing-port-permit and outgoing-port-avoid options
# are present, they are processed in order.
# outgoing-port-avoid: "3200-3208"

# number of outgoing simultaneous tcp buffers to hold per thread.
outgoing-num-tcp: 128

# number of incoming simultaneous tcp buffers to hold per thread.
incoming-num-tcp: 128

# buffer size for UDP port 53 incoming (SO_RCVBUF socket option).
# 0 is system default. Use 4m to catch query spikes for busy servers.
# so-rcvbuf: 0
so-rcvbuf: 4m

# buffer size for UDP port 53 outgoing (SO_SNDBUF socket option).
# 0 is system default. Use 4m to handle spikes on very busy servers.
# so-sndbuf: 0
so-sndbuf: 4m

# on Linux(3.9+) use SO_REUSEPORT to distribute queries over threads.
# so-reuseport: no

# EDNS reassembly buffer to advertise to UDP peers (the actual buffer
# is set with msg-buffer-size). 1480 can solve fragmentation (timeouts).
# edns-buffer-size: 4096

# Maximum UDP response size (not applied to TCP response).
# Suggested values are 512 to 4096. Default is 4096. 65536 disables it.
# max-udp-size: 4096

# buffer size for handling DNS data. No messages larger than this
# size can be sent or received, by UDP or TCP. In bytes.
# msg-buffer-size: 65552

# the amount of memory to use for the message cache.
# plain value in bytes or you can append k, m or G. default is "4Mb".
# msg-cache-size: 4m
msg-cache-size: 16m

# the number of slabs to use for the message cache.
# the number of slabs must be a power of 2.
# more slabs reduce lock contention, but fragment memory usage.
# msg-cache-slabs: 8
msg-cache-slabs: 16

# the number of queries that a thread gets to service.
# num-queries-per-thread: 1024

# if very busy, 50% queries run to completion, 50% get timeout in msec
# jostle-timeout: 200

# msec to wait before close of port on timeout UDP. 0 disables.
# delay-close: 0

# the amount of memory to use for the RRset cache.
# plain value in bytes or you can append k, m or G. default is "4Mb".
# rrset-cache-size: 4m
rrset-cache-size: 16m

# the number of slabs to use for the RRset cache.
# the number of slabs must be a power of 2.
# more slabs reduce lock contention, but fragment memory usage.
# rrset-cache-slabs: 4
rrset-cache-slabs: 16

# the time to live (TTL) value lower bound, in seconds. Default 0.
# If more than an hour could easily give trouble due to stale data.
# cache-min-ttl: 0
cache-min-ttl: 86400

# the time to live (TTL) value cap for RRsets and messages in the
# cache. Items are not cached for longer. In seconds.
# cache-max-ttl: 86400

# the time to live (TTL) value for cached roundtrip times, lameness and
# EDNS version information for hosts. In seconds.
# infra-host-ttl: 900

# the number of slabs to use for the Infrastructure cache.
# the number of slabs must be a power of 2.
# more slabs reduce lock contention, but fragment memory usage.
# infra-cache-slabs: 4
infra-cache-slabs: 16

# the maximum number of hosts that are cached (roundtrip, EDNS, lame).
# infra-cache-numhosts: 10000

# Enable IPv4, "yes" or "no".
# do-ip4: yes

# Enable IPv6, "yes" or "no".
# do-ip6: yes

# Enable UDP, "yes" or "no".
# do-udp: yes

# Enable TCP, "yes" or "no".
# do-tcp: yes

# upstream connections use TCP only (and no UDP), "yes" or "no"
# useful for tunneling scenarios, default no.
# tcp-upstream: no

# Detach from the terminal, run in background, "yes" or "no".
# do-daemonize: yes

# control which clients are allowed to make (recursive) queries
# to this server. Specify classless netblocks with /size and action.
# By default everything is refused, except for localhost.
# Choose deny (drop message), refuse (polite error reply),
# allow (recursive ok), allow_snoop (recursive and nonrecursive ok)
# deny_non_local (drop queries unless can be answered from local-data)
# refuse_non_local (like deny_non_local but polite error reply).
# access-control: 0.0.0.0/0 refuse
# access-control: 127.0.0.0/8 allow
# access-control: ::0/0 refuse
# access-control: ::1 allow
# access-control: ::ffff:127.0.0.1 allow
access-control: 127.0.0.0/8 allow_snoop
access-control: 192.168.0.0/16 allow_snoop

# if given, a chroot(2) is done to the given directory.
# i.e. you can chroot to the working directory, for example,
# for extra security, but make sure all files are in that directory.
#
# If chroot is enabled, you should pass the configfile (from the
# commandline) as a full path from the original root. After the
# chroot has been performed the now defunct portion of the config
# file path is removed to be able to reread the config after a reload.
#
# All other file paths (working dir, logfile, roothints, and
# key files) can be specified in several ways:
# o as an absolute path relative to the new root.
# o as a relative path to the working directory.
# o as an absolute path relative to the original root.
# In the last case the path is adjusted to remove the unused portion.
#
# The pid file can be absolute and outside of the chroot, it is
# written just prior to performing the chroot and dropping permissions.
#
# Additionally, unbound may need to access /dev/random (for entropy).
# How to do this is specific to your OS.
#
# If you give "" no chroot is performed. The path must not end in a /.
# chroot: "/etc/opt/csw/unbound"

# if given, user privileges are dropped (after binding port),
# and the given username is assumed. Default is user "unbound".
# If you give "" no privileges are dropped.
username: "unbound"

# the working directory. The relative files in this config are
# relative to this directory. If you give "" the working directory
# is not changed.
# directory: "/etc/opt/csw/unbound"

# the log file, "" means log to stderr.
# Use of this option sets use-syslog to "no".
# logfile: ""

# Log to syslog(3) if yes. The log facility LOG_DAEMON is used to
# log to, with identity "unbound". If yes, it overrides the logfile.
# use-syslog: yes

# print UTC timestamp in ascii to logfile, default is epoch in seconds.
# log-time-ascii: no

# print one line with time, IP, name, type, class for every query.
# log-queries: no

# the pid file. Can be an absolute path outside of chroot/work dir.
# pidfile: "/var/run/unbound.pid"

# file to read root hints from.
# get one from ftp://FTP.INTERNIC.NET/domain/named.cache
# root-hints: ""

# enable to not answer id.server and hostname.bind queries.
# hide-identity: yes

# enable to not answer version.server and version.bind queries.
# hide-version: yes

# the identity to report. Leave "" or default to return hostname.
# identity: ""

# the version to report. Leave "" or default to return package version.
# version: ""

# the target fetch policy.
# series of integers describing the policy per dependency depth.
# The number of values in the list determines the maximum dependency
# depth the recursor will pursue before giving up. Each integer means:
# -1 : fetch all targets opportunistically,
# 0: fetch on demand,
# positive value: fetch that many targets opportunistically.
# Enclose the list of numbers between quotes ("").
# target-fetch-policy: "3 2 1 0 0"

# Harden against very small EDNS buffer sizes.
# harden-short-bufsize: yes

# Harden against unseemly large queries.
# harden-large-queries: yes

# Harden against out of zone rrsets, to avoid spoofing attempts.
# harden-glue: yes

# Harden against receiving dnssec-stripped data. If you turn it
# off, failing to validate dnskey data for a trustanchor will
# trigger insecure mode for that zone (like without a trustanchor).
# Default on, which insists on dnssec data for trust-anchored zones.
# harden-dnssec-stripped: yes

# Harden against queries that fall under dnssec-signed nxdomain names.
# harden-below-nxdomain: no

# Harden the referral path by performing additional queries for
# infrastructure data. Validates the replies (if possible).
# Default off, because the lookups burden the server. Experimental
# implementation of draft-wijngaards-dnsext-resolver-side-mitigation.
# harden-referral-path: no

# Use 0x20-encoded random bits in the query to foil spoof attempts.
# This feature is an experimental implementation of draft dns-0x20.
# use-caps-for-id: no

# Enforce privacy of these addresses. Strips them away from answers.
# It may cause DNSSEC validation to additionally mark it as bogus.
# Protects against 'DNS Rebinding' (uses browser as network proxy).
# Only 'private-domain' and 'local-data' names are allowed to have
# these private addresses. No default.
# private-address: 10.0.0.0/8
# private-address: 172.16.0.0/12
# private-address: 192.168.0.0/16
# private-address: 169.254.0.0/16
# private-address: fd00::/8
# private-address: fe80::/10

# Allow the domain (and its subdomains) to contain private addresses.
# local-data statements are allowed to contain private addresses too.
# private-domain: "localdomain"

# If nonzero, unwanted replies are not only reported in statistics,
# but also a running total is kept per thread. If it reaches the
# threshold, a warning is printed and a defensive action is taken,
# the cache is cleared to flush potential poison out of it.
# A suggested value is 10000000, the default is 0 (turned off).
# unwanted-reply-threshold: 0

# Do not query the following addresses. No DNS queries are sent there.
# List one address per entry. List classless netblocks with /size,
# do-not-query-address: 127.0.0.1/8
# do-not-query-address: ::1

# if yes, the above default do-not-query-address entries are present.
# if no, localhost can be queried (for testing and debugging).
do-not-query-localhost: no

# if yes, perform prefetching of almost expired message cache entries.
prefetch: yes

# if yes, perform key lookups adjacent to normal lookups.
# prefetch-key: no

# if yes, Unbound rotates RRSet order in response.
rrset-roundrobin: yes

# if yes, Unbound doesn't insert authority/additional sections
# into response messages when those sections are not required.
minimal-responses: yes

# module configuration of the server. A string with identifiers
# separated by spaces. "iterator" or "validator iterator"
# module-config: "validator iterator"

# File with trusted keys, kept uptodate using RFC5011 probes,
# initial file like trust-anchor-file, then it stores metadata.
# Use several entries, one per domain name, to track multiple zones.
#
# If you want to perform DNSSEC validation, run unbound-anchor before
# you start unbound (i.e. in the system boot scripts). And enable:
# Please note usage of unbound-anchor root anchor is at your own risk
# and under the terms of our LICENSE (see that file in the source).
# auto-trust-anchor-file: "/etc/opt/csw/unbound/root.key"

# File with DLV trusted keys. Same format as trust-anchor-file.
# There can be only one DLV configured, it is trusted from root down.
# Download http://ftp.isc.org/www/dlv/dlv.isc.org.key
# dlv-anchor-file: "dlv.isc.org.key"

# File with trusted keys for validation. Specify more than one file
# with several entries, one file per entry.
# Zone file format, with DS and DNSKEY entries.
# Note this gets out of date, use auto-trust-anchor-file please.
# trust-anchor-file: ""

# Trusted key for validation. DS or DNSKEY. specify the RR on a
# single line, surrounded by "". TTL is ignored. class is IN default.
# Note this gets out of date, use auto-trust-anchor-file please.
# (These examples are from August 2007 and may not be valid anymore).
# trust-anchor: "nlnetlabs.nl. DNSKEY 257 3 5 AQPzzTWMz8qSWIQlfRnPckx2BiVmkVN6LPupO3mbz7FhLSnm26n6iG9N Lby97Ji453aWZY3M5/xJBSOS2vWtco2t8C0+xeO1bc/d6ZTy32DHchpW 6rDH1vp86Ll+ha0tmwyy9QP7y2bVw5zSbFCrefk8qCUBgfHm9bHzMG1U BYtEIQ=="
# trust-anchor: "jelte.nlnetlabs.nl. DS 42860 5 1 14D739EB566D2B1A5E216A0BA4D17FA9B038BE4A"

# File with trusted keys for validation. Specify more than one file
# with several entries, one file per entry. Like trust-anchor-file
# but has a different file format. Format is BIND-9 style format,
# the trusted-keys { name flag proto algo "key"; }; clauses are read.
# you need external update procedures to track changes in keys.
# trusted-keys-file: ""

# Ignore chain of trust. Domain is treated as insecure.
# domain-insecure: "example.com"

# Override the date for validation with a specific fixed date.
# Do not set this unless you are debugging signature inception
# and expiration. "" or "0" turns the feature off. -1 ignores date.
# val-override-date: ""

# The time to live for bogus data, rrsets and messages. This avoids
# some of the revalidation, until the time interval expires. in secs.
# val-bogus-ttl: 60

# The signature inception and expiration dates are allowed to be off
# by 10% of the signature lifetime (expir-incep) from our local clock.
# This leeway is capped with a minimum and a maximum. In seconds.
# val-sig-skew-min: 3600
# val-sig-skew-max: 86400

# Should additional section of secure message also be kept clean of
# unsecure data. Useful to shield the users of this validator from
# potential bogus data in the additional section. All unsigned data
# in the additional section is removed from secure messages.
# val-clean-additional: yes

# Turn permissive mode on to permit bogus messages. Thus, messages
# for which security checks failed will be returned to clients,
# instead of SERVFAIL. It still performs the security checks, which
# result in interesting log files and possibly the AD bit in
# replies if the message is found secure. The default is off.
# val-permissive-mode: no

# Ignore the CD flag in incoming queries and refuse them bogus data.
# Enable it if the only clients of unbound are legacy servers (w2008)
# that set CD but cannot validate themselves.
# ignore-cd-flag: no

# Have the validator log failed validations for your diagnosis.
# 0: off. 1: A line per failed user query. 2: With reason and bad IP.
# val-log-level: 0

# It is possible to configure NSEC3 maximum iteration counts per
# keysize. Keep this table very short, as linear search is done.
# A message with an NSEC3 with larger count is marked insecure.
# List in ascending order the keysize and count values.
# val-nsec3-keysize-iterations: "1024 150 2048 500 4096 2500"

# instruct the auto-trust-anchor-file probing to add anchors after ttl.
# add-holddown: 2592000 # 30 days

# instruct the auto-trust-anchor-file probing to del anchors after ttl.
# del-holddown: 2592000 # 30 days

# auto-trust-anchor-file probing removes missing anchors after ttl.
# If the value 0 is given, missing anchors are not removed.
# keep-missing: 31622400 # 366 days

# the amount of memory to use for the key cache.
# plain value in bytes or you can append k, m or G. default is "4Mb".
# key-cache-size: 4m

# the number of slabs to use for the key cache.
# the number of slabs must be a power of 2.
# more slabs reduce lock contention, but fragment memory usage.
# key-cache-slabs: 4

# the amount of memory to use for the negative cache (used for DLV).
# plain value in bytes or you can append k, m or G. default is "1Mb".
# neg-cache-size: 1m

# By default, for a number of zones a small default 'nothing here'
# reply is built-in. Query traffic is thus blocked. If you
# wish to serve such zone you can unblock them by uncommenting one
# of the nodefault statements below.
# You may also have to use domain-insecure: zone to make DNSSEC work,
# unless you have your own trust anchors for this zone.
# local-zone: "localhost." nodefault
# local-zone: "127.in-addr.arpa." nodefault
# local-zone: "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa." nodefault
# local-zone: "10.in-addr.arpa." nodefault
# local-zone: "16.172.in-addr.arpa." nodefault
# local-zone: "17.172.in-addr.arpa." nodefault
# local-zone: "18.172.in-addr.arpa." nodefault
# local-zone: "19.172.in-addr.arpa." nodefault
# local-zone: "20.172.in-addr.arpa." nodefault
# local-zone: "21.172.in-addr.arpa." nodefault
# local-zone: "22.172.in-addr.arpa." nodefault
# local-zone: "23.172.in-addr.arpa." nodefault
# local-zone: "24.172.in-addr.arpa." nodefault
# local-zone: "25.172.in-addr.arpa." nodefault
# local-zone: "26.172.in-addr.arpa." nodefault
# local-zone: "27.172.in-addr.arpa." nodefault
# local-zone: "28.172.in-addr.arpa." nodefault
# local-zone: "29.172.in-addr.arpa." nodefault
# local-zone: "30.172.in-addr.arpa." nodefault
# local-zone: "31.172.in-addr.arpa." nodefault
# local-zone: "168.192.in-addr.arpa." nodefault
# local-zone: "0.in-addr.arpa." nodefault
# local-zone: "254.169.in-addr.arpa." nodefault
# local-zone: "2.0.192.in-addr.arpa." nodefault
# local-zone: "100.51.198.in-addr.arpa." nodefault
# local-zone: "113.0.203.in-addr.arpa." nodefault
# local-zone: "255.255.255.255.in-addr.arpa." nodefault
# local-zone: "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa." nodefault
# local-zone: "d.f.ip6.arpa." nodefault
# local-zone: "8.e.f.ip6.arpa." nodefault
# local-zone: "9.e.f.ip6.arpa." nodefault
# local-zone: "a.e.f.ip6.arpa." nodefault
# local-zone: "b.e.f.ip6.arpa." nodefault
# local-zone: "8.b.d.0.1.0.0.2.ip6.arpa." nodefault

# a number of locally served zones can be configured.
# local-zone:
# local-data: ""
# o deny serves local data (if any), else, drops queries.
# o refuse serves local data (if any), else, replies with error.
# o static serves local data, else, nxdomain or nodata answer.
# o transparent gives local data, but resolves normally for other names
# o redirect serves the zone data for any subdomain in the zone.
# o nodefault can be used to normally resolve AS112 zones.
# o typetransparent resolves normally for other types and other names
#
# defaults are localhost address, reverse for 127.0.0.1 and ::1
# and nxdomain for AS112 zones. If you configure one of these zones
# the default content is omitted, or you can omit it with 'nodefault'.
#
# If you configure local-data without specifying local-zone, by
# default a transparent local-zone is created for the data.
#
# You can add locally served data with
# local-zone: "local." static
# local-data: "mycomputer.local. IN A 192.0.2.51"
# local-data: 'mytext.local TXT "content of text record"'
#
# You can override certain queries with
# local-data: "adserver.example.com A 127.0.0.1"
#
# You can redirect a domain to a fixed address with
# (this makes example.com, www.example.com, etc, all go to 192.0.2.3)
# local-zone: "example.com" redirect
# local-data: "example.com A 192.0.2.3"
#
# Shorthand to make PTR records, "IPv4 name" or "IPv6 name".
# You can also add PTR records using local-data directly, but then
# you need to do the reverse notation yourself.
# local-data-ptr: "192.0.2.3 www.example.com"

# service clients over SSL (on the TCP sockets), with plain DNS inside
# the SSL stream. Give the certificate to use and private key.
# default is "" (disabled). requires restart to take effect.
# ssl-service-key: "path/to/privatekeyfile.key"
# ssl-service-pem: "path/to/publiccertfile.pem"
# ssl-port: 443

# request upstream over SSL (with plain DNS inside the SSL stream).
# Default is no. Can be turned on and off with unbound-control.
# ssl-upstream: no

include: "/etc/opt/csw/unbound/unbound_ad_servers"
include: "/etc/opt/csw/unbound/unbound_local"

# Python config section. To enable:
# o use --with-pythonmodule to configure before compiling.
# o list python in the module-config string (above) to enable.
# o and give a python-script to run.
python:
# Script file to load
# python-script: "/etc/opt/csw/unbound/ubmodule-tst.py"

# Remote control config section.
remote-control:
# Enable remote control with unbound-control(8) here.
# set up the keys and certificates with unbound-control-setup.
control-enable: yes

# what interfaces are listened to for remote control.
# give 0.0.0.0 and ::0 to listen to all interfaces.
control-interface: 127.0.0.1
# control-interface: ::1

# port number for remote control operations.
control-port: 8953

# unbound server key file.
server-key-file: "/etc/opt/csw/unbound/unbound_server.key"

# unbound server certificate file.
server-cert-file: "/etc/opt/csw/unbound/unbound_server.pem"

# unbound-control key file.
control-key-file: "/etc/opt/csw/unbound/unbound_control.key"

# unbound-control certificate file.
control-cert-file: "/etc/opt/csw/unbound/unbound_control.pem"

# Stub zones.
# Create entries like below, to make all queries for 'example.com' and
# 'example.org' go to the given list of nameservers. list zero or more
# nameservers by hostname or by ipaddress. If you set stub-prime to yes,
# the list is treated as priming hints (default is no).
# With stub-first yes, it attempts without the stub if it fails.
# stub-zone:
# name: "example.com"
# stub-addr: 192.0.2.68
# stub-prime: no
# stub-first: no
# stub-zone:
# name: "example.org"
# stub-host: ns.example.com.

# Forward zones
# Create entries like below, to make all queries for 'example.com' and
# 'example.org' go to the given list of servers. These servers have to handle
# recursion to other nameservers. List zero or more nameservers by hostname
# or by ipaddress. Use an entry with name "." to forward all queries.
# If you enable forward-first, it attempts without the forward if it fails.
# forward-zone:
# name: "example.com"
# forward-addr: 192.0.2.68
# forward-addr: 192.0.2.73@5355 # forward to port 5355.
# forward-first: no
# forward-zone:
# name: "example.org"
# forward-host: fwd.example.com

forward-zone:
name: "."
forward-addr: 127.0.0.1@5553
# forward-addr: 8.8.4.4@53
# forward-addr: 8.8.8.8@53

Здесь заданы некоторые настройки, которые требуют предварительной подготовки и пояснений.

Параметры рассчитаны на 4-х ядерный сервер Intel, парамерты оптимизированы под минимальные ожидания. В качестве форвардера используется настроенный ранее dnscrypt (обновленная версия 1.4.0). Сконфигурирован unbound-control, сгенерированы серверные ключи и получен ключ валидатора. Настроенный unbound-control нам нужен для работы скрипта обслуживания кэша (в частности, в Unbound возможна такая миленькая штука, как сохранение кэша на диске и его последующая загрузка в память сервера). Кроме того, мы включили сгенерированный (и регулярно обновляемый) файл блокировки ad-серверов (реклама), а точнее, редиректа этих доменов на 127.0.0.1 - что является даже более эффективным средством блокирования рекламы, нежели Squid и его инструментарий. Особенно с учетом автоматизированного регулярного обновления списка этих серверов. Правда, список ориентирован в большей степени на западные сервера, тем не менее, процентов 50 рекламы мы таким образом просто не будем загружать, что есть хорошо.

Обратите внимание, что мы установили минимальное время TTL равное 24 часам, т.е. максимальному времени жизни. Данный параметр будет переопределять ответы форвардинговых серверов и, таким образом, наш кэш большую часть времени будет находиться в разогретом состоянии. Правда, возможен небольшой прокол с DynDNS-серверами и серверами, склонными к перемене адресов. Кроме того, у меня ругается на устаревшие данные DNS сервис freshclam (я заткнул его параметром --no-dns).

Да, и у нас определена локальная зона для серверов инфраструктуры в файле /etc/opt/csw/unbound/unbound_local.

Структура файла следующая:


# locally served zones can be configured for the machines on the LAN.

local-zone: "localdomain." static

local-data: "server1.localdomain. IN A 192.168.2.1"
local-data: "server2.localdomain. IN A 192.168.2.2"


ну и так далее.

Скрипт для скачивания и формирования списка ad-серверов был найден здесь и слегка переписан (выбран другой формат списка, за счет чего удалось избавить скрипт от лишних телодвижений - grep и awk).

Скрипт для получения и обновления списка ad-серверов вот (скачать):


#!/bin/sh
#
# Convert the Yoyo.org anti-ad server listing
# into an unbound dns spoof redirection list.
# Modified by Y.Voinov (c) 2014

# Note: Wget required!

# Variables
dst_dir="/etc/opt/csw/unbound"
work_dir="/tmp"
list_addr="http://pgl.yoyo.org/adservers/serverlist.php?hostformat=nohtml&showintro=1&startdate%5Bday%5D=&startdate%5Bmonth%5D=&startdate%5Byear%5D="

# OS commands
CAT=`which cat`
ECHO=`which echo`
WGET=`which wget`

# Check Wget installed
if [ ! -f $WGET ]; then
echo "Wget not found. Exiting..."
exit 1
fi

$WGET -O $work_dir/yoyo_ad_servers "$list_addr" && \
$CAT $work_dir/yoyo_ad_servers | \
while read line ; \
do \
$ECHO "local-zone: \"$line\" redirect" ;\
$ECHO "local-data: \"$line A 127.0.0.1\"" ;\
done > \
$dst_dir/unbound_ad_servers

echo "Done."
# then add an include line to your unbound.conf pointing to the full path of
# the unbound_ad_servers file:
#
# include: $dst_dir/unbound_ad_servers
#

Его достаточно выполнить один раз, перезапустить Unbound и поставить в cron, скажем, на еженедельное выполнение.

Еще один полезный скриптик, который пригодится нам для сохранения и загрузки кэша Unbound вот (скачать):


#!/sbin/sh
#
# --------------------------------------------------------------
# -- DNS cache save/load script
# --
# -- Version 1.0
# -- By Yuri Voinov (c) 2006, 2014
# --------------------------------------------------------------
#
# ident "@(#)unbound_cache.sh 1.1 14/04/26 YV"
#

#############
# Variables #
#############

# Installation base dir
CONF="/etc/opt/csw/unbound"
BASE="/opt/csw"

# Unbound binaries
UC="$BASE/sbin/unbound-control"
FNAME="unbound_cache.dmp"

# OS utilities
BASENAME=`which basename`
CAT=`which cat`
CUT=`which cut`
ECHO=`which echo`
GETOPT=`which getopt`
ID=`which id`
PRINTF=`which printf`
UNAME=`which uname`

# OS version
OS_VER=`$UNAME -r|$CUT -f2 -d"."`
OS_NAME=`$UNAME -s|$CUT -f1 -d" "`
OS_FULL=`$UNAME -sr`

###############
# Subroutines #
###############

usage_note ()
{
# Script usage note
$ECHO "Usage: `$BASENAME $0` [-s] or [-l] or [-r] or [-h]"
$ECHO
$ECHO "l - Load - default mode. Warming up Unbound DNS cache from saved file. cache-ttl must be high value."
$ECHO "s - Save - save Unbound DNS cache contents to plain file with domain names."
$ECHO "r - Reload - reloadind new cache entries and refresh existing cache"
$ECHO "h - this screen."
$ECHO "Note: Run without any arguments will be in default mode."
$ECHO " Also, unbound-control must be configured."
exit 0
}

check_os ()
{
# OS version check
if [ "$OS_NAME" != "SunOS" ]; then
$ECHO "ERROR: Unsupported OS $OS_NAME. Exiting..."
exit 1
elif [ "$OS_VER" -lt "10" ]; then
$ECHO "ERROR: Unsupported $OS_NAME version $OS_VER. Exiting..."
exit 1
fi
}

root_check ()
{
if [ ! `$ID | $CUT -f1 -d" "` = "uid=0(root)" ]; then
$ECHO "ERROR: You must be super-user to run this script."
exit 1
fi
}

check_uc ()
{
if [ ! -f "$UC" ]; then
$ECHO .
$ECHO "ERROR: $UC not found. Exiting..."
exit 1
fi
}

check_saved_file ()
{
if [ ! -f "$CONF/$FNAME" ]; then
$ECHO .
$ECHO "ERROR: File $CONF/$FNAME does not exists. Save it first."
exit 1
fi
}

save_cache ()
{
# Save unbound cache
$PRINTF "Saving cache in $CONF/$FNAME..."
$UC dump_cache>$CONF/$FNAME
$ECHO "ok"
}

load_cache ()
{
# Load saved cache contents and warmup DNS cache
$PRINTF "Loading cache from saved $CONF/$FNAME..."
check_saved_file
$CAT $CONF/$FNAME|$UC load_cache
}

reload_cache ()
{
# Reloading and refresh existing cache and saved dump
save_cache
load_cache
}

##############
# Main block #
##############

# OS check
check_os

# Root check
root_check

# Check unbound-control
check_uc

# Check command-line arguments
if [ "x$1" = "x" ]; then
# If arguments list empty, load cache by default
load_cache
else
arg_list=$1
# Parse command line
set -- `$GETOPT sSlLrRhH: $arg_list` || {
usage_note 1>&2
}

# Read arguments
for i in $arg_list
do
case $i in
-s | -S) save_cache;;
-l | -L) load_cache;;
-r | -R) reload_cache;;
-h | -H | \?) usage_note;;
esac
break
done
fi

exit 0


Можно положить его в /usr/local/bin и либо использовать на регулярной основе для поддержания кэша в прогретом состоянии (с использованием cron), либо выполнять интерактивно по мере необходимости.

Ну и результаты вполне удовлетворительные (статистика плагина unbound_munin_):


Две трети ответов кэша - это попадания, примерно треть - вставки в кэш, и односекундные промахи несущественно малы.