qetfw头像
关注

Debian Postfix + Dovecot + MariaDB 虚拟邮箱连接:SQL 用户、域名与别名配置

Debian Postfix + Dovecot + MariaDB 配置连接:SQL 虚拟域名、用户与别名

1. 服务介绍

Postfix 负责 SMTP 邮件收发和队列管理,Dovecot 负责 IMAP/LMTP、邮箱访问和认证,MariaDB 保存虚拟域名、邮箱用户、密码哈希和邮件别名。三者组合可以让一台 Debian 邮件服务器托管多个域名和大量邮箱,而不需要为每个邮箱创建 Linux 系统账号。

本文聚焦 MariaDB 与 Postfix/Dovecot 的连接关系:创建虚拟域名、虚拟用户和别名表;配置 Postfix MySQL map;配置 Dovecot SQL passdb/userdb;使用 vmail 用户保存 Maildir;最后用 SQL map、认证、端口、队列和日志命令验证。

原实验文本包含明文邮箱密码、数据库密码、旧 IP 和不安全的明文密码方案,本文全部移除,改用密码哈希、占位符、最小权限数据库账号和 TLS。

2. 准备运行环境

• 操作系统:Debian 10;其他版本按 Postfix、Dovecot、MariaDB 和 OpenSSL 版本调整。

• 软件包:postfixpostfix-mysqldovecot-coredovecot-imapddovecot-lmtpddovecot-mysqlmariadb-servermariadb-client

• 域名:示例使用 example.testmail.example.test,执行前替换为当前实验域名。

• DNS:邮件主机 A/AAAA、域名 MX 和反向解析已准备。

• 数据库:MariaDB 已启动,创建专用读取账号;数据库 3306 尽量只监听本机或受限管理网段。

• 邮箱:使用 /var/mail/vhosts 保存虚拟邮箱,固定 vmail UID/GID。

• TLS:证书 SAN 包含 mail.example.test;客户端使用 993 IMAPS、465 SMTPS 或 587 STARTTLS。

• 凭据:所有数据库和邮箱密码只交互输入,不写入文档、脚本、截图或日志。

3. 相关知识

3.1 三张核心表

virtual_domains:域名是否由当前邮件服务器负责。

virtual_users:邮箱地址、密码哈希和 Maildir 相对路径。

virtual_aliases:别名地址到目标邮箱的映射。

3.2 Postfix map 与 Dovecot SQL

Postfix 使用 MySQL map 查询域名、邮箱和别名;Dovecot 使用 SQL 查询密码哈希和用户目录。两边查询账号只需要 SELECT 权限,不应使用 MariaDB root 账号。

3.3 Maildir 和 LMTP

Postfix 收到邮件后,通过 Dovecot LMTP Socket 投递到 /var/mail/vhosts/域名/用户名/Maildir。Postfix、Dovecot 和 vmail 必须对路径、UID/GID、目录权限保持一致。

3.4 密码安全

邮箱密码使用 doveadm pw -s SHA512-CRYPT 生成哈希。数据库连接密码放在 root 可读的配置文件中,并设置 600 权限;不要使用原实验中的明文密码或 PLAIN 存储。

3.5 防开放中继

Postfix 必须保留 reject_unauth_destination。客户端提交邮件使用 465/587 和 SMTP AUTH;25 主要用于服务器间 SMTP。删除中继限制会导致服务器被滥发邮件。

4. 实验步骤

4.1 设置 FQDN 和 DNS

sudo hostnamectl set-hostname mail.example.test
hostname --fqdn
getent hosts mail.example.test
dig example.test MX +short
dig mail.example.test A +short

MX 目标必须是可解析的邮件主机名,不能直接写 IP。旧实验地址不适用于当前网络,执行前替换占位符。

4.2 安装软件

sudo apt update
sudo apt install -y postfix postfix-mysql \
    dovecot-core dovecot-imapd dovecot-lmtpd dovecot-mysql \
    mariadb-server mariadb-client openssl ca-certificates
sudo systemctl enable --now mariadb postfix dovecot
sudo systemctl is-active mariadb
sudo systemctl is-active postfix
sudo systemctl is-active dovecot

Postfix 安装向导选择 Internet Site,系统邮件名填写实际邮件域名。交互密码不写入文档。

4.3 创建 MariaDB 表和最小权限账号

用 MariaDB 管理账号创建数据库和读取账号。DB_READER_PASSWORD 是占位符,必须在受控终端替换,不能保留真实值。

CREATE DATABASE mailserver CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'mailreader'@'localhost' IDENTIFIED BY 'DB_READER_PASSWORD';
GRANT SELECT ON mailserver.* TO 'mailreader'@'localhost';
FLUSH PRIVILEGES;

USE mailserver;
CREATE TABLE virtual_domains (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(190) NOT NULL UNIQUE
);
CREATE TABLE virtual_users (
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    domain VARCHAR(190) NOT NULL,
    email VARCHAR(190) NOT NULL UNIQUE,
    password VARCHAR(255) NOT NULL,
    maildir VARCHAR(255) NOT NULL
);
CREATE TABLE virtual_aliases (
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    source VARCHAR(190) NOT NULL,
    destination VARCHAR(190) NOT NULL
);

4.4 插入测试数据

生成邮箱密码哈希:

sudo doveadm pw -s SHA512-CRYPT

把命令输出的哈希交互写入 SQL,不把明文密码写入数据库:

USE mailserver;
INSERT INTO virtual_domains(name) VALUES ('example.test');
INSERT INTO virtual_users(domain,email,password,maildir)
VALUES ('example.test','[email protected]','{SHA512-CRYPT}HASH_FROM_DOVEADM','example.test/user1');
INSERT INTO virtual_users(domain,email,password,maildir)
VALUES ('example.test','[email protected]','{SHA512-CRYPT}HASH_FROM_DOVEADM','example.test/user2');
INSERT INTO virtual_aliases(source,destination)
VALUES ('[email protected]','[email protected]'),
       ('[email protected]','[email protected]');

查询时只查看地址和目录:

SELECT id,name FROM virtual_domains;
SELECT id,domain,email,maildir FROM virtual_users;
SELECT id,source,destination FROM virtual_aliases;

4.5 创建 vmail 用户和邮箱目录

sudo groupadd -g 5000 vmail 2>/dev/null || true
sudo useradd -g vmail -u 5000 vmail -d /var/mail \
    -s /usr/sbin/nologin 2>/dev/null || true
sudo mkdir -p /var/mail/vhosts/example.test/user1/Maildir
sudo mkdir -p /var/mail/vhosts/example.test/user2/Maildir
sudo chown -R vmail:vmail /var/mail/vhosts
sudo chmod -R 700 /var/mail/vhosts

4.6 配置 Postfix MySQL map

sudo postconf -e 'myhostname = mail.example.test'
sudo postconf -e 'mydomain = example.test'
sudo postconf -e 'inet_interfaces = all'
sudo postconf -e 'virtual_transport = lmtp:unix:private/dovecot-lmtp'
sudo postconf -e 'virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf'
sudo postconf -e 'virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf'
sudo postconf -e 'virtual_alias_maps = mysql:/etc/postfix/mysql-virtual-alias-maps.cf'
sudo postconf -e 'smtpd_recipient_restrictions = permit_sasl_authenticated, reject_unauth_destination'

创建域名、邮箱、别名查询文件。三个文件都只允许 root 和 Postfix 必要组读取,DB_READER_PASSWORD 只在服务器上填写。

# /etc/postfix/mysql-virtual-mailbox-domains.cf
user = mailreader
password = DB_READER_PASSWORD
hosts = 127.0.0.1
dbname = mailserver
query = SELECT 1 FROM virtual_domains WHERE name='%s'

# /etc/postfix/mysql-virtual-mailbox-maps.cf
user = mailreader
password = DB_READER_PASSWORD
hosts = 127.0.0.1
dbname = mailserver
query = SELECT 1 FROM virtual_users WHERE email='%s'

# /etc/postfix/mysql-virtual-alias-maps.cf
user = mailreader
password = DB_READER_PASSWORD
hosts = 127.0.0.1
dbname = mailserver
query = SELECT destination FROM virtual_aliases WHERE source='%s'

sudo chown root:root /etc/postfix/mysql-virtual-*.cf
sudo chmod 640 /etc/postfix/mysql-virtual-*.cf
postmap -q example.test mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
postmap -q [email protected] mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
postmap -q [email protected] mysql:/etc/postfix/mysql-virtual-alias-maps.cf
sudo postfix check

4.7 配置 Dovecot SQL 和 LMTP

设置 Maildir、协议和认证:

sudo sed -i 's|^#\?mail_location.*|mail_location = maildir:/var/mail/vhosts/%d/%n/Maildir|' \
    /etc/dovecot/conf.d/10-mail.conf
sudo sed -i 's|^#\?protocols.*|protocols = imap lmtp|' /etc/dovecot/dovecot.conf
sudo sed -i 's|^#\?disable_plaintext_auth.*|disable_plaintext_auth = yes|' \
    /etc/dovecot/conf.d/10-auth.conf
sudo sed -i 's|^#\?auth_mechanisms.*|auth_mechanisms = plain login|' \
    /etc/dovecot/conf.d/10-auth.conf

auth-sql.conf.ext 使用 SQL passdb 和静态 userdb:

passdb sql {
  driver = sql
  args = /etc/dovecot/dovecot-sql.conf.ext
}
userdb static {
  driver = static
  args = uid=vmail gid=vmail home=/var/mail/vhosts/%d/%n
}

dovecot-sql.conf.ext

driver = mysql
connect = host=127.0.0.1 dbname=mailserver user=mailreader password=DB_READER_PASSWORD
default_pass_scheme = SHA512-CRYPT
password_query = SELECT email AS user, password FROM virtual_users WHERE email='%u'

设置 SQL 配置权限:

sudo chown root:root /etc/dovecot/dovecot-sql.conf.ext
sudo chmod 600 /etc/dovecot/dovecot-sql.conf.ext

10-master.conf 配置 LMTP 和 Postfix auth Socket:

service lmtp {
  unix_listener /var/spool/postfix/private/dovecot-lmtp {
    mode = 0600
    user = postfix
    group = postfix
  }
}
service auth {
  unix_listener /var/spool/postfix/private/auth {
    mode = 0660
    user = postfix
    group = postfix
  }
}

重启并检查:

sudo doveconf -n >/tmp/dovecot-effective.conf
sudo ls -l /var/spool/postfix/private/auth /var/spool/postfix/private/dovecot-lmtp
sudo systemctl restart dovecot postfix

5. 验证结果

systemctl is-active mariadb
systemctl is-active postfix
systemctl is-active dovecot
ss -lntp | grep -E ':25|:465|:587|:993|:3306'
sudo postfix check
sudo doveconf -n >/dev/null

验证 SQL map 和 Dovecot 认证:

postmap -q example.test mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
postmap -q [email protected] mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
postmap -q [email protected] mysql:/etc/postfix/mysql-virtual-alias-maps.cf
sudo doveadm auth test [email protected]
sudo doveadm user [email protected]

验证邮箱目录、LMTP Socket、队列和日志:

sudo find /var/mail/vhosts -maxdepth 4 -type d -printf '%M %u:%g %p\n'
sudo ls -l /var/spool/postfix/private/auth /var/spool/postfix/private/dovecot-lmtp
sudo postqueue -p
sudo tail -n 100 /var/log/mail.log

验证 TLS:

openssl s_client -connect mail.example.test:993 \
    -servername mail.example.test </dev/null 2>&1 \
    | grep -E 'subject=|issuer=|Verify return code'

预期结果:Postfix、Dovecot、MariaDB 均为 active;SQL map 返回有效结果;Dovecot 账号认证通过;虚拟邮箱目录属主为 vmail;LMTP Socket 存在;未认证外部中继被拒绝;配置和日志不包含真实数据库密码。

6. 常见问题

6.1 Postfix map 查询为空

检查数据库连接账号、表名、字段名、域名大小写和 SQL 查询。逐个使用 postmap -q 测试,不要直接重启猜测。

6.2 Dovecot 认证失败

检查 dovecot-sql.conf.ext、密码哈希、password_querydoveadm auth test。不要改用明文密码绕过认证。

6.3 邮件已接收但 Maildir 没有文件

检查 LMTP Socket、virtual_transportmail_locationvmail UID/GID 和目录权限;查看 /var/log/mail.log 投递状态。

6.4 数据库连接失败

确认 MariaDB 服务、mailreader 权限、数据库主机、3306 监听和防火墙。远程数据库禁止使用 % 全网授权。

6.5 证书或 IMAP 连接失败

检查 993 监听、证书 SAN、私钥权限和 Dovecot SSL 配置;客户端访问名称必须与证书一致。

6.6 日志查看

sudo journalctl -u mariadb -n 80 --no-pager
sudo journalctl -u postfix -n 100 --no-pager
sudo journalctl -u dovecot -n 100 --no-pager
sudo postqueue -p

7. 实验结论

本实验完成 MariaDB 虚拟域名、虚拟用户和别名表设计,完成 Postfix MySQL map、Dovecot SQL 认证、虚拟 Maildir、LMTP 投递和基础 TLS 验证。最终以 SQL map、Dovecot 认证、邮箱目录、SMTP/IMAP 端口、队列和日志共同确认配置生效。

生产环境必须移除明文密码,使用安全密码哈希、最小权限数据库账号、受限数据库来源、TLS、备份和账号生命周期管理。

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/weixin_44524357/article/details/164971784

文章来源转载

评论

赞0

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--