++ Описание задачи
Имеется:
*** Компания с несколькими офисами по всему миру
*** Много доменная структура на базе Microsoft Active Directory
*** Внутренняя почта на серверах MS Exchange Server 2007, которые, по разным соображениям, не желательно выставлять в интернет.
*** Шлюзы в интернет на базе FreeBSD 8+Нужно настроить Sendmail на пересылку почты из интернета в Exchange и обратно, с учётом требований
*** адекватной защитой от спама и вирусов
*** максимальной интеграцией в АД
*** обслуживание множества почтовых доменов и доменов АДа.
*** SMTP AUTH по учётным записям домена для любителей путешествовать.
++ Решение
Для начала интегрируем шлюз в АД. Это понадобится и для SMTP AUTH и для авторизации в Squid-е и ещё много для чего.
++ 1. Подготовка системы.
++ 1.1. Устанавливаем samba. 
   cd /usr/ports/net/samba35/
   make install clean
При настройке пакета нам понадобиться только параметры ADS (With Active Directory support) и WINBIND (With WinBIND support). Остальные параметры - по желанию и умению.
Первым делом создаём файл /etc/krb5.conf
   [logging]
        default = SYSLOG
   [libdefaults]
        default_realm = MSK.LAN
        clockskew = 300
        default_tgs_enctypes = RC4-HMAC DES-CBC-CRC DES-CBC-MD5
        default_tkt_enctypes = RC4-HMAC DES-CBC-CRC DES-CBC-MD5
        preferred_enctypes = RC4-HMAC DES-CBC-CRC DES-CBC-MD5
        ticket_lifetime = 21600
   [realms]
        MSK.LAN = {
                kdc = Ad-Srv0.msk.lan:88
                admin_server = Ad-Srv0.msk.lan:464
                default_domain = msk.lan
        }
        GER.LAN = {
                kdc = Ad-Srv0.ger.lan:88
        }
        TWN.LAN = {
                kdc = Ad-Srv0.twn.lan:88
        }
   [domain_realm]
        .msk.lan = MSK.LAN
        .ger.lan = GER.LAN
        .twn.lan = TWN.LAN
Настраиваем Samba. В данном случае нужен только сервис разрешения имён - остальное отключено за не надобностью.
   [global]
   server string = FreeBSD GateWay
   security = ADS
   kerberos method = system keytab
   hosts allow = 192.168.88. 127.
   load printers = no
   encrypt passwords = yes
   winbind separator = +
   winbind use default domain = yes
   winbind uid = 10000-15000
   winbind gid = 10000-15000
   winbind enum users = yes
   winbind enum groups = yes
   log file = /var/log/samba/log.%m
   max log size = 50
   password server = Ad-Srv0.msk.lan
   workgroup = MSKLAN
   realm = MSK.LAN
   interfaces = 192.168.88.0/24
   socket address = 192.168.88.254
   dns proxy = no 
Следующий шаг - синхронизация времени между доменными серверами и шлюзом. Так как на шлюзе точное глобальное время - синхронизирую по нему контроллеры домена.
И наконец интеграция в домен:
   net ads join -U Administrator@MSK.LAN
и создание файла /etc/krb5.keytab
   net ads keytab create
и добавляем строку в /etc/crontab
   0 * * * *       root    /usr/local/bin/net ads kerberos kinit -P
она позволит программам, умеющим использовать sasl2, работать в АДе без ввода пароля, используя учётную запись сервера, что позволяет не хранить пароли в скриптах.
Добавляем в /etc/rc.conf:
   winbindd_enable=YES
И запускаем его 
   /usr/local/etc/rc.d/samba
++ 1.2. Установка cyrus sasl2:
   cd /usr/ports/security/cyrus-sasl2
   make install clean
При настройке порта необходимы только параметры AUTHDAEMOND (Enable use of authdaemon), LOGIN (Enable LOGIN authentication), PLAIN (Enable PLAIN authentication) - остальные на своё усмотрение.
Сборка, установка - как обычно, дополнительных настроек ни каких делать не обязательно.
++ 1.3 Установка saslauthd пакета cyrus sasl2
   cd /usr/ports/security/cyrus-sasl2-saslauthd
   make install clean
Параметры пакета в данном случае ни на что не влияют.
Создаём файл /usr/local/etc/pam.d/smtp со следующим содержимым:
   auth    sufficient      pam_krb5.so no_user_check validate
   account sufficient      pam_permit.so
добавляем пару строк в /etc/rc.conf
   saslauthd_enable=YES
   saslauthd_flags='-a pam -c -t 3600'
и запускаем сервис
   /usr/local/etc/rc.d/saslauthd start
И проверяем, что это всё работает:
   # testsaslauthd -s smtp -u user -p 'password'
   0: OK "Success."
Если ответ другой - разобраться поможет режим отладки saslauthd -a pam -n 0 -d .
++ 1.4. Установка клиента openldap.
   cd /usr/ports/net/openldap24-client
   make install clean
Необходим параметр SASL (With (Cyrus) SASL2 support).
После установки добавляем пару строк в /usr/local/etc/openldap/ldap.conf
   BASE    dc=MSK,dc=lan
   URI     ldap://msk.lan
Проверяем, что ldapsearch работает как надо:
   ldapsearch -z 1 '(objectclass=user)'
Должно получиться что-то типа:
   SASL/GSSAPI authentication started
   SASL username: SRV-GW$@MSK.LAN
   SASL SSF: 56
   SASL data security layer installed.
   # extended LDIF
   #
   # LDAPv3
   # base <dc=MSK,dc=lan> (default) with scope subtree
   # filter: (objectclass=user)
   # requesting: ALL
   #
   
   # SRV05, Servers, Central Office, Offices, msk.lan
   dn: CN=SRV05,OU=Servers,OU=Central Office,OU=Offices,DC=MSK,DC=lan
   objectClass: top
   objectClass: person
   objectClass: organizationalPerson
   objectClass: user
   objectClass: computer
   cn: SRV05
   userCertificate:: MII...
++ 1.5 Установка антивируса.
   cd /usr/ports/security/clamav
   make install clean
Среди параметров обязательно нужен MILTER (Compile the milter interface).
Добавляем в /etc/rc.conf несколько строк
   clamav_clamd_enable=YES
   clamav_milter_enable=YES
   clamav_freshclam_enable=YES
и запускаем сервисы:
   /usr/local/etc/rc.d/clamav-clamd
   /usr/local/etc/rc.d/clamav-milter
   /usr/local/etc/rc.d/clamav-freshclam
++ 2. Настройка sendmail-а.
++ 2.1. Собираем sendmail c поддержкой SASL2. Добавляем в файл /etc/make.conf строки 
   SENDMAIL_CFLAGS=-I/usr/local/include -DSASL=2
   SENDMAIL_LDFLAGS=-L/usr/local/lib
   SENDMAIL_LDADD=-lsasl2 
и пересобираем sendmail:
   cd /usr/src/usr.sbin/sendmail
   make clean obj all install
++ 2.2. Настраиваем маршрутизацию писем и прочие функции sendmail-а.
Создаём файл /etc/mail/relay-domains и прописываем в нём все почтовые домены, обслуживаемые данным почтовым сервером
   domain1.ru
   domain2.ru
   domain3.tw
В файл /etc/mail/mailertable вносим информацию о серверах Exchange, принимающих почту этих доменов.
   domain1.ru    esmtp:srv-exch.msk.lan
   domain2.ru    esmtp:srv-exch.msk.lan
   domain3.tw    esmtp:srv-exch.twn.lan
Создаём SSL-ные ключи для Sendmail-а
   mkdir -p /etc/mail/SSL
   cd /etc/mail/SSL
   openssl req -new -x509 -keyout cakey.pem -out cacert.pem -days 365
   openssl req -nodes -new -x509 -keyout sendmail.pem -out sendmail.pem -days 365
[]Рекомендация[]: в поле "Common Name" указывайте полное доменное имя этого SMTP сервера, в том виде, как оно прописано в DNSе в полях MX.
++ 2.3 Настраиваем файлы конфигурации sendmail-а
   cd /etc/mail
   make
Редактируем файл `hostname`.mc, он должен принять примерно следующий вид.
   VERSIONID(`$FreeBSD: src/etc/sendmail/freebsd.mc,v 1.37.2.3 2011/06/20 01:48:49 gshapiro Exp $')
   OSTYPE(freebsd6)
   DOMAIN(generic)
   define(`confDOMAIN_NAME', `mx.domain.ru')dnl
   FEATURE(access_db)
   FEATURE(blacklist_recipients)
   FEATURE(local_lmtp)
   FEATURE(mailertable)
   FEATURE(virtusertable)
   define(`confDONT_BLAME_SENDMAIL',`GroupReadableSASLDBFile')dnl
   define(`confCACERT_PATH',       `/etc/mail/SSL')dnl
   define(`confCACERT',            `/etc/mail/SSL/cacert.pem')dnl
   define(`confSERVER_CERT',       `/etc/mail/SSL/sendmail.pem')dnl
   define(`confSERVER_KEY',        `/etc/mail/SSL/sendmail.pem')dnl
   define(`confCLIENT_CERT',       `/etc/mail/SSL/sendmail.pem')dnl
   define(`confCLIENT_KEY',        `/etc/mail/SSL/sendmail.pem')dnl
   TRUST_AUTH_MECH(`PLAIN LOGIN')dnl
   define(`confAUTH_MECHANISMS', `PLAIN LOGIN')dnl
   define(`confAUTH_OPTIONS', ``A,p,y'')dnl
   FEATURE(`require_rdns')dnl
   FEATURE(`delay_checks')dnl
   FEATURE(`blacklist_recipients')dnl
   FEATURE(dnsbl, `blackholes.mail-abuse.org', ``"550 Mail from " $&{client_addr} " rejected, see http://mail-abuse.org/cgi-bin/lookup?" $&
{client_addr}'')
   FEATURE(`enhdnsbl', `bl.spamcop.net', `"Spam blocked see: http://spamcop.net/bl.shtml?"$&{client_addr}', `t')dnl
   FEATURE(`dnsbl', `zen.spamhaus.org', `"Spam blocked see: http://www.spamhaus.org/query/bl?ip="$&{client_addr}', `t')dnl
   INPUT_MAIL_FILTER(`clmilter',`S=local:/var/run/clamav/clmilter.sock,F=,T=S:4m;R:4m')dnl
   define(`confCW_FILE', `-o /etc/mail/local-host-names')
   dnl Enable for both IPv4 and IPv6 (optional)
   DAEMON_OPTIONS(`Name=NoMTA, Addr=127.0.0.1, M=EA')dnl
   DAEMON_OPTIONS(`Name=IPv4, Family=inet')
   dnl DAEMON_OPTIONS(`Name=IPv6, Family=inet6, Modifiers=O')
   DAEMON_OPTIONS(`Family=inet, Port=465, Name=MTA-SSL, M=s')dnl
   CLIENT_OPTIONS(`Family=inet, Address=mx.domain.ru')
   define(`confBIND_OPTS', `WorkAroundBrokenAAAA')
   define(`confNO_RCPT_ACTION', `add-to-undisclosed')
   define(`confPRIVACY_FLAGS', `authwarnings,noexpn,novrfy')
   MAILER(local)
   MAILER(smtp)
Здесь строка define(`confDOMAIN_NAME', `mx.domain.ru')dnl должна содержать публичное доменное имя этого почтового сервера, которое прописывается в DNS-е в записях МХ. Аналогично со строкой CLIENT_OPTIONS(`Family=inet, Address=mx.domain.ru').
Строки 
  TRUST_AUTH_MECH(`PLAIN LOGIN')dnl
  define(`confAUTH_MECHANISMS', `PLAIN LOGIN')dnl
включают SMPT авторизацию, но так как saslauthd авторизует с помощью PAM в Kerberos-е, можно использовать только пароль в открытом виде. Другие способы, хотя и более безопасные на уровне SMTP требуют наличия открытого пароля на стороне сервера и в нашем случае не доступны. Проблема безопасности паролей решается принуждением почтового клиента использовать шифрование транспорта (TLS или SSL) с помощью следующего параметра:
  define(`confAUTH_OPTIONS', ``A,p,y'')dnl
Остальные параметры хорошо описаны в /usr/share/sendmail/cf/README и прочей документации.
Добавляем в /etc/rc.conf строку
   sendmail_enable=YES
и приводим в действие этот файл конфигурации:
   cd /etc/mail
   make
   make install
   /etc/rc.d/sendmail restart
++ 2.4 Настройка списка адресатов.
Осталась одна чрезвычайно важная деталь - эта настройка приводит к тому, что sendmail отправляет Exchange-ам всю почту пришедшую на наши почтовые домены, не проверяя существуют ли адресаты или нет. Разумеется, получив от Exchange-а отказ из-за отсутствия получателя, sendmail пытается уведомить об этом отправителя, но в большинстве слуаев его не существует - спам он и есть спам. Это набивает очередь sendmail-a не доставимыми письмами, забивает ящик postmaster-а письмами о не возможности доставки, но, что гораздо хуже, даёт дополнительную нагрузку на Exchange.
Существуют несколько путей решения проблемы: на пример, можно запрашивать в АДе по LDAPу существования получателя. Если у вас только один АДовский домен - задача делается тройкой команд в .mc . Если больше - придётся ручками вставлять команды sendmail-a по аналогии с готовыми. Но в результате - доменный контроллер будет довольно сильно нагружен поисками несуществующих адресатов, каждый из которых подразумевает полный проход по базе. Доменный контроллер - не самый лучший кандидат для такой нагрузки, у него много своих собственных задач.
Гораздо логичнее кешировать данные о существуюших адресатах в небольшой базе на самом почтовике. И наиболее подходящей для этой цели является база access.
Для наполнения этой базы можно воспользоваться следующим скриптом (у меня он записан в файл /etc/mail/LDAP2AccessDB):
   #!/bin/sh
   # This filter selects groups (all) and users that are not disabled.
   #Filter='(&(proxyaddresses=smtp:*)(|(&(objectClass=User)
   #(!(userAccountControl:1.2.840.113556.1.4.803:=2)))
   #(objectClass=Group)))'
   # All users that has Exchange account.
   Filter='(&(proxyaddresses=smtp:*)(|(objectClass=User)(objectClass=Group)))'
   Domains='Msk Twn'
   Msk_URL='ldap://msk.lan'
   Msk_BDN='dc=msk,dc=lan'
   Msk_Pfx='/usr/sbin/jail / tmp 192.168.88.254 '
   Msk_Aut=''
   Twn_URL='ldap://twn.lan'
   Twn_BDN='dc=twn,dc=lan'
   Twn_Pfx='/usr/sbin/jail / tmp 192.168.88.254 '
   Twn_Aut=''
   OKeyed_domains='subdom.domain1.ru'
   Relayed_Nets='192.168 127.0'
   cd /etc/mail
   (
        for d in ${Relayed_Nets};   do echo -e "Connect:$d\tRELAY"; done
        for d in ${OKeyed_domains}; do echo -e "To:$d\tOK";         done
        
        for dom in $Domains; do
                eval url="\$${dom}_URL" bdn="\$${dom}_BDN" pfx="\$${dom}_Pfx" auth="\$${dom}_Aut"
                $pfx /usr/local/bin/ldapsearch $auth -QLLL -H "$url" -b "$bdn" "$Filter" proxyaddresses || kill $$
        done                                            |
                /usr/bin/tr '[:upper:]' '[:lower:]'     |
                sed -n 's/^proxyaddresses: *smtp: *//p' |
                sort -t@ +1 +0                          |
                sed 's/.*/To:&  RELAY/'
        sed 's/#.*//;s/[         ]*//;/^$/d;s/.*/To:&   ERROR:"User _really_ unknown. Honestly!"/' relay-domains
   ) > access.new  || exit 254
   /usr/bin/cmp access access.new > /dev/null 2>&1 || {
        [ -d old.accesses ] || mkdir old.accesses || { echo Can not create dir \"old.accesses\"; exit 1; }
        mv access old.accesses/access.`date +%Y%m%d-%H%M`
        mv access.new access
        make maps
   }
В данном скрипте
   Domains    - список АДных доменов, из которых собирается список адресатов.
 
  <Domain_Name>_URL    - URI ссылающийся на сервер LDAPа домена АДа,
 
  <Domain_Name>_BDN    - адрес начала поиска в дереве LDAP,
 
  <Domain_Name>_Pfx    - команда, выполняющая команду ldapsearch - setfib, jail, chroot и прочее. В моём случае используется jail для обхода некоторый особенностей маршрутизации внутри VPN тунелей, такой метод вызова позволяет заставить ldapsearch использовать внутренний адрес при запросе.
 
  <Domain_Name>_Aut    - параметр для авторизации, если домен не принимает авторизацию в домене с помощью SASL2, настроенную в п 1.1
  OKeyed_domains    - список почтовых (под) доменов, которые необходимо пересылать. Если в домене domain1.ru, адресаты которого находятся на сервере Exchange, есть поддомен sub.domain1.ru, обслуживаемый другой почтовой системой, данная схема настройки sendmail-а не позволит пользователям Exchange-а посылать туда письма. Добавление такого домена в OKeyed_domains позволит исключить его из списка блокируемых доменов.
  Relayed_Nets        - список базовых IP адресов сетей или IP адресов компьютеров, почта которых пересылается на произвольные адреса без предварительной авторизации с помощью SMTP AUTH.
Добавляем строку в /etc/crontab
   */15  *  *  *  *   root    /etc/mail/LDAP2AccessDB > /dev/null
++ Заключение
Собственно - всё! Должно работать.
++ Литература
** [[http://www.opennet.dev/base/net/sendmail_sasl_tls.txt.html Настройка Sendmail + SASL2 + TLS/SSL]]
** [[http://wiki.samba.org/index.php/Samba_&_Active_Directory Samba + AD]]
** [[http://www.linuxmail.info/active-directory-cyrus-sasl-authen.../ Active Directory and Cyrus SASL Authentication]]
** [[http://wiki.kryukov.biz/wiki/Sendmail Sendmail WiKi по-русски]]
URL: 
Обсуждается: http://www.opennet.dev/tips/info/2607.shtml