本文档的重点在过滤器的配置,以及sample的生成,其他尽量从简,相应章节的安装过程可以参考相应的操作文档。
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 |
|
7 |
/tmp |
4G |
存放临时文件。对于多用户系统或网络服务器是有必要的。即使程序运行时生成大量的临时文件,或用户对系统进行了错误操作,文件系统的其它部分仍是安全的。因为文件系统的这一部分仍然还承受着读写操作,所以它通常会比其它的部分更快地发生问题。 |
8 |
/u01 |
剩余空间 |
存放数据库文件,或同类的大量的数据文件 |
注:上表中的容量只是参考值,或者说是最小值,具体部署时要根据业务数据要求来调整容量。
3、将下面默认都进行安装的组件都取消。原因:下面的组件经过确认都是不常用的组
件。其实下面的组件取消后,几乎已经没有会被安装的组件了。
4、计算机会自动开始安装系统。 至此裸系统安装完毕
一、设置网络
1、使用setup命令,图形化设置
设置完毕后,保存退出即可,如果需要设置DNS服务器地址,可以在下图所示的“Edit
DNS configuration”处设置。
2、使用命令行,手工录入
命令行模式,要比图形界面方便快捷,如下图所示。输入“vi /etc/sysconfig/network-
scripts/ifcfg-eth0” 即可对网卡1进行配置
示例说明:
DEVICE 设备名称,禁止修改
BROADCAST 广播地址
IPADDR IP地址
NETMASK 子网掩码
NETWORK 网络地址
GATEWAY 网关地址
ONBOOT 是否随系统启动
TYPE 网卡类型
设置完成后,需要手工对网卡进行重新启动。
DNS地址设置路径为 /etc/resolv.conf ,这里所说的DNS与我们要架设的DNS服务器的配置不一样。这里只是告诉系统DNS服务器的IP地址是多少而已。
至此,裸系统安装完毕,网络也能够连通了。配置yum需要外网的,如果在公司内部架设,不仅需要外网,还需要能够不受行为管理设备的控制。
二、设置yum
1、删除Linux系统自带的yum
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/
3、或者从其他机器复制安装包,如果知道哪台linux机器里有上面所说的安装包,linux之间互拷更快。示例只演示其中的一条拷贝命令,举一反三,真的很好用,强烈推荐。
示例说明:
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会出现如下错误提示
解决方法很简单,进入 /root/.ssh/ 目录下,rm - rf(删除)掉 known_hosts 即可。
4、安装yum安装包
如上图所示,我们首先需要到安装包所在位置才能使用rpm进行安装,这个道理Windows也是一样的。之所以用rpm –ivh yum-* 是因为我这里所要安装的三个包有依赖关系,使用yun-* 系统自己就可以搞定了。
5、确认安装信息
6、下载源配置文件CentOS-Base.repo
需要到上图所示的路径下载源配置文件,并且该配置文件需要放在 /etc/yum.repos.d/目录下,千万不要搞错了哦。
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 前面是 两个 --,最好是自己输入
8、更新yum
更新的过程是个漫长的过程,根据网速可能需要10到15分钟可能还会更长时间,不过好在系统会给你个动态的窗口显示出来,让你知道,系统还没死,在活着。
9、清空yum缓存
三、Sendmail 安装
A、 RPM包安装(推荐)
1、首先需要挂载光盘
示例说明:
cd /mnt 切换到根目录下的 mnt下面
mkdir cdrom 新建文件夹cdrom,这个目录是为了给光盘挂载的路径,必须得有才行。
mount 挂载的命令,无解释
iso9660 光盘
-t 挂载的类型还是什么东东,忘了啥意思,反正挂载的时候需要
/dev/cdrom 是光盘原位置,雷打不动,绝大部分都是用这个。光盘的话
/mnt/cdrom 这是我们刚才新设的挂载点,类似于Windows的文件夹。光盘内容就到这里找。
2、Sendmail安装
示例说明:
rpm –qa | grep sendmail 查询sendmail是否安装或者说已经安装了哪些包
需要说明的是,上面显示的是5个包,其中2个看上去以上,实际是1个32位、1个64位。
示例说明:
cd /mnt/cdrom/Server 切换到/mnt/cdrom/Server目录,其中Server是所有安装包的位置
rpm –ivh rpm包的安装方法,-ivh必须有
后边跟的一长串不解释,有大概名字之后,tab键可以补全这里只演示了一个安装包,另外四个用同样的方法举一反三
B、 YUM安装
示例说明:
yum install 是yum安装的命令,后边跟上要安装的包的名称即可,yum会自动解决掉所有的包依赖性。方便!
C、 源码安装
1、编译安装准备
卸载系统自带的sendmail
确认sasl是否已经安装,如果没有,需要重新安装一下sasl
挂载光盘
2、下载源码包
通过官方服务器下载:wget ftp://ftp.sendmail.org/pub/sendmail/sendmail.8.14.6.tar.gz
示例说明:
[root@sendmail ~]# 根据此提示,下载后的root账户的家目录下。以root账户登录,cd后就是家目录,其他账户以此类推,或者在下载前,pwd,看下自己处在哪个目录下面。
3、解压tar.gz包
示例说明:
tar –zxvf 不要搞错,解压后的在同级目录下面,会有个sendmail.8.14.6 的子目录4、编译源码
备份site.config.m4.sample文件至此,三种不同方式的安装方式都介绍结束,在linux不太熟悉
情况下,类似我这样的,可以使用rpm安装或者yum安装。编译不太建议!!
四、Sendmail配置
其实Sendmail的需要配置的内容真的不是很多,/etc/mail/access /etc/mail/sendmail.mc
这两个文档之外貌似就只有/etc/hosts 了。下面逐一截图说明一下需要修改的地方。
1、/etc/mail/access
示例说明:
vi /etc/mail/access 使用vi编辑器打开/etc/mail/access
Connect:17.16 RELAY转发来自172.16.0.0网段的所有邮件
修改完成后,需要使用makemap hash将access转换为access.db
2、/etc/mail/sendmail.mc
如果在m4的时候出现上图这样的错误,是因为没有安装sendmail-cf,通过yun安装一下就可以了
3、/etc/hosts
本次配置,该文档不用修改:
1、重启sendmail服务并测试sendmail发送
重启sendmail
测试sendmail发送邮件
示例说明:
helo 与sendmail服务器连接,后边的ddd 随便输入都可以
mail from: 发件箱,同样可以随便写,Sender ok 表示成功
rcpt to: 收件箱 Recipient ok 表示成功
data 邮件正文开始,换行 .表示结束
quit 退出发件状态
2、设置sendmail随系统自动启动
示例说明:
-bd 表示将sendmail你daemon(可以想成常驻内存)的类型启动
-q 后边跟着时间表示每隔多少时间,会将放置在邮件队列(一般在/var/spool/mqueue)的邮件尝试邮寄一次。
3、远程客户端测试
类似于本章节步骤4,只需要在非sendmail服务器本机上的其他机器,通过telnet
172.16.10.99 25 测试即可,具体细节与步骤4一致。
五、自定义Mail Filter
A、 安装GCC
1、检查gcc的安装情况:
示例说明:
上图的命令在安装sendmail的时候解释过,这里飘过
图示中的两个libgcc不是我们要的,所以要在下一个步骤通过yum安装。
2、通过yum安装gcc:
示例说明:
当出现gcc-4.1.2-54.el5时表示已经安装上去,同事也满足需求了。
3、通过rpm包安装:
gcc的安装依赖5个不同的安装包,本操作不方便,建议yum安装。
B、 编译sendmail
1、下载sendmail
本部分在第三章节第三小节里有介绍,本段跳过
2、解压sendmail
本部分在第三章节第三小节里有介绍,本段跳过
3、
C、 编译libmilter
1、sh Build
示例说明:
多个目录下都有Build,一定要看清楚再运行 sh Build ,以免对后续操作造成影响。当出现下图
所示时,表示命令已经完成。
2、sh Build install
3、find /-name libmilter.a
示例说明:
对照上图的路径,执行上图的命令,对照上图的结果,无误表示运行成功。无其他解释。
D、编译libsm
1、sh Build
示例说明:
出现上图结果,表示已经运行成功!
2、find /-name libsm.a
示例说明:
对照上图输入命令,对照上图查看执行情况,无解释。
E、新建mliter
1、新建mliter
示例说明:
在root家目录下新建子目录mliter
2、拷贝libmilter.a 和 libsm.a 以及 libmilter 目录
示例说明:
Linux的基本命令,主要用于复制粘贴,源文件在前,目标文件在后。
下面截图用的 /* 表示该目录下的所有文件都在复制粘贴的范围之内。
3、新建sample.c文件
示例说明:
sample.c 文档的源码在附件一中。
F、配置加载Filter文件(最为关键)
示例说明:
上句命令是指通过sample.c libmitler.a libsm.a 生成一个新的sample程序文件
G、启动Fiter(关键步骤)
示例说明:
./sample 是/root/mliter目录下面的一个程序,是上一个步骤生成的。
9876@localhost 是在上一个步骤新增的端口(9876)监听,在文挡/etc/mail/sendmail.mc的最后一行
& 在后台运行
H、测试Filter(关键步骤)
1、测试Filter是否成功,需要首先在/root/mliter目录下新增一个类似于白名单的whiteuser.list,该文件里面的内容如下截图所显示,每个授权外发邮箱新增一行。没有的邮箱只能发公司内部邮箱或者goldendragobus.com。
示例说明:
每个邮箱地址一行
3、在测试前完成添加whiteuser.list名单后,同时开启两个ssh窗口,一个运行
另一个窗口则是通过telnet localhost 25 的方式发送邮件,分别测试白名单内有的邮箱地址和白名单内没有的地址。当出现下图所示,即表示fiter测试成功
示例说明:
以上两个截图,是在不同的SSH窗口同时显示出来的结果。
测试过程中,如果出现意外导致linux长时间无响应,可以通过如下命令杀死相关进程。
至此,Sendmail的配置全部结束。后边的附件一位sample.c的源码,附件二为一些服务器优化数据,仅供参考。
六、远程控制SSHD配置
这里说明一下,本段配置之选择了设置于sendmail.xmjl.com这台服务器上的功能选项,更多细节,参考Redhat Linux 5 x64 SSHD配置
1、备份sshd_config配置文件
示例说明:
pwd 查看当面所处目录
cp 备份,前部分为源文件,后部分为目标文件
需要注意的是,在/etc/ssh 目录下还有另外一个类似于 sshd_config的 文件ssh_config,在编辑的时候一定要注意,不要搞错了。
2、配置sshd_config
示例说明:
port SSHD开放端口
protocol SSHD所使用的协议版本,一般用版本2
listenaddress 这里只能单个多行添加IP地址,不能添加网段。
示例说明:
Logingracetime 登录时不输入密码的等待时间
Permitrootlogin no 表示禁止root账户直接通过sshd登陆,yes表示可以
Maxauthtries 忘了啥意思了,反正这里配置了
七、防火墙iptables配置
这里说明一下,本段配置之选择了设置于sendmail.xmjl.com这台服务器上的功能选项,更多细
节,参考Redhat Linux 5 x64 iptables配置
Iptables的所有策略都保存在/etc/sysconfig/iptables里,修改完毕后直接重启iptables即可生效。
示例说明:
# 注释此条策略,不使其生效
拒绝所有流入本机的数据
拒绝所有通过本机转发的数据
允许所有流出本机的数据
允许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是否已经生效,可以通过下面命令查看
示例说明:
-L 查看当前表的所有规则,默认查看的是filter表
--line-nu 显示带有序号的防火墙策略
示例说明:
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地址。建议如此,比较好用!
示例说明:
pwd 查看
cp 复制文档
vi 编辑文档
最后一行的意思是允许172.16.28.0/255.255.255.0 网段的主机通过sshd连接服务器,除此之外的所有IP地址全部拒绝。
2、/etc/services配置
本文档可以修改各个服务默认的端口号信息,本次配置修改了sshd的默认端口号,所以在iptables里,本来是要显示dport是56088的,因为修改后,变成了sshd了。
九、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