Записи с меткой ‘rfc’

Почта для кириллических доменов

На текущий момент только один почтовик заявляет и выпускает хоть какие-то релизы с поддержкой SMTPUTF8 или RFC 6531. Это экспериментальные релизы Postfix 2.12.
Но даже при наличии поддержки в нём система доставки кириллической почты просто так не заработает. Поэтому запасаемся напильником.
Настраивать сервер будем под Debian 7. В моём случает он внутри VZ контейнера, а эксперименты проводились внутри LXC контейнера.
После создания контейнера сносим оттуда штатный почтовик, если он есть:

apt-get purge exim* sendmail* и пр.

Качаем последнюю версию Postfix 2.12 experimental release:

wget http://mirrors-ru.go-parts.com/postfix/source/experimental/postfix-2.12-20140905.tar.gz

Заранее создаём юзера и группу:

useradd postfix -s /bin/false
groupadd postdrop

Распаковываем:

tar -zxf postfix-2.12-20140905.tar.gz

Патчим src/smtpd/smtpd.c:

apt-get install patch
patch postfix-2.12-20140905/src/smtpd/smtpd.c smtpd.patch

где smtpd.patch имеет содержимое:

--- smtpd.c	2014-10-06 00:15:18.000000000 +0400
+++ smtpd.c.force.smtputf8	2014-10-07 15:36:21.352884670 +0400
@@ -2317,21 +2317,8 @@
 	return (-1);
     }
 
-    /*
-     * XXX The sender address comes first, but the optional SMTPUTF8
-     * parameter determines what address syntax is permitted. We must process
-     * this parameter early.
-     */
-    if (var_smtputf8_enable
-	&& (state->ehlo_discard_mask & EHLO_MASK_SMTPUTF8) == 0) {
-	for (narg = 3; narg < argc; narg++) {
-	    arg = argv[narg].strval;
-	    if (strcasecmp(arg, "SMTPUTF8") == 0) {	/* RFC 6531 */
-		smtputf8 = 1;
-		break;
-	    }
-	}
-    }
+    smtputf8 = 1;
+
     if (extract_addr(state, argv + 2, PERMIT_EMPTY_ADDR,
 		     var_strict_rfc821_env, smtputf8) != 0) {
 	state->error_mask |= MAIL_ERROR_PROTOCOL;

Нужно это для того, чтобы почтовые клиенты, которые на данный момент не готовы полностью к таким серверам, могли через них всё-таки почту отправлять.
Дело в том, что эта сборка Postfix для активации SMTPUTF8 режима должна на входе получить:

RCPT TO:< юзер@домен.рус> SMTPUTF8

Быстрая проверка показала, что даже почтовые клиенты заявившие о поддержке IDN почты не отправляют SMTPUTF8 в RCPT TO и тем самым создают себе проблемы с отправкой.

Готовимся к сборке:

apt-get install build-essential libdb-dev libicu-dev libssl-dev
apt-get install checkinstall
apt-get install rsyslog telnet

Заодно готовимся к использованию Dovecot в качестве средства авторизации:

apt-get install dovecot-imapd dovecot-pop3d

Собираем с поддержкой SASL и TLS:

cd postfix-2.12-20140905
make makefiles CCARGS='-DUSE_SASL_AUTH -DDEF_SERVER_SASL_TYPE=\"dovecot\" -DUSE_TLS' AUXLIBS="-ldb -lnsl -lresolv -lssl"
make
make install

Теперь надо это всё настроить:
В /etc/dovecot/conf.d/10-master.conf правим сокет для авторизации (95 строка примерно):

  # Postfix smtp-auth
  unix_listener /var/spool/postfix/private/auth {
    mode = 0660
    user = postfix
    group = postfix
  }

В /etc/dovecot/conf.d/10-auth.conf (99 строка примерно) добавляем любимые способы авторизации, например:

auth_mechanisms = plain login

Перезапускаем:

/etc/init.d/dovecot restart

Должно заработать.

После правки конфиг Postfix /etc/postfix/main.cf получился такой:

queue_directory = /var/spool/postfix
command_directory = /usr/sbin
daemon_directory = /usr/libexec/postfix
data_directory = /var/lib/postfix
mail_owner = postfix
myhostname = postfix.regtime.net
mydomain = postfix.regtime.net
inet_interfaces = all
unknown_local_recipient_reject_code = 550
alias_maps = hash:/etc/postfix/aliases
alias_database = hash:/etc/postfix/aliases
home_mailbox = Mailbox
 
mail_spool_directory = /var/mail
  
debug_peer_level = 6
debugger_command =
	 PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin
	 ddd $daemon_directory/$process_name $process_id & sleep 5
sendmail_path = /usr/sbin/sendmail
newaliases_path = /usr/bin/newaliases
mailq_path = /usr/bin/mailq
setgid_group = postdrop
html_directory = no
manpage_directory = /usr/local/man
sample_directory = /etc/postfix
readme_directory = no
inet_protocols = ipv4
meta_directory = /etc/postfix
shlib_directory = no

smtputf8_autodetect_classes = all
smtputf8_enable = yes

virtual_mailbox_domains = русскийдомен.рф
virtual_mailbox_base = /var/spool/mail
virtual_mailbox_maps = hash:/etc/postfix/virtual_mailbox
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000

smtpd_sasl_type = dovecot
smtpd_sasl_path = /var/spool/postfix/private/auth
smtpd_sasl_local_domain =
smtpd_sasl_security_options = noanonymous
broken_sasl_auth_clients = yes
smtpd_sasl_auth_enable = yes
smtpd_recipient_restrictions = permit_sasl_authenticated,permit_mynetworks,reject_unauth_destination

smtpd_tls_CAfile = /etc/ssl/certs/ca.pem
smtpd_tls_CApath = /etc/ssl/certs
smtpd_tls_cert_file = /etc/dovecot/dovecot.pem
smtpd_tls_key_file = /etc/dovecot/private/dovecot.pem
smtpd_tls_session_cache_database = btree:/var/lib/postfix/smtpd_tls_session_cache
smtpd_use_tls = yes

# Enable STARTTLS encryption 
smtp_use_tls = yes
smtp_tls_CAfile = /etc/ssl/certs/ca.pem
smtp_tls_session_cache_database = btree:/var/lib/postfix/smtp_tls_session_cache
smtpd_tls_security_level = may

smtpd_tls_received_header = yes
smtpd_tls_loglevel = 1
smtpd_tls_auth_only = no
tls_random_source = dev:/dev/urandom

Настройка для довольно простого использования обычных системых mailbox’ов на одном кириллическом домене. Те кто разбирается в Postfix чуть более глубоко — может это легко перенастроить под более привычные ему варианты.

В /etc/postfix/virtual_mailbox пишем:

имя.фамилия@русскийдомен.рф  user1

где user1 — системный юзер, которого нужно добавить штатной командой:

useradd user1 -s /bin/false

А в /etc/postfix/uid_maps:

имя.фамилия@русскийдомен.рф  1000

где 1000 — это uid для user1.

Тут же становится понятно, что для авторизации будет использован классический ASCII логин user1 и пароль к нему. В качестве POP3/IMAP4/SMTP сервера postfix.regtime.net.

Преобразуем это в хэш:

postmap /etc/postfix/aliases
postmap /etc/postfix/virtual_mailbox
postmap /etc/postfix/uid_maps

Перечитываем конфиг или запускаем, перезапускаем Postfix:

postfix reload/stop/start

Проверяем:

# telnet localhost 25
Trying ::1...
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 postfix.regtime.net ESMTP Postfix
EHLO localhost
250-postfix.regtime.net
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-STARTTLS
250-AUTH PLAIN LOGIN
250-AUTH=PLAIN LOGIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250-DSN
250 SMTPUTF8
quit
221 2.0.0 Bye
Connection closed by foreign host.

Теперь когда сервер умеет работать с кириллическими адресами настало время выбрать клиента.
Гарантировано работает Claws Mail начиная с версии 3.9.3.
Evolution 3.10.4 тоже справляется с этой задачей.
Есть специальный клиент — EAI-SMTPUTF8 v.2.0
Гарантированно не работает Mozilla Thunderbird.

DNSSEC на практике у регистратора доменов

Историческая справка

Система доменных имён (DNS) является одним из важнейших и основных интернет-сервисов, однако на момент её разработки безопасность не была главной целью. С развитием Интернет, однако, обнаружились и уязвимости в системе DNS. Достоверность ответа DNS сервера не проверяется, что позволяет подменить ответ сервера, перенаправив запрос пользователя на произвольный IP адрес. Уязвимы оказались и кэширующие DNS серверы интернет-провайдеров из-за возможности заполнения кэша DNS сервера данными, не исходящими от авторитетного DNS источника (атака Каминского).

Нельзя, впрочем, сказать, что о безопасности DNS вообще не задумывались до текущего времени. Серьёзные недостатки в безопасности этой системы были выявлены ещё в 1990 году Стивом Белловином (Steve Bellovin). Исследования в этой области начались со времён публикации доклада в 1995 году, что вызвало публикацию IETF первых спецификаций на эту тему (RFC 2065) в 1997 году. Первые попытки реализации этой спецификации привели к появлению новой спецификации (RFC 2535) в 1999 году. Именно на спецификации IETF RFC 2535 и была запланирована реализация DNSSEC, однако у этой спецификации были очень серьёзные проблемы с масштабированием на весь интернет. К 2001 году стало окончательно ясно, что эта спецификация была непригодна для крупных сетей. Это, в свою очередь, вызвало возникновение новых спецификаций (RFC 4033, 4034 4035) с принципиальными изменениями DNSSEC (DNSSEC-bis), новая версия которой устраняет основную проблему предыдущей реализации и, хотя в новой спецификации клиентам и необходимо совершать дополнительные действия для проверки ключей, тем не менее вполне пригодна для практического применения.

К сожалению, как это обычно и случается, недостатки DNSSEC являются продолжением её достоинств. Подписание и проверка данных DNS создают дополнительные накладные расходы, что отрицательно сказывается на производительности сети и серверов. К примеру, в среднем зона DNSSEC в 7-10 больше по размеру своего DNS эквивалента. Генерация и проверка подписей отнимает значительное время ЦПУ. Подписи и ключи занимают на порядок больше места на диске и в оперативной памяти, чем сами данные.

Впрочем, работа над DNSSEC еще не завершена, однако любая организация, активно использующая Internet, уже должна рассматривать DNSSEC в качестве важнейшего компонента своей инфраструктуры защиты. Протокол DNS по-прежнему уязвим для злоупотреблений.

Наши дни

Теперь нужно понять ненужность данной технологии в рунете. Вспомним, что в зону .SU DNSSEC внедрили в октябре 2011 года, в зону .РФ — в ноябре 2012, .RU — в декабре 2012. Теперь попробуйте вспомнить хоть один домен подписанный DNSEC. Не можете? 😉 Это ожидаемо. На момент написания этой статьи из трёх регистраторов заявивших о внедрении у себя DNSSEC только один (и это Регтайм) подписал свой основной домен. К этому можно добавить, что за всё время существования DNSSEC количество вопросов от пользователей о внедрении этой технологии можно пересчитать по пальцам одного человека. Прямо скажем — не густо.

Тогда возникает логичный вопрос: Зачем внедрять? Затем, что Регтайм всегда был и остаётся пионером и первооткрывателем во многим вопросах DNS. Внедрение DNSSEC, как штатной фишки, очередной шаг. Причём не только для отечественных зон, но и для многих других.

На этом предлагаю закончить с теорией и философией. Теперь рассмотрим собственно использование DNSSEC на собственных name серверах.

Практические работы

Для того чтобы DNSSEC начал использоваться как задумано авторами нужны следующие компоненты:

— подписанная зона первого уровня (у нас есть отечественные .RU .SU и .РФ)
— домен в этой зоне (у нас есть webnames.ru)
— авторитарные DNS серверы для нашего домена (имеются)
— рисолвер (кеширующий DNS сервер)

Текущей стабильной версией Debian является Squeeze уже 6.0.7. Его и продолжим использоваться в качестве базы. В качестве собственно DNS сервера у нас bind9.

Опустим подробности установки и настройки собственно bind9. Ставится он просто:

aptitude install bind9

Компоненты для работы с DNSSEC:

aptitude install dnssec-tools libcrypt-openssl-random-perl

Все конфиги по умолчанию находятся в /etc/bind/
Здесь нас интересуют опции в named.conf.options. В них нужно добавить:


dnssec-enable yes;
dnssec-validation yes;
dnssec-lookaside auto;

После этого нужно перечитать конфиги или перезагрузить bind. Тут кому как нравится: rndc reconfig или /etc/init.d/bind9 restart

Для простоты внедрения будем использовать zonesigner. Это всеобъемлющая утилита, которая подписывает зону за один проход. Но есть и более сложный путь, но зачем он нужен? 😉

Забегая вперёд скажу, что в процессе своей работы zonesigner создаёт десяток файлов и рациональнее складывать их отдельно, а не в общий каталог с зонами. Да и зоны лучше не складывать в один каталог. Это не вызывает проблем есть у вас всего несколько доменов. Но если у нас более 150 тысяч зон на каждом сервере, то надо как-то оптимизировать их хранение, иначе возникают адские накладные расходы.

В процессе эволюции мы имеем следующую иерархию зон: auto/ru/w/e/b/n/webnames.ru. Для zonesigner была создана аналогичная параллельная ветвь: dnssec/ru/w/e/b/n/webnames.ru/

Первоначальная генерация подписанной зоны выглядит так:


mkdir -p /var/named/dnssec/ru/w/e/b/n/webnames.ru/
cd /var/named/dnssec/ru/w/e/b/n/webnames.ru/
zonesigner -genkeys -usensec3 -zone webnames.ru /var/named/auto/ru/w/e/b/n/webnames.ru

На выходе получим что-то типа:

        if zonesigner appears hung, strike keys until the program completes
        (see the "Entropy" section in the man page for details)

Generating key pair.....++++++ .........................................................................++++++ 
Generating key pair..++++++ ...++++++ 
Generating key pair....+++ .........+++ 
Verifying the zone using the following algorithms: RSASHA256.
Zone signing complete:
Algorithm: RSASHA256: KSKs: 1 active, 0 stand-by, 0 revoked
                      ZSKs: 1 active, 1 stand-by, 0 revoked

zone signed successfully

webnames.ru:
        KSK (cur) 02110  -b 2048  02/22/13      (webnames.ru-signset-00003)
        ZSK (cur) 21834  -b 1024  02/22/13      (webnames.ru-signset-00001)
        ZSK (pub) 51069  -b 1024  02/22/13      (webnames.ru-signset-00002)

zone will expire in 4 weeks, 2 days, 0 seconds
DO NOT delete the keys until this time has passed.

А теперь убедимся, что файлов создано много:


$ls -1
dsset-webnames.ru.
Kwebnames.ru.+008+02110.key
Kwebnames.ru.+008+02110.private
Kwebnames.ru.+008+21834.key
Kwebnames.ru.+008+21834.private
Kwebnames.ru.+008+51069.key
Kwebnames.ru.+008+51069.private
webnames.ru.krf

А рядом с файлом обычной зоны появился второй файл webnames.ru.signed и он более чем в 20 раз больше оригинала — 32669 байт против 1369. И еще 7520 байт на служебные файлы указанные выше. Т.е. мы получили в 30 раз больше информации. Правда зона webnames.ru совсем маленькая и такой прирост не сильно тяготит.

На всякий случай проверим новый файл зоны на ошибки:


$ donuts --level 8 webnames.ru.signed webnames.ru
0 errors found in webnames.ru.signed

«—level» — это уровень выдачи ошибок. Когда ошибок нет, то в нём особого смысла нет. Кстати, есть очень простой способ напороться на эти ошибки. Например, добавив NS запись со сторонним DNS сервером.
Добавим в зону запись bad NS ns1.gde-to-tam-daleko.ru и обновимся:

zonesigner -zone webnames.ru /var/named/auto/ru/w/e/b/n/webnames.ru

Обратите внимание, что править нужно всегда обычную зону, а подписанную DNSSEC нужно обновлять именно так.

Теперь проверим на ошибки:

$ donuts --level 8 webnames.ru.signed webnames.ru 
bad.webnames.ru:
  Warning:     Only 1 NS record(s) for bad.webnames.ru found, but at least
               2 are suggested/required

bad.webnames.ru:
  Error:       sub-domain bad.webnames.ru is not securely delegated.  It is
               missing a DS record.

2 errors found in webnames.ru.signed

Вот так. 🙂 Это усложнение структуры стоит учитывать в своей практике. Если вдумчиво читать, то становится понятно, что именно нужно делать. Во-первых, добавить вторую NS запись, а во-вторых, добавить DS запись для поддомена.

Но откуда же у нас эти DS берутся? Выше у нас показан файл dsset-webnames.ru. Его содержимое таково:

webnames.ru.            IN DS 2110 8 1 4F38DB26A26DDFFB0A84052472D1AF70DAA595D7
webnames.ru.            IN DS 2110 8 2 0CC3937FE64FD4BF3B8282748F93C566870F4FCD254BCF0D91DBCF50 23D6D28C

Именно эти записи нужно передать регистратору домена, чтобы он их отправил в реестр зоны. И они же нужны для того чтобы donuts перестал выдавать ошибки для NS записей.
Процедура передачи у разных регистраторов разная. На Webnames.Ru, например, в разделе «Управления доменом» «Личного кабинета» есть специальный пункт «DNSSEC» где можно включить и выключить собственно поддержку DNSSEC, а также увидеть имеющиеся DS записи и при необходимости внести новые.

Теперь вспомним о том, что все криптографические ключи имеют срок годности. Неплохо бы автоматизировать и их замену… Радует, то что есть специальный демон rollerd. В то же время печалит, то что для этого демона нет init-скрипта. Поэтому придётся его написать самостоятельно. Можно, конечно, и не писать, а обойтись колхозными методами, но это уже каждый решает сам. Еще чуть больше печалит то, что rollerd хоть и следит за ключами и заменяет их, но не может заменить их в реестре.

Сначала определимся за чем будем следить. Для этих целей есть rollinit. Он готовит для rollerd список зон за ключами которых мы собираемся следить. Давайте определимся, что список мы будем хранить в dnssec/. Соответственно, добавим туда нашу подписанную зону:


rollinit -zonefile /var/named/auto/ru/w/e/b/n/webnames.ru.signed -keyrec /var/named/dnssec/ru/w/e/b/n/webnames.ru/webnames.ru.krf -admin support@webnames.ru webnames.ru >> /var/named/dnssec/rollrec

Если кто-то читая это уже наклепал подписанных зон, то нужно их все добавить в этот же список либо следить за ключами вручную. 😉

После этого нужно запустить rollerd. Вот обещанный init-скрипт: /etc/init.d/rollerd

#!/bin/bash

### BEGIN INIT INFO
# Provides:          rollerd
# Required-Start:    $remote_fs $network $syslog
# Required-Stop:     $remote_fs $network $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
### END INIT INFO

PATH=/bin:/usr/bin:/sbin:/usr/sbin
DESC="DNSSEC-Tools daemon to manage DNSSEC key rollover"
NAME=rollerd
DAEMON=/usr/sbin/$NAME
SCRIPTNAME=/etc/init.d/$NAME
CONF=/var/named/dnssec/rollrec
PIDFILE=/var/run/rollerd.pid

[ -x "$DAEMON" ] || exit 0
. /lib/init/vars.sh
. /lib/lsb/init-functions
[ -f $CONF ] || exit 0

start_rollerd () {
        [ -f $PIDFILE ] && return 1
        $DAEMON -rrfile $CONF -directory /etc/bind -pidfile $PIDFILE
}

stop_rollerd () {
        if [ -s $PIDFILE ]; then
                PID=`cat $PIDFILE`
                kill $PID && rm -f $PIDFILE
                sleep 3
                [ -d "/proc/$PID" ] && return 1
                return 0
        fi
        PID=`ps xa | grep -v grep | grep $DAEMON | awk '{print $1}'`
        [ -z "$PID" ] && return 0
        kill $PID
        sleep 3
        [ -d "/proc/$PID" ] && return 1
        return 0
}

case "$1" in
        start)
                log_daemon_msg "Starting $DESC" "$NAME";
                start_rollerd;
                log_end_msg $?;
                ;;
        stop|force-stop)
                log_daemon_msg "Stopping $DESC" "$NAME";
                stop_rollerd;
                log_end_msg $?;
                ;;
        restart)
                log_daemon_msg "Restarting $DESC" "$NAME";
                stop_rollerd;
                start_rollerd;
                log_end_msg $?;
                ;;
        *)
                echo "Usage: $0 ";
                exit 1;
                ;;
        esac;

exit 0;

Готовим его к запуску, автозапуску и запускаем.


chmod 755 /etc/init.d/rollerd
update-rc.d rollerd defaults
/etc/init.d/rollerd start

Если кто-то совсем расстроился, что полную ротацию ключей автоматизировать невозможно, то это зря. Можно, но уже при помощи почтового демона. У нас используется sendmail. Поэтому при помощи smrsh можно сделать почти всё что угодно. Делается это довольно просто. В /etc/mail/sendmail.mc добавляем следующие строки перед первым MAILER’ом:


FEATURE(`virtusertable', `hash /etc/mail/virtusertable')dnl
VIRTUSER_DOMAIN_FILE(`/etc/mail/local-host-names')dnl

В /etc/mail/virtusertable добавляем:
dnssec@localhost dnssec
Этим мы создали виртуальный почтовый ящик dnssec@localhost и отправили всю входящую почту на системного юзера dnssec.

В /etc/aliases добавляем:
dnssec: "|/etc/mail/smrsh/dnssec"
Этим мы всю входящую почту юзеру dnssec отправили через пайп (т.е. в его STDIN) в скрипт /etc/mail/smrsh/dnssec

А уж в скрипте /etc/mail/smrsh/dnssec мы можем делать всё что хотим.
Стоит отметить, что скриптом это называется условно. Это может быть и бинарник.

Теперь перезапустим sendmail и все изменения вступят в силу:
/etc/init.d/sendmail restart

При этом всём не забудьте, что при использовании smrsh нужно переинициировать /var/named/dnssec/rollrec с адресом dnssec@localhost. Т.е. примерно так:


rollinit -zonefile /var/named/auto/ru/w/e/b/n/webnames.ru.signed -keyrec /var/named/dnssec/ru/w/e/b/n/webnames.ru/webnames.ru.krf -admin dnssec@localhost webnames.ru >> /var/named/dnssec/rollrec

Сам скрипт /etc/mail/smrsh/dnssec приводить не имеет смысла, поэтому ограничимся обёрткой на bash без функционала.
Само письмо выглядит примерно так:

From: root
To: dnssec@localhost
Subject: assistance needed with KSK rollover of zone webnames.ru

The zone "webnames.ru" is in the middle of KSK rollover. In order for rollover
to continue, its keyset must be transferred to its parent.

Парсить его можно, например, так:

#!/bin/bash

while read L; do
    if [ "${L:0:9}" == "Subject: " ]; then
        for W in $L ; do echo -n '' ; done
        echo "Domain $W"
    fi
done

Т.е. после разбора поля Subject по словам получим в результате имя домена (в переменной W) для которого нужно послать обновлённые DS записи в реестр.

Теперь настроим последний компонент DNSSEC — рисолвер, он же кеширующий DNS сервер. И здесь всё тоже очень просто. Если взять тот же самый bind9, то в тот же самый файл /etc/bind/named.conf.options нужно добавить те же опции и перезагрузить bind:


dnssec-enable yes;
dnssec-validation yes;
dnssec-lookaside auto;

/etc/init.d/bind9 restart

Теперь на рабочем компе нужно прописать в качестве DNS сервера наш рисолвер и наслаждаться DNSSEC’ом.

Вот и всё.