发送raw tcp包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
struct iphdr {
	uint8_t ihl :4,
		 version:4;
	uint8_t tos;
	uint16_t tot_len;
	uint16_t id;
	uint16_t frag_off;
	uint8_t ttl;
	uint8_t protocol;
	uint16_t check;
	int32_t saddr;
	int32_t daddr;
};

struct tcphdr {
	uint16_t source;
	uint16_t dest;
	uint32_t seq;
	uint32_t ack_seq;
	uint16_t res1:4,
		doff:4,
		fin:1,
		syn:1,
		rst:1,
		psh:1,
		ack:1,
		urg:1,
		ece:1,
		cwr:1;
	uint16_t window;
	uint16_t check;
	uint16_t urg_ptr;
};

struct pseudo_header
{
    u_int32_t source_address;
    u_int32_t dest_address;
    u_int8_t placeholder;
    u_int8_t protocol;
    u_int16_t tcp_length;
};

static uint16_t checksum(uint8_t* buf, size_t size)
{    
    int res = 0;
    uint16_t* ptr = (uint16_t*)buf;
    
    for (int i = 0; i < size / 2; i++) {
        res += ptr[i];
    }
    
    if (size & 1) {
        res += buf[size - 1];
    }
    
    res = (res >> 16) + (res & 0xFFFF);
    res += (res >> 16);
    
    return ~res; 
}

static int send_rst(std::string ip, uint16_t port)
{
    int fd;
    uint8_t buf[128];
    uint8_t psb[128];
    struct pseudo_header psh;
    struct iphdr* iph = (struct iphdr*)buf;
    struct tcphdr* tcph = (struct tcphdr*)(buf + sizeof(struct iphdr));
    struct sockaddr_in dest;
    int val;

    fd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
    if (fd < 0) {
        printf("socket open failed\n");
        return -1;
    }
    
    val = 1;
    setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &val, sizeof(val));
    
    memset(buf, 0, sizeof(buf));

    iph->ihl = sizeof(struct iphdr) >> 2;
    iph->version = 4;
    iph->tos = 0;
    iph->tot_len = htons(sizeof(struct iphdr) + sizeof(struct tcphdr));
    iph->id = htonl(54321);
    iph->frag_off = 0;
    iph->ttl = 255;
    iph->protocol = IPPROTO_TCP;
    iph->saddr = inet_addr("192.168.1.1");
    iph->daddr = inet_addr(ip.c_str());
    iph->check = 0;
    iph->check = checksum((uint8_t*)iph, sizeof(struct iphdr));

    tcph->source = htons(7000);
    tcph->dest = htons(port);
    tcph->seq = 123456789;
    tcph->ack_seq = 0;
    tcph->doff = sizeof(struct tcphdr) >> 2;
    tcph->rst = 1;
    tcph->window = htons(5840);
    tcph->check = 0;
    tcph->urg_ptr = 0;
    
    psh.source_address = iph->saddr;
    psh.dest_address = iph->daddr;
    psh.placeholder = 0;
    psh.protocol = IPPROTO_TCP;
    psh.tcp_length = htons(sizeof(struct tcphdr));
    
    memcpy(psb, &psh, sizeof(struct pseudo_header));
    memcpy(psb + sizeof(struct pseudo_header), tcph, sizeof(struct tcphdr));
    
    tcph->check = checksum(psb, sizeof(struct pseudo_header) + sizeof(struct tcphdr));
     
    dest.sin_family = AF_INET;
    dest.sin_port = tcph->dest;
    dest.sin_addr.s_addr = iph->daddr;

    if (sendto(fd, buf, sizeof(struct iphdr) + sizeof(struct tcphdr), 0, (struct sockaddr*)&dest, sizeof(dest)) < 0) {
        printf("send failed: %s\n", strerror(errno));
    }

    close(fd);
    return 0;
}