2014年1月15日 星期三

整合 iRedMail 與Windows Active Directory

為了將 前人留下的Windows Exchange Server 換成 Linux 環境的 Mail Server
整合測試了好些不同的方案
先決條件必須 能與Windows 的 AD 網域整合帳號及權限管理
也就是
1 所有的郵件帳號是虛擬帳號,
2 使用 AD server 進行使用者收發信的帳號認證
3 使用 SSL, TLS等協定收發郵件
可以的話, 再加上 WebMail 好了.....

最後決定 用 postfix (SMTP) + dovecot (POP3, IMAP)  的架構 來建立
(話說, 這個問題也拖了好久, Postfix 和 Dovecot 的設定檔真是讓人一個頭兩個大)

最近將 一台 ubuntu 10.04LTS update 到 12.04 LTS (>_<  14.04LTS 都快出了吧)
發現了這個 iRedMail 的套件  (其實 好像 9.0x就有了  >_< 消息不靈通, 真糗! )

這個套件本身並不是一個 郵件軟體,  實際上應是一個 "郵件及相關軟體" 的 "管理包"
由郵件軟體, 網站軟體, 資料庫軟體 等等組成

可以設定郵件軟體的安裝組合內容如下:

  1. Postfix: SMTP service
  2. Dovecot: POP3/POP3S, IMAP/IMAPS, Managesieve service
  3. Apache: Web server
  4. MySQL/PostgreSQL: Storing application data and/or mail accounts
  5. OpenLDAP: Storing mail accounts
  6. Policyd: Postfix policy server
  7. Amavisd: An interface between Postfix and SpamAssassin, ClamAV. Used for spam and virus scanning.
  8. Roundcube: Webmail
  9. Awstats: Apache and Postfix log analyzer
  10. Fail2ban: scans log files (e.g. /var/log/maillog) and bans IPs that show the malicious signs -- too many password failures, seeking for exploits, etc.
可以選用的組合包括
1  Postfix + Dovecot + MySQL (or PostgreSQL) 支援帳號認證及設定資料
2  Postfix + Dovecot + OpenLDAP 支援帳號認證
外加 Policyd , Amavisd, Roundcube Webmail, AWstats, Fail2ban 等控制郵件、垃圾郵件檢查、病毒郵件攔截、網頁郵件服務、記錄檔分析及惡意登入攔截等功能

最最重要的是,  經過修改, 可以直接使用 AD 作為帳號認證的伺服器,   在 iRedMail.org 的網站上甚至有詳細的 一步步 設定的文件(已轉移到另一個URL 文件 http://www.iredmail.org/docs/active.directory.html),可以參考。  ^_^

本篇網誌 也只是將該文件作成中文摘要如下(並加上自己的經驗)而已!

Summary 
這篇教學僅在 Windows 2000, 2003, 2008 R2 上作過測試, 如您在其他版本測試成功也請通知我們(http://iredmail.org/contact.html)

使用 AD + iRedMail 整合 有如下的特色:
  • 搭配Windows 網域伺服器管理帳號及郵寄名單
  • 支援AD 網域的群組(可寄信給群組的成員?)
  • WEBMAIL使用者可讀取網域電話簿(不需要另外載入)
  • AD 停用的帳號, iRedMail 系統也同時停用。
因使用AD 作為 LDAP server , 也同時受到影響如下 :
  • 無法直接設定單一使用者或郵件網域的服務(如啟用/停用 POP3/IMAP/SMTP), 必須使用 hash file 代替。(?)
  • 其他
Requirements
要整合使用 Microsoft Active Directory 及 iRedMail 必須有的項目:
  • 一台可用的 Linus/BSD  伺服器 並安裝好 iRedMail+OpenLDAP 。(目前 Ubuntu 12.04LTS 工作的很OK, 安裝iRedMail 時記得選 OpenLDAP)
  • 一台Windows  2000/2003 伺服器, 已提升為 AD並工作正常, port 389 或 636 可接收來自前面伺服器的連線。
Install iRedMail
請參考 http://www.iredmail.org/install_iredmail_on_ubuntu.html
記得選擇 OpenLDAP 安裝,
(有關 LDAP server 的設定是連接OpenLDAP用的, 後面會手動修改為連接AD)

Integrate Microsoft Active Directory
假設如下:
  • AD 網域伺服器是  'ad.example.com',   監聽埠 389
  •  下面皆使用這個主機名稱, 也可改為IP或您真實的主機名稱
  •   若要使用 LDAPS 請設定 監聽埠 為 636
  • Base dn 使用 "dc=example,dc=com", 郵件網域是 '@example.com'
  • 所有的使用者放在 dn "cn=Users,dc=example,dc=com" 
  • 使用 LDAP 通訊協定版本 3 
  • 郵件存放在 Linux /BSD 伺服器上而不是 AD 伺服器
  • 郵件存放的位置   /var/vmail/vmail1  , 與 iRedMail 預設值一致
  • 使用者 "support@example.com" 的郵件位於 /var/vmail/vmail1/example.com/support/Maildir/, 使用 Maildir 格式
Cread user account in AD, used for LDAP query
建立供LDAP查詢的AD使用者帳號(也可使用現有的AD使用者帳號 )
為能提供iRedMail +OpenLDAP, 須建立一個低使用權的帳號 "cn=vmail,dc=example,dc=com"僅供查詢即可,  建議的帳號如 vmail, 密碼請勿過於簡單
注意事項:
  • Dovecot 會將 '#' 當作是註解而不處理其後的所有字元, 請勿使用該字元於密碼中 
Test AD query with ldap command line tool on iRedMail server
測試AD查詢是否正常工作

請使用以下的指令測試 iRedMail 是否可正常查詢 AD 的使用者資料
 
ldapsearch -x -h ad.example.com -D 'vmail' -W -b 'cn=users,dc=example,dc=com'

當畫面出現 Enter password: 請輸入 vmail 的密碼
若畫面出現AD server 回傳的使用者資料, 則表示連線查詢的作業正常完成


-----------------------------------------------------------------------------
Enable LDAP query with AD in Postfix
請依序設定Postfix 中的部份系統設定值
目的如下:
  • 停用無用的 iRedMail 部份設定
  • 轉向AD進行認證而非向本地的OpenLDAP認證
將於稍後建立3個檔案如下:
  • /etc/postfix/ad_virtual_mailbox_maps.cf
  • /etc/postfix/ad_virtual_group_maps.cf
  • /etc/postfix/ad_sender_login_maps.cf 
  • 停用無用的 iRedMail 部份設定:

# postconf -e virtual_alias_maps=''
# postconf -e sender_bcc_maps=''
# postconf -e recipient_bcc_maps=''
# postconf -e relay_domains=''
# postconf -e relay_recipient_maps=''
  • 增加郵件網域 在 "smtpd_sasl_local_domain" 及 "virtual_mailbox_domains":

# postconf -e smtpd_sasl_local_domain='example.com'
# postconf -e virtual_mailbox_domains='example.com'
  •  修改 transport maps (轉遞?) 設定:

# postconf -e transport_maps='hash:/etc/postfix/transport'
  • 啟用 AD query (注意: 稍後才會建立這裡提到的3個檔案) 
  • 驗證SMTP寄件者

# postconf -e smtpd_sender_login_maps='proxy:ldap:/etc/postfix/ad_sender_login_maps.cf'
  • 驗證虛擬帳號使用者

# postconf -e virtual_mailbox_maps='proxy:ldap:/etc/postfix/ad_virtual_mailbox_maps.cf'
  • 驗證虛擬群組使用者

# postconf -e virtual_alias_maps='proxy:ldap:/etc/postfix/ad_virtual_group_maps.cf'
  • 建立/編輯 檔案: /etc/postfix/transport 加入下列文字

example.com dovecot
注意: dovecot 是定義於 /etc/postfix/master.cf 的轉遞(?)設定, 用來轉遞收到的郵件給使用者的郵箱.
執行 'postmap' 以讀取設定 

# postmap hash:/etc/postfix/transport
  • 創建檔案1: /etc/postfix/ad_sender_login_maps.cf 內容如下:

server_host     = ad.example.com
server_port     = 389
version         = 3
bind            = yes
start_tls       = no
bind_dn         = vmail
bind_pw         = password_of_vmail
search_base     = cn=users,dc=example,dc=com
scope           = sub
query_filter    = (&(userPrincipalName=%s)(objectClass=person)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))
result_attribute= userPrincipalName
debuglevel      = 0
  • 創建檔案2: /etc/postfix/ad_virtual_mailbox_maps.cf 內容如下:

server_host     = ad.example.com
server_port     = 389
version         = 3
bind            = yes
start_tls       = no
bind_dn         = vmail
bind_pw         = passwd_of_vmail
search_base     = cn=users,dc=example,dc=com
scope           = sub
query_filter    = (&(objectclass=person)(userPrincipalName=%s))
result_attribute= userPrincipalName
result_format   = %d/%u/Maildir/
debuglevel      = 0
注意事項: 因為 AD 中未有郵件檔儲存位置 ,
故在此直接設定 result_format 為 "example.com/username/Maildir/
  • 創建檔案3: /etc/postfix/ad_virtual_group_maps.cf 內容如下:

server_host     = ad.example.com
server_port     = 389
version         = 3
bind            = yes
start_tls       = no
bind_dn         = vmail
bind_pw         = password_of_vmail
search_base     = cn=users,dc=example,dc=com
scope           = sub
query_filter    = (&(objectClass=group)(mail=%s))
special_result_attribute = member
leaf_result_attribute = mail
result_attribute= userPrincipalName
debuglevel      = 0
請注意: 
  • 若AD 的使用者資訊在 "mail " 及 "userPrincipalName"中皆有設定, 將取回重複的兩筆 郵件地址, 請註解掉 'leaf_result_attribute' 即可。
  • 若群組帳號未傳回正確的 'mail' 及 'userPrincipalName' 資料,  請修改query_filter 如下面的設定
query_filter = (&(objectClass=group)(sAMAccountName=%u)) 
同時請移除 Postfix 中 iRedAPD 相關設定
  • 開啟 /etc/postfix/main.cf
  • 移除這段文字: check_policy_service inet:127.0.0.1:7777
Veryfy LDAP query with AD in Postfix
驗證 Postfix 對AD 的查詢

使用指令  postmap 以驗證 Postfix 對AD 的查詢
  • 查詢使用者 Query mail user:

# postmap -q user@example.com ldap:/etc/postfix/ad_virtual_mailbox_maps.cf 
回傳值應如下:
example.com/user/Maildir/
  • 若無回傳值出現, 表示LDAP 查詢並未執行, 請將 "ad_sender_login_maps.cf" 中的除錯選項設為1 "debuglevel=1"  並請將結果 貼至 討論區中 (http://www.iredmail.org/forum/)尋求協助。
  •  驗證寄件者 Verify sender login check:

# postmap -q user@example.com ldap:/etc/postfix/ad_sender_login_maps.cf
回傳值應如下:
user@example.com
  • 驗證郵件群組 
  • 建立測試群組 如: testgroup@example.com
  • 建立最少1個成員於該群組
  • 執行下列指令確認是否可得到成員資料 

# postmap -q testgroup@example.com ldap:/etc/postfix/ad_virtual_group_maps.cf
回傳值應如下:

member01@example.com
member02@example.com
若無成員存在或無該群組, postmap  將無任何回傳值

Enable LDAP query with AD in Dovecot
修改 /etc/dovecot/dovecot-ldap.conf,  將 dovecot 的 LDAP查詢轉向至 AD 伺服器
修改內容如下:

hosts           = ad.example.com:389
ldap_version    = 3
auth_bind       = yes
dn              = vmail
dnpass          = passwd_of_vmail
base            = cn=users,dc=example,dc=com
scope           = subtree
deref           = never
user_filter     = (&(userPrincipalName=%u)(objectClass=person)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))
pass_filter     = (&(userPrincipalName=%u)(objectClass=person)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))
pass_attrs      = userPassword=password
default_pass_scheme = CRYPT
user_attrs      = =home=/var/vmail/vmail1/%Ld/%Ln/Maildir/,=mail=maildir:/var/vmail/vmail1/%Ld/%Ln/Maildir/
重新啟動 dovecot 服務以啟用功能

注意: 此處無法設定單一使用者的 quota  限制, 可以用 /etc/dovecot.conf (RHEL/CentOS) , /etc/dovecot.conf (Debian/Ubuntu).  加以限制使用者的 quota。
設定方式如下:

plugin {
    # --- SKIP OTHER SETTINGS HERE ---
    # Format: integer + M/G/T.
    # M -> MB, G -> GB, T -> TB.
    quota_rule = *:storage=1G
}
Verify LDAP query with AD in Dovecot
驗證 Dovecot 的 LDAP 查詢

使用 telnet 指令 驗證 Dovecot 服務的 AD 查詢動作
注意: dovecot 要重新啟動後才能連線 AD 查詢


# telnet localhost 143 
(輸入telnet localhost 143 )
* OK [...] Dovecot ready. 
(伺服器回應, 此時僅連線本機, 其他機器連Dovecot回應會不同)

. login user@example.com password_of_user 
(記得輸入 最前面的 . )
會看到 
. OK [......] Logged in
 
看到此回應就表示 dovecot + AD 工作正常囉...
 
Enable Global LDAP Address Book with AD in Roundcube webmail
加入AD 網域使用者地址簿

編輯 roundcube config 檔案 /var/www/roundcubemail/config/main.inc.php (RHEL/CentOS) /usr/share/apache2/roundcubemail/config/main.inc.php (Debian/Ubuntu)

可以移除 原來的 LDAP 地址簿, 加上 AD 的地址簿

#
# "sql" is personal address book stored in roundcube database.
# "example.com" is new LDAP address book with AD, we will create it below.
#
$rcmail_config['autocomplete_addressbooks'] = array("sql", "example.com");

#
# Global LDAP Address Book with AD.
#
$rcmail_config['ldap_public']["example.com"] = array(
    'name'          => 'Global Address Book',
    'hosts'         => array("ad.example.com"),      // <- ad="" address="" here.="" hostname="" ip="" or="" port="" set=""> 389,
    'use_tls'       => false,                        // <- ----="" 636="" above="" accounts="" change="" domain.="" if="" in="" ldaps.="" line="" on="" only="" port="" same="" search="" set="" the="" to="" too.="" true="" use="" used="" user_specific="" want="" you=""> false,
    'base_dn'       => "cn=users,dc=example,dc=com", // <- ad="" base="" bind_dn="" dn="" in="" set=""> "vmail",                      // <- bind="" bind_pass="" dn=""> "password_of_vmail",                    // <- bind="" password="" writable=""> false,                        // <- ad.="" allow="" back="" data="" do="" ldap_version="" mail="" not="" to="" user="" write=""> "3",

    // ---- Search ----
    //'search_fields' => array('displayname', 'userprincipalname', 'sn', 'givenname',),  // <- fields="" in="" search="" search_fields="" to=""> array('mail', 'cn', 'sAMAccountName', 'displayname', 'sn', 'givenName'),
    //'name_field'    => 'displayname',
    'name_field'    => 'cn',
    //'email_field'   => 'userprincipalname',
    'email_field'   => 'mail',
    'surname_field' => 'sn',
    //'firstname_field' => 'givenname',
    'firstname_field' => 'givenName',
    //'sort'          => 'displayname',
    'sort'          => 'cn',
    'scope'         => 'sub',
    //'filter'        => "(&(objectclass=person)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))",
    'filter'        => "(mail=*@*)",
    'fuzzy_search'  => true
);


12 則留言:

Unknown 提到...

不知道不在AD中的人員可以使用本機帳號來代替嗎?經測試不在AD中的帳號似乎無法使用還必須做些修正..

sclin2k 提到...

vi /etc/dovecot/conf.d/10-auth.conf

#!include auth-system.conf.ext
AS
!include auth-system.conf.ext

!include auth-ldap.conf.ext

這樣就以讓沒有AD帳號的人,用本機帳號。
但我發現這樣的設定無法寄信給AD帳號,反之也是相同問題。目前研究中,如果有答案也請告知!

sclin2k 提到...

我試著在
mydestination = bks.xxxxxx.com.tw(主機名稱)

virtual_mailbox_domains = xxxxxx.com.tw
這樣設定就可以互相寄信。

alanyang 提到...

謝謝 Lin SC. 您的寶貴經驗, 讓大家少了很多自己測試的時間... ^_^

Unknown 提到...

時隔了快一年來回報一下最近遇到的狀況..
小弟的環境是windows 2012 r2 的AD......iredmail是最新的版本採LDAP版本....
最近在測試localLDAP跟AD的整合部份...發現一直都有問題...
今天我發現是userPrincipalName出來的值非我所想像,所以一直查詢不到.
後來透過ldapsearch查詢發現userPrincipalName查詢出來的值與帳號不相符.
小弟的查詢帳號是test@example.local但是若是使用userPrincipalName出來的值是test@ntdc.example.local(ntdc.example.local是我AD的root dn)
所以後來我將userPrincipalName都改為mail之後就可以用了....
給大家做個參考...
如果 root dn 與@後面是一致的話可能就可以使用userPrincipalName沒有問題.︿︿

或許大家有其他不同的解法...可以來討論一下︿︿


alanyang 提到...

感謝 squawell huang , 我最近也正要改為2012的AD, 有您的經驗, 我就少走冤枉路了......

Unknown 提到...

拜讀您的文章順利的讓iredmail與ad整合起來, 但是有個問題想請教一下,
請問一下如果郵件的網域名稱有2個, 如@123.com, @567.com.tw, postfix是可以在main.cf裡的mydestination把這兩個網域加進來, 但是這兩個域名又與windows AD的網域名稱不一樣, ad的網域名稱可能是999.com, 這樣在收信時check ad帳號, 這樣會不會有什麼問題
謝謝

Unknown 提到...

Squawell Huang的留言也解決了我的問題, 因為我的ad domain與mail domain是不同的, 超級感謝

不過遇到另一個問題, 寄信給AD裡的群組帳號, 群組裡面的人員都可以正確收到, 但是寄件者卻收到一個Undelivered Mail Returned to Sender

Final-Recipient: rfc822; g-it@xxx.com.tw
Original-Recipient: rfc822;g-it@xxx.com.tw
Action: failed
Status: 5.1.1
Diagnostic-Code: x-unix; user unknown

這個可能是什麼地方沒弄好造成的嗎?

alanyang 提到...

Matt Tseng 您好

請問您的群組中確定没有這個帳號嗎?

請用下列方法驗證一下:
驗證郵件群組
建立測試群組 如: testgroup@example.com
建立最少1個成員於該群組 (此處的範例有兩個帳號在 testgroup群組中)
執行下列指令確認是否可得到成員資料

# postmap -q testgroup@example.com ldap:/etc/postfix/ad_virtual_group_maps.cf
回傳值應如下:

member01@example.com
member02@example.com

Unknown 提到...

g-it@xxx.com.tw 是這個群組的email,
問題已自己解掉,
是/etc/postfix裡面, ad_virtual_group_map.cf的問題, 把檔案裡面撈的attribute改成下面這樣就ok
------------------------------------------------------------
query_filter = (&(objectClass=group)(mail=%s))
special_result_attribute = member
leaf_result_attribute = mail
result_attribute= mail
------------------------------------------------------------

Unknown 提到...

Hi 剛好小弟也遇到了這個問題,目前只差在Roundcube Webmail 1.2.0 上需要如何設定修改AD上面的密碼,是否有地方可以參考呢?

snack 提到...

您好,我在驗證postfix是否有連繫到AD的時候,都沒有回應。
postmap -q test@example.com.tw ldap:/etc/postfix/ad_virtual_mailbox_maps.cf

然後出現下面的訊息
postmap: warning: dict_ldap_connect: Unable to bind to server ldap://example.com.tw:389 with dn test@example.com.tw: -5 (Timed out)
postmap: fatal: table ldap:/etc/postfix/ad_sender_login_maps.cf: query error: Operation now in progress
這有可能是哪裡的問題呢…?
Windows Server是2012