TSG-13042 构造三次握手报文,通过原始套接字注入tap_client和tap_server

This commit is contained in:
luwenpeng
2022-12-20 14:00:46 +08:00
parent 42dded52ac
commit 7978e74321
6 changed files with 672 additions and 1 deletions

View File

@@ -0,0 +1,385 @@
#include <string.h>
#include <netinet/ip.h>
#include <netinet/ip6.h>
#include <netinet/tcp.h>
#include <netinet/ether.h>
/******************************************************************************
* Struct
******************************************************************************/
struct tcp_hdr
{
uint16_t src_port;
uint16_t dst_port;
uint32_t sent_seq;
uint32_t recv_ack;
uint8_t data_off;
uint8_t flags;
uint16_t rx_window;
uint16_t checksum;
uint16_t urgent_ptr;
} __attribute__((__packed__));
struct vlan_hdr
{
uint16_t vlan_tci; // Priority (3) + CFI (1) + Identifier Code (12)
uint16_t eth_proto; // Ethernet type of encapsulated frame
} __attribute__((__packed__));
/******************************************************************************
* CheckSum
******************************************************************************/
static uint16_t ipv4_checksum(const struct iphdr *ipv4_hdr, uint16_t hdr_len)
{
uint32_t sum = 0;
const uint16_t *ip1 = (const uint16_t *)ipv4_hdr;
while (hdr_len > 1)
{
sum += *ip1++;
if (sum & 0x80000000)
{
sum = (sum & 0xFFFF) + (sum >> 16);
}
hdr_len -= 2;
}
while (sum >> 16)
{
sum = (sum & 0xFFFF) + (sum >> 16);
}
return (~sum);
}
static uint16_t tcp_checksum_v4(const void *l4_hdr, uint16_t l4_len, struct in_addr *src_addr, struct in_addr *dst_addr)
{
uint16_t *ip_src = (uint16_t *)src_addr;
uint16_t *ip_dst = (uint16_t *)dst_addr;
const uint16_t *buffer = (u_int16_t *)l4_hdr;
uint32_t sum = 0;
size_t len = l4_len;
while (len > 1)
{
sum += *buffer++;
if (sum & 0x80000000)
{
sum = (sum & 0xFFFF) + (sum >> 16);
}
len -= 2;
}
if (len & 1)
{
sum += *((uint8_t *)buffer);
}
sum += *(ip_src++);
sum += *ip_src;
sum += *(ip_dst++);
sum += *ip_dst;
sum += htons(IPPROTO_TCP);
sum += htons(l4_len);
while (sum >> 16)
{
sum = (sum & 0xFFFF) + (sum >> 16);
}
return ((uint16_t)(~sum));
}
static uint16_t tcp_checksum_v6(const void *l4_hdr, uint16_t l4_len, struct in6_addr *src_addr, struct in6_addr *dst_addr)
{
uint16_t *ip_src = (uint16_t *)src_addr;
uint16_t *ip_dst = (uint16_t *)dst_addr;
const uint16_t *buffer = (u_int16_t *)l4_hdr;
uint32_t sum = 0;
size_t len = l4_len;
while (len > 1)
{
sum += *buffer++;
if (sum & 0x80000000)
{
sum = (sum & 0xFFFF) + (sum >> 16);
}
len -= 2;
}
if (len & 1)
{
sum += *((uint8_t *)buffer);
}
for (int i = 0; i < 8; i++)
{
sum += *ip_src;
ip_src++;
}
for (int i = 0; i < 8; i++)
{
sum += *ip_dst;
ip_dst++;
}
sum += htons(IPPROTO_TCP);
sum += htons(l4_len);
while (sum >> 16)
{
sum = (sum & 0xFFFF) + (sum >> 16);
}
return ((uint16_t)(~sum));
}
/******************************************************************************
* TCP header
******************************************************************************/
/*
* TCP Header Format
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Source Port | Destination Port |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Sequence Number |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Acknowledgment Number |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Data | |U|A|P|R|S|F| |
* | Offset| Reserved |R|C|S|S|Y|I| Window |
* | | |G|K|H|T|N|N| |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Checksum | Urgent Pointer |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Options | Padding |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | data |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
int tcp_header_construct(char *buffer, uint16_t src_port, uint16_t dst_port, uint32_t seq, uint32_t ack, u_char flags, uint16_t window, uint16_t urgent)
{
struct tcp_hdr *tcp_hdr = (struct tcp_hdr *)buffer;
tcp_hdr->src_port = src_port;
tcp_hdr->dst_port = dst_port;
tcp_hdr->sent_seq = htonl(seq);
tcp_hdr->recv_ack = htonl(ack);
tcp_hdr->data_off = 0x50;
tcp_hdr->flags = flags;
tcp_hdr->rx_window = htons(window);
tcp_hdr->checksum = 0;
tcp_hdr->urgent_ptr = urgent;
return sizeof(struct tcp_hdr);
}
/******************************************************************************
* IPv4 header
******************************************************************************/
/*
* Internet Header Format
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |Version| IHL |Type of Service| Total Length |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Identification |Flags| Fragment Offset |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Time to Live | Protocol | Header Checksum |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Source Address |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Destination Address |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Options | Padding |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
int ipv4_header_construct(char *buffer, uint16_t carry_layer_len, struct in_addr *src_addr, struct in_addr *dst_addr, u_char tos, uint16_t id, uint16_t frag, u_char ttl, u_char protocol)
{
struct iphdr *ip_hdr = (struct iphdr *)buffer;
ip_hdr->version = 4;
ip_hdr->ihl = 5;
ip_hdr->tos = tos;
ip_hdr->tot_len = htons(sizeof(struct iphdr) + carry_layer_len);
ip_hdr->id = htons(id);
ip_hdr->frag_off = 0;
ip_hdr->ttl = ttl;
ip_hdr->protocol = protocol;
ip_hdr->check = 0;
ip_hdr->saddr = *(uint32_t *)src_addr;
ip_hdr->daddr = *(uint32_t *)dst_addr;
ip_hdr->check = ipv4_checksum(ip_hdr, sizeof(struct iphdr));
return sizeof(struct iphdr);
}
/******************************************************************************
* IPv6 header
******************************************************************************/
/*
* IPv6 Header Format
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |Version| Traffic Class | Flow Label |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Payload Length | Next Header | Hop Limit |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* + +
* | |
* + Source Address +
* | |
* + +
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* + +
* | |
* + Destination Address +
* | |
* + +
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
int ipv6_header_construct(char *buffer, uint16_t carry_layer_len, struct in6_addr *src_addr, struct in6_addr *dst_addr, u_char ttl, u_char protocol)
{
struct ip6_hdr *ip6_hdr = (struct ip6_hdr *)buffer;
ip6_hdr->ip6_flow = 0;
ip6_hdr->ip6_plen = htons(carry_layer_len);
ip6_hdr->ip6_nxt = protocol;
ip6_hdr->ip6_hlim = ttl;
ip6_hdr->ip6_vfc &= 0x0F;
ip6_hdr->ip6_vfc |= (6U << 4U);
ip6_hdr->ip6_src = *src_addr;
ip6_hdr->ip6_dst = *dst_addr;
return sizeof(struct ip6_hdr);
}
/******************************************************************************
* Vlan header
******************************************************************************/
int vlan_header_construct(char *buffer, uint16_t tci, uint16_t type)
{
struct vlan_hdr *vlan_hdr = (struct vlan_hdr *)buffer;
vlan_hdr->vlan_tci = htons(tci);
vlan_hdr->eth_proto = htons(type);
return sizeof(struct vlan_hdr);
}
/******************************************************************************
* Ether header
******************************************************************************/
int ether_header_construct(char *buffer, struct ether_addr *src_mac, struct ether_addr *dst_mac, uint16_t type)
{
struct ethhdr *eth_hdr = (struct ethhdr *)buffer;
memcpy(eth_hdr->h_dest, (u_char *)dst_mac, ETHER_ADDR_LEN);
memcpy(eth_hdr->h_source, (u_char *)src_mac, ETHER_ADDR_LEN);
eth_hdr->h_proto = htons(type);
return sizeof(struct ethhdr);
}
/******************************************************************************
* Build Ether + IPv4 + TCP Packet
******************************************************************************/
int tcp_packet_v4_construct(
char *buffer, // buffer
struct ether_addr *src_mac, struct ether_addr *dst_mac, uint16_t vlan_tci, uint16_t l3_protocol, // Ether
struct in_addr *src_addr, struct in_addr *dst_addr, u_char tos, u_char ttl, uint16_t id, // IPv4
uint16_t src_port, uint16_t dst_port, uint32_t seq, uint32_t ack, u_char flags, uint16_t window, // TCP
const char *payload, uint16_t payload_len) // APP
{
uint16_t length = 0;
// Ethernet header
uint16_t eth_protocol = vlan_tci > 0 ? ETH_P_8021Q : l3_protocol;
length += ether_header_construct(buffer + length, src_mac, dst_mac, eth_protocol);
// VLAN header
if (vlan_tci > 0)
{
length += vlan_header_construct(buffer + length, vlan_tci, l3_protocol);
}
// IPv4 Header
u_char protocol = IPPROTO_TCP;
uint16_t frag = 0;
length += ipv4_header_construct(buffer + length, payload_len + sizeof(struct tcphdr), src_addr, dst_addr, tos, id, frag, ttl, protocol);
// TCP header and payload
uint16_t urgent = 0;
struct tcp_hdr *tcp_hdr = (struct tcp_hdr *)(buffer + length);
length += tcp_header_construct((char *)tcp_hdr, src_port, dst_port, seq, ack, flags, window, urgent);
memcpy(buffer + length, payload, payload_len);
length += payload_len;
tcp_hdr->checksum = tcp_checksum_v4((void *)tcp_hdr, sizeof(struct tcp_hdr) + payload_len, src_addr, dst_addr);
return length;
}
/******************************************************************************
* Build Ether + IPv6 + TCP Packet
******************************************************************************/
int tcp_packet_v6_construct(
char *buffer, // buffer
struct ether_addr *src_mac, struct ether_addr *dst_mac, uint16_t vlan_tci, uint16_t l3_protocol, // Ether
struct in6_addr *src_addr, struct in6_addr *dst_addr, u_char ttl, // IPv6
uint16_t src_port, uint16_t dst_port, uint32_t seq, uint32_t ack, u_char flags, uint16_t window, // TCP
const char *payload, uint16_t payload_len) // APP
{
uint16_t length = 0;
// Ethernet header
uint16_t eth_protocol = vlan_tci > 0 ? ETH_P_8021Q : l3_protocol;
length += ether_header_construct(buffer + length, src_mac, dst_mac, eth_protocol);
// VLAN header
if (vlan_tci > 0)
{
length += vlan_header_construct(buffer + length, vlan_tci, l3_protocol);
}
// IPv6 Header
u_char protocol = IPPROTO_TCP;
length += ipv6_header_construct(buffer + length, payload_len + sizeof(struct tcphdr), src_addr, dst_addr, ttl, protocol);
// TCP header and payload
uint16_t urgent = 0;
struct tcp_hdr *tcp_hdr = (struct tcp_hdr *)(buffer + length);
length += tcp_header_construct((char *)tcp_hdr, src_port, dst_port, seq, ack, flags, window, urgent);
memcpy(buffer + length, payload, payload_len);
length += payload_len;
tcp_hdr->checksum = tcp_checksum_v6((void *)tcp_hdr, sizeof(struct tcp_hdr) + payload_len, src_addr, dst_addr);
return length;
}

101
common/src/raw_socket.cpp Normal file
View File

@@ -0,0 +1,101 @@
#include <stdio.h>
#include <arpa/inet.h>
#include <netinet/ether.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <sys/socket.h>
#include <linux/if_packet.h>
#include <net/ethernet.h>
#include <stdlib.h>
#include <unistd.h>
#include <pcap/pcap.h>
#include "raw_socket.h"
#include "packet_construct.h"
void raw_socket_destory(struct raw_socket *raw)
{
if (raw)
{
if (raw->sockfd)
{
close(raw->sockfd);
}
free(raw);
raw = NULL;
}
}
struct raw_socket *raw_socket_create(const char *interface, int fd_so_mask)
{
struct ifreq ifr = {0};
struct raw_socket *raw = (struct raw_socket *)calloc(1, sizeof(struct raw_socket));
memcpy(raw->interface, interface, strlen(interface));
raw->sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (raw->sockfd < 0)
{
printf("socket() failed, (%d: %s)", errno, strerror(errno));
goto error;
}
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", raw->interface);
if (ioctl(raw->sockfd, SIOCGIFHWADDR, &ifr) < 0)
{
printf("ioctl(SIOCGIFHWADDR) failed, (%d: %s)", errno, strerror(errno));
goto error;
}
memcpy(&(raw->mac_addr), ifr.ifr_hwaddr.sa_data, 6);
raw->sockaddr.sll_ifindex = if_nametoindex(interface);
if (raw->sockaddr.sll_ifindex == 0)
{
printf("if_nametoindex() failed, (%d: %s)", errno, strerror(errno));
goto error;
}
raw->sockaddr.sll_family = AF_PACKET;
memcpy((void *)&(raw->sockaddr.sll_addr), (void *)&(raw->mac_addr), 6);
raw->sockaddr.sll_halen = 6;
if (setsockopt(raw->sockfd, SOL_SOCKET, SO_MARK, (char *)&fd_so_mask, sizeof(fd_so_mask)) < 0)
{
printf("setsockopt(SO_MARK) failed, (%d: %s)", errno, strerror(errno));
goto error;
}
return raw;
error:
raw_socket_destory(raw);
return NULL;
}
int raw_socket_send(struct raw_socket *raw, const char *data, int data_len)
{
int ret = sendto(raw->sockfd, data, data_len, 0, (struct sockaddr *)&raw->sockaddr, sizeof(raw->sockaddr));
if (ret < 0)
{
printf("sendto() failed, (%d: %s)", errno, strerror(errno));
}
return ret;
}
int raw_socket_recv(struct raw_socket *raw, char *buff, int buff_size)
{
socklen_t addr_len = sizeof(raw->sockaddr);
int ret = recvfrom(raw->sockfd, buff, buff_size, 0, (struct sockaddr *)&raw->sockaddr, &addr_len);
if (ret < 0)
{
printf("sendto() failed, (%d: %s)", errno, strerror(errno));
}
return ret;
}