把一个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 ...
随机推荐
- Vue 开发经验总结
Vue 开发经验总结 1.变量和方法,别写在全局,使用模块化导出.导入 对比项目 优点 缺点 适用场景 写在全局 会一直存在 使用模块化导出.导入 按需要导入 2.组件的prop值是请求接口后设置的( ...
- SolrJ的使用
SolrJ的使用 1.添加依赖 <?xml version="1.0" encoding="UTF-8"?> <project xmlns=& ...
- excel安装wps后不能正常启动
1. HKCU\Software\Microsoft\Office\15.0\Word\Options 设置NoReReg REG_DWORD =1 2.重命名C:\Program Files (x8 ...
- L1、L2范数理解
读了博主https://blog.csdn.net/a493823882/article/details/80569888的文章做简要的记录. 范数可以当作距离来理解. L1范数: 曼哈顿距离,是机器 ...
- 工控随笔_21_西门子_WinCC的VBS脚本_10_对象_01
最近有点小忙,各种事情,心情也不是很好,烦心事特别多,因此最近更新的比较慢. 不敢再松懈了,今天正好有点时间,就继续看了一下VBScript中关于对象的一些内容. 一.对象 OOP是编程规模发展到一定 ...
- 辨析字节序(Endianness)
字节序(Endianness, Byte Order)指的是对于一个多字节数值,当在内存中存储该值或者在链路中传输该值时,其值所包含的多个字节的排列顺序. 在计算机科学中,一般存在两种字节序,大端字节 ...
- python3学习笔记11(函数)
函数 python提供了许多内建函数,例如print(). 自己创建的函数,叫做用户自定义函数. 定义一个由自己想要功能的函数,以下是简单的规则: 函数代码块以 def 关键词开头,后接函数标识符名称 ...
- Python 目录整理
基础部分: 1 常量 2 字符编码 字符编码补充 3 编码集 4 break与continue 5装饰器 6 迭代器 7生成器 8面向过程 9模块 10包 11 递归调用 12文件的用途 13类 ...
- three.js使用base64 图片创建Texture纹理
下面使用的是literallycanvas绘图,然后获取绘图结果为base64内容 var lc = LC.init( document.getElementById('canvas-output') ...
- CPU的概念
1.CPU的运算都是以纳秒为单位的,内存相比要慢百倍,硬盘要慢百万倍. 2.CPU的主要工作就是运行指令,指令全在内存里,第一条指令地址为0xFFFFFF0处(BIOS发出的跳转指令). 3.CPU工 ...