使用OpenSMTPD,Dovecot,Rspamd和RainLoop的OpenBSD电子邮件服务器

介绍

本教程演示了使用OpenSMTPD,Dovecot,Rspamd和RainLoop在OpenBSD上运行的全功能电子邮件服务器。OpenSMTPD是OpenBSD的默认邮件服务器。选择具有足够存储量的Vultr Compute Cloud实例,以供预期的用户数量使用。

初步步骤

设置您的用户帐户以root身份执行任务。

su -
usermod -G wheel <username>
echo "permit nopass keepenv :wheel" > /etc/doas.conf
exit

为OpenBSD设置软件包存储库。

doas su
echo "https://cdn.openbsd.org/pub/OpenBSD" > /etc/installurl
exit

添加所需的程序包。

doas pkg_add opensmtpd-extras opensmtpd-filter-rspamd dovecot dovecot-pigeonhole rspamd redis

配置OpenSMTPD

默认情况下,OpenSMTPD仅在本地主机上侦听。必须将其显式配置为侦听外部接口。为了安全起见,应将其配置为使用虚拟用户而不是系统用户。

备份默认/etc/smtpd.conf文件并从头开始创建一个新文件。

cd /etc/mail
mv smtpd.conf smtpd.conf.default

smtpd.conf如下所示创建一个新的。example.com用您的域替换。在测试OpenSMTP时,此初始配置不会激活rspamd筛选器。垃圾邮件过滤器将在以后激活。

pki "mail" cert "/etc/ssl/mail.crt"
pki "mail" key "/etc/ssl/private/mail.key"

table aliases file:/etc/mail/aliases
table credentials passwd:/etc/mail/credentials
table virtuals file:/etc/mail/virtuals

filter "rspamd" proc-exec "/usr/local/libexec/smtpd/filter-rspamd"

# To accept external mail, replace with: listen on all

# listen on all tls pki "mail" hostname "mail.example.com"
listen on egress port submission tls-require pki "mail" hostname "mail.example.com" \
  auth <credentials>

action "local_mail" mbox alias <aliases>
action "domain_mail" maildir "/var/vmail/example.com/%{dest.user}" \
  virtual <virtuals>
action "outbound" relay

# Uncomment the following to accept external mail for domain "example.org"

# match from any for domain "example.com" action "domain_mail"
match from local for local action "local_mail"

match from local for any action "outbound"
match auth from any for any action "outbound"

创建/ etc / credentials文件

OpenSMTPD和Dovecot可以共享身份验证数据库。该数据库类似于系统密码文件,格式为Dovecot的两个额外字段。这两个特殊字段定义了虚拟主目录和邮件位置。密码为河豚格式。本教程创建了三个示例用户。

生成密码并将其连接到/etc/mail/credentials文件。

doas su
smtpctl encrypt example_password1 >> /etc/mail/credentials
smtpctl encrypt example_password2 >> /etc/mail/credentials
smtpctl encrypt example_password3 >> /etc/mail/credentials
exit

输出看起来像这样:

$2b$10$agmNBPvFm1zqCjbbZC3JbO4Ns2jJNZQfTS45MAnKi.IPrkKITyTa6
$2b$10$LwkcKVVnwG8hDxu2W4YKD.K0kQ2oylOmQ9SBUb0hIopBsmNxYPb4e
$2b$10$bgLW/GMZyRXKbROgRQIvRu4xbeOqOJJXlgEAKuS5sIrBvfdPvEzeq

编辑/etc/mail/credentials以添加必填字段。每行映射到一个系统帐户vmail,其UID和GID为2000。用您的域替换example.com。虚拟用户名是完整的电子邮件地址。

john@example.com:$2b$10$agmNBPvFm1zqCjbbZC3JbO4Ns2jJNZQfTS45MAnKi.IPrkKITyTa6:vmail:2000:2000:/var/vmail/example.com/john::userdb_mail=maildir:/var/vmail/example.com/john
adam@example.com:$2b$10$LwkcKVVnwG8hDxu2W4YKD.K0kQ2oylOmQ9SBUb0hIopBsmNxYPb4e:vmail:2000:2000:/var/vmail/example.com/adam::userdb_mail=maildir:/var/vmail/example.com/adam
natalie@example.com:$2b$10$bgLW/GMZyRXKbROgRQIvRu4xbeOqOJJXlgEAKuS5sIrBvfdPvEzeq:vmail:2000:2000:/var/vmail/example.com/natalie::userdb_mail=maildir:/var/vmail/example.com/natalie

创建虚拟邮件帐户并设置安全性

  • /etc/mail/credentials权限设置为系统用户_smtpd和只读_dovecot用户。
  • 创建vmail系统用户,组和主目录。

    • 创建vmail系统用户时,您将收到以下警告:useradd: Warning: home directory '/var/vmail' doesn't exist, and -m was not specified。这是预期的。这样可避免目录中包含来自的点文件/etc/skel。不需要它们,因为vmail帐户不允许登录。

      doas chmod 0440 / etc / mail / credentials doas chown smtpd: dovecot / etc / mail / credentials doas useradd -c“虚拟邮件帐户” -d / var / vmail -s / sbin nologin -u 2000 -g = uid -L人员vmail doas mkdir / var / vmail doas chown vmail:vmail / var / vmail

创建虚拟用户映射

创建/etc/mail/virtuals以定义有效的电子邮件地址。

  • 前四行为滥用hostmasterpostmasterwebmaster分配john@example.com别名。
  • 最后三行将电子邮件地址映射到vmail帐户。OpenSMTPD会将邮件传递到/var/vmail/example.com/<user>
  • 对于未在此文件中定义的地址尝试发送邮件,将以“发送状态通知”退回。

    abuse@example.com:john@example.com hostmaster@example.com:john@example.com postmaster@example.com:john@example.com webmaster@example.com:john@example.com john@example.com: vmail adam@example.com:vmail natalie@example.com:vmail

为OpenSMTPD创建公用/专用密钥

本示例使用自签名证书。如果有,请使用有效的签名证书。当提示输入公用名时,请确保它与服务器的FQDN相匹配。本示例使用mail.example.com。

doas su
cd /etc/ssl
openssl genrsa -out private/mail.key 4096
openssl req -x509 -new -nodes -key private/mail.key -out mail.crt -days 3650 -sha256
chmod 0400 /etc/ssl/private/mail.key
exit

测试服务器

使用OpenSMTPD配置语法检查器。如果未发现问题,请重新启动smtpd守护程序。

doas smtpd -n
doas rcctl restart smtpd

从外部邮件帐户,将测试电子邮件发送给其中一个用户。

  • OpenSMTPD将在下面创建maildir文件夹结构/var/vmail,并将邮件传递到/var/vmail/example.com/<username>/new
  • 作为root用户,浏览到该位置并验证您是否具有一个类似于以下文件的文件:1576339842.4d64757b.example.com:2,
  • 查看文件的内容,包括所有邮件标题,以验证电子邮件传递是否正常。

    Return-Path: <n0244e80da3-54b1ed125c5342fc-adam===example.org@bounce.example.org>
    Delivered-To: adam@example.com
    Received: from spruce-goose-ba.twitter.com (spruce-goose-ba.twitter.com [199.59.150.96])
        by mail.example.com (OpenSMTPD) with ESMTPS id 75b514d3 (TLSv1.2:ECDHE-RSA-AES256-GCM-    SHA384:256:NO)
        for <adam@example.com>;
        Sat, 14 Dec 2019 11:10:40 -0500 (EST)
    DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=twitter.com;
        s=dkim-201406; t=1576339839;
        bh=jhKB5/w9v87GaXSuizT576ntJ/72gvLRDhsqmGQQrCE=;
        h=Date:From:To:Subject:MIME-Version:Content-Type:List-Unsubscribe:
        Message-ID;
        b=TWn/QVUJ1VDlWiweWoanwHLABCL1nqmm0+TBzh3PjmYNm0quRMXB7QL2ykzHGME5A
        DTz/JFHa0cOvQsrdhxxbjOLFKimK0nF+Ou5kI+2HzTzfVNZS0qGnTVP/tZyaIsWjjl
        an5EiR6HFOHG4iClOOEOJW4oLDEZfPTefrlW+378bmHGIRUNDvVKrbXKunL9fJFAb3
        JSrhWQNwbrF/aARFzw4nKfb1I7vTRSrN1eXE5JxzGwI2XAjqDIWdR5ExwUNbJH5ZPs
        wQ85j8KLZEEgQkbH9CypgeUMJWsVK95FqOCCaqKMS10M7intGMb3aeiiFcB7yDHi9t
        u7rVESm4eGp/g==
    X-MSFBL: DM7pSZns+YDRgNEmGNre9aPjZTtc1tDlN97w5rQDBts=|eyJ1IjoibWF0dEBnb2J
        sYWNrY2F0LmNvbUBpaWQjIzU0YjFlZDEyNWM1MzQyZmNiNThiMzVmNzI0NDZlMGF
        mQHVzYiMjNkAyNDRAMTA4MjgwNTAxMDYzNzk1MDk3NkAwQDA4MjY5ZWI4OTI3YzR
        kNTFiNTZkMjY3YzY2OGRmN2IwY2Y4M2ExZGIiLCJyIjoibWF0dEBnb2JsYWNrY2F
        0LmNvbSIsImciOiJCdWxrIiwiYiI6InNtZjEtYmd4LTM0LXNyMS1CdWxrLjE4NiJ
        9
    Date: Sat, 14 Dec 2019 16:10:39 +0000
    ...
    

配置Dovecot IMAP

设置登录类别

与默认类所允许的相比,Dovecot要求能够打开更多文件以供读取和写入。否则,将导致难以排除的错误。

定义Dovecot守护程序的登录类。在底部/etc/login.conf添加以下行。

    dovecot:\
        :openfiles-cur=1024:\
        :openfiles-max=2048:\
        :tc=daemon:    

创建Dovecot配置文件

创建/etc/dovecot/local.conf

auth_mechanisms = plain
first_valid_uid = 2000
first_valid_gid = 2000
mail_location = maildir:/var/vmail/%d/%n
mail_plugin_dir = /usr/local/lib/dovecot
managesieve_notify_capability = mailto
managesieve_sieve_capability = fileinto reject envelope encoded-character vacation subaddress comparator-i;ascii-numeric relational regex  imap4flags copy include variables body enotify environment mailbox date index ihave duplicate mime foreverypart extracttext imapsieve vnd.dovecot.imapsieve
mbox_write_locks = fcntl
mmap_disable = yes
namespace inbox {
  inbox = yes
  location =
  mailbox Archive {
  auto = subscribe
  special_use = \Archive
  }
  mailbox Drafts {
  auto = subscribe
  special_use = \Drafts
  }
  mailbox Junk {
  auto = subscribe
  special_use = \Junk
  }
  mailbox Sent {
  auto = subscribe
  special_use = \Sent
  }
  mailbox Trash {
  auto = subscribe
  special_use = \Trash
  }
  prefix =
}
passdb {
  args = scheme=CRYPT username_format=%u /etc/mail/credentials
  driver = passwd-file
  name =
}
plugin {
  imapsieve_mailbox1_before = file:/usr/local/lib/dovecot/sieve/report-spam.sieve
  imapsieve_mailbox1_causes = COPY
  imapsieve_mailbox1_name = Junk
  imapsieve_mailbox2_before = file:/usr/local/lib/dovecot/sieve/report-ham.sieve
  imapsieve_mailbox2_causes = COPY
  imapsieve_mailbox2_from = Junk
  imapsieve_mailbox2_name = *
  sieve = file:~/sieve;active=~/.dovecot.sieve
  sieve_global_extensions = +vnd.dovecot.pipe +vnd.dovecot.environment
  sieve_pipe_bin_dir = /usr/local/lib/dovecot/sieve
  sieve_plugins = sieve_imapsieve sieve_extprograms
}
protocols = imap sieve
service imap-login {
  inet_listener imaps {
  port = 0
  }
}
service managesieve-login {
  inet_listener sieve {
  port = 4190
  }
  inet_listener sieve_deprecated {
  port = 2000
  }
}
ssl_cert = </etc/ssl/mail.crt
ssl_key = </etc/ssl/private/mail.key
userdb {
  args = username_format=%u /etc/mail/credentials
  driver = passwd-file
  name =
}
protocol imap {
  mail_plugins = " imap_sieve"
}

Dovecot错误修复

Dovecot中有一个错误,其中ssl_certssl_key设置不会在local.conf文件中被覆盖,因此我们必须将其注释掉。如果您错过此步骤,则Dovecot将无法正确启动。

/etc/dovecot/conf.d/10-ssl.conf如图所示进行编辑。

...
# 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/dovecotcert.pem
#ssl_key = </etc/ssl/private/dovecot.pem
...

创建筛查脚本

筛分脚本对Rspamd进行垃圾邮件火腿培训。将电子邮件移入或移出垃圾文件夹会触发一个事件,以训练Rspamd。

这些文件位于/usr/local/lib/dovecot/sieve

创建report-ham.sieve文件。

require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "variables"];

if environment :matches "imap.mailbox" "*" {
  set "mailbox" "${1}";
}

if string "${mailbox}" "Trash" {
  stop;
}

if environment :matches "imap.user" "*" {
  set "username" "${1}";
}

pipe :copy "sa-learn-ham.sh" [ "${username}" ];

创建report-spam.sieve文件。

require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "variables"];

if environment :matches "imap.user" "*" {
  set "username" "${1}";
}

pipe :copy "sa-learn-spam.sh" [ "${username}" ];

编译文件。

sievec report-ham.sieve
sievec report-spam.sieve 

在下面创建以下两个shell脚本 /usr/local/lib/dovecot/sieve

将以下内容添加到 sa-learn-ham.sh

#!/bin/sh
exec /usr/local/bin/rspamc -d "${1}" learn_ham

将以下内容添加到 sa-learn-spam.sh

#!/bin/sh
exec /usr/local/bin/rspamc -d "${1}" learn_spam

使文件可执行。

chmod 0755 sa-learn-ham.sh
chmod 0755 sa-learn-spam.sh

启用并启动Dovecot。

rcctl enable dovecot
rcctl start dovecot

检查Dovecot是否正确启动。

ps ax | grep dovecot

88005 ??  I        0:00.11 /usr/local/sbin/dovecot
69640 ??  I        0:00.03 dovecot/anvil
91207 ??  I        0:00.03 dovecot/log
98178 ??  I        0:00.19 dovecot/config
34712 ??  I        0:00.06 dovecot/stats
96674 ??  I        0:00.03 dovecot/imap-login
 8891 ??  S        0:00.02 dovecot/imap

验证Dovecot可以正确读取 /etc/mail/credentials

doveadm user john@example.com

field    value
uid      2000
gid      2000
home /var/vmail/example.com/john
mail maildir:/var/vmail/example.com/john

验证邮件用户可以登录。

doveadm auth login john@example.com

Password: ********
passdb: john@example.com auth succeeded
extra fields:
  user=john@example.com

userdb extra fields:
  john@example.com
  mail=maildir:/var/vmail/example.com/john
  uid=2000
  gid=2000
  home=/var/vmail/example.com/john
  auth_mech=PLAIN

设置Rspamd

这是Rspamd的基本配置,有关更多详细信息,请参考官方文档。本示例为我们的域创建一个定义以启用DKIM签名。

在其中创建公用/专用密钥对/etc/mail/dkim并设置正确的权限。

doas su
mkdir /etc/mail/dkim
cd /etc/mail/dkim
openssl genrsa -out private.key 1024
openssl rsa -in private.key -pubout -out public.key
chmod 0440 private.key
chown root:_rspamd private.key

为包含公用密钥的DKIM创建DNS记录。有关如何创建DKIM记录的详细信息,请咨询DNS提供商。复制内容/etc/mail/dkim/public.key,并将其粘贴p=到DKIM记录的一部分之后,如下所示。请注意,此示例还会创建一个SPF记录。

default._domainkey.example.com. IN TXT "v=DKIM1;k=rsa;p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQClcuK3FV3Ug64li8iFsuJ2ykgb7FMZsujk9uG79ppPUp57vCfjzO7F+HBfx5qIwvlGxv2IJXK86FZwhpUX+HFCDUtfB2z0ZNGerWcZfNzM1w1Bru/fdMd2tCYkiHEa5RWIkLfs/Fm+neXxRZfAG2UDWmAghNbgzYv7xViwgufDIQIDAQAB"
example.com. IN TXT "v=spf1 a ip4:192.0.2.1 mx ~all"

创建一个DMARC记录。

_dmarc.example.com. IN TXT "v=DMARC1;p=none;pct=100;rua=mailto:postmaster@example.com"

创建/etc/rspamd/local.d/dkim_signing.conf配置文件。

  • selector="default";行来自default._domainkey....上面创建的DKIM DNS记录()的第一部分。

    domain {
        example.com {
            path = "/etc/mail/dkim/example.com.key";
            selector = "default";
        }
    }
    

启用并启动Rspamd。

doas rcctl enable redis rspamd
doas rcctl start redis rspamd

更改下面的行,/etc/mail/smtpd.conf然后重新启动OpenSMTPD以启用Rspamd。

...
listen on all tls pki "mail" hostname "mail.example.com" filter "rspamd"
listen on egress port submission tls-require pki "mail" hostname "mail.example.com" \
  auth <credentials> filter "rspamd"
...
rcctl restart smtpd

使用POP3或IMAP电子邮件客户端测试邮件服务器。如果您不需要网络邮件,请在此处停止。

(可选)配置RainLoop Webmail

安装必备软件包

出现提示时,请选择最新版本的PHP。

pkg_add php php-curl php-pdo_sqlite php-zip pecl73-mcrypt zip unzip wget curl

取得RainLoop网络邮件tarball并将其解压缩到/var/www/htdocs/

使用包括自动更新程序的标准版。

cd /tmp
wget https://www.rainloop.net/repository/webmail/rainloop-latest.zip
unzip rainloop-latest.zip -d /var/www/htdocs/rainloop
chown -R www:www /var/www/htdocs

创建让我们加密SSL证书

  • 复制/etc/examples/acme-client.conf/etc
  • 在文件底部添加以下行:

    domain webmail.example.com {
    domain key "/etc/ssl/private/webmail.example.com.key"
    domain full chain certificate "/etc/ssl/webmail.example.com.crt"
    sign with letsencrypt
    }
    

配置httpd

  • 为子域创建DNS条目(CNAME或A记录) webmail.example.com
  • /etc/httpd.conf按照以下示例进行编辑。

    prefork 3
    types { include "/usr/share/misc/mime.types" }
    
    server "default" {
        listen on egress port 80 
        root "/htdocs"
        directory index index.html
    
        location "/.well-known/acme-challenge/*" {
                root "/acme"
                request strip 2
        }
    }
    

运行httpd语法检查。

httpd -n

启用并启动httpd。

rcctl enable httpd
rcctl start httpd

申请“加密”证书。

acme-client -v webmail.example.com

将RainLoop的服务器定义添加到 /etc/httpd.conf

server "webmail.example.com" {
    listen on egress port 80
    block return 302 "https://$SERVER_NAME$REQUEST_URI"
}

server "webmail.example.com" {
    listen on egress tls port 443
    root "/htdocs/rainloop"
    directory index "index.php"

    tcp { nodelay, backlog 10 }

    tls {
            certificate "/etc/ssl/webmail.example.com.crt"
            key "/etc/ssl/private/webmail.example.com.key"
    }

    hsts {
            max-age 31556952
            preload
    }

    # Value below is 25MB in bytes. 1MB = 1048576 bytes
    connection max request body 26214400

    location "/data*" {
            block return 403
    }

    location "*.php*" {
            fastcgi socket "/run/php-fpm.sock"
    }
}

配置PHP以允许最大25 MB的附件。在中进行以下更改/etc/php-7.3.ini

; Maximum allowed size for uploaded files.
; http://php.net/upload-max-filesize
upload_max_filesize = 25M
...
; Maximum size of POST data that PHP will accept.
; Its value may be 0 to disable the limit. It is ignored if POST data reading
; is disabled through enable_post_data_reading.
; http://php.net/post-max-size
post_max_size = 29M

通过将其配置文件复制到以下位置来启用必要的PHP模块: /etc/php-7.3/

cp /etc/php-7.3.sample/* /etc/php-7.3/.

检查的语法 /etc/httpd.conf

httpd -n

启用并启动httpd和php-fpm。

rcctl reload httpd
rcctl enable php73_fpm
rcctl start php73_fpm

最后一个考试

浏览到https://webmail.example.com/?admin

默认用户名是:admin
默认密码是:12345

浏览到每个配置部分,然后进行所需的更改。完成配置后,请通过以下网址登录网络邮件https://webmail.example.com

留下評論

在Arch Linux上使用Makepkg

在Arch Linux上使用Makepkg

在Arch Linux上使用Makepkg可以避免系统污染,确保仅安装必要的依赖关系。

如何在Ubuntu 16.04上安装OpenSIPS控制面板

如何在Ubuntu 16.04上安装OpenSIPS控制面板

快速学习如何在Ubuntu 16.04上安装OpenSIPS控制面板,为VoIP提供商提供支持的功能。

在Fedora 28上安装Akaunting

在Fedora 28上安装Akaunting

学习如何在Fedora 28上安装Akaunting,一款适合小型企业和自由职业者的开源会计软件。

如何在CentOS 7上安装Mailtrain新闻通讯应用程序

如何在CentOS 7上安装Mailtrain新闻通讯应用程序

使用其他系统?Mailtrain是一个基于Node.js和MySQL / MariaDB构建的开源自托管新闻通讯应用程序。

诊断Minecraft服务器延迟和低TPS

诊断Minecraft服务器延迟和低TPS

了解導致Minecraft延遲的原因和解決方案,包括優化伺服器性能和減少滯後的步驟。

AI 能否應對越來越多的勒索軟件攻擊?

AI 能否應對越來越多的勒索軟件攻擊?

勒索軟件攻擊呈上升趨勢,但人工智能能否幫助應對最新的計算機病毒?AI 是答案嗎?在這裡閱讀知道是 AI 布恩還是禍根

ReactOS:這是 Windows 的未來嗎?

ReactOS:這是 Windows 的未來嗎?

ReactOS,一個開源和免費的操作系統,這裡有最新版本。它能否滿足現代 Windows 用戶的需求並打倒微軟?讓我們更多地了解這種老式但更新的操作系統體驗。

通過 WhatsApp 桌面應用程序 24*7 保持聯繫

通過 WhatsApp 桌面應用程序 24*7 保持聯繫

Whatsapp 終於為 Mac 和 Windows 用戶推出了桌面應用程序。現在您可以輕鬆地從 Windows 或 Mac 訪問 Whatsapp。適用於 Windows 8+ 和 Mac OS 10.9+

人工智能如何將流程自動化提升到新的水平?

人工智能如何將流程自動化提升到新的水平?

閱讀本文以了解人工智能如何在小型公司中變得流行,以及它如何增加使它們成長並為競爭對手提供優勢的可能性。

macOS Catalina 10.15.4 補充更新引發的問題多於解決

macOS Catalina 10.15.4 補充更新引發的問題多於解決

最近,Apple 發布了 macOS Catalina 10.15.4 補充更新以修復問題,但似乎該更新引起了更多問題,導致 mac 機器變磚。閱讀這篇文章以了解更多信息