免费获取学习方案
ARTICLE DETAIL

资讯详情

深耕编程基础知识与建站技术分享的一线实战洞察。

Docker Mailserver 对接 LDAP 目录服务:Postfix / Dovecot / saslauthd 全套账户供给实战指南

Docker Mailserver 对接 LDAP 目录服务:Postfix / Dovecot / saslauthd 全套账户供给实战指南 Docker Mailserver 对接 LDAP 目录服务Postfix / Dovecot / saslauthd 全套账户供给实战指南【免费下载链接】docker-mailserverProduction-ready fullstack but simple mail server (SMTP, IMAP, LDAP, Antispam, Antivirus, etc.) running inside a container.项目地址: https://gitcode.com/gh_mirrors/do/docker-mailserver导读本文以 Docker MailserverDMS官方文档为骨架系统讲解如何用 LDAP 目录服务统一管理邮箱账户收信、投递由 Postfix 完成信箱访问与 IMAP 登录由 Dovecot 完成SMTP 发信认证由 saslauthd 完成。读完本文你将掌握LDAP_QUERY_FILTER_*系列查询过滤器、DOVECOT_*_FILTER/DOVECOT_*_ATTRS属性映射、StartTLS / LDAPS 安全连接以及面向 Active Directory含 Samba4 AD的完整落地方案并可直接复制文中完整的 docker-compose 配置启动一个 LDAP 驱动的邮件服务器。本文对应的官方文档位于 docs/content/config/account-management/provisioner/ldap.md所有环境变量的默认值可在 环境变量参考 中查询。LDAP 供给模型三个组件各司其职让 DMS 与 LDAP 协同工作需要理解三个组件的分工组件职责在 DMS 中的角色postfix接收与投递邮件SMTP通过virtual_mailbox_maps、virtual_alias_maps、virtual_mailbox_domains查询 LDAP决定域名是否有效、信箱归属与别名解析dovecot访问邮箱IMAP/POP3通过 userdb/passdb 的 LDAP 查询验证用户口令并取回 uid、gid、home、mail 路径等账号细节saslauthdSMTP 认证当SASLAUTHD_MECHANISMSldap时Postfix 把认证请求转发给 saslauthd 查 LDAP也可用rimap机制把认证委托给 Dovecot从源码结构看三者分别对应 target/postfix/ 目录下的ldap-*.cf文件、target/dovecot/auth-ldap.conf.ext 以及 saslauthd 的独立配置。容器启动时由 target/scripts/startup/setup.d/ldap.sh 统一完成这三套配置的渲染与装配。通过环境变量控制账户供给启用 LDAP 供给的前提是把ACCOUNT_PROVISIONER设为LDAP并配置 LDAP 服务器连接参数LDAP_SERVER_HOST、LDAP_SEARCH_BASE、LDAP_BIND_DN、LDAP_BIND_PW。以下分三组变量详细说明。LDAP_QUERY_FILTER_*Postfix 的 LDAP 查询过滤器这组变量存放 Postfix 使用的 LDAP 查询过滤器用%s作为域名或邮箱地址的占位符。不同过滤器服务于不同的邮件生命周期阶段收信incoming email域名必须能被DOMAIN过滤器命中对应 Postfix 的virtual_alias_domains语义。实际投递到哪些信箱由USER、ALIAS、GROUP三个过滤器共同决定USER指定个人信箱每个地址通常只应有一个命中项例如(mail%s)对应virtual_mailbox_mapsALIAS指定信箱的别名例如(mailAlias%s)通过virtual_alias_maps实现GROUP指定群组内的个人信箱多人共同收信例如(mailGroupMember%s)同样走virtual_alias_maps。技术上ALIAS与GROUP没有区别但最佳实践是ALIAS用于指向单一个人的个人别名如ceoexample.orgGROUP用于指向多人如hrexample.org。发信outgoing email发件人地址会被送入SENDERS过滤器只有认证用户属于返回的条目之一时才允许其以此地址发信。该行为仅在SPOOF_PROTECTION1时生效若未设置SENDERS过滤器则退化为USER、ALIAS、GROUP三个过滤器的或OR组合例如允许admin组成员伪造任意发件人、其余用户只能用个人信箱地址发信可写为(|(memberOfcnadmin,*)(mail%s))。一个只使用 user 过滤器、且仅允许admin*伪造发件地址的最小化配置示例- LDAP_START_TLSyes - ACCOUNT_PROVISIONERLDAP - LDAP_SERVER_HOSTldap.example.org - LDAP_SEARCH_BASEdcexample,dcorg - LDAP_BIND_DNcnadmin,dcexample,dcorg - LDAP_BIND_PWmypassword - SPOOF_PROTECTION1 - LDAP_QUERY_FILTER_DOMAIN(mail*%s) - LDAP_QUERY_FILTER_USER(mail%s) - LDAP_QUERY_FILTER_ALIAS(|) # 不匹配任何内容 - LDAP_QUERY_FILTER_GROUP(|) # 不匹配任何内容 - LDAP_QUERY_FILTER_SENDERS(|(mail%s)(mailadmin*))提示LDAP_QUERY_FILTER_ALIAS与LDAP_QUERY_FILTER_GROUP设置为(|)不匹配任何条目用于明确关闭别名与群组查询。底层实现环境变量如何落到 Postfix 配置文件DMS 在容器镜像内预置了五份 Postfix LDAP 映射模板target/postfix/ldap-users.cf、target/postfix/ldap-aliases.cf、target/postfix/ldap-groups.cf、target/postfix/ldap-domains.cf、target/postfix/ldap-senders.cf。它们在容器内实际位于/etc/postfix/由 ldap.sh 中的_setup_ldap()函数用_replace_by_env_in_file LDAP_将LDAP_QUERY_FILTER_USER等环境变量逐一替换进对应文件的query_filter行见 ldap.sh 的 L108-L133。替换完成后脚本通过postconf将 LDAP 映射接入 Postfix 主配置ldap.sh 的 L189-L205postconf virtual_mailbox_maps ldap:/etc/postfix/ldap-users.cf postconf virtual_mailbox_domains /etc/postfix/vhost, ldap:/etc/postfix/ldap-domains.cf postconf virtual_alias_maps ldap:/etc/postfix/ldap-aliases.cf, ldap:/etc/postfix/ldap-groups.cf由此可以看出USER对应virtual_mailbox_mapsALIAS与GROUP共同对应virtual_alias_mapsDOMAIN对应virtual_mailbox_domains。若希望在启动时使用自定义的ldap-*.cf例如 Active Directory 场景下为ldap-groups.cf追加额外参数只需把文件放入挂载目录/tmp/docker-mailserver/脚本会优先复制自定义文件ldap.sh 的 L108-L113。模板文件同时也展示了各映射的默认查询写法例如 ldap-users.cf 默认query_filter ((mail%s)(mailEnabledTRUE))、result_attribute mailldap-domains.cf 默认query_filter ((|(mail*%s)(mailalias*%s))(mailEnabledTRUE))可作为理解过滤器语义的参考。DOVECOT_*_FILTER与DOVECOT_*_ATTRSDovecot 的登录与属性映射这组变量指定 Dovecot 判定用户能否登录 IMAP 的 LDAP 过滤器以及为某个 Postfix 用户接收邮件时应当使用哪个信箱。它拆分为两次查询均以%{user}作为完整登录名的占位符Dovecot 占位符全集见其官方配置文档DOVECOT_USER_FILTER取回账号细节uid、gid、home 目录、quota 等DOVECOT_PASS_FILTER取回口令信息绝大多数情况下与DOVECOT_USER_FILTER完全一致默认行为未设置时自动复用DOVECOT_USER_FILTER。通常你只需设置DOVECOT_USER_FILTER它会被同时用于两次查询。如果你的目录没有安装 postfix-book schema则必须调整 Dovecot 的内部属性处理即修改pass_attr与user_attr映射- DOVECOT_PASS_ATTRSYOUR_USER_IDENTIFIER_ATTRIBUTEuser,YOUR_USER_PASSWORD_ATTRIBUTEpassword - DOVECOT_USER_ATTRSYOUR_USER_HOME_DIRECTORY_ATTRIBUTEhome,YOUR_USER_MAILSTORE_ATTRIBUTEmail,YOUR_USER_MAIL_UID_ATTRIBUTEuid,YOUR_USER_MAIL_GID_ATTRIBUTEgid关于DOVECOT_*_ATTRS的两种写法既可以用ldapAttrdovecotAttr形式也可以换成dovecotAttr%{ldap:ldapAttr}以换取更高灵活性例如home/var/mail/%{ldap:uid}或直接写死uid5000。DMS 会把这种旧式映射转换为 Dovecot 2.4 的fields { }条目其中mail字段会被转换为mail_path且会去除开头的maildir:前缀。Dovecot 属性全集可查阅其 userdb 官方文档。默认值示例对应 postfix-book schema- DOVECOT_USER_ATTRSmailHomeDirectoryhome,mailUidNumberuid,mailGidNumbergid,mailStorageDirectorymail - DOVECOT_PASS_ATTRSuniqueIdentifieruser,userPasswordpassword - DOVECOT_USER_FILTER((objectClassPostfixBookMailAccount)(uniqueIdentifier%{user | username}))qmail schema 目录示例使用uid- DOVECOT_PASS_ATTRSuiduser,userPasswordpassword - DOVECOT_USER_ATTRShomeDirectoryhome,qmailUIDuid,qmailGIDgid,mailMessageStoremail - DOVECOT_USER_FILTER((objectClassqmailUser)(uid%{user})(accountStatusactive))注意DOVECOT_*_ATTRS左侧是目录属性名右侧是 Dovecot 变量名环境变量参考 中DOVECOT_USER_ATTRS与DOVECOT_PASS_ATTRS条目有同样说明。底层实现属性映射如何转换成 Dovecot 2.4 配置Dovecot 的 LDAP 模板 target/dovecot/auth-ldap.conf.ext 中passdb 与 userdb 各留有一个fields { }块内部含# DOVECOT_PASSDB_FIELDS/# DOVECOT_USERDB_FIELDS标记行模板默认值即 postfix-book schema 的映射passdb ldap { fields { # DOVECOT_PASSDB_FIELDS user %{ldap:uniqueIdentifier} password %{ldap:userPassword} } } userdb ldap { fields { # DOVECOT_USERDB_FIELDS uid %{ldap:mailUidNumber} gid %{ldap:mailGidNumber} home %{ldap:mailHomeDirectory} mail_path %{ldap:mailStorageDirectory} } }ldap.sh 中的_dovecot_ldap_attrs_to_fields()L3-L51会把DOVECOT_USER_ATTRS/DOVECOT_PASS_ATTRS逐个解析成字段 值行并替换进上述标记位mail字段改名mail_path、剥离maildir:前缀、以及DOVECOT_AUTH_BINDyes时跳过password字段等逻辑均在该函数中实现L37-L43。同时Dovecot 的连接参数默认继承自 Postfix 的 LDAP 配置ldap.sh 的 L137-L158DOVECOT_URIS默认取LDAP_SERVER_HOST、DOVECOT_BASE默认取LDAP_SEARCH_BASE、DOVECOT_DN/DOVECOT_DNPASS默认取LDAP_BIND_DN/LDAP_BIND_PW、DOVECOT_TLS默认no、LDAP 版本默认 3、默认口令方案为SSHA。其余可调项同样见 环境变量参考 的 Dovecot 小节。DOVECOT_AUTH_BIND使用认证绑定设为yes可启用认证绑定authentication bindsDovecot 通过以该用户身份绑定来验证其口令此时DOVECOT_PASS_ATTRS中的password字段会被忽略。底层逻辑同样体现在 ldap.sh 中——启用后不仅写入passdb_ldap_bind yes还会删除auth-ldap.conf.ext中默认的password字段行L176-L180且_dovecot_ldap_attrs_to_fields()在OMIT_PASSWORDyes时也会跳过 password 映射。该方案适合口令散列方式不透明例如 sambaNTPassword 等的目录。SASLAUTHD_LDAP_FILTERSMTP 认证专用过滤器当 Postfix 收到 SMTP 认证请求且SASLAUTHD_MECHANISMSldap时认证由saslauthd完成此过滤器即供其使用。注意 saslauthd 的 LDAP 服务器需要单独配置与 Postfix 相对独立。该过滤器的可用 token 与 saslauthd 的 LDAP 支持一致但目前对域名支持并不理想%U是其中唯一有实际意义的 token——即把整个登录名含或不含域名作为匹配依据。何时使用、如何绕开它使用独立的 SMTP 认证过滤器可以做到类似允许noreplyexample.org发信但不允许它登录 IMAP 或收信的精细控制((mail%Uexample.org)(|(memberOfcnemail,*)(mailnoreplyexample.org)))如果不想为 SMTP 认证单独维护过滤器可设置SASLAUTHD_MECHANISMSrimap与SASLAUTHD_MECH_OPTIONS127.0.0.1把认证委托给本机 Dovecot——此时DOVECOT_USER_FILTER与DOVECOT_PASS_FILTER也会被用于 SMTP 认证。saslauthd LDAP 的最小配置示例- ENABLE_SASLAUTHD1 - SASLAUTHD_MECHANISMSldap - SASLAUTHD_LDAP_FILTER(mail%Uexample.org)saslauthd 相关可调参数较多包括SASLAUTHD_LDAP_START_TLS、SASLAUTHD_LDAP_TLS_CACERT_DIR/FILE、SASLAUTHD_LDAP_BIND_DN、SASLAUTHD_LDAP_PASSWORD、SASLAUTHD_LDAP_SEARCH_BASE、SASLAUTHD_LDAP_AUTH_METHOD默认bind等详见 环境变量参考 的 SASL Auth 小节。安全连接LDAPS 与 StartTLS启用 LDAPS 只需在LDAP_SERVER_HOST中写明协议例如ldaps://example.org:636。若改用 StartTLS389 端口则需设置以下环境变量注意此时协议绝不能写成ldaps://- LDAP_START_TLSyes - DOVECOT_TLSyes - SASLAUTHD_LDAP_START_TLSyes三者分别对 Postfix、Dovecot、saslauthd 开启 StartTLS。从实现看LDAP_START_TLSyes会写入ldap-*.cf的start_tls字段模板默认no见 target/postfix/ldap-users.cfDOVECOT_TLS则映射为 Dovecot 2.4 的ldap_starttlsldap.sh 的 L143-L144。另外若/etc/ldap/ldap.conf中的TLS_REQCERT保持默认的demand/hard则用于校验 LDAP 服务器证书的 CA 必须被系统信任详见下文 Active Directory 一节的 CA 注入方法。对接 Active Directory以 Samba4 AD 实现验证当 DMS 对接 Active Directory或 Samba4 AD DC 等等效实现时除上述通用 LDAP 说明外还需注意以下几点Samba4 AD 要求与域控制器DC之间必须使用安全连接即 SSL/TLSLDAPS或 StartTLSAD 中的用户名对应属性为sAMAccountNameproxyAddresses可用于存放单个用户的邮箱别名约定以smtp:为前缀如smtp:some.nameexample.comAD 通常不只是 LDAP 目录还充当域控制器负责认证等众多事务。若需同时容纳 Linux 与 Windows 客户端应使用 RFC2307 属性即uidNumber、gidNumber而非常见的uid。这种方案也可以为不同邮箱文件夹指定不同属主但当前 DMS 存在一个已知问题容器启动时会覆盖所有权限对应 PR #2256 所跟踪的缺陷。在修复前要么手动修复要么临时用硬编码的ldap:uidNumber5000作为变通要让邮件投递到 AD安全组或通讯组类似邮件列表的不同成员需借助 user-patches.sh 脚本 修改ldap-groups.cf使其包含leaf_result_attribute mail与special_result_attribute member# user-patches.sh ... grep -q ^leaf_result_attribute mail$ /etc/postfix/ldap-groups.cf || echo leaf_result_attribute mail /etc/postfix/ldap-groups.cf grep -q ^special_result_attribute member$ /etc/postfix/ldap-groups.cf || echo special_result_attribute member /etc/postfix/ldap-groups.cf ...若/etc/ldap/ldap.conf的TLS_REQCERT为demand/hard默认值用于校验 LDAP 服务器证书的 CA 必须被识别为受信 CA。可通过挂载ca.crt文件并用user-patches.sh更新信任库# user-patches.sh ... cp /MOUNTED_FOLDER/ca.crt /usr/local/share/ca-certificates/ update-ca-certificates ...说明user-patches.sh是 DMS 提供的容器内启动时执行自定义脚本的扩展点详细用法见 user-patches 文档。以下是与 Active Directory 协同所需的配置变更仅列出变更项其余 LDAP 配置可从本文其他示例中获取# 若选择 StartTLS 与 AD 建立安全连接 - LDAP_START_TLSyes - SASLAUTHD_LDAP_START_TLSyes - DOVECOT_TLSyes - LDAP_QUERY_FILTER_USER((objectclassperson)(mail%s)) - LDAP_QUERY_FILTER_ALIAS((objectclassperson)(proxyAddressessmtp:%s)) # 过滤 AD 组邮件列表。同时还需按上文修改 ldap-groups.cf。 - LDAP_QUERY_FILTER_GROUP((objectClassgroup)(mail%s)) - LDAP_QUERY_FILTER_DOMAIN(mail*%s) # 仅允许 Domain Admins 使用任意发件地址其余发件地址必须与 LDAP 属性 mail 匹配 - SPOOF_PROTECTION1 - LDAP_QUERY_FILTER_SENDERS(|(mail%s)(proxyAddressessmtp:%s)(memberOfcnDomain Admins,cnUsers,dc*)) - DOVECOT_USER_FILTER((objectclassperson)(sAMAccountName%{user | username})) # 当前要使用 %{ldap:uidNumber} 需先应用上文所述手动修复否则将其替换为硬编码值 5000 - DOVECOT_USER_ATTRSuid%{ldap:uidNumber},gid5000,home/var/mail/%{user | username},mailmaildir:~/Maildir - DOVECOT_PASS_ATTRSsAMAccountNameuser,userPasswordpassword - SASLAUTHD_LDAP_FILTER((sAMAccountName%U)(objectClassperson))完整的 LDAP 部署示例基础配置Basic Setup面向典型的 OpenLDAP / 具备 Postfix Book 类 schema 的目录Postfix 与 Dovecot 双 LDAP 供给外加 saslauthd 的 LDAP SMTP 认证services: mailserver: image: ghcr.io/docker-mailserver/docker-mailserver:latest container_name: mailserver hostname: mail.example.com ports: - 25:25 - 143:143 - 587:587 - 993:993 volumes: - ./docker-data/dms/mail-data/:/var/mail/ - ./docker-data/dms/mail-state/:/var/mail-state/ - ./docker-data/dms/mail-logs/:/var/log/mail/ - ./docker-data/dms/config/:/tmp/docker-mailserver/ - /etc/localtime:/etc/localtime:ro environment: - ENABLE_SPAMASSASSIN1 - ENABLE_CLAMAV1 - ENABLE_FAIL2BAN1 - ENABLE_POSTGREY1 # Postfix LDAP 集成 - ACCOUNT_PROVISIONERLDAP - LDAP_SERVER_HOSTldap.example.org - LDAP_BIND_DNcnadmin,ouusers,dcexample,dcorg - LDAP_BIND_PWmypassword - LDAP_SEARCH_BASEdcexample,dcorg - LDAP_QUERY_FILTER_DOMAIN(|(mail*%s)(mailAlias*%s)(mailGroupMember*%s)) - LDAP_QUERY_FILTER_USER((objectClassinetOrgPerson)(mail%s)) - LDAP_QUERY_FILTER_ALIAS((objectClassinetOrgPerson)(mailAlias%s)) - LDAP_QUERY_FILTER_GROUP((objectClassinetOrgPerson)(mailGroupMember%s)) - LDAP_QUERY_FILTER_SENDERS((objectClassinetOrgPerson)(|(mail%s)(mailAlias%s)(mailGroupMember%s))) - SPOOF_PROTECTION1 # Postfix LDAP 集成 # Dovecot LDAP 集成 - DOVECOT_USER_FILTER((objectClassinetOrgPerson)(mail%{user})) - DOVECOT_PASS_ATTRSuiduser,userPasswordpassword - DOVECOT_USER_ATTRShome/var/mail/%{ldap:uid},mailmaildir:~/Maildir,uidNumberuid,gidNumbergid # Dovecot LDAP 集成 # SASL LDAP 认证 - ENABLE_SASLAUTHD1 - SASLAUTHD_MECHANISMSldap - SASLAUTHD_LDAP_FILTER((mail%Uexample.org)(objectClassinetOrgPerson)) # SASL LDAP 认证 - SSL_TYPEletsencrypt - PERMIT_DOCKERhost cap_add: - NET_ADMINKopano / Zarafa 场景若后端使用 Kopano / Zarafa 而非 Dovecot 提供邮箱服务SMTP-only 模式则关闭 Dovecot、开启SMTP_ONLY1并把投递代理指向 Kopano 的 LMTP 端口services: mailserver: image: ghcr.io/docker-mailserver/docker-mailserver:latest container_name: mailserver hostname: mail.example.com ports: - 25:25 - 143:143 - 587:587 - 993:993 volumes: - ./docker-data/dms/mail-data/:/var/mail/ - ./docker-data/dms/mail-state/:/var/mail-state/ - ./docker-data/dms/config/:/tmp/docker-mailserver/ environment: # 此处不使用 dovecot - SMTP_ONLY1 - ENABLE_SPAMASSASSIN1 - ENABLE_CLAMAV1 - ENABLE_FAIL2BAN1 - ENABLE_POSTGREY1 - SASLAUTHD_PASSWD # SASL 认证 - ENABLE_SASLAUTHD1 - SASLAUTHD_LDAP_FILTER((sAMAccountName%U)(objectClassperson)) - SASLAUTHD_MECHANISMSldap # SASL 认证 # Postfix LDAP 集成 - ACCOUNT_PROVISIONERLDAP - LDAP_SERVER_HOSTyourLdapContainer/yourLdapServer - LDAP_SEARCH_BASEdcmydomain,dcloc - LDAP_BIND_DNcnAdministrator,cnUsers,dcmydomain,dcloc - LDAP_BIND_PWmypassword - LDAP_QUERY_FILTER_USER((objectClassuser)(mail%s)) - LDAP_QUERY_FILTER_GROUP((objectclassgroup)(mail%s)) - LDAP_QUERY_FILTER_ALIAS((objectClassuser)(otherMailbox%s)) - LDAP_QUERY_FILTER_DOMAIN((|(mail*%s)(mailalias*%s)(mailGroupMember*%s))(mailEnabledTRUE)) # Postfix LDAP 集成 # Kopano 集成 - POSTFIX_DAGENTlmtp:kopano:2003 # Kopano 集成 - SSL_TYPEletsencrypt - PERMIT_DOCKERhost cap_add: - NET_ADMIN相关参考与进一步阅读账户供给概述了解ACCOUNT_PROVISIONER的取值与文件型供给file provisioner的差异文件型账户供给file.md基于postfix-accounts.cf的非 LDAP 方案环境变量完整参考本文所有变量的默认值与取值范围user-patches.sh 用法启动时注入自定义脚本Active Directory 场景必需LDAP 供给的启动装配源码target/scripts/startup/setup.d/ldap.shPostfix LDAP 映射模板target/postfix/ 目录下的ldap-users.cf/ldap-aliases.cf/ldap-groups.cf/ldap-domains.cf/ldap-senders.cfDovecot LDAP 模板target/dovecot/auth-ldap.conf.ext仓库内置的 LDAP 测试配置与用例test/config/ldap/、test/tests/serial/mail_with_ldap.bats可用于对照验证目录结构OpenLDAP schema、用户树、别名与多主域名等与过滤器写法。【免费下载链接】docker-mailserverProduction-ready fullstack but simple mail server (SMTP, IMAP, LDAP, Antispam, Antivirus, etc.) running inside a container.项目地址: https://gitcode.com/gh_mirrors/do/docker-mailserver创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表