[Карта]                [Начало]                [Sendmail-ссылки]                [Синтаксис]                [Типовые задачки]                  [Задачки по маршрутизации]                  [Задачки по маcкарадингу]                  [SendmailACL]                  [Spamooborona]                  [VadeRetro]                  [Regex]                  [Тонкости]                  [Недок.особен.]                  [Несущ.юзеры]                  [Прячемся!]                  [RFC1893.Цитаты]                  [ТП.Эмоции]                  [Антиспам&Разум]                  [Экзерсисы]                 


Прячем имя внутреннего почтового сервера



Иногда может возникнуть необходимость изменить данные, заполняемые нашим почтовиком в заголовке письма. Чаще всего это HELO/EHLO, каноническое имя хоста.
Также может возникнуть необходимость скрыть имя внутренного почтового сервера в исходящей почте, заменив его на имя внешнего почтового сервера (шлюза) mail.domain.ru.

Во-первых, имя почтового сервера "выдает с потрохами" внутренний макрос sendmail'a - макрос $j.
( "... "Официальное" доменное имя для этого узла. Оно полностью уточнено, если может быть найдена полная квалификация.(т.е. команда hostname -f должна выдавать полное доменное имя) Оно должно быть переопределено, чтобы быть полностью уточненным доменным именем, если ваша система не сконфигурирована таким образом, что может найти его автоматически... )"

Другими словами, $j - это полностью разрешенное имя хоста, которое определяется следующим образом: сначала вызывается команда gethostname, которая дает имя хоста, это имя хоста затем передается команде gethostbyname, которое должно вернуть каноническое имя хоста (см. op.me).
$j - полностью определенное имя хоста (FQDN - fully qualified domain name).
"It is unwise to try to change this" - http://www.sendmail.org/m4/README.txt

Теперь посмотрим на заголовок письма. У меня нет внешних и внутренних серверов, но я могу привести пример письма, пришедшего с моего mx-a с большим весом на основной mx. Правда, для того, чтобы воспринимать этот заголовок в нужном контексте, мысленно перевернем последовательность продвижения письма и вообразим, что первый mx, на который пришло письмо - это внутренний почтовик, с которого письмо ушло на внешний сервер, а основной mx - внешний сервер, отправляющий письмо с нутреннего почтовика в мир.
А 213.60.13.146 - адрес моего почтового клиента (хотя на самом деле, это какой-то злобный спамер).
Если ничего не понятно, то считайте просто, что apache.anrb.ru - это внутренний сервер, а mail.anrb.ru - внешний, и все :)

Заполнено внешним почтовиком:
Return-Path: < Josif211@oljelundslyft.com >
Received: from apache.anrb.ru (www.anrb.ru [212.193.134.3])

здесь: apache.anrb.ru - HELO, указанное внутренним сервером во время SMTP-сессии,
то есть, открывая smtp-сеанс, внутренний почтовик сказал HELO apache.anrb.ru
www.anrb.ru - имя внутреннего почтовика, определенное по PTR-записи ip-адреса 212.193.134.3 в обратной зоне;
[212.193.134.3] - ip-адрес внутреннего почтовика;

         by mail.anrb.ru (8.14.2/8.14.2) with ESMTP id m0Q6E6wP024784
         for < webmaster@anrb.ru >; Sat, 26 Jan 2008 11:14:06 +0500


Заполнено внутренним почтовиком:
Received: from [213.60.13.146] ([213.60.13.146])
        213.60.13.146 - якобы мой пользователь
         by apache.anrb.ru (8.14.2/8.14.2) with ESMTP id m0Q5rP89011675
apache.anrb.ru - значение макроса $j, указанного явно (см. ниже)
         for < webmaster@anrb.ru >; Sat, 26 Jan 2008 10:53:29 +0500


Макрос $j по умолчанию упоминается в следующих местах.
I.  В приветствии внутреннего почтового сервера (к заголовку письма это не имеет никакого отношения): в стандартной конфигурации макрос $j вставляется в в приветствие по умолчанию, обнародуя таким образом имя почтовика.
II.  В подзаголовке Received:, который заполняет внешний сервер, а именно
в HELO/EHLO, которым поздоровался внутрений сервер (макрос $s- имя хоста отправителя, выставляется из флага командной строки -p или кодом сервера SMTP), для HELO/EHLO по умолчанию он также использует макрос $j;
III.  В подзаголовке Received:, который заполняет внутренний сервер, внутренний макрос $j указывается явно.

Во-вторых, внутренний почтовый сервер засвечивается и во внутреннем макросе $_ (подтвержденный адрес отправителя, состоит из доменного имени и ip-адреса релея отправителя -
$&{client_name}[$&{client_addr}])

Итак, если мы сумеем повлиять на макросы $j и $_ , то задачу мы решим.

Но для начала рассмотрим неявные способы воздействия.

  • 1. Сначала разберемся с приветствием. В стандартном конфиге приветствие имеет вид:
    SmtpGreetingMessage=$j Sendmail $v/$Z; $b
    Как видите, и здесь упоминается макрос $j.

    1.1. Можно его иключить из заголовка, заменив его на другое доменное имя.
    Для этого необходимо добавить в sendmail.mc:
    define(`confSMTP_LOGIN_MSG', `mail.domain.ru; Sendmail $v/$Z; $b;')

    README:
    confSMTP_LOGIN_MSG SmtpGreetingMessage
    [$j Sendmail $v/$Z; $b]
    The initial (spontaneous) SMTP greeting message. The word "ESMTP" will be inserted between the first and second words to convince other sendmails to try to speak ESMTP.

    1.2. Можно самостоятельно задать доменное имя, используя опцию
    define(`confDOMAIN_NAME', `mail.domain.ru') на внутреннем почтовике.
    Это позволит заменить макрос $j в
    - приветствии,
    - Received: внутреннего сервера (явный $j),
    - Received: внешнего сервера (HELO/EHLO внутреннего).

    Подчеркну: оба способа не изменяют содержание макроса $j, а просто заменяют макрос на указанный домен.

  • 2. Теперь разберемся с подзаголовком Received.
    2.1. Как я только что сказала, опция define(`confDOMAIN_NAME', `mail.domain.ru') с успехом справится с именем внутреннего почтовика в пп.I и II.

    2.2. Однако существует еще другая возможность.
    2.2.1.За формат подзаголовка Received: отвечает опция confRECEIVED_HEADER, и в стандартной конфигурации он имеет вид:
             Received: [$?sfrom $s $.$?_($?s$|from $.$_)
             $.$?{auth_type}(authenticated)
             $.by $j ($v/$Z)$?r with $r$. id $i$?u
             for $u; $|; $.$b]

    Этот заголовок можно переписать, заменив $j на mail.domain.ru.
    Вариант особо немногословного заголовка для внутреннего почтовика:
    define (`confRECEIVED_HEADER',`id $i; $b') -
    здесь обозначены лишь идентификационный номер письма в очереди и дата, и нет канонического имени хоста.

    2.2.2. А для изменения HELO/EHLO, которым здоровается внутренний почтовик, и который внешний почтовик записывает в свой Received, начиная с версии 8.14.0 можно использовать опцию:
    confHELO_NAME        HeloName         If defined, use as name for EHLO/HELO command (instead of $j).
    Эта опция д.б. прописана в конфиге внутреннего сервера, она позволит изменить его HELO по своему уразумению.
    Для младших версий подействовать на HELO напрямую невозможно.

    Вот вы теперь скажете, зачем городить весь этот огород, если можно повлиять на макрос $j.

    Еще раз вернусь к его определению:
    Значение макроса $j определяется вызовом gethostname для получения текущего hostname, с последующей передачей его в gethostbyname, который должен вернуть каноническую версию имени хоста. Если все прошло успешно, то в $j выставляется полностью определенное имя.
    Проще говоря, при наличии у хоста полного доменного имени, определяемого командой hostname -f, именно это значение и будет выставлено в макрос $j.

    Мы знаем, что внутренний резолвер системы обращается за информацией в те файлы, которые определены в строке hosts файла /etc/nsswitch.conf.
    Эта строка может иметь вид:
    hosts:        files dns
    что будет означать, что резолвер сначала поищет записи в /etc/hosts, а потом обратится в dns.

    И казалось бы, зачем городить огород: достаточно прописать в /etc/hosts
    212.193.134.3        mail.domain.ru mail
    и sendmail начнет отдавать в качестве $j mail.domain.ru

    Ан нет! Не все так просто. Sendmail так устроен, что он устанавливает свой порядок резолвинга через файл /etc/mail/service.switch (тут все зависит от ОС, см. подробности в op.me).
    Если этот файл отсутствует, то порядок резолвинга следующий:
    hosts:        dns nis files

    1. Значит, для того, чтобы изменить значение $j, нужно отредактировать соотв. запись в dns.
    2. Другой способ - создать-таки /etc/mail/services.switch на внутреннем почтовике и поменять последовательность обращений резолвера:
    hosts:        files dns
    И затем отредактировать /etc/hosts, указав необходимое доменное имя.
    И тот, и другой способ может потянуть за собой массу неприятностей.
    Например, если обновленное доменной имя в /etc/hosts не прописано в dns, то внешний почтовик обязательно проворчит Domain of sender address paradise@something.ru does not exist


    Сложнее дело обстоит с $_ ($&{client_name}[$&{client_addr}]); здесь внешний сервер запишет доменное имя внутреннего почтовика (обратившись за ним в /etc/hosts и обратную зону домена в dns) и его ip.
    И если доменное имя $&{client_name} вы еще можете изменить через /etc/hosts или dns (в зависимости от того, какой порядок указан в /etc/nsswitch.conf, да-да, здесь будет обращение именно к nsswitch.conf, почему? - спросите что-нить полегче :), тo спрятать ip-адрес источника письма нельзя.
    Но можно изменить формат заголовка Received внешнего почтовика, просто опустив $_ или указав вместо него просто доменное имя макросом $&{client_name}.

    Ссылки по теме:
    [1]
    [2]. Who Am I?
    [3]. Per Hedeland: "And, if you actually care about the "banner" (there isn't much reason to do that), you need to have different confSMTP_LOGIN_MSG definitions - or again, make it macro-expanded (there's an example of precisely this in doc/op/op.*)."
    [4]. Из нерешенного ...
    [5]. define(`confSMTP_LOGIN_MSG', `$?{if_name}${if_name}$|$j$. Sendmail $v/$Z; $b'): "Имя хоста в SmtpGreetingMessage будет резолвиться из соответствующего IP-адреса (обратный резовл надо настроить)."
    [6]. D.Stussy. System name in SMTP messages and virtual hosting.

    Обратная связь
    Страница создана 27 декабря 2007г.
    Последнее обновление: 19 ноября 2008 г.