diff --git a/common/include/packet_construct.h b/common/include/packet_construct.h index 16ca00d..8d30b02 100644 --- a/common/include/packet_construct.h +++ b/common/include/packet_construct.h @@ -17,25 +17,27 @@ extern "C" #define TCP_FIN_FLAG 0x01 #define TCP_FLAG_ALL 0x3F - 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); - 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); - 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); - int vlan_header_construct(char *buffer, uint16_t tci, uint16_t type); - int ether_header_construct(char *buffer, struct ether_addr *src_mac, struct ether_addr *dst_mac, uint16_t type); +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, const char *options, uint16_t options_len); +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); +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); +int vlan_header_construct(char *buffer, uint16_t tci, uint16_t type); +int ether_header_construct(char *buffer, struct ether_addr *src_mac, struct ether_addr *dst_mac, uint16_t type); - 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); +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 Header + const char *tcp_options, uint16_t tcp_options_len, // TCP Options + const char *payload, uint16_t payload_len); // Payload - 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); +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 Header + const char *tcp_options, uint16_t tcp_options_len, // TCP Options + const char *payload, uint16_t payload_len); // Payload #ifdef __cpluscplus } diff --git a/common/src/packet_construct.cpp b/common/src/packet_construct.cpp index 2ee24cf..6e17fa9 100644 --- a/common/src/packet_construct.cpp +++ b/common/src/packet_construct.cpp @@ -167,7 +167,7 @@ static uint16_t tcp_checksum_v6(const void *l4_hdr, uint16_t l4_len, struct in6_ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ -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) +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, const char *options, uint16_t options_len) { struct tcp_hdr *tcp_hdr = (struct tcp_hdr *)buffer; @@ -175,13 +175,14 @@ int tcp_header_construct(char *buffer, uint16_t src_port, uint16_t dst_port, uin 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->data_off = (sizeof(struct tcp_hdr) + options_len) << 2; tcp_hdr->flags = flags; tcp_hdr->rx_window = htons(window); tcp_hdr->checksum = 0; tcp_hdr->urgent_ptr = urgent; + memcpy(buffer + sizeof(struct tcp_hdr), options, options_len); - return sizeof(struct tcp_hdr); + return sizeof(struct tcp_hdr) + options_len; } /****************************************************************************** @@ -312,11 +313,12 @@ int ether_header_construct(char *buffer, struct ether_addr *src_mac, struct ethe ******************************************************************************/ int tcp_packet_v4_construct( - char *buffer, // buffer + 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 + 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 Header + const char *tcp_options, uint16_t tcp_options_len, // TCP Options + const char *payload, uint16_t payload_len) // Payload { uint16_t length = 0; @@ -333,15 +335,15 @@ int tcp_packet_v4_construct( // 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); + length += ipv4_header_construct(buffer + length, sizeof(struct tcphdr) + tcp_options_len + payload_len, 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); + length += tcp_header_construct((char *)tcp_hdr, src_port, dst_port, seq, ack, flags, window, urgent, tcp_options, tcp_options_len); 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); + tcp_hdr->checksum = tcp_checksum_v4((void *)tcp_hdr, sizeof(struct tcp_hdr) + tcp_options_len + payload_len, src_addr, dst_addr); return length; } @@ -351,11 +353,12 @@ int tcp_packet_v4_construct( ******************************************************************************/ int tcp_packet_v6_construct( - char *buffer, // buffer + 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 + 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 Header + const char *tcp_options, uint16_t tcp_options_len, // TCP Options + const char *payload, uint16_t payload_len) // Payload { uint16_t length = 0; @@ -371,15 +374,15 @@ int tcp_packet_v6_construct( // IPv6 Header u_char protocol = IPPROTO_TCP; - length += ipv6_header_construct(buffer + length, payload_len + sizeof(struct tcphdr), src_addr, dst_addr, ttl, protocol); + length += ipv6_header_construct(buffer + length, sizeof(struct tcphdr) + tcp_options_len + payload_len, 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); + length += tcp_header_construct((char *)tcp_hdr, src_port, dst_port, seq, ack, flags, window, urgent, tcp_options, tcp_options_len); 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); + tcp_hdr->checksum = tcp_checksum_v6((void *)tcp_hdr, sizeof(struct tcp_hdr) + tcp_options_len + payload_len, src_addr, dst_addr); return length; } diff --git a/platform/src/acceptor_kni_v3.cpp b/platform/src/acceptor_kni_v3.cpp index ced9511..512cc71 100644 --- a/platform/src/acceptor_kni_v3.cpp +++ b/platform/src/acceptor_kni_v3.cpp @@ -278,11 +278,23 @@ static void tcp_restore_info_parse_from_pkt(struct pkt_info *pktinfo, struct tcp } } +struct tcp_option_window_scale{ + uint8_t kind; + uint8_t length; + uint8_t shift_count; +}; + static int fake_tcp_handshake(struct tfe_proxy *proxy, struct tcp_restore_info *restore_info) { char buffer[1500] = {0}; int length = 0; + char tcp_option_buffer_c[40] = {0}; + char tcp_option_buffer_s[40] = {0}; + int tcp_option_length_c = 0; + int tcp_option_length_s = 0; + int options_padding_size = 0; + const struct tcp_restore_endpoint *client = &restore_info->client; const struct tcp_restore_endpoint *server = &restore_info->server; struct raw_socket *raw_socket_c = raw_socket_create(proxy->traffic_steering_options.device_client, proxy->traffic_steering_options.so_mask_client); @@ -298,6 +310,34 @@ static int fake_tcp_handshake(struct tfe_proxy *proxy, struct tcp_restore_info * uint32_t c_seq = client->seq - 1; uint32_t s_seq = server->seq - 1; + /* + * Window Scale option (WSopt): Kind: 3, Length: 3 + * +---------+---------+---------+ + * | Kind=3 |Length=3 |shift.cnt| + * +---------+---------+---------+ + * 1 1 1 + */ + if (client->wscale_perm && server->wscale_perm) + { + // padding + memset(tcp_option_buffer_c + tcp_option_length_c, 1, 1); + tcp_option_length_c += 1; + memset(tcp_option_buffer_s + tcp_option_length_s, 1, 1); + tcp_option_length_s += 1; + + struct tcp_option_window_scale *option_c = (struct tcp_option_window_scale *)(tcp_option_buffer_c + tcp_option_length_c); + option_c->kind = 3; + option_c->length = 3; + option_c->shift_count = client->wscale; + tcp_option_length_c += sizeof(struct tcp_option_window_scale); + + struct tcp_option_window_scale *option_s = (struct tcp_option_window_scale *)(tcp_option_buffer_s + tcp_option_length_s); + option_s->kind = 3; + option_s->length = 3; + option_s->shift_count = server->wscale; + tcp_option_length_s += sizeof(struct tcp_option_window_scale); + } + if (client->addr.ss_family == AF_INET6) { struct sockaddr_in6 *sk_client = (struct sockaddr_in6 *)&client->addr; @@ -307,31 +347,34 @@ static int fake_tcp_handshake(struct tfe_proxy *proxy, struct tcp_restore_info * // C -> S length = tcp_packet_v6_construct( - buffer, // buffer - &raw_socket_c->mac_addr, &raw_socket_s->mac_addr, 0, ETH_P_IPV6, // Ether - &sk_client->sin6_addr, &sk_server->sin6_addr, 55, // IPv6 - port_client, port_server, c_seq, s_seq, TCP_SYN_FLAG, client->window, // TCP - NULL, 0); + buffer, // buffer + &raw_socket_c->mac_addr, &raw_socket_s->mac_addr, 0, ETH_P_IPV6, // Ether + &sk_client->sin6_addr, &sk_server->sin6_addr, 55, // IPv6 + port_client, port_server, c_seq, 0, TCP_SYN_FLAG, client->window, // TCP Header + tcp_option_buffer_c, tcp_option_length_c, // TCP Options + NULL, 0); // Payload raw_socket_send(raw_socket_c, buffer, length); c_seq += 1; // S -> C length = tcp_packet_v6_construct( - buffer, // buffer - &raw_socket_s->mac_addr, &raw_socket_c->mac_addr, 0, ETH_P_IPV6, // Ether - &sk_server->sin6_addr, &sk_client->sin6_addr, 65, // IPv6 - port_server, port_client, s_seq, c_seq, TCP_SYN_FLAG | TCP_ACK_FLAG, server->window, // TCP - NULL, 0); + buffer, // buffer + &raw_socket_s->mac_addr, &raw_socket_c->mac_addr, 0, ETH_P_IPV6, // Ether + &sk_server->sin6_addr, &sk_client->sin6_addr, 65, // IPv6 + port_server, port_client, s_seq, c_seq, TCP_SYN_FLAG | TCP_ACK_FLAG, server->window, // TCP Header + tcp_option_buffer_s, tcp_option_length_s, // TCP Options + NULL, 0); // Payload raw_socket_send(raw_socket_s, buffer, length); s_seq += 1; // C -> S length = tcp_packet_v6_construct( - buffer, // buffer - &raw_socket_c->mac_addr, &raw_socket_s->mac_addr, 0, ETH_P_IPV6, // Ether - &sk_client->sin6_addr, &sk_server->sin6_addr, 55, // IPv6 - port_client, port_server, c_seq, s_seq, TCP_SYN_FLAG, client->window, // TCP - NULL, 0); + buffer, // buffer + &raw_socket_c->mac_addr, &raw_socket_s->mac_addr, 0, ETH_P_IPV6, // Ether + &sk_client->sin6_addr, &sk_server->sin6_addr, 55, // IPv6 + port_client, port_server, c_seq, s_seq, TCP_SYN_FLAG, client->window, // TCP Header + NULL, 0, // TCP Options + NULL, 0); // Payload raw_socket_send(raw_socket_c, buffer, length); } else @@ -346,7 +389,8 @@ static int fake_tcp_handshake(struct tfe_proxy *proxy, struct tcp_restore_info * buffer, // buffer &raw_socket_c->mac_addr, &raw_socket_s->mac_addr, 0, ETH_P_IP, // Ether &sk_client->sin_addr, &sk_server->sin_addr, 0, 55, 0x11, // IPv4 - port_client, port_server, c_seq, s_seq, TCP_SYN_FLAG, client->window, // TCP + port_client, port_server, c_seq, 0, TCP_SYN_FLAG, client->window, // TCP Header + tcp_option_buffer_c, tcp_option_length_c, // TCP Options NULL, 0); raw_socket_send(raw_socket_c, buffer, length); c_seq += 1; @@ -356,17 +400,19 @@ static int fake_tcp_handshake(struct tfe_proxy *proxy, struct tcp_restore_info * buffer, // buffer &raw_socket_s->mac_addr, &raw_socket_c->mac_addr, 0, ETH_P_IP, // Ether &sk_server->sin_addr,&sk_client->sin_addr, 0, 65, 0x12, // IPv4 - port_server, port_client, s_seq, c_seq, TCP_SYN_FLAG | TCP_ACK_FLAG, server->window, // TCP + port_server, port_client, s_seq, c_seq, TCP_SYN_FLAG | TCP_ACK_FLAG, server->window, // TCP Header + tcp_option_buffer_s, tcp_option_length_s, // TCP Options NULL, 0); raw_socket_send(raw_socket_s, buffer, length); s_seq += 1; // C -> S length = tcp_packet_v4_construct( - buffer, // buffer - &raw_socket_c->mac_addr, &raw_socket_s->mac_addr, 0, ETH_P_IP, // Ether - &sk_client->sin_addr, &sk_server->sin_addr, 0, 55, 0x13, // IPv4 - port_client, port_server, c_seq, s_seq, TCP_ACK_FLAG, client->window, // TCP + buffer, // buffer + &raw_socket_c->mac_addr, &raw_socket_s->mac_addr, 0, ETH_P_IP, // Ether + &sk_client->sin_addr, &sk_server->sin_addr, 0, 55, 0x13, // IPv4 + port_client, port_server, c_seq, s_seq, TCP_ACK_FLAG, client->window, // TCP Header + NULL, 0, // TCP Options NULL, 0); raw_socket_send(raw_socket_c, buffer, length); }