把一个syn报文给rst掉
下面展示一个极其简单的例子,看如何使用netfilter来将一个指定端口的syn报文给rst掉。
//***************************************************************
// https://i.cnblogs.com/EditPosts.aspx?postid=10650263&update=1
//
// Simple hook test to be called.
// We drop the syn packet and rst the request
//***************************************************************
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <net/tcp.h>
#include <linux/init.h> #ifndef NIPQUAD
#define NIPQUAD(addr) \
((unsigned char *)&addr)[0], \
((unsigned char *)&addr)[1], \
((unsigned char *)&addr)[2], \
((unsigned char *)&addr)[3]
#endif #ifndef NIPQUAD_FMT
#define NIPQUAD_FMT "%u.%u.%u.%u"
#endif #define Serve_Port 5886
#define My_DEBUG_ENABLE 1 static unsigned int test_nf_filter(const struct nf_hook_ops *ops,
struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
#ifndef __GENKSYMS__
const struct nf_hook_state *state
#else
int (*okfn)(struct sk_buff *)
#endif
)
{
struct sk_buff * skb_send;
struct iphdr *iph_send ;
struct tcphdr *tcph_send;
struct ethhdr *eth_send;
struct iphdr *iph ;
struct tcphdr *tcph;
struct ethhdr *eth;
__u32 sip;
__u32 dip;
__u16 sport;
__u16 dport;
int tcphdrlen, iphdrlen, ethhdrlen;
int err; int tcphdrlen_recv, iphdrlen_recv; /*取出mac头部*/
eth = (struct ethhdr *)skb_mac_header(skb); /*取出IP头,源IP地址.目的IP地址*/
iph=ip_hdr(skb);
sip=iph->saddr;
dip=iph->daddr; /*如果不是TCP协议,直接返回*/
if(iph->protocol != IPPROTO_TCP){
return NF_ACCEPT;
} tcph = (struct tcphdr *)((__u32 *)iph + iph->ihl);
sport = tcph->source;
dport = tcph->dest; /*如果不是指定的端口,直接返回*/
if (ntohs(dport)!=Serve_Port)
{
return NF_ACCEPT;
}
if(!(tcph->syn))
{
return NF_ACCEPT;
}
if (My_DEBUG_ENABLE)
{
printk("TCP PACKET. ");
printk("recv packet,syn=%u\r\n,tcph->syn");
printk("from %d.%d.%d.%d to %d.%d.%d.%d - ",
NIPQUAD(sip),NIPQUAD(dip));
printk("from %u to %u. ",ntohs(sport),ntohs(dport));
printk("skb->len(%u) ", skb->len);
printk("seq(%x) ", ntohl(tcph->seq));
printk("ack_seq(%x) ", ntohl(tcph->ack_seq));
printk(".\n");
} /*分析tcp载荷,并存放接收的Rtsp信息*/
iphdrlen_recv = iph->ihl * 4;
tcphdrlen_recv = tcph->doff * 4; /* handle syn packet ,first Malloc up new buffer. */
ethhdrlen = sizeof(struct ethhdr);
iphdrlen = sizeof(struct iphdr);
tcphdrlen = sizeof(struct tcphdr);
/* only respond with one byte */
skb_send = dev_alloc_skb(ethhdrlen + iphdrlen + tcphdrlen);
if (skb_send == NULL)
{
printk(KERN_WARNING "Memory squeeze, dropping packet.\n");
return NF_ACCEPT;
} if (skb_send)
{
/*将头部指针往后移动。然后从高层协议开始填充。*/
skb_reserve(skb_send, ethhdrlen + iphdrlen + tcphdrlen); /*调整TCP指针*/
tcph_send = (struct tcphdr *)__skb_push(skb_send, tcphdrlen);
skb_set_transport_header(skb_send, 0);
tcph_send->source = dport;
tcph_send->dest = sport;
tcph_send->seq = tcph->ack_seq;
//tcph_send->ack_seq =0;
tcph_send->ack_seq = htonl(ntohl(tcph->seq)+1); tcph_send->res1 = 0;
tcph_send->doff = htons(sizeof(struct tcphdr) >> 2);
tcph_send->fin = 0;
tcph_send->syn = 0;
tcph_send->rst = 1;
tcph_send->psh = 0;
tcph_send->ack = 1;
tcph_send->urg = 0;
tcph_send->ece = 0;
tcph_send->cwr = 0; //*(((__be16 *)tcph_send) + 6) = htons(((tcphdrlen >> 2) << 12) |0x0014);
tcph_send->doff = (tcphdrlen >> 2); tcph_send->window = htons(0x3CF2);
tcph_send->urg_ptr = 0;
tcph_send->check = 0; /*ip头部*/
iph_send = (struct iphdr * )__skb_push(skb_send, iphdrlen);
skb_set_network_header(skb_send, 0); iph_send->version = 4;
iph_send->ihl = sizeof(struct iphdr)/4;
iph_send->tos = 0;
iph_send->tot_len = htons(iphdrlen + tcphdrlen);
iph_send->id = 0;
iph_send->frag_off = 0;
iph_send->ttl = 55;
iph_send->protocol = IPPROTO_TCP;
iph_send->check = 0;
iph_send->saddr = iph->daddr;
iph_send->daddr = iph->saddr;
iph_send->check = 0;
iph_send->check = ip_fast_csum((unsigned char *)iph_send, iph_send->ihl); /*tcp头部校验和初始值计算*/
skb_send->csum = 0;
skb_send->ip_summed = CHECKSUM_UNNECESSARY;
tcph_send->check = tcp_v4_check(tcphdrlen , iph_send->saddr, iph_send->daddr,
csum_partial(tcph_send, tcphdrlen , 0)); /*eth头部*/
eth_send = (struct ethhdr * )__skb_push(skb_send, ethhdrlen);
skb_set_mac_header(skb_send, 0);
memcpy(eth_send->h_dest, eth->h_source, ETH_ALEN);
memcpy(eth_send->h_source, eth->h_dest, ETH_ALEN);
eth_send->h_proto = eth->h_proto; /*其他配置*/
skb_send->mac_len = ethhdrlen;
skb_send->dev = skb->dev;
skb_send->queue_mapping = skb->queue_mapping;
skb_send->protocol = htons(ETH_P_IP);;
skb_send->vlan_tci = skb->vlan_tci;
skb_send->pkt_type = PACKET_OUTGOING;
skb_send->mark = 0;
memset(skb_send->cb, 0, sizeof(skb_send->cb)); /*完成数据包的发送*/
err = dev_queue_xmit(skb_send);
if (err > 0 && (err = net_xmit_errno(err)) != 0)
{
printk(KERN_WARNING "dev_queue_xmit=%d.\n", err);
}
} //*走到这,丢弃所有的包*/
return NF_DROP;
} static struct nf_hook_ops test_filter = {
.owner = THIS_MODULE,
.list = {NULL, NULL},
.hook = &test_nf_filter,
.pf = PF_INET,
//.hooknum = NF_INET_LOCAL_IN, /*NF_IP_LOCAL_IN,*/
.hooknum = NF_INET_PRE_ROUTING, /*NF_IP_LOCAL_IN,*/
.priority = NF_IP_PRI_FIRST
}; static int testnf_init(void)
{
printk(KERN_ALERT "Test netfilter!\n"); return nf_register_hook(&test_filter);
} static void testnf_exit(void)
{
nf_unregister_hook(&test_filter); printk(KERN_ALERT "GOODBYE netfilter!\n");
}
MODULE_LICENSE("GPL");
module_init(testnf_init); module_exit(testnf_exit);
服务器端监听端口:
[root@localhost hook]# gdb ./tcp_sever.o
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-100.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/caq/hook/tcp_sever.o...done.
(gdb) r
Starting program: /home/caq/hook/./tcp_sever.o
========waiting for client's request========
端口已经侦听:
[root@localhost hook]# ss -tlp |grep -i 5886
LISTEN 0 10 *:5886 *:* users:(("tcp_sever.o",pid=42818,fd=7))
客户端发起链接,很快被服务器端rst掉。
linux:/home/caq # ./tcp_client.o
connect: Connection refused
执行的抓包结果:
10:39:29.762503 IP (tos 0x0, ttl 64, id 58665, offset 0, flags [DF], proto TCP (6), length 52) 10.229.200.12.13952 > 10.229.200.30.5886: S, cksum 0xa61b (incorrect (-> 0x0ae2), 744885068:744885068(0) win 14600 <mss 1460,nop,nop,sackOK,nop,wscale 9>
0x0000: 0004 0001 0006 98f5 37e2 f373 0000 0800
0x0010: 4500 0034 e529 4000 4006 afa5 0ae5 c80c
0x0020: 0ae5 c81e 3680 16fe 2c66 0b4c 0000 0000
0x0030: 8002 3908 a61b 0000 0204 05b4 0101 0402
0x0040: 0103 0309
10:39:29.763024 IP (tos 0x0, ttl 55, id 0, offset 0, flags [none], proto TCP (6), length 40) 10.229.200.30.5886 > 10.229.200.12.13952: R, cksum 0x47b8 (correct), 0:0(0) ack 744885069 win 15602
0x0000: 0000 0001 0006 74a4 b500 f12e 0000 0800
0x0010: 4500 0028 0000 0000 3706 dddb 0ae5 c81e
0x0020: 0ae5 c80c 16fe 3680 0000 0000 2c66 0b4d
0x0030: 5014 3cf2 47b8 0000 0000 0000 0000
这个简单的示例,是展示netfilter的钩子到底怎么使用,当然,我们不可能对所有的规则都写一个模块实现,所以,用户态的配置工具就出来了,我们后续博客再记录。
有个tcpkill的工具,也可以实现类似的功能,它的原理是利用抓包,然后根据获取的seq和四源组信息,发送rst来干掉链路。如果抓不到包,比如对于一条不活跃的链接,
可以构造syn包,然后等对端回复一个正确的ack,里面有seq信息,再发送rst复位之。
把一个syn报文给rst掉的更多相关文章
- TCP协议: SYN ACK FIN RST PSH URG 详解
TCP的三次握手是怎么进行的了:发送端发送一个SYN=1,ACK=0标志的数据包给接收端,请求进行连接,这是第一次握手:接收端收到请求并且允许连接的话,就会发送一个SYN=1,ACK=1标志的数据包给 ...
- 一个TCP报文段的数据部分最多为多少个字节,为什么
IP数据报的最大长度=2^16-1=65535(字节)TCP报文段的数据部分=IP数据报的最大长度-IP数据报的首部-TCP报文段的首部=65535-20-20=65495(字节) 一个tcp报文段的 ...
- php同一个用户同时只能登陆一个, 后登陆者踢掉前登陆者(排他登陆)
通常用户登陆,如果没有特别的限定, 同一个用户可以同时登陆, 今天搞了一个东西限定一个用户不能同时登陆到一个系统上, 后登陆者会把前面登陆的踢出来.(有点像QQ,同个帐号不能在多个地方同时在线, 后面 ...
- Android ListView的一个坑,你可掉进去过?
需要的功能很简单,就是一个带checkbox的列表,提交时需要知道用户选择了那些项目,如下图: 使用SimpleAdapter作为数据适配器,重写SimpleAdapter.ViewBinder的方法 ...
- [SoapUI] 怎样确定一个应答报文的格式是不是标准的JSON
有一个网站 : http://jsonviewer.stack.hu/ 将Response的文本贴进去,如果是标准的JSON格式,就可以以JSON的view显示出来
- TCP重置报文段及RST常见场景分析
RST表示连接重置,用于关闭那些已经没有必要继续存在的连接.一般情况下表示异常关闭连接,区别与四次分手正常关闭连接. 产生RST的三个条件是: 目的地为某端口的SYN到达,然而在该端口上并没有正在监听 ...
- linux内核参数sysctl.conf,TCP握手ack,洪水攻击syn,超时关闭wait
题记:优化Linux内核sysctl.conf参数来提高服务器并发处理能力 PS:在服务器硬件资源额定有限的情况下,最大的压榨服务器的性能,提高服务器的并发处理能力,是很多运维技术人员思考的问题.要提 ...
- linux内核参数sysctl.conf,TCP握手ack,洪水攻击syn,超时关闭wait(转)
http://www.xshell.net/linux/Linux_sysctl_conf.html 优化Linux内核sysctl.conf参数来提高服务器并发处理能力 Posted by 破冰 o ...
- 为什么服务器突然回复RST——小心网络中的安全设备
RST产生原因 一般情况下导致TCP发送RST报文的原因有如下3种: 1. SYN数据段指定的目的端口处没有接收进程在等待. 2.TCP想放弃一个已经存在的连接. 3.TCP ...
随机推荐
- Yii2 设计模式——简单工厂模式
除了使用 new 操作符之外,还有更多的制造对象的方法.你将了解到实例化这个活动不应该总是公开进行,也会认识到初始化经常造成“耦合”问题. 应用举例 yii\db\mysql\Schema 中: // ...
- 深入理解CSS选择器优先级
题外话 今天把 <CSS REFACTORING>(中文名叫<CSS重构:样式表性能调优>)电子书粗略的浏览了一遍,这本书很薄,150页左右,首先是介绍了什么是重构并举了两个简 ...
- Day 22 初识面向对象
一.两种编程思想 1.面向过程编程 核心是'过程',过程指的是解决问题的步骤,就是先干什么再干什么 基于面向过程思想编写程序相当于写一条流水线,是一种机械式的思维方式 优点:解决问题的思路清晰,可以把 ...
- 【MatConvNet代码解析】 vl_nnsoftmaxloss
背景知识:http://deeplearning.stanford.edu/wiki/index.php/Softmax%E5%9B%9E%E5%BD%92 假设softmax层的输入(softmax ...
- py-day4-3 python 内置函数 man和mix的高级使用
### man和mix的高级使用 age_dic={'xiaoma':18,'zhangfei':20,'xiaowang':36,'lihao':13,} print(max(age_dic.val ...
- 剑指offer 13.代码的完整性 调整数组顺序使奇数位于偶数前面
题目描述 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变. 本渣渣解题思路: ...
- JQuery操作属性、样式、风格(attr、class、css)
样式操作 <p class="myclass" title="选择喜欢的水果">你最喜欢的水果是?</p> 在上面代码中,class也是 ...
- python中的RE模块
re模块(* * * * *) 就其本质而言,正则表达式(或 RE)是一种小型的.高度专业化的编程语言,(在Python中)它内嵌在Python中,并通过 re 模块实现.正则表达式模式被编译成一系列 ...
- os常用模块,json,pickle,shelve模块,正则表达式(实现运算符分离),logging模块,配置模块,路径叠加,哈希算法
一.os常用模块 显示当前工作目录 print(os.getcwd()) 返回上一层目录 os.chdir("..") 创建文件包 os.makedirs('python2/bin ...
- 画流程图挺好的软件---visio
visio 2016 下载地址链接: https://pan.baidu.com/s/1oyfJL_QgOA7qUHOt7p8CIA 提取码: mv79 第一次做的样式图: