Postfix--邮件传输代理
Dovecot—pop3、imap服务器,并提供SASL认证
Mysql-用于存储虚拟域和虚拟用户
AmaVis-用来扫描邮件中的垃圾邮件、病毒及附件
Squirremail-实现Webmail,用户可以修改密码
为了实现虚拟域和虚拟用户,我们使用了MySQL数据库来存储这些信息。POP3和IMAP手心的支持,我们使用Dovecot来实现,使用AMaVisd、SpamAssassin和ClamAVailable,我们可以实现垃圾邮件和病毒过滤,在默认情况下,磁盘限额功能没有编译进Postfix,如果需要这个功能的话需要打补丁,最后将介绍使用SquirrelMail。通过它用户登陆到Web页面使用信箱。
虚拟域和虚拟用户的好处,真实系统用户的真实域大得多。在系统中创建真实域和真实用户,操作复杂、管理麻烦、更重要的是还涉及安全问题。
实验环境,服务器地址192.168.1.10,主机名ubox.mytest.com
$ sudo apt-get install postfix-mysql mysql-server dovecot-pop3d dovecot-imapd amav isd-new libclass-dbi-mysql-perl
New password for the MySQL "root" user: <-- 输入密码
Repeat password for the MySQL "root" user: <-- 再次输入密码
Create directories for web-based administration? <-- 选择No
General type of mail configuration: <-- 选择Internet Site
System mail name: <-- 输入DNS全名(ubox.mytest.com)
SSL certificate required <-- 选择Ok
Web server to reconfigure automatically: <-- 选择apache2
libclass-dbi-mysql-perl提供了Perl的 DBI模块,AmaVis就可以访问数据库了。
AmaVis只是一个“接口”,要实现病毒和垃圾邮件过滤,需要安装的软件如下
反病毒软件(比如clamav)
反垃圾邮件软件(比如SpamAssassin)
接口软件(比如AmaVis)
前两种成为“内容过滤软件”。接口软件的作用是在邮件服务器和内容过滤软件之间加起桥梁。
$ sudo apt-get install SpamAssassin clamav-daemon razor pyzor cpio arj zoo nomarch lzop cabextract pax lha unrar
SpamAssassin是基于文本分析的垃圾邮件管理程序,而razor和pyzor则是CS架构的垃圾邮件过滤程序。这种CS架构的过滤程序,其服务器成为“编录服务器”,维护着一个垃圾邮件信息库(类似于病毒库),并且会不断的更新;当客户端收到一个垃圾邮件时,会自动将该邮件的20位SHA编码发给最近的“编录服务器”。总多的“编录服务器”会相互同步,以确保最新的编录数据库。当客户端收到一封邮件时,会自动去“编录服务器”核对其SHA编码,以检查其是否是垃圾邮件。
安装squirrelmail以便提供Webmail界面,squirrelmail-locales提供了多语言界面翻译,php5-imap软件包则为访问IMAP提供了可能
$ sudo apt-get install squirrelmail squirrelmail-locales php5-imap
下面的软件包以便创建SSL证书
$ sudo apt-get install openssl
Phpmyadmin提供管理数据库,telnet可以连接到并测试服务器,mutt可以让我们在控制台中读取邮件,mailx带了一个mail命令可以让我们在命令行上发邮件,
$ sudo apt-get install phpmyadmin telnet mutt mailx
$ mysql -uroot -p
创建数据库
mysql> create database maildb;
创建用户并赋予相应权限
mysql> GRANT SELECT, INSERT, UPDATE, DELETE ON maildb.* TO 'mailadmin'@'localhost' IDENTIFIED BY 'mailadminPassword';
mysql> GRANT SELECT, INSERT, UPDATE, DELETE ON maildb.* TO 'mailadmin'@'localhost. localdomain' IDENTIFIED BY 'mailadminPassword';
mysql> FLUSH PRIVILEGES;
mysql> use maildb;
virtual_domains表用来存放虚拟域
mysql> CREATE TABLE `virtual_domains` (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL
) TYPE=MyISAM;
插入测试数据
mysql> INSERT INTO virtual_domains (name)
VALUES ('mytest.com'),
('dongyouji.cn');
virtual_users表用来存放邮件用户信息(包括用户名,密码[MD5加密],磁盘限额大小[单位为字节])
表带有DELETE CASCADE(级联删除)
mysql> CREATE TABLE `virtual_users` (
id int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
domain_id INT(11) NOT NULL,
user VARCHAR(40) NOT NULL,
password VARCHAR(32) NOT NULL,
quota INT(10) DEFAULT '102400',
CONSTRAINT UNIQUE_EMAIL UNIQUE (domain_id,user),
FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE
) TYPE=MyISAM;
插入测试数据
mysql> INSERT INTO virtual_users (domain_id, user, password, quota)
VALUES (1, 'bajie', MD5('bajiePassword'), 10240),
(1, 'wukong', MD5('wukongPassword'), 102400),
(2, 'tangseng', MD5('tangsengPassword'), 1048576),
(1, 'spams', MD5('spamsPassword'), 1024);
virtual_aliases用来实现邮件转发。该表存储信箱的“源”地址和“目的”地址
mysql> CREATE TABLE `virtual_aliases` (
id int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
domain_id INT(11) NOT NULL,
source VARCHAR(40) NOT NULL,
destination VARCHAR(80) NOT NULL,
FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE
) TYPE=MyISAM;
插入测试数据
mysql> INSERT INTO virtual_aliases (domain_id, source, destination)
VALUES (2, 'tangseng', '[email protected]'),
(1, 'bajie', '[email protected]'),
(1, 'bajie', '[email protected]'),
(1, '', '[email protected]');
最后的@mytest.com其实就是一个垃圾信箱,匹配本域所有。这种方法可以用于垃圾邮件分析等(比如将发件人的E-mail地址或IP地址写入黑名单,然后将邮件丢弃)
数据库表设计的很巧妙,但是给我们带来的是不直观。因为在浏览virtual_users时一眼看不出哪个用户属于哪个域的,而且,每次要用到[email protected]格式的邮件时,都需要使用Join来进行“联合查询”。如下
mysql> SELECT CONCAT(virtual_users.user, '@', virtual_domains.name) AS email, vir tual_users.password
FROM virtual_users
LEFT JOIN virtual_domains ON virtual_users.domain_id=virtual_domains.id;
+-----------------------+----------------------------------+
| email | password |
+-----------------------+----------------------------------+
| [email protected] | 00e 28675230f 4c 9b16666098941e5d6d |
| [email protected] | 407dbf 9a 4ca 5a 9906332ff0ea 9c 330fb |
| [email protected] | 3dbc34bca13af30ed7aa2769ee468b40 |
| [email protected] | 946bfb68686ed81aa5b 0c 58bb2633175 |
+-----------------------+----------------------------------+
创建视图,该视图有两个字段即email和password
mysql> CREATE VIEW view_users AS
SELECT CONCAT(u.user, '@', virtual_domains.name) AS email, u.password
FROM virtual_users u
LEFT JOIN virtual_domains ON u.domain_id=virtual_domains.id;
下面直接Select语句就可以
mysql> SELECT * FROM view_users WHERE email LIKE 'bajie%';
+------------------+----------------------------------+
| email | password |
+------------------+----------------------------------+
| [email protected] | 00e 28675230f 4c 9b16666098941e5d6d |
+------------------+----------------------------------+
为了选取别名的方便,也创建一个view_virtual_aliases视图
mysql> CREATE VIEW view_aliases AS
SELECT CONCAT(virtual_aliases.source, '@', virtual_domains.name) AS email, destin ation
FROM virtual_aliases
LEFT JOIN virtual_domains ON virtual_aliases.domain_id=virtual_domains.id;
mysql> SELECT * FROM view_aliases;
+---------------------+------------------------+
| email | destination |
+---------------------+------------------------+
| [email protected] | [email protected] |
| [email protected] | [email protected] |
| [email protected] | [email protected] |
| @mytest.com | [email protected] |
+---------------------+------------------------+
domains.cf、mailbox-maps.cf、alias-maps.cf、email2email.cf是Postfix与MySQL的配置映射关系的4个文件。我们将这几个文件放在/etc/postfix/mysql/目录下。
$ sudo mkdir /etc/postfix/mysql/
$ sudo nano /etc/postfix/mysql/domains.cf
内容如下
user = mailadmin
password = mailadminPassword
hosts = 127.0.0.1
dbname = maildb
query = SELECT 1 FROM virtual_domains WHERE name='%s'
这样Postfix需要查看是否存在mytest.com域时,上面配置中的'%s'会被替换成‘mytest.com’,如果找到返回1,其实只要能查询到正确的结果,返回上面值无所谓
将其写入Postfix配置文件(postconf –e的好处是不需要重新启动服务器,并将配置信息直接写入/etc/postfix/main.cf配置文件)
$ sudo postconf -e virtual_mailbox_domains=mysql:/etc/postfix/mysql/domains.cf
测试
$ postmap -q mytest.com mysql:/etc/postfix/mysql/domains.cf
1
Postfix配置中的virtual_mailbox_domains也就是关于虚拟域配置,下面来配置virtual_mailbox_maps也就是虚拟用户的配置。
创建文件,Postfix可以从数据库中找到邮件地址别名(转发)的资料
$ sudo nano /etc/postfix/mysql/mailbox-maps.cf
user = mailadmin
password = mailadminPassword
hosts = 127.0.0.1
dbname = maildb
query = SELECT 1 FROM view_users WHERE email='%s'
测试
$ postmap -q [email protected] mysql:/etc/postfix/mysql/mailbox-maps.cf
1
写入Postfix配置文件
$ sudo postconf -e virtual_mailbox_maps=mysql:/etc/postfix/mysql/mailbox- maps.cf
配置virtual_mailbox_maps,他本来应该是一种映射关系,这种映射关系表现为左边(LHS)是email地址,右边(RHS)是信箱在磁盘上所存放的位置,但是在数据库virual_users表及view_users视图中,只有LHS的Email地址,没有RHS的信箱存储路径。因为如果使用Postfix内置的“虚拟分发代理”(Virtual Delivery Agent)来存储收到的邮件,那么这种映射关系必须在数据库中得到体现,以便Postfix能够查询到。不过这里使用的是Dovecot的“本地分发代理”(Local Delivery Agent,简称LDA)来进行邮件分发存储,所以Postfix不必知道邮箱保存在什么位置,只需要知道某个Email地址是否属于某个用户即可。不需要配置RHS的mailbox地址。
尽管如此,我们还是需要创建目录,用来存放mailbox。建议将其创建在/var/mail/virtual中。要自爱硬盘上创建目录就设计到用户权限问题。处于安全考虑,创建一个用户和组,将mailbox赋予这个用户,下面创建的用户id和组id可以不同,只要是没有使用的。
$ sudo groupadd -g 5000 vmail
$ sudo useradd -g vmail -u 5000 vmail -d /var/mail/virtual -m
上面得命令创建了用户和组的同时,也创建了/var/mail/virtual目录,并设定了权限。用户的mailbox将存储在/var/mail/virtual/$DOMAIN/$USER目录下。在邮件到达的时候,postfix会自动创建目录。
将上诉UID和GID信息写入Postfix的配置文件,以便Postfix有权限操作这个目录。
$ sudo postconf -e virtual_uid_maps=static:5000
$ sudo postconf -e virtual_gid_maps=static:5000
利用前面创建的view_aliases别名视图,让Postfix将信件可以从一个Email地址转发到另一个Email地址
$ sudo nano /etc/postfix/mysql/alias-maps.cf
user = mailadmin
password = mailadminPassword
hosts = 127.0.0.1
dbname = maildb
query = SELECT destination FROM view_aliases WHERE email='%s'
测试
$ postmap -q [email protected] mysql:/etc/postfix/mysql/alias-maps.cf
[email protected],[email protected]
写入配置文件
$ sudo postconf -e virtual_alias_maps=mysql:/etc/postfix/mysql/alias-maps.cf
virtual_alias_maps的优先级高于virtual_mailbox_maps
即Postfix在接受邮件时,先去搜索virtual_alias_maps,看看是否需要转发,需要转发就转发,不需要转发才会去搜索virtual_mailbox_maps。
在该实验中,我们将设置catchall垃圾邮箱,把所有发给@test.com未知账号的email转发给[email protected](请替换成自己真是的邮件地址)
$ mysql maildb -u root -p
为减少视觉障碍,将virtual_aliases清空
mysql> DELETE FROM `virtual_aliases`;
重新添加新数据
mysql> INSERT INTO virtual_aliases (domain_id, source, destination)
VALUES (1, '', '[email protected]');
mysql> exit
只添加了最后的垃圾邮件
下面的测试,向[email protected]发邮件
$ mail [email protected]
Subject: hi bajie, this is wukong <-- 输入邮件主题
ni ge bi ma wen! <-- 输入正文
. <-- 输入“.”结束正文
Cc: <-- “抄送”地址,可以留空,直接回车
发送后查看日志
$ sudo tail /var/log/mail.log
Dec 7 23:16:36 mail postfix/smtp[8990]: 5304F 42BA5: to=<[email protected]>, orig_to=<[email protected]>, relay=gmail-smtp-in.l.google.com[209.85.143.114]:25, delay=32, delays=0.28/0.09/0.47/31, dsn= 2.0.0 , status=sent (250 2.0.0 OK 1228709789 i6si27692tid.5)
如果转发到163、126或者yeah.net等信箱,可能就直接被当做垃圾邮件挡掉(status=bounced)
Dec 7 23:22:45 mail postfix/smtp[9005]: 9656542BA7: to=<[email protected]>, orig_to= <[email protected]>, relay=126.mxmail.netease.com[220.181.15.135]:25, delay=0.42, delays=0.06/0.01/0.27/0.08, dsn= 5.0.0 , status=bounced (host 126.mxmail.netease.co m[220.181.15.135] said: 550 MI :SPF mx5,I8mowLC7KBAUoTxJxeflWQ--.47417S2 1228710164 http://mail.163.com/help/help_spam_16.htm?ip=1020372198&hostid=mx5&time=1228710164 (in reply to MAIL FROM command))
但是至少说明被转发了!!
查看/var/mail/virtual/目录下根本没bajie的邮件
$ ls /var/mail/virtual/
清空关于转发的数据库设置
$ sudo postconf -e virtual_alias_maps=
再次测试
$ mail [email protected]
Subject: hi bajie, test 2 <-- 输入邮件主题
Bajie, ni ge bi ma wen! <-- 输入正文
Test 2, Hehe.
. <-- 输入“.”结束正文
Cc: <-- “抄送”地址,可以留空,直接回车
查看日志
Dec 8 00:19:31 mail postfix/qmgr[8873]: 0AE9542BA7: from=<[email protected]. com>, size=302, nrcpt=1 (queue active)
Dec 8 00:19:32 mail postfix/pipe[9067]: 0AE9542BA7: to=<[email protected]>, relay= dovecot, delay=1.6, delays=0.67/0.65/0/0.31, dsn= 2.0.0 , status=sent (delivered via dovecot service)
用过mutt来阅读邮件
$ sudo mutt -f /var/mail/virtual/mytest.com/bajie/Maildir
由于在转寄表中有一行关于垃圾邮件的记录,所以我们必须将所有用户的email地址也填在转寄表中才可以,用户才能收到邮件。
文章整理来自于《Ubuntu Server最佳方案》书籍
由于字数限制,笔记可能无法全部上传,关于具体细节的信息,请下载笔记