Описание задачи
Имеется:
Компания с несколькими офисами по всему миру
Много доменная структура на базе 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
Заключение
Собственно - всё! Должно работать.
Литература
Настройка Sendmail + SASL2 + TLS/SSL
Samba + AD
Active Directory and Cyrus SASL Authentication
Sendmail WiKi по-русски
|