个人电子邮箱服务器的搭建:Postfix+Dovecot+Sqlite+PostfixAdmin+RoundCube

个人电子邮箱服务器的搭建:Postfix+Dovecot+Sqlite+PostfixAdmin+RoundCube

一、前言

个人网站上的Http服务已经搭建了不少,准备在其上整一个高大上的:电子邮箱服务(俗称伊妹儿)。

整个服务还是基于arm的盒子之上。

Host环境:Ubuntu 18.04.5 (PC)

编译工具链:arm-himix200-linux(解包自arm-himix200-linux.tgz,据说来自Hi3516dv300SDK),海思提供的arm编译工具链

环境变量:执行命令:export PATH=/opt/hisi-linux/x86-arm/arm-himix200-linux/bin:$PATH

二、Postfix/Dovecot软件包的编译

Postfix版本:3.7.2

Dovecot版本:2.3.19.1

cyrus-sasl版本:2.1.28

虽然希望基于Host的PC环境交叉编译出三个软件包出来,但Postfix及Dovecot其实并没有考虑交叉编译情况,手工来调整、修改的工作量太大(主要也是懒得再去花几天时间来搞)。所以,除cyrus-sasl库外,Postfix与Dovecot均是在ARM的盒子上编译出来的。

2.1 编译cyrus-sasl

编译命令如下:

env LD_LIBARAY_PATH=${LD_LIBRARY_PATH}:/data/app/lib PATH=$PATH:/data/app/bin PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/data/app/lib/pkgconfig ./configure --host=arm-linux CC=/opt/hisi-linux/arm-himix200-linux/bin/arm-himix200-linux-gcc --prefix=/data/app \
      --disable-krb4 \
      --disable-macos-framework \
      --disable-otp \
      --disable-passdss \
      --disable-srp \
      --disable-srp-setpass \
      --disable-static \
      --enable-alwaystrue \
      --enable-anon \
      --enable-auth-sasldb \
      --enable-checkapop \
      --enable-cram \
      --enable-digest \
      --enable-plain \
      --enable-shared \
      --enable-sql \
      --with-devrandom=/dev/urandom \
      --with-configdir=/data/app/etc/sasl2:/data/app/etc/sasl:/data/app/usr/lib/sasl2 \
      --with-sqlite3=/data/app/lib  \
	  --without-pgsql  \
	  --without-mysql  \
	  LDFLAGS="-L/data/app/lib -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4" CFLAGS="-I/data/app/include  -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4"

这儿将软件包编译后,安装到/data/app目录,同时指定了LDFLAGS与CFLAGS,以适应ubuntu下armhf规范的运行要求。

编译完成后,使用make DESTDIR=xxx/bin install命令安装到特定目录待打包。

进入特定目录,可使用如下脚本命令打包。

exec_line() { sudo rm ../../../01.bin/$1.bin.tar.gz ../../../01.bin/$1.strip.bin.tar.gz; sudo tar czf ../../../01.bin/$1.bin.tar.gz ./*; arm-himix200-linux-strip data/app/bin/* data/app/sbin/* data/app/lib/*.so* data/app/lib/sasl2/*.so*; tar czf ../../../01.bin/$1.strip.bin.tar.gz ./*; }; exec_line `basename \`dirname $PWD\` `

2.2 编译Postfix

由于是在ARM盒子上编译的PostFix,一应的编译依赖就比较好处理(通过apt去安装即可)。

编译命令如下:

make makefiles shared=yes dynamicmaps=yes \
command_directory=/data/app/bin \
config_directory=/data/app/etc/postfix \
daemon_directory=/data/app/libexec/postfix \
mailq_path=/data/app/bin/mailq \
meta_directory=/data/app/etc/postfix \
newaliases_path=/data/app/bin/newaliases \
sendmail_path=/data/app/bin/sendmail \
shlib_directory=/data/app/lib \
manpage_directory=/data/app/share/man \
mail_spool_directory=/data/mail/data \
OPT=" -O2 " DEBUG="" \
'CCARGS=-DNO_DB -DDEF_CONFIG_DIR=\"/data/app/etc/postfix\" -DUSE_SASL_AUTH -DUSE_CYRUS_SASL -I/data/app/include/sasl -DUSE_TLS -I/data/app/include/openssl/ -DHAS_PCRE=2 -DHAS_SQLITE  -I/data/app/include -DHAS_MYSQL -I/data/app/include/mysql/' 'AUXLIBS=-L/data/app/lib -L/data/app/lib/sasl2 -lsasl2  -lssl -lcrypto -L/data/app/lib -lpcre -L/data/app/lib -lsqlite3 -lpthread -L/data/app/lib -lmysqlclient -lz -lm ' 'AUXLIBS_MYSQL=-L/data/app/lib -lmysqlclient -lz -lm ' 'AUXLIBS_SQLITE=-L/data/app/lib -lsqlite3 -lpthread' 'AUXLIBS_PCRE=-L/data/app/lib -lpcre'
make

这儿有几个要注意的点,OPT=-o2,即指定O2级别的优化,DEBUG如果不指定为空,此版本的Postfix会自带-g参数进行编译(即会带调试符号)。CCARGS与AUXLIBS从诸多参考、说明文档中也能见到,但3.0版本后的Postfix,还必须指定诸如AUXLIBS_MYSQL、AUXLIBS_SQLITE、AUXLIBS_PCRE这样的变量,这些宏定义在Postfix以dynamicmaps方式编译时是必须的。例如,编译后的postfix-mysql.so之类的动态库,如果未指定AUXLIBS_MYSQL,会出现加载时报相应so加载不成功(没有在链接so时指定mysqlclient依赖库,此so会找不到依赖的某些mysql函数)。

上一步生成的Makefile,再使用make命令,即会开始整个编译工作。

编译后,应使用如下命令,将编译好的软件安装到特定目录待打包。

sh postfix-install -non-interactive install_root="/xxxx/postfix-3.7.2/dest"

在dest目录下,可使用如下脚本命令打包。

exec_line() { sudo rm ../../../01.bin/$1.bin.tar.gz ../../../01.bin/$1.strip.bin.tar.gz; sudo tar czf ../../../01.bin/$1.bin.tar.gz ./*; strip data/app/bin/* data/app/sbin/* data/app/libexec/postfix/* data/app/lib/*.so* ; tar czf ../../../01.bin/$1.strip.bin.tar.gz ./*; }; exec_line `basename \`dirname $PWD\` `

2.3 编译Dovecot

Dovecot的编译系统是依赖于autoconf/automake的,相对好配置。

可使用如下编译命令:

env LD_LIBARAY_PATH=${LD_LIBRARY_PATH}:/data/app/lib PATH=$PATH:/data/app/bin systemdsystemunitdir=/usr/lib/systemd/system ZSTD_CFLAGS=-I/data/app/include ZSTD_LIBS="-L/data/app/lib -lzstd -lpthread" ./configure --prefix=/data/app CFLAGS=-I/data/app/include LDFLAGS=-L/data/app/lib --with-moduledir=/data/app/lib/dovecot/modules --with-ssldir=/data/app/etc/ssl --with-rundir=/run/dovecot --disable-static --with-sqlite --with-mysql --with-zstd
make

这儿强制指定了systemdsystemunitdir目录、moduledir、ssl目录等,同时禁用静态库,链接mysql/sqlite/zstd。

autoconf/automake系统的软件安装,使用make DESTDIR=XXX/bin install安装即可安装到特定目录待打包。

在bin目录下,可使用如下脚本命令打包。

exec_line() { sudo rm ../../../01.bin/$1.bin.tar.gz ../../../01.bin/$1.strip.bin.tar.gz; sudo tar czf ../../../01.bin/$1.bin.tar.gz ./*; strip data/app/bin/* data/app/sbin/* data/app/libexec/dovecot/* data/app/lib/*.so* data/app/lib/dovecot/*.so*  data/app/lib/dovecot/modules/*.so* data/app/lib/dovecot/modules/auth/*.so* data/app/lib/dovecot/modules/doveadm/*.so* data/app/lib/dovecot/modules/old-stats/*.so* ; tar czf ../../../01.bin/$1.strip.bin.tar.gz ./*; }; exec_line `basename \`dirname $PWD\` `

2.4 安装Postfix及Dovecot

软件包编译好后,即可以拷贝、并安装至相应目录。mail服务的特性,会对软件执行环境、软件权限有较多检查,这儿可以参考ArchLinux的Postfix、Dovecot的包配置,参考其中的xxx.sysusers、xxx.tmpfiles。

对Postfix而言,参考postfix.sysusers,生成/usr/lib/sysusers.d/postfix.conf

g postdrop 75 -
u postfix 73 - /var/spool/postfix

参考postfix.sysusers,生成/usr/lib/tmpfiles.d/postfix.conf

z /data/app/bin/postdrop 2755 root postdrop
z /data/app/bin/postqueue 2755 root postdrop
z /var/lib/postfix 700 postfix root
z /var/spool/postfix/active 700 postfix root
z /var/spool/postfix/bounce 700 postfix root
z /var/spool/postfix/corrupt 700 postfix root
z /var/spool/postfix/defer 700 postfix root
z /var/spool/postfix/deferred 700 postfix root
z /var/spool/postfix/flush 700 postfix root
z /var/spool/postfix/hold 700 postfix root
z /var/spool/postfix/incoming 700 postfix root
z /var/spool/postfix/maildrop 730 postfix postdrop
z /var/spool/postfix/private 700 postfix root
z /var/spool/postfix/public 710 postfix postdrop
z /var/spool/postfix/saved 700 postfix root
z /var/spool/postfix/trace 700 postfix root

对Dovecot而言,参考dovecot.sysusers,生成/usr/lib/sysusers.d/dovecot.conf

u dovenull 74 "Dovecot user for completely untrustworthy processes" -
u dovecot  76 "Dovecot user" -

参考dovecot.sysusers,生成/usr/lib/tmpfiles.d/dovecot.conf

d /run/dovecot 0755 root dovecot -

如上四个文件生成后,可以执行sudo systemd-sysusers创建用户、组,sudo systemd-tmpfiles --create调整文件、目录权限归属等。

(似乎有遗漏,还需要执行如下命令调整权限,否则在启动Postfix服务时,会有告警提示)

sudo chgrp postdrop /data/app/bin/postdrop
sudo chgrp postdrop /data/app/bin/postqueue
sudo chmod g+s /data/app/bin/postqueue
sudo chmod g+s /data/app/bin/postdrop

如果shlib_directory目录的权限不正确(group或all)的有写权限,会有警告,使用如下命令修改

sudo chmod -R g=rx /data/app/lib
sudo chmod -R o=rx /data/app/lib

即使如此,postfix-script依然存在告警提示,这就要参考Debian的bugfix来修复了(链接https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=832576):

--- postfix-script.origin       2022-08-26 10:48:35.513746421 +0800
+++ postfix-script      2022-08-26 11:02:43.751868100 +0800
@@ -314,9 +314,17 @@
        find $todo ! -user root \
            -exec $WARN not owned by root: {} \;

-       find $todo \( -perm -020 -o -perm -002 \) \
+       # Handle symlinks separately
+       find -L $todo \( -perm -020 -o -perm -002 \) \
            -exec $WARN group or other writable: {} \;

+       #find $todo -type l | while read f; do
+           # makedefs out known to be a symlink and OK
+       #    if [ "$f" != "/data/app/etc/postfix/./makedefs.out" ]; then
+       #       readlink "$f" | grep -q / && $WARN symlink leaves directory: "$f";
+       #    fi
+       #done;
+
        # Check Postfix mail_owner-owned directory tree owner/permissions.

        find $data_directory/. ! -user $mail_owner \

三、配置

Postfix号称配置简单,那是相对于SendMail而言,实际上的配置也是复杂、麻烦得要死,而且这个服务特别的灵活,灵活就意味着麻烦多多。

Dovecot的配置则相对好一些,文档也清晰些,从代码的examples里面将配置都拷贝过来,修改几个点,就完成了。

包含PostFixAdmin、RoundCube这些东西,整个服务器的配置、搭建,花了一周左右才算完成,期间花费很多时间去查找资料、理解配置项的理由、背景等等。

搜索了很多资料,链接如下:

https://www.myfreax.com/install-and-configure-postfix-and-dovecot/
https://www.cnblogs.com/apexchu/p/4271264.html
https://www.cnblogs.com/renweihang/p/7988591.html
https://www.jianshu.com/p/ffe2182c12f3
https://www.liaoxuefeng.com/article/895886450140288

3.1 配置的前言

很多资料里面讲述了MTA/MDA/MUA等等的概念,不在这儿赘述了。

简单来说,Dovecot实现了pop3及imap协议(包含带ssl加密的)。因此配置好后,即可登陆上去,查看其他人发送给你的邮件了。

而Postfix,主要实现SMTP(及带s)协议,只有通过这个协议,用户才能将手里的邮件发送出去(具体而言,用户使用邮件客户端编写好邮件后,通过SMTP协议发送到PostFix服务器上,PostFix根据配置路由一下发送出去。至于是发送到中转服务,或者直接发送到目标邮箱服务器,根据配置而定)。

PostFixAdmin能够简化一些PostFix的配置办法,主要是简化PostFix配置虚拟域方式下,如何添加域名、添加域名下的用户、认证用户、用户别名等等。

RoundCube这个就是一个WebMail的PHP实现,提供的是基于Web浏览器下访问邮件服务器,接收、发送邮件等功能,底层还是基于PostFix/Dovecot提供的SMTP/POP3/IMAP协议(类似实现有RainLoop与alps,后者基于go语言)。

3.2 操作系统配置

采用虚拟域、用户方式来配置邮箱服务器的信息,依然还是需要一个系统用户的,因此,执行如下配置命令

sudo mkdir -p /YYYY
sudo groupadd -g 5000 vmail
sudo useradd -u 5000 -g vmail -s /usr/bin/nologin -d /YYYY -m vmail
sudo chown -R vmail:vmail /YYYY

添加一个vmail用户,其UID/GID均为5000,不允许登陆,并配置其用户HOME路径为YYYY,此路径也用来存储所有虚拟域、虚拟用户的邮件。

3.3 Dovecot的配置

先从简单的入手,配置好Dovecot。

Dovecot的软件包中,提供了一个示例配置,路径是:doc/example-config/目录

3.3.1 Dovecot主配置

主配置文件位于/data/app/etc/dovecot/dovecot.conf。

这儿定义了启动哪些服务,监听端口,并引入哪些配置文件。

配置很简单,如下

protocols = pop3 imap lmtp
listen = *, ::
mail_max_userip_connections = 50
 !include conf.d/*.conf

 !include_try local.conf

这儿配置会启动pop3/imap/lmtp三个服务,监听所有端口,并引入conf.d目录下所有的conf文件。

conf.d下面有很多文件,诸如:

10-auth.conf      10-mail.conf     10-ssl.conf        20-imap.conf  20-submission.conf  90-quota.conf                auth-dict.conf.ext    auth-passwdfile.conf.ext  auth-system.conf.ext
10-director.conf  10-master.conf   15-lda.conf        20-lmtp.conf  90-acl.conf         auth-checkpassword.conf.ext  auth-ldap.conf.ext    auth-sql.conf.ext
10-logging.conf   10-metrics.conf  15-mailboxes.conf  20-pop3.conf  90-plugin.conf      auth-deny.conf.ext           auth-master.conf.ext  auth-static.conf.ext

3.3.1 Dovecot的10-auth.conf配置

此配置文件中,存放用户认证相关的配置信息,默认是仅包含auth-system.conf.ext,即使用本地用户认证的方式。

修改为如下:

disable_plaintext_auth = yes
auth_mechanisms = plain login
#!include auth-system.conf.ext
!include auth-sql.conf.ext

这儿注释掉了auth-system.conf.ext的引用,改为引用auth-sql.conf.ext文件。即不使用本地用户认证,而使用数据库存储的用户信息进行认证。使用数据库的存储数据作为用户认证数据,就可以与PostFixAdmin生成的域、用户数据信息同源了。

auth-sql.conf.ext文件就改动很少了,将几个args指向的配置文件路径修改为实际路径即可

-  args = /etc/dovecot/dovecot-sql.conf.ext
+  args = /data/app/etc/dovecot/dovecot-sql.conf.ext

dovecot-sql.conf.ext存储了实际访问SQL(小型的数据库,用SQLITE也行了)数据库的SQL语句,内容如下。

driver = sqlite
connect = /XXXX/authdb.db
user_query = \
     SELECT ('/YYYYY/' || maildir) AS home,     \
          ('maildir:/YYYYY/' || maildir) AS mail, \
          5000 AS uid, 5000 AS gid, ('*:bytes=' || quota) AS quota_rule \
     FROM mailbox WHERE username = '%u' AND active = '1'

password_query = SELECT username AS user, password FROM mailbox \
  WHERE username = '%u' AND active = '1'

iterate_query = SELECT username AS user FROM mailbox

driver说明是使用的sqlite数据库

connect指向实际的Sqlite数据库文件名(也是PostFixAdmin配置的Sqlite数据库文件位置)

user_query与password_query分别指明获取用户信息、认证用户时的SQL语句(这儿是从MySQL的SQL语句参考修改而言,Sqlite中没有concat函数,对应是 ||连接符)。

到这儿,10-auth.conf的功能基本完备了。

3.3.2 Dovecot的10-logging.conf配置

10-logging.conf主要配置Dovecot的日志记录,已经正常运行后,大多数的开关应该关闭。

配置信息如下:

# // 如果你不想使用 syslog,你可以让 Dovecot 直接记录到文件中
log_path = /var/log/dovecot.log
# If not set, use the value from log_path
info_log_path = /var/log/dovecot-info.log
# If not set, use the value from info_log_path
debug_log_path = /var/log/dovecot-debug.log

# // 启用记录所有失败的身份验证尝试
 #auth_verbose = no
#auth_verbose = yes

# // auth_verbose_passwords=no|plain|sha1如果身份验证失败,此设置会记录使用的密码。如果您真的不需要知道密码本身是什么,但更想知道用户是否只是每次都尝试使用错误的密码或者是暴力攻击,您可以将其设置为sha1且仅记录密码的 SHA1。这足以知道登录尝试之间的密码是相同还是不同
 #auth_verbose_passwords = no
#auth_verbose_passwords = plain

# // 启用所有身份验证调试日志记录(也启用auth_verbose)。密码记录为<hidden>
 #auth_debug = no
#auth_debug = yes

# // 做所有事情auth_debug=yes,但它也消除了密码隐藏(但前提是您不使用 PAM,因为 PAM 错误不会写入 Dovecot 自己的日志)
 #auth_debug_passwords = no
#auth_debug_passwords = yes

3.3.3 Dovecot的10-mail.conf配置

10-mail.conf主要配置Dovecot存储邮件的位置、相应的UID/GID等。

# See doc/wiki/Variables.txt for full list. Some examples:
#
#   mail_location = maildir:~/Maildir
#   mail_location = mbox:~/mail:INBOX=/var/mail/%u
#   mail_location = mbox:/var/mail/%d/%1n/%n:INDEX=/var/indexes/%d/%1n/%n
#
# <doc/wiki/MailLocation.txt>
#
mail_location = maildir:/YYYY/%d/%n

mail_uid = 5000
mail_gid = 5000

first_valid_uid = 5000
last_valid_uid = 5000

mail_privileged_group = vmail

mail_location指定用户路径,其中%d会被替换成邮箱地址上的相应域名,%n则会被替换成邮箱地址中去除域名后的用户名(即分别是@前后两部分)。

这儿,邮箱内文件格式指定为maildir格式,也可以为mbox等其他格式。

而mail_uid/mail_gid/first_valid_uid/last_valid_uid/mail_privileged_group这些信息就不需要介绍了。

3.3.4 Dovecot的10-master.conf配置

10-master.conf配置Dovecot启动服务的用户、创建的unix socket等,基本上就是权限与对外(其实就是对PostFix)交互接口的配置。

--- /ZZZZ/dovecot-2.3.19.1/doc/example-config/conf.d/10-master.conf	2022-06-14 14:55:03.000000000 +0800
+++ ./conf.d/10-master.conf	2022-08-25 10:42:59.933891605 +0800
@@ -52,8 +52,10 @@
 }
 
 service lmtp {
-  unix_listener lmtp {
-    #mode = 0666
+  unix_listener /var/spool/postfix/private/dovecot-lmtp {
+    mode = 0600
+    user = postfix
+    group = postfix
   }
 
   # Create inet listener only if you can't use the above UNIX socket
@@ -98,15 +100,17 @@
   # something else than 0666 and Dovecot lets the kernel enforce the
   # permissions (e.g. 0777 allows everyone full permissions).
   unix_listener auth-userdb {
-    #mode = 0666
-    #user = 
-    #group = 
+    mode = 0600
+    user = vmail
+    group = vmail
   }
 
   # Postfix smtp-auth
-  #unix_listener /var/spool/postfix/private/auth {
-  #  mode = 0666
-  #}
+  unix_listener /var/spool/postfix/private/auth {
+    mode = 0666
+    user = postfix
+    group = postfix
+  }
 
   # Auth process is run as this user.
   #user = $default_internal_user
@@ -117,14 +121,15 @@
   # /etc/shadow. If this isn't necessary, the user should be changed to
   # $default_internal_user.
   #user = root
+  user = vmail
 }
 
 service dict {
   # If dict proxy is used, mail processes should have access to its socket.
   # For example: mode=0660, group=vmail and global mail_access_groups=vmail
   unix_listener dict {
-    #mode = 0600
-    #user = 
-    #group = 
+    mode = 0660
+    user = vmail
+    group = vmail
   }
 }

参考网上的资料修改了如上一些内容,其中unix_listener lmtp,是LMTP协议参数配置(LMTP即本地邮件传输协议,一般用于本机或局域网内传送电子邮件的方法,这儿就是PostFix传输邮件至Dovecot的途径);而Postfix smtp-auth,则是提供给PostFix的SMTP认证的UNIX Socket(因此,能够访问的用户、组为postfix)。

3.3.5 Dovecot的10-ssl.conf配置

10-ssl.conf配置就是配置Dovecot支持SSL的能力了。

--- /BBBB/dovecot-2.3.19.1/doc/example-config/conf.d/10-ssl.conf	2022-06-14 14:55:03.000000000 +0800
+++ ./conf.d/10-ssl.conf	2022-08-26 14:31:21.965148857 +0800
@@ -2,15 +2,28 @@
 ## SSL settings
 ##
 
+# // https://doc.dovecot.org/configuration_manual/dovecot_ssl_configuration/#dovecot-ssl-configuration
+# // ssl=no: SSL/TLS 完全禁用。
+# // ssl=no: SSL/TLS 完全禁用。
+# // ssl=yesand disable_plaintext_auth=no: SSL/TLS 提供给客户端,但客户端不需要使用它。即使在连接上未启用 SSL/TLS,客户端也可以使用纯文本身份验证登录。这是不安全的,因为明文密码暴露在互联网上。
+# // ssl=yesand disable_plaintext_auth=yes: SSL/TLS 提供给客户端,但客户端不需要使用它。不允许客户端使用明文身份验证,除非先启用 SSL/TLS。但是,如果启用了非明文身份验证机制,即使没有 SSL/TLS,它们仍然是允许的。根据它们的安全程度,身份验证要么是完全安全的,要么可能有一些方法使其受到攻击。
+# // ssl=required:即使使用非明文身份验证机制,也始终需要 SSL/TLS。任何在启用 SSL/TLS 之前进行身份验证的尝试都将导致身份验证失败。请注意,此设置与 STARTTLS 命令无关 - 允许使用隐式 SSL/TLS 或 STARTTLS 命令。
+# // 如果您只启用了纯文本机制(例如) 和,和是完全等效的,因为在任何一种情况下,除非首先启用 SSL/TLS,否则身份验证将失败。auth_mechanisms = plain logindisable_plaintext_auth=yesssl=yesssl=required
+# // 两者都有ssl=yes,ssl=required客户端仍然有可能在启用 SSL/TLS 之前尝试进行明文身份验证,这会将明文密码暴露给互联网。
+# // Dovecot 尝试通过 LOGINDISABLED 功能向 IMAP 客户端指示这一点,但许多客户端仍然忽略它并发送密码。不幸的是,Dovecot 无法阻止这种行为。POP3 标准根本没有同等的能力,因此 POP3 客户端甚至无法知道服务器是否会接受明文身份验证。
+# // ssl=required和的主要区别在于disable_plaintext_auth=yesif ssl=required,它保证整个连接不被窃听(SSL/TLS 加密连接的其余部分),而disable_plaintext_auth=yes只保证密码不被窃听(SASL 机制被加密,但没有 SSL /TLS 必须使用)。现在你很可能应该在整个连接中使用 SSL/TLS,因为 SSL/TLS 的成本足够便宜。同时使用 SSL/TLS 和非明文身份验证将是理想的情况,因为它甚至可以保护明文密码免受中间人攻击。
+# // 对于来自 localhost 的连接,始终允许使用明文身份验证(并且不需要 SSL),因为无论如何它们都被认为是安全的。这适用于本地和远程 IP 地址相等的所有连接。此外,通过设置指定的 IP 范围也login_trusted_networks被认为是安全的。
+
 # SSL/TLS support: yes, no, required. <doc/wiki/SSL.txt>
 #ssl = yes
+ssl = yes
 
 # PEM encoded X.509 SSL/TLS certificate and private key. They're opened before
 # dropping root privileges, so keep the key file unreadable by anyone but
 # root. Included doc/mkcert.sh can be used to easily generate self-signed
 # certificate, just make sure to update the domains in dovecot-openssl.cnf
-ssl_cert = </etc/ssl/certs/dovecot.pem
-ssl_key = </etc/ssl/private/dovecot.pem
+ssl_cert = </AAAA/etc/ssl/private/vmail.crt
+ssl_key = </AAAA/etc/ssl/private/vmail.key
 
 # If key file is password protected, give the password here. Alternatively
 # give it when starting dovecot with -p parameter. Since this file is often
@@ -52,6 +65,7 @@
 # Or migrate from old ssl-parameters.dat file with the command dovecot
 # gives on startup when ssl_dh is unset.
 #ssl_dh = </etc/dovecot/dh.pem
+ssl_dh = </AAAA/etc/ssl/dhparam_2048.pem
 
 # Minimum SSL protocol version to use. Potentially recognized values are SSLv3,
 # TLSv1, TLSv1.1, TLSv1.2 and TLSv1.3, depending on the OpenSSL version used.
@@ -64,6 +78,7 @@
 #ssl_cipher_list = ALL:!kRSA:!SRP:!kDHd:!DSS:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK:!RC4:!ADH:!LOW@STRENGTH
 # To disable non-EC DH, use:
 #ssl_cipher_list = ALL:!DH:!kRSA:!SRP:!kDHd:!DSS:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK:!RC4:!ADH:!LOW@STRENGTH
+ssl_cipher_list = EECDH+AES:EDH+AES+aRSA
 
 # Colon separated list of elliptic curves to use. Empty value (the default)
 # means use the defaults from the SSL library. P-521:P-384:P-256 would be an
@@ -72,6 +87,7 @@
 
 # Prefer the server's order of ciphers over client's.
 #ssl_prefer_server_ciphers = no
+ssl_prefer_server_ciphers = yes

这儿,设置ssl为yes,即打开ssl(同时pop3与imap,也就升级为带s版本的了,端口也从110、143升级为995、993)。

ssl_cert、ssl_key与ssl_dh使用的信息,也是与域名网站的证书、私钥、DHPARAM是一样的(域名网站的证书,也应该支持mail.xxx,或pop3.xxx,或imap.xxx),需要注意的是,这些配置项,在文件名前必须带<,意思是引入整个文件。

ssl_cipher_list配置SSL加密算法,这儿是随便配置了一些。

ssl_prefer_server_ciphers为yes,说明服务器加密算法将优于客户端加密算法。

3.3.6 Dovecot的20-imap.conf配置

20-imap.conf配置没有做修改。

3.3.7 Dovecot的20-lmtp.conf配置

--- /BBBB/dovecot-2.3.19.1/doc/example-config/conf.d/20-lmtp.conf	2022-06-14 14:55:03.000000000 +0800
+++ ./conf.d/20-lmtp.conf	2022-08-25 10:47:35.414844226 +0800
@@ -35,6 +35,8 @@
 #lmtp_client_workarounds =
 
 protocol lmtp {
+  postmaster_address = postmaster@xxx.cn
   # Space separated list of plugins to load (default is global mail_plugins).
   #mail_plugins = $mail_plugins
+  mail_plugins = $mail_plugins
 }

仅配置了postmaster_address。

至此,Dovecot的配置全部完成,可以直接以sudo systemctl start dovecot方式,启动相应服务。

3.3.8 服务检测

Dovecot启动成功后,可以执行telnet命令,登陆相应服务端口,检测服务是否正常,命令如下。

telnet pop3.xxx.cn 110
telnet imap.xxx.cn 143

3.4 PostFixAdmin的配置

在配置PostFix之前,先配置好PostFixAdmin,并进行一些域、用户等的初始化,能够更便于理解PostFix的配置。

PostFixAdmin需要运行在NGINX+PHP下,初始配置并不困难。

PostFixAdmin在NGINX下的配置没有特殊之处

    location ^~ /webmailadmin {
        alias   /CCCC/postfixadmin/public/;

        # 日志文件分开
        error_log     /var/log/nginx/webmailadmin.error.log;
        access_log    /var/log/nginx/webmailadmin.access.log;

        # set max upload size
        client_max_body_size 128M;
        fastcgi_buffers 64 4K;

        # Uncomment if your server is build with the ngx_pagespeed module
        # This module is currently not supported.
        #pagespeed off;

        location = /webmailadmin {
            #try_files $uri/ = 404;
            rewrite ^ /webmailadmin/index.php redirect;
        }
        location ~ ^\/webmailadmin\/.*\.php(\/.*)*$ {
            fastcgi_split_path_info ^(.+?\.php)(\/.*|)$;
            set $path_info $fastcgi_path_info;
            try_files $fastcgi_script_name = 404;
            include fastcgi_params;
            # 目录限制控制
            fastcgi_param PHP_ADMIN_VALUE "open_basedir=/CCCC/postfixadmin:/YYYY:/ZZZZ:/tmp/:/proc/";
            fastcgi_param SCRIPT_FILENAME $request_filename;
            fastcgi_param PATH_INFO $path_info;
            fastcgi_param HTTPS on;
            # Avoid sending the security headers twice
            fastcgi_param modHeadersAvailable true;
            # Enable pretty urls
            fastcgi_param front_controller_active true;
            fastcgi_pass php-handler;
            fastcgi_intercept_errors on;
            fastcgi_request_buffering off;
        }
        location ~ ^\/webmailadmin\/(?:.+)*(\/|)$ {
            index index.php;
        }
        location ~ ^\/webmailadmin\/.+[^\/]\.(?:css|js|svg|gif|png)$ {
            try_files $uri /postfixadmin/index.php$request_uri;
            add_header Cache-Control "public, max-age=15778463";
            add_header Referrer-Policy "no-referrer" always;
            add_header X-Content-Type-Options "nosniff" always;
            add_header X-Download-Options "noopen" always;
            add_header X-Frame-Options "SAMEORIGIN" always;
            add_header X-Permitted-Cross-Domain-Policies "none" always;
            add_header X-Robots-Tag "none" always;
            add_header X-XSS-Protection "1; mode=block" always;

            # Optional: Don't log access to assets
            #access_log off;
        }
    }

需要注意一点,当前版本的PostFixAdmin,主体文件路径是解压的文件路径下的public目录(例/CCCC/postfixadmin/public),但配置PHP能够访问的文件路径,则需要整个解压的文件路径(同时包含SQLITE数据库文件路径)。

由于在location中使用了alias,则SCRIPT_FILENAME应指向request_filename。

配置了NGINX文件后,还需要在/CCCC/postfixadmin目录下创建templates_c目录,并修改目录归属用户、组。

下一步,需要在PostFixAdmin目录下生成一个config.local.php文件,以配置数据库等信息。

<?php
$CONF['configured'] = true;
// correspond to dovecot maildir path /home/vmail/%d/%u
$CONF['domain_path'] = 'YES';
$CONF['domain_in_mailbox'] = 'NO';
$CONF['database_type'] = 'sqlite';
$CONF['database_name'] = '/YYYY/authdb.db';
$CONF['setup_password'] = '...........................';

$CONF['default_aliases'] = array (
    'abuse' => 'abuse@ZZZZZZZZ.cn',
    'hostmaster' => 'hostmaster@ZZZZZZZZ.cn',
    'postmaster' => 'postmaster@ZZZZZZZZ.cn',
    'webmaster' => 'webmaster@ZZZZZZZZ.cn'
);

然后,即可以登陆http://ZZZZZZZZ.cn/webmailadmin,创建SQLITE的相应表、并在PostFixAdmin里添加域名、用户名(这儿添加一个support@xxx.cn)

3.5 PostFix的配置

PostFix的配置项之多,简直令人发麻,具体可以参考postconf.5.html、master.5.html、master.8.html等文档(由PostFix软件包提供了)。

主要来说,分成两个文件,master.cf与main.cf。

master.cf文件是指示PostFix启动哪些服务、监听哪些端口等,其中可以配置服务启动参数(优先级最高)。

main.cf则配置PostFix的所有参数信息(某一项未配置时,则会使用默认值)。

main.cf在配置虚拟域时,会引用几个配置文件,具体示例类似于https://www.myfreax.com/install-and-configure-postfix-and-dovecot/中的配置说明。

3.5.1 PostFix的master.cf配置

--- /CCC/postfix-3.7.2/dest/data/app/etc/postfix/master.cf	2022-08-25 18:44:17.424783195 +0800
+++ ./master.cf	2022-08-27 13:27:29.958358702 +0800
@@ -14,9 +14,11 @@
 #smtpd     pass  -       -       n       -       -       smtpd
 #dnsblog   unix  -       -       n       -       0       dnsblog
 #tlsproxy  unix  -       -       n       -       0       tlsproxy
+smtps     inet  n       -       n       -       -       smtpd
+  -o smtpd_tls_wrappermode=yes
 # Choose one: enable submission for loopback clients only, or for any client.
 #127.0.0.1:submission inet n -   n       -       -       smtpd
-#submission inet n       -       n       -       -       smtpd
+submission inet n       -       n       -       -       smtpd
 #  -o syslog_name=postfix/submission
 #  -o smtpd_tls_security_level=encrypt
 #  -o smtpd_sasl_auth_enable=yes
@@ -26,7 +28,7 @@
 #     specify "smtpd_<xxx>_restrictions=$mua_<xxx>_restrictions"
 #     here, and specify mua_<xxx>_restrictions in main.cf (where
 #     "<xxx>" is "client", "helo", "sender", "relay", or "recipient").
-#  -o smtpd_client_restrictions=
+#  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
 #  -o smtpd_helo_restrictions=
 #  -o smtpd_sender_restrictions=
 #  -o smtpd_relay_restrictions=

master.cf并不需要修改太多,添加smtps,打开submission即可,参数信息集中在main.cf更容易管理。

3.5.2 PostFix虚拟用户下的几个配置文件

参考https://www.myfreax.com/install-and-configure-postfix-and-dovecot/中的虚拟用户配置,生成了五个在SQLITE下的虚拟用户配置。

virtual_alias_domain_catchall_maps.cf文件,

--- /CCC/postfix-3.7.2/dest/data/app/etc/postfix/virtual_alias_domain_catchall_maps.cf	1970-01-01 08:00:00.000000000 +0800
+++ ./virtual_alias_domain_catchall_maps.cf	2022-08-24 17:44:15.457787477 +0800
@@ -0,0 +1,4 @@
+dbpath=/XXXX/authdb.db
+#query = SELECT goto FROM alias,alias_domain WHERE alias_domain.alias_domain = '%d' and alias.address = CONCAT('@', alias_domain.target_domain) AND alias.active = 1 AND alias_domain.active='1'
+query=SELECT goto FROM alias,alias_domain WHERE alias_domain.alias_domain = '%d' and alias.address = ('@' || alias_domain.target_domain) AND alias.active = 1 AND alias_domain.active='1'
+

virtual_alias_domain_mailbox_maps.cf文件,

--- /CCC/postfix-3.7.2/dest/data/app/etc/postfix/virtual_alias_domain_mailbox_maps.cf	1970-01-01 08:00:00.000000000 +0800
+++ ./virtual_alias_domain_mailbox_maps.cf	2022-08-24 17:50:22.332173785 +0800
@@ -0,0 +1,4 @@
+dbpath=/XXXX/authdb.db
+# query = SELECT maildir FROM mailbox,alias_domain WHERE alias_domain.alias_domain = '%d' and mailbox.username = CONCAT('%u', '@', alias_domain.target_domain) AND mailbox.active = 1 AND alias_domain.active='1'
+query=SELECT maildir FROM mailbox,alias_domain WHERE alias_domain.alias_domain = '%d' and mailbox.username = ('%u' || '@' || alias_domain.target_domain) AND mailbox.active = 1 AND alias_domain.active='1'
+

virtual_alias_domain_maps.cf文件,

--- /CCC/postfix-3.7.2/dest/data/app/etc/postfix/virtual_alias_domain_maps.cf	1970-01-01 08:00:00.000000000 +0800
+++ ./virtual_alias_domain_maps.cf	2022-08-24 17:45:36.239097657 +0800
@@ -0,0 +1,3 @@
+dbpath=/XXXX/authdb.db
+# query = SELECT goto FROM alias,alias_domain WHERE alias_domain.alias_domain = '%d' and alias.address = CONCAT('%u', '@', alias_domain.target_domain) AND alias.active = 1 AND alias_domain.active='1'
+query = SELECT goto FROM alias,alias_domain WHERE alias_domain.alias_domain = '%d' and alias.address = ('%u' ||  '@' || alias_domain.target_domain) AND alias.active = 1 AND alias_domain.active='1' 

virtual_alias_maps.cf文件,

--- /CCC/postfix-3.7.2/dest/data/app/etc/postfix/virtual_alias_maps.cf	1970-01-01 08:00:00.000000000 +0800
+++ ./virtual_alias_maps.cf	2022-08-24 17:27:56.799255594 +0800
@@ -0,0 +1,3 @@
+dbpath=/XXXX/postfix.db
+#query=SELECT goto FROM alias WHERE address = '%s'
+query=SELECT goto FROM alias WHERE address='%s' AND active = '1'

virtual_mailbox_domains.cf文件,

--- /CCC/postfix-3.7.2/dest/data/app/etc/postfix/virtual_mailbox_domains.cf	1970-01-01 08:00:00.000000000 +0800
+++ ./virtual_mailbox_domains.cf	2022-08-24 17:29:30.320478863 +0800
@@ -0,0 +1,2 @@
+dbpath=/XXXX/authdb.db
+query=SELECT domain FROM domain WHERE domain='%s' AND active = '1'

virtual_mailbox_maps.cf文件,

--- /CCC/postfix-3.7.2/dest/data/app/etc/postfix/virtual_mailbox_maps.cf	1970-01-01 08:00:00.000000000 +0800
+++ ./virtual_mailbox_maps.cf	2022-08-24 17:32:14.415586351 +0800
@@ -0,0 +1,3 @@
+dbpath=/XXXX/authdb.db
+query = SELECT maildir FROM mailbox WHERE username='%s' AND active = '1'

这些文件的主要修改参考https://www.myfreax.com/install-and-configure-postfix-and-dovecot/说明,将其中MySQL的语句,修改适配至Sqlite而已。

3.5.3 PostFix的main.cf配置

由于main.cf的配置项修改较多,就一个个分开说明(大量参数说明仅仅是拷贝机翻,能大致看懂即可):

1). myhostname

当前邮件系统在互联网上的主机名,如果OS主机名就修改好了,这儿也可以不设置,但通常而言,设置比不设置更好。

 # from gethostname(). $myhostname is used as a default value for many
 # other configuration parameters.
 #
+# // 与其他SMTP服务器通信时,Postfix使用此主机名来标识自己。 但是,操作系统主机名可能会更改,因此,最好直接在配置文件中设置。
 #myhostname = host.domain.tld
 #myhostname = virtual.domain.tld
+myhostname = mail.XXXX.cn
2).mydomain

域名,缺省是使用myhostname减去前面那一块,或者localdomain。

 # The mydomain parameter specifies the local internet domain name.
 # The default is to use $myhostname minus the first component.
 # $mydomain is used as a default value for many other configuration
 # parameters.
 #
+# 设置域名是XXXX.cn 
 #mydomain = domain.tld
+mydomain = XXXX.cn
3).myorigin

这个域名,是本地投递显示的来源处,或本地邮件投递的派发地。缺省情况下,等于myhostname即可;如果在多个机器上运行一个域(多个MTA?),则应该修改为mydomain,或者建立域名范围的别名数据库(针对每个用户,建立用户名到用户@xxx的别名映射)。

 # For the sake of consistency between sender and recipient addresses,
 # myorigin also specifies the default domain name that is appended
 # to recipient addresses that have no @domain part.
-#
+# 
+# // myorigin参数指定默认域名,该默认域名将附加到没有@domain部分的发件人和收件人地址。 需要将其值更改为XXXX.cn,因此邮件服务器上的发件人将具有@XXXX.cn地址。
 #myorigin = $myhostname
-#myorigin = $mydomain
+myorigin = $mydomain
4).inet_interfaces

inet_interfaces定义网卡监听地址,如果希望收到外部邮件,无疑要使用all。

 #
 # Note: you need to stop/start Postfix when this parameter changes.
 #
-#inet_interfaces = all
+#定义网卡监听地址。可以指定要使用服务器的哪些IP地址对外提供电子邮件服务;也可以干脆写成all,代表所有IP地址都能提供电子邮件服务
+inet_interfaces = all
 #inet_interfaces = $myhostname
 #inet_interfaces = $myhostname, localhost
5).mydestination

mydestination定义邮件服务器上自身最终目的地的域列表。这个听起来有点拗口,说白了就是别人给您发信,哪些信你是接受的。

默认postfix从mydestination和virtual_mailbox_domains两个参数来确定postfix需要接收哪些域的邮件。如果接收的邮件域与mydestination匹配,则使用系统帐号处理邮件;如果接收的邮件域与virtual_mailbox_domains匹配则使用虚拟帐号处理邮件。

因此,在定义虚拟帐号来处理邮件时,应将mydomain从mydestination中删除。

 # The mydestination parameter specifies the list of domains that this
 # machine considers itself the final destination for.
@@ -179,11 +186,17 @@
 # Continue long lines by starting the next line with whitespace.
 #
 # See also below, section "REJECTING MAIL FOR UNKNOWN LOCAL USERS".
-#
+# 
+# //mydestination参数指定服务器将其视为自身最终目的地的域列表。这个听起来有点拗口,说白了就是别人给您发信,哪些信你是接受的。比如12345@qq.com给您发一封信,收件人是webmaster@example.com,当你的smtp服务器接收到这封信的时候表示接受,对应的规则就是$mydomain。注意:此处如果设错了,有可能出现一个问题:你可以给别人发信,但是别人给你发的信你会收不到。
 #mydestination = $myhostname, localhost.$mydomain, localhost
+#定义可接收邮件的主机名或域名列表
 #mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain
 #mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain,
 #	mail.$mydomain, www.$mydomain, ftp.$mydomain
+# // 默认postfix从mydestination和virtual_mailbox_domains两个参数来确定postfix需要接收哪些域的邮件。如果接收的邮件域与mydestination匹配,则使用系统帐号处理邮件;如果接收的邮件域与virtual_mailbox_domains匹配则使用虚拟帐号处理邮件。
+# // 此处mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain,($mydomain=test.edu.cn)且virtual_mailbox_domains指定的mysql数据库中也存在test.edu.cn域,这样test1@test.edu.cn邮件就同时匹配两种帐号,postfix不能判断使用哪种帐号去处理这个邮件,所以就出现了上述这种错误。
+# //所以配置mydestination时,一定要考虑到不能与虚拟域有相同的域名。
+mydestination = $myhostname, localhost.$mydomain, localhost
6).mynetworks_style

mynetworks_style为mynetworks参数定义生成默认值的方法。这是用于中继访问控制等的受信任网络列表。

为host时,仅信任本机;为subnet时,信任子网的机器(在Linux上,仅在指定了ifconfig或ip命令的网口时正常工作);为class时,则信任指定的A、B或C类网络。

 # REJECTING MAIL FOR UNKNOWN LOCAL USERS
 #
@@ -270,7 +283,8 @@
 # 
 #mynetworks_style = class
 #mynetworks_style = subnet
-#mynetworks_style = host
+# // Postfix默认将子网内的机器设置为可信任机器,如果只信任本机,就设置为host:
+mynetworks_style = host
7).mynetworks

mynetworks生效时,则mynetworks_style不起作用。

在此限制范围内的SMTP客户端有更高的优先权。

 # Alternatively, you can specify the mynetworks list by hand, in
 # which case Postfix ignores the mynetworks_style setting.
@@ -284,6 +298,8 @@
 # (the value on the table right-hand side is not used).
 #
 #mynetworks = 168.100.3.0/28, 127.0.0.0/8
+# //263行,设置内网和本地IP  
+mynetworks = 192.168.1.0/24, 127.0.0.0/8
 #mynetworks = $config_directory/mynetworks
 #mynetworks = hash:/etc/postfix/network_table
8).alias_maps

alias_maps,这个应该是别名映射表。配置了虚拟账号,就不需要配置这个参数了。

 #alias_maps = hash:/etc/aliases
 #alias_maps = hash:/etc/aliases, nis:mail.aliases
 #alias_maps = netinfo:/aliases
+# // 虚拟域,不配置本地别名投递
+alias_maps = 
 
 # The alias_database parameter specifies the alias database(s) that
 # are built with "newaliases" or "sendmail -bi".  This is a separate
9).home_mailbox

home_mailbox定义邮件保存位置,也是本地帐号邮箱投递体系的一个参数。

 # "Maildir/" for qmail-style delivery (the / is required).
 #
 #home_mailbox = Mailbox
-#home_mailbox = Maildir/
+# // Postfix设置Maildir格式的邮箱  用来定义邮件保存位置
+home_mailbox = Maildir/
  
 # The mail_spool_directory parameter specifies the directory where
 # UNIX-style mailboxes are kept. The default setting depends on the
10).smtpd_banner

smtpd_banner为SMTP客户端登陆上来时的欢迎提示信息。

 #
 #smtpd_banner = $myhostname ESMTP $mail_name
 #smtpd_banner = $myhostname ESMTP $mail_name ($mail_version)
+smtpd_banner = $myhostname ESMTP unknown
 
 # PARALLEL DELIVERY TO THE SAME DESTINATION
 #
11).relay_domains

relay_domains,该参数指定会将邮件中继到哪些目标域(及其子域)。有关如何使用relay_domains值的详细信息,请参阅 permit_auth_destination和reject_unauth_destination SMTP 收件人限制的描述。

与 $ relay_domains匹配的域使用 $ relay_transport邮件传递传输进行传递。 SMTP 服务器使用$relay_recipient_maps验证收件人地址并拒绝不存在的收件人。另请参见ADDRESS_CLASS_README文件 中的中继域地址类 。

注意:Postfix 不会自动转发将此系统列为主要或备用 MX 主机的域的邮件。请参阅 postconf(5)手册页 中的permit_mx_backup限制。

指定主机名或域名列表、“/file/name”模式或“ type:table ”查找表,以逗号和/或空格分隔。通过以空格开始下一行来继续长行。“/file/name”模式被其内容替换;当(父)域作为查找键出现时,匹配“ type:table ”查找表。指定“!pattern”以从列表中排除域。只有 Postfix 版本 2.4 和更高版本才支持 "!/file/name" 形式。

域名的模式匹配由parent_domain_matches_subdomains 参数值中是否存在“ relay_domains ”来控制。

+
+relay_domains = $mydestination
12).biff

是否使用本地biff服务。此服务向使用 UNIX 命令“ biff y” 请求新邮件通知的用户发送“新邮件”通知

+# // 是否使用本地biff服务。此服务向使用 UNIX 命令“ biff y” 请求新邮件通知的用户发送“新邮件”通知
+# // 出于兼容性原因,此功能默认启用。在具有大量交互式用户的系统上,biff服务可能会消耗性能。在main.cf中指定“ biff = no”以禁用
+biff = no
+
13).virtual_alias_maps

virtual_alias_maps、virtual_mailbox_domains及virtual_mailbox_maps这三个参数放在一起,参考https://www.myfreax.com/install-and-configure-postfix-and-dovecot/中的虚拟用户配置,使用了3.5.2部分完成五个配置文件。

virtual_alias_maps,将特定邮件地址或域别名为其他本地或远程地址的可选查找表。表格格式和查找记录在virtual(5)中。有关 Postfix 地址操作的概述,请参阅ADDRESS_REWRITING_README文档。

指定零个或多个“type:name”查找表,以空格或逗号分隔。将按指定顺序搜索表,直到找到匹配项。注意:这些查找是递归的。

+virtual_alias_maps = sqlite:/data/app/etc/postfix/virtual_alias_maps.cf,sqlite:/data/app/etc/postfix/virtual_alias_domain_maps.cf,sqlite:/data/app/etc/postfix/virtual_alias_domain_catchall_maps.cf
14).virtual_mailbox_domains

virtual_mailbox_domains,Postfix 是指定域列表的最终目的地;邮件通过 $ virtual_transport邮件传递传输传递。默认情况下,这是 Postfix virtual(8)传递代理。SMTP 服务器使用 $ virtual_mailbox_maps验证收件人地址并拒绝不存在的收件人的邮件。另请参见ADDRESS_CLASS_README文件中的虚拟邮箱域类。

此参数需要与mydestination 配置参数 相同的语法。

+virtual_mailbox_domains = sqlite:/data/app/etc/postfix/virtual_mailbox_domains.cf
15).virtual_mailbox_maps

virtual_mailbox_maps,可选查找表,其中包含与 $ virtual_mailbox_domains 匹配的域中的所有有效地址。

指定零个或多个“type:name”查找表,以空格或逗号分隔。将按指定顺序搜索表,直到找到匹配项。

在查找表中,指定“@domain.tld”的左侧以匹配指定域中没有特定“user@domain.tld”条目的任何用户。

使用默认的“ virtual_mailbox_domains = $ virtual_mailbox_maps ”,查找表还需要具有“domain.tld”左侧的条目以满足 virtual_mailbox_domain 查找(右侧是必需的,但不会使用)。

本文的其余部分特定于virtual(8)交付代理。当使用不同的邮件递送程序递送邮件时,它不适用。

virtual(8)传递代理 使用此表来查找每个收件人的邮箱或 maildir 路径名。如果查找结果以斜杠(“/”)结尾,则执行 maildir 样式的传递,否则假定路径指定了 UNIX 样式的邮箱文件。请注意,$ virtual_mailbox_base无条件地添加到此路径。

当收件人地址具有可选的地址扩展名 (user+foo@domain.tld) 时,virtual(8)投递代理首先查找完整地址,当查找失败时,它会查找未扩展地址 (user@domain.tld)。顶级域名)。

注意 1:出于安全原因,virtual(8)传递代理不允许在正则表达式查找表中用正则表达式替换 $1 等,因为这会打开一个安全漏洞。

注意 2:出于安全原因,virtual(8)传递代理将默默地忽略使用proxymap(8)服务器的请求。相反,它将直接打开表。在 Postfix 版本 2.2 之前, virtual(8)传递代理将终止并出现致命错误。

+virtual_mailbox_maps = sqlite:/data/app/etc/postfix/virtual_mailbox_maps.cf,sqlite:/data/app/etc/postfix/virtual_alias_domain_mailbox_maps.cf
16).virtual_mailbox_base、virtual_mailbox_limit、virtual_minimum_uid

virtual_mailbox_base,virtual传递代理添加到所有路径名的前缀,通常是去 $ virtual_mailbox_maps表查找。设置此变量是一种安全措施,可确保错误映射时不会在文件系统中乱扔邮箱。虽然virtual_mailbox_base可以设置为“/”,但不建议使用此设置。

virtual_mailbox_limit,单个virtual邮箱或 maildir 文件 的最大字节大小,或零(无限制)

virtual_minimum_uid,virtual交付代理作为 $ virtual_uid_maps表查找的结果接受 的最小用户 ID 值。小于此值的返回值将被拒绝,并且消息将被延迟。

此参数仅用于于virtual付代理。当使用不同的邮件递送程序递送邮件时,它不适用。

+virtual_mailbox_base = /data/mail/data
+virtual_mailbox_limit = 512000000
+virtual_minimum_uid = 5000
17).virtual_transport

virtual_transport,最终传递到 $ virtual_mailbox_domains列出的域的默认邮件传递传输和下一跳目标。与transport互斥。

指定格式为transport:nexthop的字符串,其中transport是在master.cf中 定义的邮件传递传输的名称。: nexthop目的地是可选的;其语法记录在相应交付代理的手册页中。

我们这儿定义Postfix以LMTP协议,传递至Dovecot存储。

+# virtual_transport = virtual
+#Handing off local delivery to Dovecot's LMTP, and telling it where to store mail  
+virtual_transport = lmtp:unix:private/dovecot-lmtp
18).virtual_uid_maps

virtual_uid_maps,使用virtual(8) 传递代理在写入收件人邮箱时使用 的每个收件人用户 ID 查找表。

此参数特定于virtual(8)交付代理。当使用不同的邮件递送程序递送邮件时,它不适用。

指定零个或多个“type:name”查找表,以空格或逗号分隔。将按指定顺序搜索表,直到找到匹配项。

在查找表中,指定“@domain.tld”的左侧以匹配指定域中没有特定“user@domain.tld”条目的任何用户。

当收件人地址具有可选的地址扩展名 (user+foo@domain.tld) 时,virtual(8)投递代理首先查找完整地址,当查找失败时,它会查找未扩展地址 (user@domain.tld)。顶级域名)。

注意 1:出于安全原因,virtual(8)传递代理不允许在正则表达式查找表中用正则表达式替换 $1 等,因为这会打开一个安全漏洞。

注意 2:出于安全原因,virtual(8)传递代理将默默地忽略使用proxymap(8)服务器的请求。相反,它将直接打开表。在 Postfix 版本 2.2 之前, virtual(8)传递代理将终止并出现致命错误。

+virtual_uid_maps = static:5000
19).virtual_gid_maps

具有每个收件人组 ID 的查找表以进行虚拟 (8)邮箱传递。

此参数特定于virtual(8)交付代理。当使用不同的邮件递送程序递送邮件时,它不适用。

指定零个或多个“type:name”查找表,以空格或逗号分隔。将按指定顺序搜索表,直到找到匹配项。

在查找表中,指定“@domain.tld”的左侧以匹配指定域中没有特定“user@domain.tld”条目的任何用户。

当收件人地址具有可选的地址扩展名 (user+foo@domain.tld) 时,virtual(8)投递代理首先查找完整地址,当查找失败时,它会查找未扩展地址 (user@domain.tld)。顶级域名)。

注意 1:出于安全原因,virtual(8)传递代理不允许在正则表达式查找表中用正则表达式替换 $1 等,因为这会打开一个安全漏洞。

注意 2:出于安全原因,virtual(8)传递代理将默默地忽略使用proxymap(8)服务器的请求。相反,它将直接打开表。在 Postfix 版本 2.2 之前, virtual(8)传递代理将终止并出现致命错误。

+virtual_gid_maps = static:5000
+#local_transport = virtual
+#local_recipient_maps = $virtual_mailbox_maps
+#transport_maps = hash:/data/app/etc/postfix/transport
20).smtpd_sasl_auth_enable

smtpd_sasl_auth_enable,在 Postfix SMTP 服务器中启用 SASL 身份验证。默认情况下,Postfix SMTP 服务器不使用身份验证。

如果远程 SMTP 客户端经过身份验证,则permit_sasl_authenticated 访问限制可用于允许中继访问,如下所示:

# 对于 Postfix 2.10 及更高版本,邮件中继策略为
# 最好在smtpd_relay_restrictions下指定。
smtpd_relay_restrictions =
     permit_mynetworks , permit_sasl_authenticated , ...
# 使用2.10之前的Postfix,中继策略可以是
# 仅在smtpd_recipient_restrictions下指定。
smtpd_recipient_restrictions =
     permit_mynetworks,permit_sasl_authenticated,...

要拒绝来自未经身份验证的客户端的所有 SMTP 连接,请指定“ smtpd_delay_reject = yes”(这是默认值)并使用:

smtpd_client_restrictions = permit_sasl_authenticated,reject

有关 SASL 配置和操作的详细信息,请参阅SASL_README文件。

+
+# // 启用sasl服务,并配置一些属性。它们的作用,大家参考文档
+# //使用SMTP认证  
+smtpd_sasl_auth_enable = yes
21).smtpd_sasl_type

smtpd_sasl_type,Postfix SMTP 服务器应用于身份验证的 SASL 插件类型。可用类型使用“ postconf -a ”命令列出。

通常编译有cyrus与dovecot,这里直接使用dovecot的sasl认证服务。

+# // #使用dovecot的sasl服务。默认使用cyrus,所以一定要配置这个选项
+smtpd_sasl_type = dovecot
22).smtpd_sasl_path

smtpd_sasl_path,调用sasl服务的路径。支持文件句柄(适合在同一台机器)和请求接口(适合不同机器)

+# // # Can be an absolute path, or relative to $queue_directory
+# smtpd_sasl_path = /var/run/dovecot/auth-client
+# // #调用sasl服务的路径。支持文件句柄(适合在同一台机器)和请求接口(适合不同机器)
+# // dovecot开启sasl服务的在/etc/dovecot/conf.d/10-master.conf,里面有明显的注释,去掉就可以
+smtpd_sasl_path = /var/spool/postfix/private/auth
23).smtpd_sasl_security_options

smtpd_sasl_security_options,SMTP服务的SASL安全选项(也依赖于smtpd_sasl_type)。

可指定如下0个或多个:

  • noplaintext

    禁止使用明文密码的方法。

  • noactive

    禁止方法受到主动(非字典)攻击。

  • nodictionary

    禁止方法受到被动(字典)攻击。

  • noanonymous

    禁止允许匿名身份验证的方法。

  • forward_secrecy

    只允许支持前向保密的方法(仅限 Dovecot)。

  • mutual_auth

    仅允许提供相互身份验证的方法(不适用于 Cyrus SASL 版本 1)。

默认情况下,Postfix SMTP 服务器接受明文密码,但不接受匿名登录。

smtpd_sasl_tls_security_options,Postfix SMTP 服务器用于 TLS 加密的 SMTP 会话的 SASL 身份验证安全选项。

+# //取消匿名登陆方式
+smtpd_sasl_security_options = noanonymous
+smtpd_sasl_tls_security_options = $smtpd_sasl_security_options
24).smtpd_tls_security_level

smtpd_tls_security_level,指定Postfix SMTP 服务器的 SMTP TLS 安全级别;当指定非空值时,这将覆盖过时的参数 smtpd_use_tls和smtpd_enforce_tls。使用“ smtpd_tls_wrappermode = yes” 忽略此参数。

三个选择其一:

none不会使用 TLS

may 可选TLS:向远程 SMTP 客户端宣布 STARTTLS 支持,但不要求客户端使用 TLS 加密。

encrypt

强制 TLS 加密:宣布远程 SMTP 客户端支持 STARTTLS,并要求客户端使用 TLS 加密。根据RFC 2487,这绝不能应用于公共引用的 SMTP 服务器。相反,此选项应仅在专用服务器上使用。

参数设置“ smtpd_tls_security_level = encrypt”意味着“ smtpd_tls_auth_only = yes”。

+
+smtpd_tls_security_level = may
25).smtpd_tls_auth_only

smtpd_tls_auth_only,当 TLS 加密在 Postfix SMTP 服务器中是可用时,不接受未加密连接上的 SASL 身份验证。

打开此选项时,会导致RoundCube无法发送邮件,因此关闭此选项。

+# // RoundCube fail if smtpd_tls_auth_only = yes
+#smtpd_tls_auth_only = yes
26).smtpd_tls_received_header

smtpd_tls_received_header,请求 Postfix SMTP 服务器生成 Received消息头,其中包括有关使用的协议和密码的信息,以及远程 SMTP 客户端 CommonName 和客户端证书颁发者 CommonName。默认情况下禁用此功能,因为信息可能在通过其他邮件服务器的传输过程中被修改。只有最终目的地记录的信息是可信的。

+smtpd_tls_received_header = yes
27).smtpd_tls_cert_file与smtpd_tls_key_file

smtpd_tls_cert_file,带有 PEM 格式的 Postfix SMTP 服务器 RSA 证书的文件。该文件还可能包含 Postfix SMTP 服务器私有 RSA 密钥。对于 Postfix ≥ 3.4,配置服务器密钥和证书的首选方法是通过“ smtpd_tls_chain_files ”参数。

没有由“信誉良好的”CA 签署的证书的公共 Internet MX 主机必须生成并准备向大多数客户提供自签署或私有 CA 签署的证书。客户端将无法对服务器进行身份验证,但除非它运行 Postfix 2.3 或类似软件,否则它仍会坚持使用服务器证书。

对于不是公共 Internet MX 主机的服务器,Postfix 支持没有证书的配置。这需要仅使用典型 SMTP 客户端不支持的匿名 TLS 密码。由于某些客户端在 TLS 握手失败后可能不会回退到纯文本,因此无证书的 Postfix SMTP 服务器将无法接收来自某些启用 TLS 的客户端的电子邮件。为避免意外配置无证书,Postfix 仅在管理员明确设置“ smtpd_tls_cert_file = none”时启用无证书操作。这确保了新的 Postfix SMTP 服务器配置不会在没有证书的情况下意外启用 TLS。

请注意,服务器证书在 TLS 1.3 中不是可选的。要在没有证书的情况下运行,您必须通过在“ smtpd_tls_protocols ”中包含“!TLSv1.3 ”以及可能在“ smtpd_tls_mandatory_protocols ”中包含“! TLSv1.3 ”来禁用TLS 1.3 协议。相反,只配置证书链更简单。不推荐无证书操作。

支持 RSA 和 DSA 证书。当这两种类型都存在时,使用的密码确定将向客户端提供哪个证书。对于没有特殊密码选择的 Netscape 和 OpenSSL 客户端,首选 RSA 证书。

要使远程 SMTP 客户端能够验证 Postfix SMTP 服务器证书,颁发 CA 证书必须对客户端可用。您应该在服务器证书文件中包含所需的证书,首先是服务器证书,然后是颁发 CA(自下而上的顺序)。

示例:“server.example.com”的证书由“中间 CA”颁发,该 CA 本身具有“根 CA”证书。使用“cat server_cert.pem intermediate_CA.pem root_CA.pem > server.pem”创建 server.pem 文件。

如果您还想验证这些 CA 颁发的客户端证书,您可以将 CA 证书添加到smtpd_tls_CAfile,在这种情况下,不必将它们放在smtpd_tls_cert_filesmtpd_tls_dcert_file(已过时)或smtpd_tls_eccert_file中。

此处提供的证书必须可用作 SSL 服务器证书,因此必须通过“openssl verify - purpose sslserver ...”测试。

smtpd_tls_key_file,带有 PEM 格式的 Postfix SMTP 服务器 RSA 私钥的文件。该文件可以与 $ smtpd_tls_cert_file指定的 Postfix SMTP 服务器 RSA 证书文件结合使用。对于 Postfix ≥ 3.4,配置服务器密钥和证书的首选方法是通过“ smtpd_tls_chain_files ”参数。

私钥必须可以在没有密码的情况下访问,即它不能被加密。文件权限应授予对系统超级用户帐户(“root”)的只读访问权限,而不授予其他任何人访问权限。

+# // 设置SMTP使用SSL加密的证书与私钥
+smtpd_tls_cert_file = /XXXX/etc/ssl/private/vmail.crt
+smtpd_tls_key_file = /XXXX/etc/ssl/private/vmail.key
28).smtpd_sasl_local_domain

smtpd_sasl_local_domain,Postfix SMTP 服务器的本地 SASL 身份验证的域名。

+smtpd_sasl_local_domain = $mydomain
29).smtpd_tls_loglevel

smtpd_tls_loglevel,启用 TLS 活动的附加 Postfix SMTP 服务器日志记录。每个日志记录级别自动包括以较低日志记录级别记录的信息。

  • 0 禁用记录 TLS 活动。
  • 1 仅记录 TLS 握手完成的摘要消息 — 如果不需要客户端证书验证,则不记录客户端证书信任链验证错误。使用 Postfix 2.8 及更早版本,记录摘要消息、对等证书摘要信息并无条件记录信任链验证错误。
  • 2 还在 TLS 协商期间记录级别。
  • 3 同时记录 TLS 协商过程的十六进制和 ASCII 转储。
  • 4 还记录 STARTTLS 后完整传输的十六进制和 ASCII 转储。

除非出现问题,否则不要使用“ smtpd_tls_loglevel = 2”或更高版本。强烈建议不要使用 loglevel 4。

+smtpd_tls_loglevel = 1
30).smtpd_recipient_restrictions

smtpd_recipient_restrictions、smtpd_relay_restrictions与smtpd_sender_restrictions,限定PostFix对于邮件接收、发送及回复的规则限制,Postfix的反垃圾邮件的功能主要集中在这几个参数上。因此,这几个参数的配置,也是很灵活、内容很多。

Postfix SMTP 服务器在客户端 执行RCPT TO 命令的上下文中应用的可选限制. 可参阅SMTPD_ACCESS_README的“延迟评估 SMTP 访问限制列表”部分。.

With Postfix versions before 2.10, the rules for relay permission and spam blocking were combined under smtpd_recipient_restrictions, resulting in error-prone configuration. As of Postfix 2.10, relay permission rules are preferably implemented with smtpd_relay_restrictions, so that a permissive spam blocking policy under smtpd_recipient_restrictions will no longer result in a permissive mail relay policy.

For backwards compatibility, sites that migrate from Postfix versions before 2.10 can set smtpd_relay_restrictions to the empty value, and use smtpd_recipient_restrictions exactly as before.

重要信息:smtpd_relay_restrictionssmtpd_recipient_restrictions参数必须至少指定以下限制之一。否则 Postfix 将拒绝接收邮件:

reject, reject_unauth_destination
defer, defer_if_permit, defer_unauth_destination

指定限制列表,以逗号和/或空格分隔。通过以空格开始下一行来继续长行。限制按指定的顺序应用;首先匹配OK的限制获胜。

以下限制特定于使用 RCPT TO 命令接收的收件人地址。

  • check_recipient_access *type:table*

    在指定的access(5)数据库中搜索已解析的 RCPT TO 地址、域、父域或 localpart@,并执行相应的操作。

  • check_recipient_a_access *type:table*

    在指定的access(5)数据库中搜索 RCPT TO 域的 IP 地址,并执行相应的操作。注意:出于安全原因,不允许出现“OK”的结果。相反,使用 DUNNO 从拒绝名单中排除特定主机。此功能在 Postfix 3.0 及更高版本中可用。

  • check_recipient_mx_access *type:table*

    在指定的access(5)数据库中搜索 RCPT TO 域的 MX 主机,并执行相应的操作。如果没有找到 MX 记录,则查找 A 或 AAAA 记录,就像 Postfix SMTP 客户端那样。注意:出于安全原因,不允许出现“OK”的结果。相反,使用 DUNNO 从拒绝名单中排除特定主机。此功能在 Postfix 2.1 及更高版本中可用。

  • check_recipient_ns_access *type:table*

    在指定的access(5)数据库中搜索 RCPT TO 域的 DNS 服务器,并执行相应的操作。注意:出于安全原因,不允许出现“OK”的结果。相反,使用 DUNNO 从拒绝名单中排除特定主机。此功能在 Postfix 2.1 及更高版本中可用。

  • permit_auth_destination

    当下列情况之一为真时,允许该请求:

  • permit_mx_backup

    当本地邮件系统是 RCPT TO 域的备份 MX 时,或者当域是授权目的地时,允许请求(参见permit_auth_destination的定义)。

  • reject_non_fqdn_recipient

    当 RCPT TO 地址指定的域不是完全限定的域形式时,拒绝请求,如 RFC 所要求的。
    non_fqdn_reject_code 参数指定拒绝请求的响应代码(默认值:504)

  • reject_rhsbl_recipient *rbl_domain=d.d.d.d*

    当 RCPT TO 域与rbl_domain下的 A 记录“ dddd ”一起列出时拒绝请求(仅限 Postfix 版本 2.1 和更高版本)。每个“ d ”是一个数字,或者是“[]”内的一个模式,它包含一个或多个“;”分隔的数字或数字..数字范围(Postfix 2.8 及更高版本)。如果未指定“ =dddd ”,则当 RCPT TO 域与rbl_domain下的任何 A 记录一起列出时,拒绝请求。maps_rbl_reject_code 参数指定拒绝请求的响应代码(默认值:554);default_rbl_reply参数指定默认的服务器回复;和rbl_reply_maps
    参数指定具有由rbl_domain索引的服务器回复的表。此功能在 Postfix 2.0 及更高版本中可用

  • reject_unauth_destination

    除非满足以下条件之一,否则拒绝请求:

  • defer_unauth_destination

    拒绝与reject_unauth_destination相同的请求,并带有非永久性错误代码。此功能在 Postfix 2.10 及更高版本中可用。

  • reject_unknown_recipient_domain

    当 Postfix 不是收件人域的最终目的地,并且 RCPT TO 域具有 1) 没有 DNS MX 和 DNS A 记录或 2) 格式错误的 MX 记录,例如具有零长度 MX 主机名的记录(Postfix 2.3 及更高版本)。
    使用unknown_address_reject_code参数(默认值:450)、unknown_address_tempfail_action(默认值: defer_if_permit)或 556(nullmx,Postfix 3.0 及更高版本)指定回复。详见各参数说明

  • reject_unlisted_recipient (with Postfix version 2.0: check_recipient_maps)

    如果 RCPT TO 地址未列在其域类的有效收件人列表中,则拒绝该请求。有关详细信息,请参阅 smtpd_reject_unlisted_recipient参数说明。此功能在 Postfix 2.1 及更高版本中可用.

  • reject_unverified_recipient

    当已知发往 RCPT TO 地址的邮件被退回或无法到达收件人地址目的地时,拒绝该请求。地址验证信息由verify(8)服务器管理;有关详细信息,请参阅ADDRESS_VERIFICATION_README文件。
    unverified_recipient_reject_code 参数指定当地址被退回时的数字响应代码(默认值:450,当您确信这样做是安全的时将其更改为 550)
    unverified_recipient_defer_code参数指定地址探测由于临时问题而失败时的数字响应代码(默认值:450)unverified_recipient_tempfail_action
    _ 参数指定由于临时问题导致地址探测失败后的操作(默认值: defer_if_permit)。对于具有“ enable_original_recipient = no”(后缀≤3.2)
    的别名地址,此功能会中断。 此功能在 Postfix 2.1 及更高版本中可用

在此上下文中有效的其他限制:

在这儿允许接收由本地网络发送过来的邮件,同时允许SASL认证通过的,并拒绝无认证的目标。

+# //设定邮件中有关收件人部分的限制
+smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination

可以参考https://www.cnblogs.com/AloneSword/p/3222912.html给出的一个限制,如下:

#1、postfix配置说明(强烈建议参看“postfix权威指南 第十一章 反垃圾邮件”)
#fqdn格式:完全限定域名格式,即用点分隔开的包括域名和主机名的主机全名
# smtpd related config
smtpd_recipient_restrictions =
        permit_mynetworks,        #检测客户端是否来自mynetworks或者mynetworks_style的网络,是的话返回OK,否则返回DUNNO状态码。
        permit_sasl_authenticated,    #检测用户认证是否通过的,认证通过的返回状态OK,否则返回DUNNO状态码。
        reject_non_fqdn_hostname,    #HELO/EHLO时:客户端提供的主机名不是RFC要求的完整形式(FQND),返回REJECT,否则返回DUNNO状态码。 
        reject_non_fqdn_sender,        #MAIL FROM时:客户端提供的主机名不是RFC要求的完整形式(FQND),返回REJECT,否则返回DUNNO状态码。
        reject_non_fqdn_recipient,    #RCPT TO时:客户端提供的主机名不是RFC要求的完整形式(FQND),返回REJECT,否则返回DUNNO状态码。
        reject_unauth_destination,    #RCPT TO时:收件人不在postfix管辖的区域(由mydestination定义),返回REJECT,否则返回DUNNO状态码。
        reject_unauth_pipelining,    #禁止非授权客户端使用pipelining
        reject_invalid_hostname        #HELO/EHLO时:客户端提供的主机名不是有效的主机名时,返回REJECT,否则返回DUNNO状态码。
31).smtpd_relay_restrictions

smtpd_relay_restrictions,转发邮件时的限制规则。

在smtpd_recipient_restrictions之前,Postfix SMTP 服务器在 RCPT TO 命令的上下文中应用的邮件中继控制的访问限制 。

转发权限规则最好使用smtpd_relay_restrictions来实现。

为了向后兼容,从 2.10 之前的 Postfix 版本迁移的站点可以将smtpd_relay_restrictions设置为空值,并像以前一样使用smtpd_recipient_restrictions 。

默认情况下,Postfix SMTP 服务器接受:

重要信息:smtpd_relay_restrictionssmtpd_recipient_restrictions参数必须至少指定以下限制之一。否则 Postfix 将拒绝接收邮件:

reject, reject_unauth_destination
defer, defer_if_permit, defer_unauth_destination

指定限制列表,以逗号和/或空格分隔。通过以空格开始下一行来继续长行。smtpd_recipient_restrictions下记录的限制相同 。

在这儿允许接收由本地网络发送过来的邮件,同时允许SASL认证通过的,并拒绝无认证的目标。

+# //设定邮件中有关收件人部分的限制
+smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
32).smtpd_sender_restrictions

smtpd_sender_restrictions,Postfix SMTP 服务器在客户端 MAIL FROM 命令的上下文中应用的可选限制。

默认是允许一切。

指定限制列表,以逗号和/或空格分隔。通过以空格开始下一行来继续长行。限制按指定的顺序应用;首先匹配OK的限制。

以下限制特定于使用 MAIL FROM 命令接收的发件人地址。

  • check_sender_access *type:table*

    在指定的access(5)数据库中搜索 MAIL FROM 地址、域、父域或 localpart@,并执行相应的操作。

  • check_sender_a_access *type:table*

    在指定的access(5)数据库中搜索 MAIL FROM 域的 IP 地址,并执行相应的操作。注意:出于安全原因,不允许出现“OK”的结果。相反,使用 DUNNO 从拒绝名单中排除特定主机。此功能在 Postfix 3.0 及更高版本中可用。

  • check_sender_mx_access *type:table*

    在指定的access(5)数据库中搜索 MAIL FROM 域的 MX 主机,并执行相应的操作。如果没有找到 MX 记录,则查找 A 或 AAAA 记录,就像 Postfix SMTP 客户端那样。注意:出于安全原因,不允许出现“OK”的结果。相反,使用 DUNNO 从拒绝名单中排除特定主机。此功能在 Postfix 2.1 及更高版本中可用。

  • check_sender_ns_access *type:table*

    在指定的access(5)数据库中搜索 MAIL FROM 域的 DNS 服务器,并执行相应的操作。注意:出于安全原因,不允许出现“OK”的结果。相反,使用 DUNNO 从拒绝名单中排除特定主机。此功能在 Postfix 2.1 及更高版本中可用。

  • reject_authenticated_sender_login_mismatch

    仅对经过身份验证的客户端强制执行reject_sender_login_mismatch限制。此功能在 Postfix 2.1 及更高版本中可用。

  • reject_known_sender_login_mismatch

    仅将reject_sender_login_mismatch限制应用于 $ smtpd_sender_login_maps中已知的 MAIL FROM 地址。此功能在 Postfix 版本 2.11 及更高版本中可用。

  • reject_non_fqdn_sender

    当 MAIL FROM 地址指定的域不是 RFC 要求的完全限定域形式时,拒绝请求。
    non_fqdn_reject_code 参数指定拒绝请求的响应代码(默认值:504)。

  • reject_rhsbl_sender *rbl_domain=d.d.d.d*

    当 MAIL FROM 域与rbl_domain下的 A 记录“ dddd ”一起列出时拒绝请求(仅限 Postfix 版本 2.1 和更高版本)。每个“ d ”是一个数字,或者是“[]”内的一个模式,它包含一个或多个“;”分隔的数字或数字..数字范围(Postfix 2.8 及更高版本)。如果未指定“ =dddd ”,则当 MAIL FROM 域与rbl_domain下的任何 A 记录一起列出时,拒绝请求。maps_rbl_reject_code参数指定拒绝请求的响应代码(默认值:554); default_rbl_reply参数指定默认的服务器回复;和rbl_reply_maps
    参数指定具有由rbl_domain索引的服务器回复的表。此功能在 Postfix 2.0 及更高版本中可用.

  • reject_sender_login_mismatch

    当 $ smtpd_sender_login_maps为 MAIL FROM 地址指定所有者,但客户端未(SASL)以该 MAIL FROM 地址所有者身份登录时拒绝请求;或者当客户端(SASL)登录时,但客户端登录名不拥有根据 $ smtpd_sender_login_maps的 MAIL FROM 地址.

  • reject_unauthenticated_sender_login_mismatch

    仅对未经身份验证的客户端强制执行reject_sender_login_mismatch限制。此功能在 Postfix 2.1 及更高版本中可用。

  • reject_unknown_sender_domain

    当 Postfix 不是发件人地址的最终目的地且 MAIL FROM 域具有 1) 没有 DNS MX 和 DNS A 记录,或 2) 格式错误的 MX 记录(例如具有零长度 MX 主机名的记录)时拒绝请求(后缀版本 2.3 及更高版本)。
    回复由unknown_address_reject_code参数(默认值:450)、unknown_address_tempfail_action(默认值: defer_if_permit)或 550(nullmx,Postfix 3.0 及更高版本)指定。详见各参数说明.

  • reject_unlisted_sender

    如果 MAIL FROM 地址未列在其域类的有效收件人列表中,则拒绝该请求。有关详细信息,请参阅 smtpd_reject_unlisted_sender参数说明。此功能在 Postfix 2.1 及更高版本中可用。

  • reject_unverified_sender

    当已知发往 MAIL FROM 地址的邮件被退回或无法到达发件人地址目的地时,拒绝该请求。地址验证信息由verify(8)服务器管理;有关详细信息,请参阅ADDRESS_VERIFICATION_README文件。
    unverified_sender_reject_code 参数指定已知地址退回时的数字响应代码(默认值:450,当您确信这样做是安全的时更改为 550)。
    unverified_sender_defer_code指定地址探测由于临时问题而失败时的数字响应代码(默认值:450) unverified_sender_tempfail_action
    _参数指定由于临时问题导致地址探测失败后的操作(默认值:defer_if_permit)。 对于具有“ enable_original_recipient = no”(后缀≤3.2)
    的别名地址,此功能会中断。此功能在 Postfix 2.1 及更高版本中可用。

在此上下文中有效的其他限制:

在这儿允许接收由本地网络发送过来的邮件,拒绝声称是XXXX.cn的(保证XXXX.cn仅允许本地网络发出邮件),允许其他。

+# //设定邮件中有关收件人部分的限制
+smtpd_sender_restrictions = permit_mynetworks, reject_rhsbl_sender rbl_domain=XXXXX.cn, permit

也可以参考其他给出的:

# SMTP sender login matching config
smtpd_sender_restrictions =
        permit_mynetworks,        #检测客户端是否来自mynetworks或者mynetworks_style的网络,是的话返回OK,否则返回DUNNO状态码。
        reject_sender_login_mismatch,    #拒绝发送者在$smtpd_sender_owner_maps中所匹配的用户名和sasl登录名不一致的连接。
        reject_authenticated_sender_login_mismatch,    #拒绝认证成功的发送者在$smtpd_sender_owner_maps中所匹配的用户名和sasl登录名不一致的连接。
        reject_unauthenticated_sender_login_mismatch    #拒绝认证失败的发送者在$smtpd_sender_owner_maps中所匹配的用户名和sasl登录名不一致的连接。

一个大佬给出的说明:

+# //参考 https://www.liaoxuefeng.com/article/895886450140288
+# //我们需要对邮件的发送进行控制:
+# //对于外域到本域的邮件,必须接收,否则,收不到任何来自外部的邮件;
+# //对于本域到外域的邮件,只允许从本机发出,否则,其他人通过伪造本域地址就可以向# //外域发信;
+# //对于外域到外域的邮件,直接拒绝,否则我们的邮件服务器就是Open Relay,将被视为# //垃圾邮件服务器。
+# //先设置发件人的规则:
+# //smtpd_sender_restrictions = permit_mynetworks, check_sender_access hash:/etc/postfix/sender_access, permit
+# //以上规则先判断是否是本域地址,如果是,允许,然后再从sender_access文件里检查发件人是否存在,拒绝存在的发件人,最后允许其他发件人。
+# //然后设置收件人规则:
+# // smtpd_recipient_restrictions = permit_mynetworks, check_recipient_access hash:/etc/postfix/recipient_access, reject
+# // 以上规则先判断是否是本域地址,如果是,允许,然后再从recipient_access文件里检查收件人是否存在,允许存在的收件人,最后拒绝其他收件人。
+# ///etc/postfix/sender_access的内容:
+# //example.com REJECT
+# //目的是防止其他用户从外部以xxx@example.com身份发送邮件,但登录到本机再发送则不# //受影响,因为第一条规则permit_mynetworks允许本机登录用户发送邮件。
+# ///etc/postfix/recipient_access的内容:
+# // postmaster@example.com OK
+# //webmaster@example.com OK
+# // 因此,外域只能发送给以上两个Email地址,其他任何地址都将被拒绝。但本机到本机发送不受影响。
+# //最后用postmap生成hash格式的文件:
+# postmap sender_access
+# postmap recipient_access

至此,PostFix的配置基本调整完成,通过systemctl来启动PostFix即可,验证PostFix服务是否正常的办法类似Dovecot,使用telnet,更改对应端口即可。

3.6 配置RoundCube

RoundCube配置比较类似PostFixAdmin。不过,需要注意,RoundCube使用的数据库,应该也PostFix/Dovecot使用的数据库不相同,防止额外影响。

首先配置Nginx

    location ^~ /webmail {
        alias   /DDDD/roundcubemail/;

        # 日志文件分开
        error_log     /var/log/nginx/webmail.error.log;
        access_log    /var/log/nginx/webmail.access.log;
        index         index.php index.html index.htm;

        try_files $uri $uri/ = 404;

        # Favicon
        location ~ ^/webmail/favicon.ico$ {
                alias /DDDD/roundcubemail/skins/classic/images;
                log_not_found off;
                access_log off;
                expires max;
        }
        # Robots file
        location ~ ^/webmail/robots.txt {
                allow all;
                log_not_found off;
                access_log off;
        }
        # Deny Protected directories
        location ~ ^/webmail/(config|temp|logs)/ {
                 deny all;
        }
        location ~ ^/webmail/(README|INSTALL|LICENSE|CHANGELOG|UPGRADING)$ {
                deny all;
        }
        location ~ ^/webmail/(bin|SQL)/ {
                deny all;
        }
        # Hide .md files
        location ~ ^/webmail/(.+\.md)$ {
                deny all;
        }
        # Hide all dot files
        location ~ ^/webmail/\. {
                deny all;
                access_log off;
                log_not_found off;
        }
        # Roundcube fastcgi config
        location ~ /webmail(/.*\.php)$ {
                fastcgi_split_path_info ^(.+?\.php)(\/.*|)$;
                set $path_info $fastcgi_path_info;
                try_files $fastcgi_script_name = 404;
                include fastcgi_params;
                # fastcgi_split_path_info ^/webmail/(.+\.php)(/.*)$;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $request_filename;
                fastcgi_param PATH_INFO $fastcgi_path_info;
                fastcgi_param PHP_ADMIN_VALUE "open_basedir=/tmp/:/var/cache/roundcubemail:/data/mail:/CCC/roundcubemail:/CCCC/etc/roundcubemail:/var/log/roundcubemail";
                fastcgi_param HTTPS on;
                # Avoid sending the security headers twice
                fastcgi_param modHeadersAvailable true;
                fastcgi_param front_controller_active true;
                fastcgi_pass php-handler;
                fastcgi_intercept_errors on;
                fastcgi_request_buffering off;
        }
    }

然后,配置RoundCube的config目录下config.inc.php文件,这个文件从config.inc.php.sample拷贝过来,进行修改

<?php

/* Local configuration for Roundcube Webmail */

// ----------------------------------
// SQL DATABASE
// ----------------------------------
// Database connection string (DSN) for read+write operations
// Format (compatible with PEAR MDB2): db_provider://user:password@host/database
// Currently supported db_providers: mysql, pgsql, sqlite, mssql, sqlsrv, oracle
// For examples see http://pear.php.net/manual/en/package.database.mdb2.intro-dsn.php
// Note: for SQLite use absolute path (Linux): 'sqlite:////full/path/to/sqlite.db?mode=0646'
//       or (Windows): 'sqlite:///C:/full/path/to/sqlite.db'
// Note: Various drivers support various additional arguments for connection,
//       for Mysql: key, cipher, cert, capath, ca, verify_server_cert,
//       for Postgres: application_name, sslmode, sslcert, sslkey, sslrootcert, sslcrl, sslcompression, service.
//       e.g. 'mysql://roundcube:@localhost/roundcubemail?verify_server_cert=false'
$config['db_dsnw'] = 'sqlite:////DDDDDDDDDDDDDDDDDDDDD/roundcubemail.db?mode=0646';

// IMAP host chosen to perform the log-in.
// See defaults.inc.php for the option description.
$config['imap_host'] = 'localhost:143';

// provide an URL where a user can get support for this Roundcube installation
// PLEASE DO NOT LINK TO THE ROUNDCUBE.NET WEBSITE HERE!
$config['support_url'] = '';

// This key is used to encrypt the users imap password which is stored
// in the session record. For the default cipher method it must be
// exactly 24 characters long.
// YOUR KEY MUST BE DIFFERENT THAN THE SAMPLE VALUE FOR SECURITY REASONS
$config['des_key'] = '.................................';

// Automatically add this domain to user names for login
// Only for IMAP servers that require full e-mail addresses for login
// Specify an array with 'host' => 'domain' values to support multiple hosts
// Supported replacement variables:
// %h - user's IMAP hostname
// %n - hostname ($_SERVER['SERVER_NAME'])
// %t - hostname without the first part
// %d - domain (http hostname $_SERVER['HTTP_HOST'] without the first part)
// %z - IMAP domain (IMAP hostname without the first part)
// For example %n = mail.domain.tld, %t = domain.tld
$config['username_domain'] = 'XXXXXXXXXX.cn';

// This domain will be used to form e-mail addresses of new users
// Specify an array with 'host' => 'domain' values to support multiple hosts
// Supported replacement variables:
// %h - user's IMAP hostname
// %n - http hostname ($_SERVER['SERVER_NAME'])
// %d - domain (http hostname without the first part)
// %z - IMAP domain (IMAP hostname without the first part)
// For example %n = mail.domain.tld, %t = domain.tld
$config['mail_domain'] = '%t';

// Absolute path to a local mime.types mapping table file.
// This is used to derive mime-types from the filename extension or vice versa.
// Such a file is usually part of the apache webserver. If you don't find a file named mime.types on your system,
// download it from http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
$config['mime_types'] = '/data/roundcubemail/config/mime.types';

// List of active plugins (in plugins/ directory)
$config['plugins'] = ['archive', 'zipdownload'];

#$config['smtp_host'] = 'localhost:25';
$config['smtp_port'] = 587;
$config['smtp_auth_type'] = 'LOGIN';

#$config['debug_level'] = 1;
#$config['smtp_debug'] = true;

再在浏览器端访问XXXXXXXXXX.cn/webmail/installer,就可以检查RoundCube配置是否正确了。

posted @ 2022-08-30 16:50  日月王  阅读(2009)  评论(0编辑  收藏  举报