本文档的重点在过滤器的配置,以及sample的生成,其他尽量从简,相应章节的安装过程可以参考相应的操作文档。 

一、从简架设裸Linux服务器

1、为了节约系统资源,采用文本安装的方式,输入 Linux text 按 回车 键,这样系统安装完毕后,会默认工作在 init 3 的级别下,同时不会使用RedHat 的图形界面安装,可以节约安装时间及效率。里面有个地方涉及到需要输入 installation number ,经过验证,可以输入:550dd56b51499bd

2、下面简单说下分区分区要求:通常情况安装系统是/boot; /; swap 三个分区。

序号

挂载点

容量

说明

1

/boot 

200M

作为单独的/boot系统引导区,即使主要的root分区出了问题,计算机依然能够启动。同时将容量调整为200M,以备后用

2

swap

8G

交互分区,大小一般设定为机器物理内存的1-2倍。

3

/

15G

是根目录“/的所在地,启动系统所须的文件和系统配置文件

5

/home

20G

用户的home目录所在地,用户登录分区,同时可以对用户或者用户分组实行硬盘限额功能,这样当进行升级或者安装新版本的linux操作系统时,就不会覆盖原有的用户登录数据了。这个分区的大小取决于有多少用户,根用户可以很好地控制普通用户使用计算机,如对用户或者用户组实行硬盘限量使用,限制普通用户访问哪些文件等。

6

/var

10G

主要存放系统日志,设立单独分区,即使系统日志文件出现问题,也不影响系统主分区。也就不会使计算机崩溃。如WEB服务器,可分20GB或根据实际情况加大

7

/tmp

4G

存放临时文件。对于多用户系统或网络服务器是有必要的。即使程序运行时生成大量的临时文件,或用户对系统进行了错误操作,文件系统的其它部分仍是安全的。因为文件系统的这一部分仍然还承受着读写操作,所以它通常会比其它的部分更快地发生问题。

8

/u01

剩余空间

存放数据库文件,或同类的大量的数据文件

注:上表中的容量只是参考值,或者说是最小值,具体部署时要根据业务数据要求来调整容量。

3、将下面默认都进行安装的组件都取消。原因:下面的组件经过确认都是不常用的组

件。其实下面的组件取消后,几乎已经没有会被安装的组件了。

         4、计算机会自动开始安装系统。 至此裸系统安装完毕

一、设置网络

1、使用setup命令,图形化设置

201404071618001388.png

201404071618008109.png

201404071618005355.png

201404071618001862.png

设置完毕后,保存退出即可,如果需要设置DNS服务器地址,可以在下图所示的“Edit

DNS configuration”处设置。

201404071618008109.png

2、使用命令行,手工录入

命令行模式,要比图形界面方便快捷,如下图所示。输入“vi /etc/sysconfig/network-

scripts/ifcfg-eth0” 即可对网卡1进行配置

201404071618003011.png

201404071618002671.png

示例说明:

               DEVICE                         设备名称,禁止修改

               BROADCAST               广播地址

               IPADDR                        IP地址

               NETMASK                    子网掩码

               NETWORK                   网络地址

               GATEWAY                     网关地址

               ONBOOT                      是否随系统启动

               TYPE                              网卡类型

201404071618008465.png

设置完成后,需要手工对网卡进行重新启动。

 DNS地址设置路径为 /etc/resolv.conf ,这里所说的DNS与我们要架设的DNS服务器的配置不一样。这里只是告诉系统DNS服务器的IP地址是多少而已。

201404071618005346.png

至此,裸系统安装完毕,网络也能够连通了。配置yum需要外网的,如果在公司内部架设,不仅需要外网,还需要能够不受行为管理设备的控制。

二、设置yum

1、删除Linux系统自带的yum

201404071618002513.png

2、下载指定的yum安装包,从下图可以看出,yum-*yum-fastestmirror-*yum-metadata-parser*-这三个安装包都是从http://centos.ustc.edu.cn/centos/5/os/x86_64/CentOS/ 下载得来的,还有就是需要注意,本次下载都是64的安装包。32位的安装包在这里http://centos.ustc.edu.cn/centos/5/os/i386/CentOS/ 

201404071618004506.png

201404071618009357.png

201404071618009661.png

3、或者从其他机器复制安装包,如果知道哪台linux机器里有上面所说的安装包,linux之间互拷更快。示例只演示其中的一条拷贝命令,举一反三,真的很好用,强烈推荐。

201404071618008384.png

示例说明:

               Scp                linux间互相拷贝的命令

               -r                    可以传输整个文件夹,没有这个参数,只能拷贝单个文件

源文件在前,需指定绝对路径,系统会补全,后边同样是绝对路径,系统不能补全,只要指定需要复制到的文件夹即可

root@172.16.10.99:   root是目标主机有管理权限的账户,172.16.10.99是目标主机IP地址,ip地址前面的@符号和地址后边的冒号必须有,命令格式如此,无解释。

命令执行过程中,可能会让你选择yes或者no,个人理解应该是yes ,root@172.16.10.99's password: 需要输入的是目标主机的root账户的密码。

另外需要注意的是,当同一个IP地址用在不同的linux主机上时,SCP会出现如下错误提示

201404071618003614.png

解决方法很简单,进入 /root/.ssh/ 目录下,rm - rf(删除)掉 known_hosts 即可。

4、安装yum安装包

201404071618005269.png

如上图所示,我们首先需要到安装包所在位置才能使用rpm进行安装,这个道理Windows也是一样的。之所以用rpm –ivh yum-* 是因为我这里所要安装的三个包有依赖关系,使用yun-* 系统自己就可以搞定了。

5、确认安装信息

201404071618005740.png

6、下载源配置文件CentOS-Base.repo

201404071618007373.png

需要到上图所示的路径下载源配置文件,并且该配置文件需要放在 /etc/yum.repos.d/目录下,千万不要搞错了哦。

201404071618005237.png

7、激活yum (看命令“i386”应该是32位的,但是激活后也可以用)

64位系统激活:rpm –import http://ftp.sjtu.edu.cn/centos/5/os/x86_64/RPM-GPG-KEY-CentOS-5

32位系统激活:rpm –import http://ftp.sjtu.edu.cn/centos/5/os/i386/RPM-GPG-KEY-CentOS-5

需要补充说明一下,复制上面的激活地址,import 前面是 两个 --,最好是自己输入

201404071618007553.png

8、更新yum

201404071618003082.png

更新的过程是个漫长的过程,根据网速可能需要10到15分钟可能还会更长时间,不过好在系统会给你个动态的窗口显示出来,让你知道,系统还没死,在活着。

9、清空yum缓存

201404071618002374.png

三、Sendmail 安装

A、 RPM包安装(推荐)

1、首先需要挂载光盘

201404071618001337.png

示例说明:

              cd /mnt                 切换到根目录下的 mnt下面

              mkdir     cdrom    新建文件夹cdrom,这个目录是为了给光盘挂载的路径,必须得有才行。

201404071618001922.png

        mount                  挂载的命令,无解释

        iso9660                光盘

         -t                           挂载的类型还是什么东东,忘了啥意思,反正挂载的时候需要

         /dev/cdrom         是光盘原位置,雷打不动,绝大部分都是用这个。光盘的话

        /mnt/cdrom         这是我们刚才新设的挂载点,类似于Windows的文件夹。光盘内容就到这里找。

2、Sendmail安装

201404071618005996.png

示例说明:

               rpm –qa | grep sendmail 查询sendmail是否安装或者说已经安装了哪些包

需要说明的是,上面显示的是5个包,其中2个看上去以上,实际是1个32位、1个64位。

201404071618006859.png

示例说明:

    cd  /mnt/cdrom/Server           切换到/mnt/cdrom/Server目录,其中Server是所有安装包的位置

     rpm –ivh                                   rpm包的安装方法,-ivh必须有

后边跟的一长串不解释,有大概名字之后,tab键可以补全这里只演示了一个安装包,另外四个用同样的方法举一反三

B、 YUM安装

201404071618001127.png

示例说明:

     yum install         是yum安装的命令,后边跟上要安装的包的名称即可,yum会自动解决掉所有的包依赖性。方便!

C、 源码安装

1、编译安装准备

201404071618005813.png

卸载系统自带的sendmail

201404071618008998.png

确认sasl是否已经安装,如果没有,需要重新安装一下sasl

201404071618004307.png

挂载光盘

201404071618002011.png

201404071618006715.png

201404071618006318.png

201404071618001022.png

201404071618005003.png

201404071618007318.png

2、下载源码包

201404071618008713.png

通过官方服务器下载:wget ftp://ftp.sendmail.org/pub/sendmail/sendmail.8.14.6.tar.gz

示例说明:

        [root@sendmail ~]#   根据此提示,下载后的root账户的家目录下。以root账户登录,cd后就是家目录,其他账户以此类推,或者在下载前,pwd,看下自己处在哪个目录下面。

3、解压tar.gz包

201404071618003797.png

201404071618001097.png

示例说明:

          tar –zxvf              不要搞错,解压后的在同级目录下面,会有个sendmail.8.14.6 的子目录4、编译源码

201404071618008107.png

201404071618005332.png

备份site.config.m4.sample文件至此,三种不同方式的安装方式都介绍结束,在linux不太熟悉

情况下,类似我这样的,可以使用rpm安装或者yum安装。编译不太建议!!

四、Sendmail配置

其实Sendmail的需要配置的内容真的不是很多,/etc/mail/access /etc/mail/sendmail.mc

这两个文档之外貌似就只有/etc/hosts 了。下面逐一截图说明一下需要修改的地方。

       1、/etc/mail/access

201404071618001694.png

201404071618008076.png

示例说明:

                            vi /etc/mail/access 使用vi编辑器打开/etc/mail/access

                            Connect:17.16 RELAY转发来自172.16.0.0网段的所有邮件

修改完成后,需要使用makemap hash将access转换为access.db

201404071618005542.png

       2、/etc/mail/sendmail.mc

201404071618004959.png

如果在m4的时候出现上图这样的错误,是因为没有安装sendmail-cf,通过yun安装一下就可以了

201404071618007396.png

       3、/etc/hosts

本次配置,该文档不用修改:

1、重启sendmail服务并测试sendmail发送

重启sendmail

201404071618000668.png

测试sendmail发送邮件

201404071618009328.png

示例说明:

                      helo                     与sendmail服务器连接,后边的ddd 随便输入都可以

                      mail from:          发件箱,同样可以随便写,Sender ok 表示成功

                      rcpt to:                 收件箱                              Recipient ok 表示成功

                      data                     邮件正文开始,换行 .表示结束

                      quit                      退出发件状态

2、设置sendmail随系统自动启动

201404071618003715.png

示例说明:

              -bd         表示将sendmail你daemon(可以想成常驻内存)的类型启动

              -q           后边跟着时间表示每隔多少时间,会将放置在邮件队列(一般在/var/spool/mqueue)的邮件尝试邮寄一次。

3、远程客户端测试

类似于本章节步骤4,只需要在非sendmail服务器本机上的其他机器,通过telnet

172.16.10.99  25 测试即可,具体细节与步骤4一致。

五、自定义Mail Filter

A、 安装GCC

1、检查gcc的安装情况:

201404071618000240.png

示例说明:

上图的命令在安装sendmail的时候解释过,这里飘过

图示中的两个libgcc不是我们要的,所以要在下一个步骤通过yum安装。

2、通过yum安装gcc:

201404071618009519.png

201404071618002598.png

示例说明:

当出现gcc-4.1.2-54.el5时表示已经安装上去,同事也满足需求了。

3、通过rpm包安装:

gcc的安装依赖5个不同的安装包,本操作不方便,建议yum安装。

B、 编译sendmail

1、下载sendmail

本部分在第三章节第三小节里有介绍,本段跳过

2、解压sendmail

本部分在第三章节第三小节里有介绍,本段跳过

3、

C、 编译libmilter

1、sh Build

201404071618002432.png

示例说明:

多个目录下都有Build,一定要看清楚再运行 sh Build ,以免对后续操作造成影响。当出现下图

所示时,表示命令已经完成。

201404071618012875.png

2、sh Build install

201404071618018298.png

3、find  /-name libmilter.a

201404071618016036.png

201404071618013876.png

示例说明:

对照上图的路径,执行上图的命令,对照上图的结果,无误表示运行成功。无其他解释。

D、编译libsm

1、sh Build

201404071618019477.png

示例说明:

出现上图结果,表示已经运行成功!

2、find /-name libsm.a

201404071618016036.png

201404071618016958.png

示例说明:

对照上图输入命令,对照上图查看执行情况,无解释。

E、新建mliter

1、新建mliter

201404071618014220.png

示例说明:

在root家目录下新建子目录mliter

2、拷贝libmilter.a 和 libsm.a 以及 libmilter 目录

201404071618011695.png

201404071618019805.png示例说明:

               Linux的基本命令,主要用于复制粘贴,源文件在前,目标文件在后。

下面截图用的 /* 表示该目录下的所有文件都在复制粘贴的范围之内。

3、新建sample.c文件

201404071618013606.png

示例说明:

               sample.c 文档的源码在附件一中。

F、配置加载Filter文件(最为关键

201404071618012139.png

示例说明:

上句命令是指通过sample.c libmitler.a libsm.a 生成一个新的sample程序文件

201404071618015509.png

201404071618017485.png

201404071618013862.png

G、启动Fiter(关键步骤

201404071618016922.png

示例说明:

       ./sample                     是/root/mliter目录下面的一个程序,是上一个步骤生成的。

       9876@localhost        是在上一个步骤新增的端口(9876)监听,在文挡/etc/mail/sendmail.mc的最后一行

                       &                                在后台运行

H、测试Filter(关键步骤

1、测试Filter是否成功,需要首先在/root/mliter目录下新增一个类似于白名单的whiteuser.list,该文件里面的内容如下截图所显示,每个授权外发邮箱新增一行。没有的邮箱只能发公司内部邮箱或者goldendragobus.com。

201404071618012790.png

示例说明:

每个邮箱地址一行

3、在测试前完成添加whiteuser.list名单后,同时开启两个ssh窗口,一个运行

201404071618016922.png 另一个窗口则是通过telnet localhost 25 的方式发送邮件,分别测试白名单内有的邮箱地址和白名单内没有的地址。当出现下图所示,即表示fiter测试成功201404071618011964.png

201404071618016331.png

示例说明:

以上两个截图,是在不同的SSH窗口同时显示出来的结果。

测试过程中,如果出现意外导致linux长时间无响应,可以通过如下命令杀死相关进程。

201404071618016130.png

至此,Sendmail的配置全部结束。后边的附件一位sample.c的源码,附件二为一些服务器优化数据,仅供参考。

六、远程控制SSHD配置

这里说明一下,本段配置之选择了设置于sendmail.xmjl.com这台服务器上的功能选项,更多细节,参考Redhat Linux 5 x64 SSHD配置

1、备份sshd_config配置文件

201404071618014328.png

201404071618016607.png

示例说明:

       pwd              查看当面所处目录

       cp                 备份,前部分为源文件,后部分为目标文件

需要注意的是,在/etc/ssh 目录下还有另外一个类似于 sshd_config的 文件ssh_config,在编辑的时候一定要注意,不要搞错了。

2、配置sshd_config

201404071618016147.png

示例说明:

              port                                SSHD开放端口

              protocol                        SSHD所使用的协议版本,一般用版本2

              listenaddress              这里只能单个多行添加IP地址,不能添加网段。

201404071618016263.png

示例说明:

              Logingracetime          登录时不输入密码的等待时间

              Permitrootlogin no     表示禁止root账户直接通过sshd登陆,yes表示可以

              Maxauthtries                忘了啥意思了,反正这里配置了

七、防火墙iptables配置

这里说明一下,本段配置之选择了设置于sendmail.xmjl.com这台服务器上的功能选项,更多细

节,参考Redhat Linux 5 x64 iptables配置

201404071618017291.png

              Iptables的所有策略都保存在/etc/sysconfig/iptables里,修改完毕后直接重启iptables即可生效。

201404071618019041.png

示例说明:

              #                   注释此条策略,不使其生效

拒绝所有流入本机的数据

拒绝所有通过本机转发的数据

允许所有流出本机的数据

允许172.16.28.0/24网段使用tcp协议通过eth0网口以目的端口为56088的数据进入本机

允许172.16.28.0/24网段使用udp协议通过eth0网口以目的端口为56088的数据进入本机

允许使用tcp协议通过eth0网口以目的端口为25的数据进入本机

允许使用udp协议通过eth0网口以目的端口为25的数据进入本机

允许使用tcp协议通过eth0网口以源端口为53的数据进入本机

允许使用tcp协议通过eth0网口以目的端口为53的数据进入本机

允许使用icmp协议(俗称ping)通过eth0网口的数据进入本机

允许使用icmp协议(俗称ping)通过eth0网口的数据进入本机

              ……………….

允许所有的数据流出本机

如果想看到iptables是否已经生效,可以通过下面命令查看

201404071618017435.png

示例说明:

              -L                          查看当前表的所有规则,默认查看的是filter表

              --line-nu              显示带有序号的防火墙策略

201404071618016615.png

示例说明:

1、允许172.16.28.0/24段IP地址通过tcp协议目的端口56088流量进入eth0网口

2、允许172.16.28.0/24段IP地址通过udp协议目的端口56088流量进入eth0网口

3、允许通过tcp协议目的端口25流量进入eth0网口

4、允许通过udp协议目的端口25流量进入eth0网口

5、允许通过udp协议源端口53流量进入eth0网口

6、允许通过udp协议目的端口53流量进入eth0网口

7、允许通过icmp 协议(俗称ping)流量进入本机

8、允许通过icmp协议(俗称ping)流量进入本机

。。。。。。。。

9、拒绝通过本机转发的所有数据流量

10、允许通过本机流出的所有数据流量

有时候iptables未能生效,service iptables restart 也不行,这样就需要重启系统了。

八、安全管控

1、/etc/hosts.deny配置

由于sshd只能逐行添加IP地址,在生产环境中操作非常不便,所以在这里通过服务器系统层面来管控可以接入这台服务器的IP地址。建议如此,比较好用!

201404071618016802.png

201404071618011485.png

201404071618012356.png

示例说明:

              pwd                     查看

              cp                        复制文档

              vi                          编辑文档

最后一行的意思是允许172.16.28.0/255.255.255.0 网段的主机通过sshd连接服务器,除此之外的所有IP地址全部拒绝。

2、/etc/services配置

本文档可以修改各个服务默认的端口号信息,本次配置修改了sshd的默认端口号,所以在iptables里,本来是要显示dport是56088的,因为修改后,变成了sshd了。

201404071618014644.png

201404071618018954.png

九、sendmail日常维护

1、查看队列

#mailq      查看MTA队列的滞留情况(等价于sendmail -bp)     

#mailq -Ac  查看MSP队列的滞留情况(等价于sendmail -bp -Ac)

2、强制发送队列邮件

#/usr/sbin/sendmail -q -v                  对MTA队列强制送信

#/usr/sbin/sendmail -q -v -Ac               对MSP队列强制送信

3、邮件日志

#tail –f /var/log/maillog实时查看linux日志

#tail -1000 /var/log/maillog查看linux日志的最后1000行

#cat /var/log/maillog | grep ‘1234@abcl.com’查看与某个指定账户有关的记录

#egrep ‘23456@abcl.com|1234@abcl.com’ /var/log/maillog 以两个关键词来查询日志

附件一:sample.c 源码

#include <sys/param.h>

#include <netinet/in.h>

#include <stdio.h>

#include <stdlib.h>

#include <errno.h>

#include <sysexits.h>

#include <string.h>

#include <time.h>

#include "mfapi.h"

#include "mfdef.h"

#define MAXADDRESS 128

#define MAXHEADER 1024

#define MAXHEADERS 32

#define MAXIP      16

#define MAXRCPTS   32

#define TMPPATH    "/tmp/exfiXXXXXX"

FILE *fp;

struct private {

        int nhdrs;

        int nrcpts;

        int fd;

        FILE *fp;

        char *jobid;

        char tf[MAXPATHLEN];

        char host[MAXHOSTNAMELEN];

        char ip[MAXIP];

        char sender[MAXADDRESS];

        char hdrs[MAXHEADERS][MAXHEADER];

        char rcpts[MAXRCPTS][MAXADDRESS];

};

/*

 * Copy src to string dst of size siz. At most siz-1 characters

 * will be copied. Always NUL terminates (unless siz == 0).

 * Returns strlen(src); if retval >= siz, truncation occurred.

 */

size_t strlcpy(dst, src, siz)

char *dst;

const char *src;

size_t siz;

{

        register char *d = dst;

        register const char *s = src;

        register size_t n = siz;

        /* Copy as many bytes as will fit */

        if (n != 0 && --n != 0) {

                do {

                        if ((*d = *s ) == 0)

                                break;

                } while (--n != 0);

        }

        /* Not enough room in dst, add NUL and traverse rest of src */

        if (n == 0) {

                if (siz != 0)

                        *d = '\0';      /* NUL-terminate dst */

                while (*s )

                        ;

        }

        return(s - src - 1);    /* count does not include NUL */

}

int exfi_connect(SMFICTX *ctx, char *host,

                 _SOCK_ADDR *addr)

{

        struct private *prv;

        struct sockaddr *sa;

        prv = malloc(sizeof *prv);

        if (prv == NULL)

                return SMFIS_TEMPFAIL;

        memset(prv, '\0', sizeof *prv);

        prv->fd = -1;

        smfi_setpriv(ctx, prv);

        strlcpy(prv->host, host,

                sizeof prv->host);

        /*sa = addr;

        if (sa != NULL &&

            sa->sa_family == AF_INET) {

                struct sockaddr_in *sin;

                sin = addr;

                strlcpy(prv->ip,

                        inet_ntoa(sin->sin_addr),

                        sizeof prv->ip);

        }

*/

        fp = fopen("/tmp/mail.log","a ");

        if(fp) {

                time_t rec_time;

                time(&rec_time);

                fprintf(fp,"%s hostname: %s    ip_address: %s \r\n", ctime(&rec_time),prv->host,prv->ip);

                printf("%s hostname: %s        ip_address: %s \r\n", ctime(&rec_time),prv->host,prv->ip);

        }

        return SMFIS_CONTINUE;

}

int exfi_envfrom(SMFICTX *ctx,

                 char **args)

{

        struct private *prv;

        prv = smfi_getpriv(ctx);

        strlcpy(prv->sender,

                args[0],

                sizeof prv->sender);

        prv->jobid =

            smfi_getsymval(ctx, "i");

        prv->nrcpts = 0;

        prv->nhdrs = 0;

        prv->fd = -1;

        return SMFIS_CONTINUE;

}

char *substr_right(char *dst,char *src, int n)

{

    char *p = src;

    char *q = dst;

    int len = strlen(src);

    if(n>len) n = len;

    p = (len-n);

    while(*(q ) = *(p ));

    return dst;

}

int user_check(char *usermail)

{

        FILE *fp;

        fp = fopen("whiteuser.list", "r");

        if(fp == NULL) {

                return 0;

        }

        fseek( fp , 0 , SEEK_END );

        int file_size;

        file_size = ftell( fp );

        if(file_size<=0)

                return 0;

        char *filetmp;

        fseek( fp , 0 , SEEK_SET);

        filetmp = (char *)malloc( file_size * sizeof( char ) );

        fread( filetmp , file_size , sizeof(char) , fp);

        char *p;

        p=strstr(filetmp,usermail);

        if(p) {

                /*printf("user check sucess!%s",p);*/

                return 1;

        }

        else {

                /*printf("user check fail!");*/

                return 0;

        }

//2013-07-13 newadd “free(filetmp);”

              free(filetmp);

//2013-07-13 end

        fclose(fp);

}

int indexOf(char *str1,char *str2)

{

        char *p=str1;

        int i=0;

        p=strstr(str1,str2);

        if(p==NULL)

                return -1;

        else {

                while(str1!=p) {

                        str1 ;

                        i ;

                }

        }

        return i;

}

void trim_char(char s[],int c)

{

        int i,j;

        for (i = 0, j = 0; s[i] != '\0'; i ) {

                if (s[i] != c) {

                        s[j ] = s[i];

                }

        }

        s[j] = '\0';

}

int exfi_envrcpt(SMFICTX *ctx, char **args)

{

        char mail_passerver1[50]="@goldendragonbus.com";

        char mail_passerver2[20]="@test.com";

        char mail_buf[50];

        char send_user[50];

        struct private *prv;

        prv = smfi_getpriv(ctx);

        if (prv->nrcpts >= MAXRCPTS)

                return SMFIS_TEMPFAIL;

        strlcpy(prv->rcpts[prv->nrcpts],

                args[0],

                sizeof prv->rcpts[prv->nrcpts]);

        int rcpt_len=strlen(prv->rcpts[prv->nrcpts]);

        int e_pos=indexOf(prv->rcpts[prv->nrcpts],"@");

        strncpy(mail_buf,prv->rcpts[prv->nrcpts] e_pos,rcpt_len);

        trim_char(mail_buf,'>');

        strlcpy(send_user,prv->sender,sizeof send_user);

        trim_char(send_user,'<');

        trim_char(send_user,'>');

        /*printf("send_user:%s\r\n",send_user);*/

        /*printf("rcpt :%s,lenth is:%d,pos is:%d,mail_buf is:%s\r\n" ,prv->rcpts[prv->nrcpts],rcpt_len,e_pos,mail_buf);*/

        int sender_check= user_check(send_user);

        if(strcasecmp(mail_buf,mail_passerver1)!=0 && sender_check==0)

        {

                if(fp) {

                        fprintf(fp," sender:%s reciver[%d] is : %s     send Fail!\r\n", prv->sender,prv->nrcpts,prv->rcpts[prv->nrcpts]);

                        printf(" sender:%s     reciver[%d] is : %s     send Fail!\r\n", prv->sender,prv->nrcpts,prv->rcpts[prv->nrcpts]);

                }

                return SMFIS_REJECT;

              //return SMFIS_TEMPFAIL;

        }

        if(fp) {

                fprintf(fp," sender:%s reciver[%d] is : %s     send Sucess!\r\n", prv->sender,prv->nrcpts,prv->rcpts[prv->nrcpts]);

                printf(" sender:%s     reciver[%d] is : %s     send Sucess!\r\n", prv->sender,prv->nrcpts,prv->rcpts[prv->nrcpts]);

        }

        prv->nrcpts ;

        return SMFIS_CONTINUE;

}

int exfi_close(SMFICTX *ctx)

{

        struct private *prv;

        prv = smfi_getpriv(ctx);

        free(prv);

        smfi_setpriv(ctx, NULL);

        if(fp) {

                fclose(fp);

        }

        return SMFIS_CONTINUE;

}

struct smfiDesc filter = {

        "Example Filter",

        SMFI_VERSION,

        SMFIF_ADDHDRS,

        exfi_connect,

        NULL,

        exfi_envfrom,

        exfi_envrcpt,

        NULL,

        NULL,

        NULL,

        NULL,

        NULL,

        NULL

};

int main(int argc, char **argv)

{

        if (argc != 2) {

                fprintf(stderr,

                        "usage: %s socket\n",

                        argv[0]);

                return EX_USAGE;

        }

        smfi_setconn(argv[1]);

        smfi_register(filter);

        if (smfi_main() == 0)

                return EX_OK;

        else

                return EX_OSERR;

}

附录二:批量执行脚本

A、 单台转发

并发数量

邮件处理

50

正常

80

正常

100

失败

因为我们的环境是单台服务器的转发,所以并发数量为80个数量左右,而邮件服务器,

正常是由队列发出的,邮件服务器domino需要控制并发发送的数量。

B、 多台转发

并发数量

邮件处理

20

正常

30

正常

50

失败

为了测试,在2台客户端机器上执行该脚本,在2台客户端上上执行,如果循环50次的话,会出现内存问题,而退出过滤条件,而稳定在30个循环,即并发数量在每秒50个邮件左右。后续需要改进程序,加强效率。

附录三:SMTP交互指令说明

SMTP基本命令集:

命令

描述

HELO

向服务器标识用户身份

MAIL

初始化邮件传输 mail from:

RCPT

标识单个的邮件接收人;常在MAIL命令后面,可有多个rcpt to:

DATA

在单个或多个RCPT命令后,表示所有的邮件接收人已标识,并初始化数据传输,以.结束

QUIT

结束会话

MAIL FROM

命令中指定的地址是称作envelope from地址,不需要和发送者自己的地址是一致的

RCPT TO

与之等同,指明的接收者地址称为envelope to地址,而与实际的to:行是什么无关

现在的SMTP服务器一般都需要身份验证,下面是一个telnet发送邮件的例子:

C:\>telnet smtp.163.com 25    //登陆 smtp.163.com 端口号为 25

220 163.com Anti-spam GT for Coremail System(163com[071018])

HELO localhost // 与服务器打招呼,并告知客户端使用的机器名字,可以随便填写

250 OK 

AUTH LOGIN  //使用身份认证登陆指令

334 dXNlcm5hbWU6

cmVkc25zMw== //输入base64_encode()过的用户名,只输入用户名,不需要带@163.com

334 UGFzc3dvcmQ6

MbM2MMQ35Q== //输入base64_encode()过的密码

235 Authentication successful

MAIL FROM:<rain@163.com> //告诉服务器发信人的地址,必须和前面输入的用户名一致。

附录四:自动发送脚本

A、 脚本代码

                          [root@Sendmail ~]# vi telnet.sh

#!/usr/bin/expect

set smtp    [lindex $argv 0]

set from    [lindex $argv 1]

set to      [lindex $argv 2]

set title   [lindex $argv 3]

set content [lindex $argv 4]

spawn telnet $smtp 25

expect "220"

send "HELO xinhua.org\r"

expect "250 OK"

send "MAIL FROM: $from\r"

expect "250 Mail OK"

send "RCPT TO: $to\r"

expect "250 Mail OK"

send "DATA\r"

expect "354"

send "TO: $to\r"

send "FROM: $from\r"

send "SUBJECT: $title\r"

send "\r"

send "$content\r"

send ".\r"

expect "250"

send "QUIT"

B、 脚本测试(stmp的意义参考附录三)

[root@Sendmail ~]# ./telnet.sh  localhost abc123@163.com abc1230@gmail.com subjects content spawn  telnet  localhost  25

Trying 127.0.0.1...

Connected to localhost.localdomain (127.0.0.1).

Escape character is '^]'.

220 localhost.localdomain ESMTP Sendmail 8.14.6/8.13.8; Wed, 27 Feb 2013 16:14:40 0800

HELO xinhua.org

250 localhost.localdomain Hello localhost.localdomain [127.0.0.1], pleased to meet you

MAIL FROM: <abc123@163.com>

250 2.1.0 < abc123@163.com >... Sender ok

RCPT TO: abc1230@gmail.com

250 2.1.5 abc1230@gmail.com... Recipient ok

DATA

354 Enter mail, end with "." on a line by itself

TO: abc1230@gmail.com

FROM: abc123@163.com

SUBJECT: subjects

content

.

250 2.0.0 r1R8EeNW025980 Message accepted for delivery

附录五:批量发送脚本

                     [root@xml-ora1 ~]# vi parasend.sh

#!/bin/sh

for((i=0;i<50;i ));do

{

echo "$i send start `date` pid:$!.";

echo `./telnet.sh 172.16.28.127 $i@126.com abc1230@gmail.com subjects$i content`

echo `./telnet.sh 172.16.28.127 987654321@qq.com abc1230@gmail.com subjects$i content$i`

echo `./telnet.sh 172.16.28.127 $i@1.com abc1230@gmail.com subjects$i content`

echo `./telnet.sh 172.16.28.127 $i@qq.com wujianhua@goldendragonbus.com subjects$i content$i`

echo 1>> aa && echo "$i send complete `date` pid:$!.";

} &

done

wait

cat aa | wc -l

rm aa



 原文转载自:http://www.pangshayu.com/html/8366.html