本文檔的重點在過濾器的配置,以及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 | 主要存放系統日誌,設立單獨分區,即使系統日誌文件出現問題,也不影響系統主分區。也就不會使計算機崩潰。如WEB服務器,可分20GB或根據實際情況加大 |
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 可以傳輸整個文件夾,沒有這個參數,只能拷貝單個文件
源文件在前,需指定絕對路徑,系統會補全,後邊同樣是絕對路徑,系統不能補全,只要指定需要複製到的文件夾即可
[email protected]: root是目標主機有管理權限的賬戶,172.16.10.99是目標主機IP地址,ip地址前面的@符號和地址後邊的冒號必須有,命令格式如此,無解釋。
命令執行過程中,可能會讓你選擇yes或者no,個人理解應該是yes ,[email protected]'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 ‘[email protected]’查看與某個指定賬戶有關的記錄
#egrep ‘[email protected]|[email protected]’ /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 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:<[email protected]> //告訴服務器發信人的地址,必須和前面輸入的用戶名一致。
附錄四:自動發送腳本
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 [email protected] [email protected] 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: <[email protected]>
250 2.1.0 < [email protected] >... Sender ok
RCPT TO: [email protected]
250 2.1.5 [email protected]... Recipient ok
DATA
354 Enter mail, end with "." on a line by itself
FROM: [email protected]
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 [email protected] [email protected] subjects$i content`
echo `./telnet.sh 172.16.28.127 [email protected] [email protected] subjects$i content$i`
echo `./telnet.sh 172.16.28.127 [email protected] [email protected] subjects$i content`
echo `./telnet.sh 172.16.28.127 [email protected] [email protected] subjects$i content$i`
echo 1>> aa && echo "$i send complete `date` pid:$!.";
} &
done
wait
cat aa | wc -l
rm aa