緣由

原本就有一台 postfix, 採用 apt 套件安裝 (之後再改成 docker container), 想要幾個目的
1. 為吉甲資訊, gilgal.tw 建立 mail server
2. 為 postfix 建立 virtual user 和 mailbox
3. 需建立 POP3/IMAP 服務
4. 整合 Let’s Encrypt 提供 SMTP(25, 465, 587), POP3(995), IMAP(993)
5. 因無 PTR 紀錄, 無法自動轉寄信件到 gmail, 所以採用 gmail + pop3 取信
6. 整合 LDAP 帳號供 gmail 取信用, 並不能使用原帳密, 另外再做一個類似 service account 的帳號供 gmail 使用

以下紀錄說明重要的步驟

幾個重要設定

  • 調整 DNS RR
@ IN A IP1
@ IN  MX  0 mx.gilgal.tw.
www IN A IP1
mail IN A IP2
mx IN A IP2
pop3 IN A IP1
imap IN A IP1
smtp IN A IP1

其中 IP1 提供 HTTP/HTTPS 供 Let’s Encrypt 申請 SSL 憑證用
IP2 則提供 SMTPs, POP3s, IMAPs 服務

  • 利用 certbot 取得 SSL 憑證
# dry run 確認是否有問題, 若沒有問題, 則移除 --dry-run 並再執行一次
certbot certonly --dry-run --email cytseng@gmail.com --agree-tos -d pop3.gilgal.tw -d imap.gilgal.tw -d mx.gilgal.tw -d smtp.gilgal.tw -w /srv/web --manual

並把 fullchain.pem 和 privkey.pem 複製到 /etc/postfix/ssl 之下
因 30天需要更新 Let’s Encrypt SSL 憑證, 所以寫了一個小小的 script 判斷

  • 自動更新 Let’s Encrypt SSL 憑證

/usr/local/sbin/renew_postfix_ssl.sh 內容如下

#!/bin/sh
BASEDIR='/etc/postfix/ssl'

# 產生憑證 checksum 檔
CERT_CHECK=`cat BASEDIR/fullchain.checksum 2>/dev/null`
KEY_CHECK=`catBASEDIR/privkey.checksum 2>/dev/null`

if [ "x{CERT_CHECK}" != "x`md5sum /etc/certbot/etc/live/pop3.gilgal.tw/fullchain.pem | awk '{print1}'`" ]; then
    echo `md5sum /etc/certbot/etc/live/pop3.gilgal.tw/fullchain.pem | awk '{print 1}'`>BASEDIR/fullchain.checksum
    cp /etc/certbot/etc/live/pop3.gilgal.tw/fullchain.pem BASEDIR
fi

if [ "x{KEY_CHECK}" != "x`md5sum /etc/certbot/etc/live/pop3.gilgal.tw/privkey.pem | awk '{print 1}'`" ]; then
    echo `md5sum /etc/certbot/etc/live/pop3.gilgal.tw/privkey.pem | awk '{print1}'` > BASEDIR/privkey.checksum
    cp /etc/certbot/etc/live/pop3.gilgal.tw/privkey.pemBASEDIR
else
    exit
fi

postfix reload

/etc/cron.d/local

10 0 * * * root /bin/sh /usr/local/sbin/renew_postfix_ssl.sh > /dev/null 2>&1
  • 安裝 docker, 並調整 daemon.json 設定

參考以下文章

Install Docker Engine on Debian
調整 docker 基本設定

  • 建立 postfix virtual user 專用帳號

為讓此帳號能和 container 裡的帳號對應, 所以 uid/gid 調整為 1001000

groupadd -g 1001000 virtualmail
useradd -u 1001000 -g virtualmail -s /usr/bin/nologin -d /var/mail/vhosts -m virtualmail
  • 修改 postfix 以支援 virtual domain 和 virtual user
# 讓 postfix 不再支援舊設定
compatibility_level = 3.6

smtpd_tls_cert_file=/etc/postfix/ssl/fullchain.pem
smtpd_tls_key_file=/etc/postfix/ssl/privkey.pem
myhostname = mail
mydomain = gilgal.tw

# 要放 virtual domain 的網域, 則不能放在 mydestination
# 因 mydestination 屬於處理未在 virtual domain 的 email
# virtual_mailbox_domains 則處理 virtual domain 的 email
mydestination = localhost.localdomain, localhost

virtual_mailbox_domains = gilgal.tw, mail.gilgal.tw
virtual_mailbox_base = /var/mail/vhosts
virtual_mailbox_maps = hash:/etc/postfix/vmailbox
virtual_minimum_uid = 1000
virtual_uid_maps = static:1001000
virtual_gid_maps = static:1001000
  • 新增 vmailbox 檔案, 設定 virtual user mailbox

/etc/postfix/vmailbox 內容

joshua@gilgal.tw        cytseng/
joshua@mail.gilgal.tw   cytseng/
service@gilgal.tw       cytseng/
service@mail.gilgal.tw  cytseng/
postmap /etc/postfix/vmailbox

其中 cytseng/ 為 maildir 格式, 會在 /var/mail/vhosts/cytseng 裡產生這樣的目錄結果

.
├── cur
├── new
└── tmp

若為 cytseng 則為 mailbox 格式, 則會在 /var/mail/vhosts/cytseng 用一個 cytseng 檔案放置所有的 mail 資料

因吉甲會用到的 mail 都只有自己在用, 所以都轉到自己帳號(cytseng) 之下

會用 cytseng/ 也是為了配合 LDAP 帳號為 cytseng

  • 利用 dovecot docker image 建立 POP3s/IMAPs 服務, 並和 LDAP 連結取得帳號資訊

/srv/docker/dovecot/docker-compose.yaml 內容

services:
  dovecot:
    image: dovecot/dovecot
    container_name: dovecot
    hostname: dovecot
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /etc/certbot:/certbot
      - ./etc-dovecot:/etc/dovecot
      - /var/mail/vhosts:/srv/mail
      - /srv/prod/dovecot/log:/log
    ports:
      - 993:993/tcp
      - 995:995/tcp

etc-dovecot/dovecot.conf 內容

mail_home=/srv/mail/%n
mail_location=maildir:/srv/mail/%n
mail_uid=1000
mail_gid=1000

protocols = imap pop3

first_valid_uid = 1000
last_valid_uid = 1099

passdb {
  args = /etc/dovecot/dovecot-ldap.conf.ext
  driver = ldap
}

userdb {
  driver = prefetch
}

userdb {
  args = /etc/dovecot/dovecot-ldap.conf.ext
  driver = ldap
}

ssl=yes
ssl_cert=</certbot/etc/live/pop3.gilgal.tw/fullchain.pem
ssl_key=</certbot/etc/live/pop3.gilgal.tw/privkey.pem

namespace {
  inbox = yes
  separator = /
}

service lmtp {
  inet_listener {
    port = 24
  }
}

listen = *

log_path=/log/dovecot.log
info_log_path=/log/dovecot-info.log
debug_log_path=/log/dovecot-debug.log

auth_verbose=yes
auth_debug=yes
mail_debug=yes
verbose_ssl=yes

!include_try /etc/dovecot/conf.d/*.conf

etc-dovecot/dovecot-ldap.conf.ext 內容

hosts = LDAP IP
dn = 'BIND DN'
dnpass = 'BIND PWD'
base = BASEDN

pass_attrs = \
           =password=%{ldap:userPassword}, \
           =user=%{ldap:cn}, \
           =home=%{ldap:homeDirectory}, \
           =uid=%{ldap:uidNumber}, \
           =gid=%{ldap:gidNumber}

pass_filter = (&(objectclass=user)(cn=%u))
user_filter = (&(objectclass=user)(cn=%u))

# For using doveadm -A:
iterate_attrs = =user=%{ldap:cn}
iterate_filter = (objectClass=user)

LDAP 設定幾乎都是客製, 其中 base 不要和常用帳號的 basedn 相同, 避免常用帳號的密碼被猜出來, 而能登入工作站或其他服務

  • 啟動 postfix / dovecot
postfix reload
docker-compose -f /srv/docker/dovecot/docker-compose up -d

這樣就能完成 POP3s/IMAPs 服務

  • 調整 gmail 帳號, 利用 POP3 取用 吉甲信箱

TODO

  1. 讓 postfix 能使用 LDAP 認證
  2. 確認 DNS PTR 結果, 之後改用自動轉寄至 gmail

參考文件

整合 postfix + virtual user + dovecot + LDAP

發表迴響

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料

Verified by MonsterInsights