用FreeBSD 11构建自己的邮件服务器

・16 分钟阅读

运行自己的电子邮件服务器有许多好处,然而也会有一些挑战,你要冒着服务器存在漏洞的风险,以及你的服务器可能会成为垃圾邮件发送者的潜在中继。

概述

FreeBSD基础系统中没有包含三个必需的软件:

  • OpenSMTPd
  • Dovecot
  • spamd

OpenSMTPd是邮件传输代理(MTA )和邮件传递代理(MDA ),这意味着,它可以通过SMTP协议与其他邮件服务器通信,也可以处理向各个用户的邮箱发送邮件的操作,我们将设置OpenSMTPd,以便它能够与外部服务器(通过SPAMD过滤)通信,并且向本地用户传递邮件。

Dovecot是一个MDA,它读取本地邮箱,并且通过IMAP或POP3向用户提供服务,

SPAMD是一个邮件过滤服务,我们可以通过spamd转发邮件,它将根据各种黑名单,白名单和灰名单过滤邮件。

此邮件服务器的一般思路,需要几个不同的路径:


Outside world -> Firewall -> spamd -> OpenSMTPD -> User mail boxes
Outside world -> Firewall (spamd-whitelist) -> OpenSMTPD -> User mailboxes
Outside world -> Firewall (IMAP/POP3) -> Dovecot
Outside world -> Firewall (SMTPD submission)

在本教程中,我们将使用FreeBSD版本的OpenBSD PF来防火墙。你也可以使用ipfw,其中配置非常相似。

如果你想运行一个功能齐全的电子邮件服务器,你必须打开25端口。

初始设置

首先,我们需要安装所需的程序。

软件包(推荐)

除非你需要在这些实用程序中内置特定功能,否则建议通过软件包进行安装。它更容易,占用更少的服务器时间和资源,并提供直观,用户友好的界面。


sudo pkg install opensmtpd dovecot spamd

make命令将提供大量编译选项,默认选项就工作的很好,除非你知道自己在做什么,否则不要改变。


sudo portsnap fetch update # or run portsnap fetch extract if using ports for the first time
cd /usr/ports/mail/opensmtpd 
make install # Installs openSMTPd
make clean
cd /usr/ports/mail/dovecot
make install # Installs dovecot
make clean
cd /usr/ports/mail/spamd
make install # Installs spamd
make clean

我们需要将以下代码添加到/etc/rc.conf


pf_enable="YES"
pf_rules="/usr/local/etc/pf.conf"
pflog_enable="YES"
pflog_logfile="/var/log/pflog"

obspamd_enable="YES"
obspamd_flags="-v"
obspamlogd_enable="YES"

dovecot_enable="YES"

防火墙设置

要配置PF,我们可以创建/usr/local/etc/pf.conf


## Set public interface ##
ext_if="vtnet0"

## set and drop IP ranges on the public interface ##
martians ="{ 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, 
 10.0.0.0/8, 169.254.0.0/16, 192.0.2.0/24, 
 0.0.0.0/8, 240.0.0.0/4 }"

table <spamd> persist
table <spamd-white> persist

# Whitelisted webmail services
table <webmail> persist file"/usr/local/etc/pf.webmail.ip.conf"

## Skip loop back interface - Skip all PF processing on interface ##
set skip on lo

## Sets the interface for which PF should gather statistics such as bytes in/out and packets passed/blocked ##
set loginterface $ext_if

# Deal with attacks based on incorrect handling of packet fragments 
scrub in all


# Pass spamd whitelist
pass quick log on $ext_if inet proto tcp from <spamd-white> to $ext_if port smtp 
 -> 127.0.0.1 port 25
# Pass webmail servers
rdr pass quick log on $ext_if inet proto tcp from <gmail> to $ext_if port smtp 
 -> 127.0.0.1 port 25
# pass submission messages.
pass quick log on $ext_if inet proto tcp from any to $ext_if port submission modulate state
# Pass unknown mail to spamd
rdr pass log on $ext_if inet proto tcp from {!<spamd-white> <spamd>} to $ext_if port smtp 
 -> 127.0.0.1 port 8025 

## Blocking spoofed packets
antispoof quick for $ext_if

## Set default policy ##
block return in log all
block out all

# Drop all Non-Routable Addresses 
block drop in quick on $ext_if from $martians to any
block drop out quick on $ext_if from any to $martians

pass in inet proto tcp to $ext_if port ssh

# Allow Ping-Pong stuff. Be a good sysadmin 
pass inet proto icmp icmp-type echoreq

# Open up imap/pop3 support
pass quick on $ext_if proto tcp from any to any port {imap, imaps, pop3, pop3s} modulate state


# Allow outgoing traffic
pass out on $ext_if proto tcp from any to any modulate state
pass out on $ext_if proto udp from any to any keep state

这是一个有效的PF配置。

首先,我们为vtnet0设备定义我们的$ext_if变量,以便稍后使用,我们还定义了应该在外部接口上删除的无效IP地址。

我们还定义了两个表spamd和spamd-white,这两个表是由spamd创建的,这是默认配置,同样,我们定义了一个名为webmail的表,我们将使用它来允许一些主要的webmail提供者通过。

若要查看规则表,可以使用命令 pfctl -t tablename -T show 列出表中的元素。

启动PF :


sudo service pf start

现在我们有了防火墙设置,我们可以继续使用邮件服务器配置了。

OpenSMTPd

OpenSMTPd有一个非常简单、易读的配置语法,


#This is the smtpd server system-wide configuration file.
# See smtpd.conf(5) for more information.

ext_if=vtnet0

# If you edit the file, you have to run"smtpctl update table aliases"
table aliases file:/etc/mail/aliases
table domains file:/etc/mail/domains

# Keys
pki mail.example.com key"/usr/local/etc/letsencrypt/live/mail.example.com/privkey.pem"
pki mail.example.com certificate"/usr/local/etc/letsencrypt/live/mail.example.com/fullchain.pem"
# If you want to listen on multiple subdomains (e.g. mail.davidlenfesty) you have to add more lines
# of keys, and more lines of listeners

# Listen for local SMTP connections
listen on localhost hostname mail.example.com

# listen for filtered spamd connections
listen on lo0 port 10026

# Listen for submissions
listen on $ext_if port 587 tls-require auth pki mail.example.com tag SUBMITTED

# Accept mail from external sources.
accept from any for domain <domains> alias <aliases> deliver to maildir"~/mail"

accept for local alias <aliases> deliver to maildir"~/mail"
accept from local for any relay tls
accept tagged SUBMITTED for any relay tls

别名

FreeBSD的别名文件/etc/mail/aliases,默认用以下格式 :


vuser1: user1
vuser2: user1
vuser3: user1
vuser4: user2

定义了不同的邮箱,以及我们希望转发到这些已定义邮箱的消息,我们可以将用户定义为本地系统用户或转发到外部邮箱。

域名

FreeBSD没有提供默认的域名文件,但是这非常简单:


# Domains
example.com
mail.example.com
smtp.example.com

这只是一个纯文本文件,每个域名都在新的一行上,你可以使用#符号进行注释。

SSL证书

有两种方法可以保护你与邮件服务器的通信,自签名和签名的证书,当然,可以自己签名证书,但是像let's Encrypt这样的服务提供免费且容易使用的签名。

首先,我们必须安装certbot程序。


sudo pkg install py-certbot

另外,也可以通过ports安装:


cd /usr/ports/security/py-certbot
make install
make clean

然后,要获取证书,需要确保在外部接口上打开了端口80 ,在/usr/local/etc/pf.conf中的筛选规则中添加以下行:


pass quick on $ext_if from any to any port http

然后运行pfctl -f/usr/local/etc/pf.conf重新加载规则集。

然后可以为你想要获得证书的任何域名运行该命令:


certbot certonly --standalone -d mail.example.com

建议每隔3个月设置一次crontab条目,以运行certbot renew以确保你的证书不会过期。

然后对于每个域名,你可以修改这些行,以指向正确的密钥文件:


pki mail.example.com key"/usr/local/etc/letsencrypt/live/mail.example.com/privkey.pem"
pki mail.example.com certificate"/usr/local/etc/letsencrypt/live/mail.example.com/fullchain.pem"


sudo chmod 700 /usr/local/etc/letsencrypt/archive/mail.example.com/*

注:你必须对每个原始密钥文件执行这个操作,否则OpenSMTPd将不会打开它们。

现在我们可以启动服务:


sudo service smtpd start

配置SPAMD

这里我们使用的是OpenBSD守护进程的spamd,用来减少我们从互联网上获得的垃圾邮件数量,

你必须运行以下命令才能挂载fdescfs


mount -t fdescfs null /dev/fd

然后,你必须将此行添加到/etc/fstab


fdescfs /dev/fd fdescfs rw 0 0

默认配置文件(在 /usr/local/etc/spamd/spamd.conf.sample )工作正常,你可以编辑它以添加新来源或更改你使用的源:


sudo cp /usr/local/etc/spamd/spamd.conf.sample /usr/local/etc/spamd/spamd.conf

我们可以使用以下命令启动服务:


sudo service obspamd start

此时已设置SPAMD

启用电子邮件服务

要向web mail表中添加电子邮件范围,可以运行以下命令:


pfctl -t webmail -T add 192.0.2.0/24

Dovecot

如果你希望用户无需通过SSH登录即可访问它邮件,则你需要支持IMAP和/或POP3的MDA。一个配置简单和功能强大,而且非常流行的程序是Dovecot。

我们可以复制默认配置:


cd /usr/local/etc/dovecot
cp -R example-config/* ./

这个配置是由几个不同的文件组成的,要查看配置和DoveCot默认值之间的差异,请运行以下命令:

 
sudo doveconf -n

 

下面是一个简单的工作配置:


# 2.3.2.1 (0719df592): /usr/local/etc/dovecot/dovecot.conf
# OS: FreeBSD 11.2-RELEASE amd64 
# Hostname: mail.example.com
hostname = mail.example.com
mail_location = maildir:~/mail
namespace inbox {
 inbox = yes
 location = 
 mailbox Archive {
 auto = create
 special_use = Archive
 }
 mailbox Archives {
 auto = create
 special_use = Archive
 }
 mailbox Drafts {
 auto = subscribe
 special_use = Drafts
 }
 mailbox Junk {
 auto = create
 autoexpunge = 60 days
 special_use = Junk
 }
 mailbox Sent {
 auto = subscribe
 special_use = Sent
 }
 mailbox"Sent Mail" {
 auto = no
 special_use = Sent
 }
 mailbox"Sent Messages" {
 auto = no
 special_use = Sent
 }
 mailbox Spam {
 auto = no
 special_use = Junk
 }
 mailbox Trash {
 auto = no
 autoexpunge = 90 days
 special_use = Trash
 }
 prefix = 
 separator = /
}
passdb {
 args = imap
 driver = pam
}
ssl = required
ssl_cert = </usr/local/etc/letsencrypt/live/mail.example.com/fullchain.pem
ssl_dh = </usr/local/etc/dovecot/dh.pem
ssl_key = </usr/local/etc/letsencrypt/live/mail.example.com/privkey.pem
userdb {
 driver = passwd
}

大多数配置文件将在conf.d

重要的是10-auth.conf10-mail.conf10-ssl.conf

你可以配置在15-mailboxes.conf中使用的不同邮箱,你在上面看到的是许多系统中工作正常的配置,但是,在你那儿可能会有所不同。

身份验证

大多数默认设置都是正确的,如果要使用系统用户进行身份验证,则必须编辑10-auth.conf

取消注释以下行:

include auth-system.conf.ext!

加密

我们必须生成Diffie-Hellman参数:


sudo nohup openssl dhparam -out /usr/local/etc/dovecot/dh.pem

注意:这将需要运行很长时间,比你想象的要长得多。

我们现在可以启动 Dovecot 了 :


sudo service dovecot start

结束语

现在,我们有一个功能强大,安全且相对没什么垃圾邮件的邮件服务器了。

Chinaxiong profile image