Введение
Итак, имеем следующую схему: есть Postfix, который должен хранить всю информацию по виртуальным пользователям в LDAP. LDAP сервер в моем примере работает под управлением FreeBsd 7.0, с openldap-server-2.4.8 в качестве LDAP-сервера. Postfix (2.3.8-2) работает под управлением Debian Linux (4.0). Все вместе это крутится на Vmware-server 1.0.7 (так-как доступа к компам, акромя домашнего не имею).
Настройка openldap
Итак, нам надо настроить openldap так, чтобы он мог хранить информацию о ящиках пользавателей, алиасах, и тд. Для этого сначала надо написать соответствующую схему, в стандартных схемах не определены многие необходимые атрибуты. Например, я использую следующую схему, под названием mail.schema:
Код:
#mail.schema
#########
# old postfix mail address attribute from postfix-courier.schema
#attributetype ( 0.9.2342.19200300.100.5.3
# NAME ( 'postfix-alias' 'postfix-email' )
# DESC 'Postfix virtual mailbox'
# EQUALITY caseIgnoreIA5Match
# SUBSTR caseIgnoreIA5SubstringsMatch
# SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
# standart mail address attribute from core.schema included at OpenLDAP 2.1.x version
#attributetype ( 0.9.2342.19200300.100.1.3
# NAME ( 'mail' 'rfc822Mailbox' )
# DESC 'RFC1274: RFC822 Mailbox'
# EQUALITY caseIgnoreIA5Match
# SUBSTR caseIgnoreIA5SubstringsMatch
# SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
# standart (from) mail address (for routing forwarding ) attribute from
# misc.schema included at OpenLDAP 2.1.x version
#attributetype ( 2.16.840.1.113730.3.1.13
# NAME 'mailLocalAddress'
# DESC 'RFC822 email address of this recipient'
# EQUALITY caseIgnoreIA5Match
# SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
# standart mail host attribute. see description.
# new unique attribute i'm not used this older howto.
#attributetype ( 2.16.840.1.113730.3.1.18
# NAME 'mailHost'
# DESC 'FQDN of the SMTP/MTA of this recipient'
# EQUALITY caseIgnoreIA5Match
# SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256}
# SINGLE-VALUE )
# old postfix mail forwarding attribute from postfix-courier.schema
#attributetype ( 0.9.2342.19200300.100.5.5
# NAME ( 'postfix-forward' 'postfix-remote-alias')
# DESC 'Postfix forwarding maps'
# EQUALITY caseIgnoreIA5Match
# SUBSTR caseIgnoreIA5SubstringsMatch
# SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
# standart mail routing attribute. may be used for forwarding (to)
#attributetype ( 2.16.840.1.113730.3.1.47
# NAME 'mailRoutingAddress'
# DESC 'RFC822 routing address of this recipient'
# EQUALITY caseIgnoreIA5Match
# SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256}
# SINGLE-VALUE )
# very intresting attribute. This it can used in mail subscribe by members.
# You know any MTA support this ?
#attributetype ( 1.3.6.1.4.1.42.2.27.2.1.15
# NAME 'rfc822MailMember'
# DESC 'rfc822 mail address of group member(s)'
# EQUALITY caseIgnoreIA5Match
# SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
########## courier schema ###############
# Remember ! if you use this schema exclude authldap.schema.
attributetype ( 1.3.6.1.4.1.10018.1.1.2 NAME 'quota'
DESC 'A string that represents the quota on a mailbox'
EQUALITY caseExactIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.10018.1.1.3 NAME 'maildrop'
DESC 'The absolute path to the mailbox for a mail account in a non-default location'
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
# use mailHost ?
attributetype ( 1.3.6.1.4.1.10018.1.1.4 NAME 'mailDomain'
DESC 'A virtual mail domain'
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
attributetype ( 1.3.6.1.4.1.10018.1.1.5
NAME 'mailTransport'
DESC 'transport for domain'
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
attributetype ( 1.3.6.1.4.1.10018.1.1.6
NAME 'mailAccess'
DESC 'Access string'
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
############################
# object class
############################
# old postfix object for mail forwarding.
#objectclass (0.9.2342.19200300.100.5.13
# NAME 'postfix-forward-map'
# DESC 'Postfix forward map'
# SUP top STRUCTURAL
# MUST ( postfix-alias $ postfix-forward ) )
#
# standart object for mail forward.
# object class for routing & forwarding.
# additional information mailHost.
# Can help routing in multi MTA & LDAP server configuration and saves timein search.
# objectclass ( 2.16.840.1.113730.3.2.147
# NAME 'inetLocalMailRecipient'
# DESC 'Internet local mail recipient'
# SUP top STRUCTURAL
# MAY ( mailLocalAddress $ mailHost $ mailRoutingAddress ) )
# warning !!! change AUXILIARY to STRUCTURAL !
#objectclass (0.9.2342.19200300.100.5.12
# NAME 'postfix-alias-map'
# DESC 'Postfix virtual account map'
# SUP top STRUCTURAL
# MUST ( postfix-alias $ postfix-uid $ postfix-gid $ postfix-maildir )
# MAY ( userPassword $ courier-clearPassword $ courier-home $ courier-quota ) )
# object class for full mail account
objectclass ( 1.3.6.1.4.1.10018.1.2.1 NAME 'fullMailAccount' SUP top STRUCTURAL
DESC 'Full mail account object as used by the mail for server recive &storage messages'
MUST ( mail $ maildrop $ uidNumber $ gidNumber )
MAY ( uid $ cn $ description $ quota $ userPassword ) )
# object class for mail account
# others attributes contains in additonal posixAccount.
objectclass ( 1.3.6.1.4.1.10018.1.2.2 NAME 'mailAccount' SUP organizationalPerson STRUCTURAL
DESC 'mail account object as used by the mail for server recive & storage messages'
MUST ( mail $ maildrop )
MAY ( quota ) )
#objectclass (0.9.2342.19200300.100.5.11
# NAME 'postfix-transport-map'
# DESC 'Postfix virtual domain-transport map'
# SUP top STRUCTURAL
# MUST ( postfix-domain $ postfix-transport ) )
# object class for virtual mail domain
# & additional transport table
objectclass ( 1.3.6.1.4.1.10018.1.2.3 NAME 'mailDomainTransport' SUP top STRUCTURAL
DESC 'Domain mail aliasing/transporting entry'
MUST ( mailDomain )
MAY ( mailTransport $ description ) )
# alternate object class
#objectclass ( 1.3.6.1.4.1.10018.1.2.3 NAME 'mailDomainTransport' SUP top STRUCTURAL
# DESC 'Domain mail aliasing/transporting entry'
# MUST ( mailHost )
# MAY ( mailTransport $ description ) )
# additional class object for access network & ip we can got in nis.schema
# ipHost & ipNetwork
# blacklist object class
objectclass ( 1.3.6.1.4.1.10018.1.2.4 NAME 'mailAccess' SUP top STRUCTURAL
DESC 'mail & domain access entry'
MUST ( mail )
MAY ( mailAccess $ description ) )
Теперь нам надо настроить slapd.conf, и ldap.conf.
Код:
#/usr/local/etc/openldap/slapd.conf
#
# See slapd.conf(5) for details on configuration options.
# This file should NOT be world readable.
#
include /usr/local/etc/openldap/schema/core.schema
include /usr/local/etc/openldap/schema/misc.schema
include /usr/local/etc/openldap/schema/mail.schema
# Define global ACLs to disable default read access.
# Do not enable referrals until AFTER you have a working directory
# service AND an understanding of referrals.
#referral ldap://root.openldap.org
pidfile /var/run/openldap/slapd.pid
argsfile /var/run/openldap/slapd.args
# Load dynamic backend modules:
modulepath /usr/local/libexec/openldap
moduleload back_bdb
# moduleload back_hdb
# moduleload back_ldap
# Sample security restrictions
# Require integrity protection (prevent hijacking)
# Require 112-bit (3DES or better) encryption for updates
# Require 63-bit encryption for simple bind
# security ssf=1 update_ssf=112 simple_bind=64
# Sample access control policy:
# Root DSE: allow anyone to read it
# Subschema (sub)entry DSE: allow anyone to read it
# Other DSEs:
# Allow self write access
# Allow authenticated users read access
# Allow anonymous users to authenticate
# Directives needed to implement policy:
# access to dn.base="" by * read
# access to dn.base="cn=Subschema" by * read
# access to *
# by self write
# by users read
# by anonymous auth
#
# if no access controls are present, the default policy
# allows anyone and everyone to read anything but restricts
# updates to rootdn. (e.g., "access to * by * read")
#
# rootdn can always read and write EVERYTHING!
#######################################################################
# BDB database definitions
#######################################################################
database bdb
directory /var/db/ldap/local.net
suffix "dc=local,dc=net"
rootdn "cn=ldapadmin,dc=local,dc=net"
rootpw {SSHA}gtnZ2mIrPlSD5E9EsrT3xelxYxCfE1PA
index objectClass eq
index cn eq,sub
index sn eq,sub
access to attrs=userPassword
by * auth
########################
#/usr/local/etc/openldap/ldap.conf
#
# LDAP Defaults
#
# See ldap.conf(5) for details
# This file should be world readable but not world writable.
BASE dc=local,dc=net
URI ldap://127.0.0.1
#SIZELIMIT 12
#TIMELIMIT 15
#DEREF never
Запускаем slapd:
Код: Выделить всё
echo "spald_enable="YES" >> /etc/rc.conf
/usr/local/etc/rc.d/slapd startПосле этого создаем ldif-файл следующего содержания:
Код:
#base.ldif
dn: dc=local,dc=net
objectClass: dcObject
objectClass: organizationalUnit
ou: Bell labs
dc: local
dn: ou=peoples,dc=local,dc=net
objectClass: organizationalUnit
ou: peoples
dn: ou=it,ou=peoples,dc=local,dc=net
objectClass: organizationalUnit
ou: it
description: IT workers
dn: ou=managers,ou=peoples,dc=local,dc=net
objectClass: organizationalUnit
ou: managers
description: All other workers
dn: cn=Denis,ou=it,ou=peoples,dc=local,dc=net
objectClass: mailAccount
mail: denis@mail.local.net
maildrop: denis/
cn: Denis
sn: Vasiljev
dn: cn=Peta,ou=managers,ou=peoples,dc=local,dc=net
objectClass: mailAccount
mail: peta@mail.local.net
maildrop: peta/
cn: Peta
sn: Pupkin
И добавляем данные записи в базу.
Код: Выделить всё
ldapadd -x -W -D "cn=ldapamin,dc=local,dc=net" -f base.ldifЕсли все прошло без ошибок, тогда пробуем прочитать данные из базы
Код:
%ldapsearch -x -W -D "cn=ldapadmin,dc=local,dc=net" "(objectClass=mailAccount)"
Enter LDAP Password:
# extended LDIF
#
# LDAPv3
# base <dc=local,dc=net> (default) with scope subtree
# filter: (objectClass=mailAccount)
# requesting: ALL
#
# Denis, it, peoples, local.net
dn: cn=Denis,ou=it,ou=peoples,dc=local,dc=net
objectClass: mailAccount
mail: denis@mail.local.net
maildrop: denis/
cn: Denis
sn: Repkov
# Peta, managers, peoples, local.net
dn: cn=Peta,ou=managers,ou=peoples,dc=local,dc=net
objectClass: mailAccount
mail: peta@mail.local.net
maildrop: peta/
cn: Peta
sn: Pupkin
# search result
search: 2
result: 0 Success
# numResponses: 3
# numEntries: 2
Настройка Postfix
Создаем следующий /etc/postfix/main.cf
Код:
myorigin = $myhostname
myhostname = mail.local.net
smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
biff = no
# appending .domain is the MUA's job.
append_dot_mydomain = no
# Uncomment the next line to generate "delayed mail" warnings
#delay_warning_time = 4h
# TLS parameters
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${queue_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${queue_directory}/smtp_scache
# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.
#максимальный размер сообщения - 3мб
message_size_limit = 3145728
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
mynetworks = 127.0.0.0/8 192.168.100.0/25
inet_interfaces = all
#почта для пользователей из /etc/passwd
mydestination = localhost
mailbox_command = procmail -a "$EXTENSION"
#максимальный размер ящика - 20мб
mailbox_size_limit = 20971520
recipient_delimiter = +
#почта для виртуальных пользователей
virtual_mailbox_domains = $myhostname
virtual_mailbox_maps = ldap:/etc/postfix/virtual-mbox.cf
virtual_mailbox_base = /var/mail/virtual
virtual_uid_maps = static:1999
virtual_gid_maps = static:1999
#максимальный размер ящика - 20мб
virtual_mailbox_limit = 20971520
Теперь создаем /etc/postfix/virtual/mbox.cf, в котором описывается подключение к LDAP-серверу, ключи поиска, поле результата и тд (подробнее можно узнать по [i]man ldap_table[i]
Код:
#по умолчанию используется вторая версия
version = 3
server_host = ldap://192.168.100.69
search_base = dc=local,dc=net
query_filter = (&(mail=%s)(objectClass=mailAccount))
result_attribute = maildrop
bind_dn = cn=ldapadmin,dc=local,dc=net
bind_pw = gmzyyfz
Теперь проверяем правильность вышеописанного файла при помощи postmap:
Код: Выделить всё
/usr/sbin/postmap -q denis@mail.local.net ldap:/etc/postfix/virtual-mbox.cf
denis/Теперь создаем системного пользователя, кому будут принадлежать все ящики виртуальных пользователей:
Код: Выделить всё
sudo /usr/sbin/addgroup --system --gid 1999 vmailgroup
sudo /usr/sbin/adduser --system --no-create-home --uid 1999 --ingroup vmailgroup vmailuser
sudo mkdir /var/mail/virtual
sudo chown vmailuser:vmailgroup /var/mail/virtualИ запускаем Postfix:
Код: Выделить всё
/etc/init.d/postfix startВот, собственно, и всё. Отдельное спасибо хочется сказать Ork'у Paladin'у за книжный архив и зеркало портов на www.simlada.ru, а так-же разработчикам Vmware-server, так-как без них пришлось-бы реализовывать схему на одном компе, что было-бы не очень познавательно.