|
本帖最后由 karl_marx_1818 于 2016-11-5 14:15 编辑
1、扩展nf_conn对layer7的数据结构:
hope@ubuntu:~/barrier_breaker/build_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/linux-ramips_mt7620a/linux-3.10.49/include/net/netfilter$ vi nf_conntrack.h
在数据结构nf_coon中增加蓝色部分:
#if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || \
defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE)
struct {
/*
* e.g. "http". NULL before decision. "unknown" after decision
* if no match.
*/
char *app_proto;
/*
* application layer data so far. NULL after match decision.
*/
char *app_data;
char *original_app_data;
unsigned int app_data_len;
unsigned int original_app_data_len;
} layer7;
#endif
 
2、由于layer7将payload都转换为小写,因此在进行base64解码时,无法获取原有邮件原始数据。
需要将payload的原始数据放到nf_coon新扩展的变量中。
hope@ubuntu:~/barrier_breaker/build_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/linux-ramips_mt7620a/linux-3.10.49/net/netfilter$ vi xt_layer7.c
(1)修改__init xt_layer7_init中的包大小判断
/* This is not a hard limit. It's just here to prevent people from
bringing their slow machines to a grinding halt. */
else if(maxdatalen > 1024*128) {
printk(KERN_WARNING "layer7: maxdatalen can't be > 65536, "
"using 65536\n");
maxdatalen = 1024*128;
(2)增大组装包的数量和payload的长度
(根据CPU、内存和邮件大小等调整变量,同时调整设备的最大并发,测试最大并发时的内存)
static int num_packets = 30;
static int maxdatalen = 1024*128;
(3)在match函数中增加蓝色部分:
/* On the first packet of a connection, allocate space for app data */
if(total_acct_packets(master_conntrack) == 1 && !skb->cb[0] &&
!master_conntrack->layer7.app_data && !master_conntrack->layer7.original_app_data){
master_conntrack->layer7.app_data =
kmalloc(maxdatalen, GFP_ATOMIC);
master_conntrack->layer7.original_app_data =
kmalloc(maxdatalen, GFP_ATOMIC);
if(!master_conntrack->layer7.app_data && !master_conntrack->layer7.original_app_data){
if (net_ratelimit())
printk(KERN_ERR "layer7: out of memory in "
"match, bailing.\n");
spin_unlock_bh(&l7_lock);
return info->invert;
}
master_conntrack->layer7.app_data[0] = '\0';
master_conntrack->layer7.original_app_data[0] = '\0';
}
/* Can be here, but unallocated, if numpackets is increased near
the beginning of a connection */
if(master_conntrack->layer7.app_data == NULL && master_conntrack->layer7.original_app_data == NULL){
spin_unlock_bh(&l7_lock);
return info->invert; /* unmatched */
}
(4)match函数中增加蓝色部分,如果命中,将文件正文打印到/var/layer7.log中:
/* If looking for "unknown", then never match. "Unknown" means that
we've given up; we're still trying with these packets. */
if(!strcmp(info->protocol, "unknown")) {
pattern_result = 0;
/* If looking for "unset", then always match. "Unset" means that we
haven't yet classified the connection. */
} else if(!strcmp(info->protocol, "unset")) {
pattern_result = 2;
DPRINTK("layer7: matched unset: not yet classified "
"(%d/%d packets)\n",
total_acct_packets(master_conntrack), num_packets);
/* If the regexp failed to compile, don't bother running it */
} else if(comppattern &&
regexec(comppattern, master_conntrack->layer7.app_data)){
DPRINTK("layer7: matched %s\n", info->protocol);
// Gxxie modify begin: Output payload to /var/layer7.log
DPRINTK("====================================== Layer7 payload begin ======================================\nLayer7 protocol is:%s\n%s\n====================================== Layer7 payload end ======================================\n", info->protocol, master_conntrack->layer7.original_app_data);
// Gxxie modify end
pattern_result = 1;
} else pattern_result = 0; } else pattern_result = 0;
(5)在match_no_append函数中增加释放layer7.app_data代码
kfree(master_conntrack->layer7.app_data);
master_conntrack->layer7.app_data = NULL; /* don't free again */
kfree(master_conntrack->layer7.original_app_data);
master_conntrack->layer7.original_app_data = NULL; /* don't free again */
 
3、增加释放nf_coon扩展字段的内存,增加蓝色部分:
hope@ubuntu:~/barrier_breaker/build_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/linux-ramips_mt7620a/linux-3.10.49/net/netfilter$ vi nf_conntrack_core.c
#if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE)
if(ct->layer7.app_proto)
kfree(ct->layer7.app_proto);
if(ct->layer7.app_data)
kfree(ct->layer7.app_data);
kfree(ct->layer7.original_app_data);
#endif
4、修改 #define LOG_LINE_MAX,增大DPRINTK的单行大小
hope@ubuntu:~/barrier_breaker/build_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/linux-ramips_mt7620a/linux-3.10.49/kernel$ vi printk.c
#define LOG_LINE_MAX 1024*128 - PREFIX_MAX
5、修改 #define CONFIG_LOG_BUF_SHIFT扩大dmesg的buffer
(或者通过make kernel_menuconfig中General setup --> Kernel log buffer size设置)
hope@ubuntu:~/barrier_breaker/build_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/linux-ramips_mt7620a/linux-3.10.49/include/generated$ vi autoconf.h
#define CONFIG_LOG_BUF_SHIFT 20
6、编辑pop3特征
root@Shanty:/usr/shanty/script# cat /etc/l7-protocols/mail_content.pat
mail_content
Subject:.*(html|221 Bye)
 
7、增加iptables规则
iptables -N LAYER7
iptables -A FORWARD -p tcp --dport 25 -j LAYER7
iptables -A FORWARD -p tcp --sport 25 -j LAYER7
iptables -A FORWARD -p tcp --dport 110 -j LAYER7
iptables -A FORWARD -p tcp --sport 110 -j LAYER7
iptables -A LAYER7 -m layer7 --l7proto mail_content -j ACCEPT
python /usr/shanty/script/mail_collector.py start &
6、创建python脚本(这个脚本比较粗略,主要是说明一下如何读取数据)
#!/usr/bin/python
# -*- coding:utf-8 -*-
import sys,os,time,commands,pexpect,base64
def start():
# open("/etc/sysctl.conf.new", "w").write(''.join(map(lambda x: "net.netfilter.nf_conntrack_max" in x and "net.netfilter.nf_conntrack_max=1000\n" or x, open("/etc/sysctl.conf", "r"))))
# os.system("rm /etc/sysctl.conf")
# os.system("mv /etc/sysctl.conf.new /etc/sysctl.conf")
# os.system("sysctl -p >/dev/null 2>&1")
while True:
# ================================== Encryption Begin ==================================
if (os.path.exists(r'/usr/shanty/log/mail.log')):
try:
(status, result) = commands.getstatusoutput("ls -al /usr/shanty/log/mail.log | awk {'print $5'}")
except:
os.system('echo "Error: execute [ ls -al /usr/shanty/log/mail.log ] failed. error in mail.py" >> /usr/shanty/error_log')
result = 0
if ( int(result) > 500000 ):
(status, result) = commands.getstatusoutput('date "+%Y-%m-%d-%H-%M-%S"')
try:
child = pexpect.spawn('openssl enc -aes-128-cbc -in /usr/shanty/log/mail.log -out /mnt/m.sec.' + result)
child.expect ('enter aes-128-cbc encryption password:')
child.sendline ('CAFE*1981')
child.expect ('Verifying - enter aes-128-cbc encryption password:')
child.sendline ('CAFE*1981')
child.expect ('root@')
os.system('rm /usr/shanty/log/mail.log')
except:
os.system('echo "Error: encryption /usr/shanty/log/mail.log failed. error in mail.py" >> /usr/shanty/error_log')
else:
# File mail.log is small, no need encrypt.
pass
else:
# /usr/shanty/log/mail.log is not exist.
pass
# ================================== Encryption End ==================================
os.system('dmesg -c >/usr/shanty/log/layer7.log')
time.sleep(60)
try:
f = open(r'/usr/shanty/log/layer7.log','r')
except:
print('Error: open file /usr/shanty/log/layer7.log failed.')
os.system('echo "Error: open file /usr/shanty/log/layer7.log failed. error in mail.py" >> /usr/shanty/error_log')
continue
while True:
line = f.readline()
if not line:
break
if( 'Layer7 protocol is:' in line and 'mail' in line):
username = 'null'
password = 'null'
mail_from = 'null'
mail_to = 'null'
mail_cc = 'null'
mail_date = 'null'
mail_subject = 'null'
mail_content = 'null'
if ( 'USER' in line ):
username = line.split('USER ')[1].replace('\n','')
elif ( 'PASS' in line ):
password = line.split('PASS ')[1].replace('\n','')
elif ( 'From:' in line ):
mail_from = line.split('From: ')[1]
elif ( 'To: "' in line ):
mail_to = line.split('To: ')[1].replace("'",'')
elif ( 'Cc:' in line ):
mail_cc = line.split('Cc: ')[1].replace("'",'')
elif ( 'Date:' in line ):
mail_date = line.split('Date: ')[1]
elif ( 'Subject:' in line ):
mail_subject = line.split('?')[3]
try:
mail_subject = base64.decodestring(mail_subject)
except:
print("Except: decoding base64 from mail_subject error.")
elif ( 'Content-Transfer-Encoding: base64' in line ):
f.readline() # Read the following line which is \r\n\
mail_content = ''
while True:
tmp = f.readline()
if ( tmp == '\r\n' ):
break
else:
mail_content += tmp.replace('\r\n','')
try:
mail_content = base64.decodestring(mail_content)
except:
print("Except: decoding base64 from mail_contend error.")
elif ( 'Layer7 payload end' in line ):
if ( mail_content != 'null' ):
print ("获得一封内容完整的邮件")
else:
print ("获得一封内容不完整的邮件")
mail_content = "Got a large mail, ignore content."
if ( mail_subject != 'null' ):
try:
fd = open(r'/usr/shanty/log/mail.log','a')
fd.write("\n"+"="*80+"\nUsername:{0}\nPassword:{1}\nFrom :{2}To :{3}Cc :{4}Date :{5}Subject :{6}\n{7}".format(username, password, mail_from, mail_to, mail_cc, mail_date, mail_subject, mail_content))
fd.close()
except:
print("Except: open and write to /usr/shanty/log/mail.log error.")
else:
os.system('echo "Error: Get a mail but mail_subject is null. error in mail.py" >> /usr/shanty/error_log')
else:
pass
f.close()
def stop():
# open("/etc/sysctl.conf.new", "w").write(''.join(map(lambda x: "net.netfilter.nf_conntrack_max" in x and "net.netfilter.nf_conntrack_max=16000\n" or x, open("/etc/sysctl.conf", "r"))))
# os.system("rm /etc/sysctl.conf")
# os.system("mv /etc/sysctl.conf.new /etc/sysctl.conf")
# os.system("sysctl -p >/dev/null 2>&1")
# os.system("ps aux | grep mail | awk '{system(\"kill \"$2)}' >/dev/null 2>&1")
pass
if __name__ == '__main__':
if (sys.argv[1] == "start"):
start()
elif (sys.argv[1] == "stop"):
stop()
7、测试。发送邮件后下载mail.log并查看结果(通过shell查看可能会有乱码)
root@Shanty:~# sz /usr/shanty/log/mail.log
请不要胡乱输入以及粘贴、复制等方式灌水
请尊重作者、并共同维护网站的正常阅读,否则账户将会被限制发帖、回帖,并且积分可能会被清零,站内短信以及阅读权限等都会受到影响,谢谢。
具体限制方式:https://www.right.com.cn/forum/thread-8307840-1-1.html
|
评分
-
查看全部评分
|