修正解密流量转发中重建TCP流部分序列号错误的问题。

This commit is contained in:
luqiuwen
2019-06-09 14:53:17 +08:00
committed by zhengchao
parent d5c54b96a7
commit f518ebfa00
3 changed files with 95 additions and 37 deletions

View File

@@ -6,16 +6,14 @@
struct traffic_mirror_rebuild
{
struct tfe_stream_addr * addr;
struct tfe_stream_addr * c_s_addr;
struct tfe_stream_addr * s_c_addr;
struct profile_table_ex_data * target;
struct traffic_mirror_ethdev * ethdev;
uint32_t c_seq;
uint32_t s_seq;
uint32_t c_ipid;
uint32_t s_ipid;
uint8_t c_ttl;
uint8_t s_ttl;
};
/* The definition of vlan_hdr and tcp_hdr is from DPDK 17.05 */
@@ -56,7 +54,7 @@ static int tcp_header_construct(unsigned char *buf, unsigned short sp,
tcp_hdr->dst_port = dp;
tcp_hdr->sent_seq = htonl(seq);
tcp_hdr->recv_ack = htonl(ack);
tcp_hdr->data_off = 5;
tcp_hdr->data_off = 0x50;
tcp_hdr->tcp_flags = flags;
tcp_hdr->rx_win = htons(win);
tcp_hdr->cksum = 0;
@@ -188,24 +186,25 @@ static void tcp_segment_send_to_target_group(struct tfe_stream_addr * addr, stru
unsigned int seq, unsigned int ack, char flags)
{
char pkt[ETHER_MAX_LEN];
unsigned sz_pkt_prepend = sizeof(struct ethhdr) + sizeof(struct vlan_hdr) + sizeof(struct iphdr) + sizeof(struct tcphdr);
unsigned l3_l4_header_len = 0;
unsigned sz_pkt_prepend = sizeof(struct ethhdr) + sizeof(struct vlan_hdr) +
sizeof(struct iphdr) + sizeof(struct tcphdr);
unsigned header_len = 0;
header_len = tcp_header_construct_by_stream_addr(addr,
(unsigned char *)pkt + sz_pkt_prepend, seq, ack, flags, 0xffff, 0);
assert(sizeof(pkt) - sz_pkt_prepend >= payload_len);
memcpy(pkt + sz_pkt_prepend, payload, payload_len);
sz_pkt_prepend -= header_len;
l3_l4_header_len += header_len;
sz_pkt_prepend -= sizeof(struct tcp_hdr);
header_len += tcp_header_construct_by_stream_addr(addr, (unsigned char *)pkt + sz_pkt_prepend,
seq, ack, flags, 0xffff, 0);
header_len = ip_header_construct_by_stream_addr(addr, (unsigned char *)pkt + sz_pkt_prepend,
sizeof(struct tcphdr) + payload_len, 0, 0x1000, 0, 128, IPPROTO_TCP);
sz_pkt_prepend -= header_len;
l3_l4_header_len += header_len;
sz_pkt_prepend -= sizeof(struct iphdr);
header_len += ip_header_construct_by_stream_addr(addr, (unsigned char *)pkt + sz_pkt_prepend,
header_len + payload_len, 0, 0x1000, 0, 128, IPPROTO_TCP);
l2_send_to_target_group(ethdev, t_group, (unsigned char *)pkt, sz_pkt_prepend,
l3_l4_header_len + payload_len, ETHERTYPE_IP);
header_len + payload_len, ETHERTYPE_IP);
}
static void tcp_send_to_target_group(struct tfe_stream_addr * addr, struct traffic_mirror_ethdev * ethdev,
@@ -215,16 +214,21 @@ static void tcp_send_to_target_group(struct tfe_stream_addr * addr, struct traff
unsigned int payload_offset = 0;
unsigned mss = ethdev->mtu - (sizeof(struct iphdr) + sizeof(struct tcphdr));
while(payload_offset <= payload_len)
/* Handshake or farewall */
if (payload == NULL || payload_len == 0)
{
unsigned int payload_sz_seg = MIN(payload_offset, mss);
tcp_segment_send_to_target_group(addr, ethdev, t_group, NULL, 0, seq, ack, flags);
return;
}
while(payload_offset < payload_len)
{
unsigned int payload_sz_seg = MIN(payload_len - payload_offset, mss);
const char * payload_ptr_seg = payload + payload_offset;
tcp_segment_send_to_target_group(addr, ethdev, t_group, payload_ptr_seg, payload_sz_seg, seq, ack, flags);
seq += payload_sz_seg;
payload_offset += payload_sz_seg;
if (payload_sz_seg == 0) break;
}
}
@@ -232,7 +236,8 @@ struct traffic_mirror_rebuild * traffic_mirror_rebuild_create(struct tfe_stream_
struct profile_table_ex_data * target, struct traffic_mirror_ethdev * ethdev)
{
struct traffic_mirror_rebuild * instance = ALLOC(struct traffic_mirror_rebuild, 1);
instance->addr = addr;
instance->c_s_addr = addr;
instance->s_c_addr = tfe_stream_addr_reverse(addr);
instance->target = target;
instance->ethdev = ethdev;
@@ -240,27 +245,24 @@ struct traffic_mirror_rebuild * traffic_mirror_rebuild_create(struct tfe_stream_
* TODO: use the fast random algorithm like Linux TCP/IP stack */
instance->c_seq = random();
instance->s_seq = random();
instance->c_ipid = random();
instance->s_ipid = random();
instance->s_ttl = 128;
instance->c_ttl = 64;
return instance;
}
void traffic_mirror_rebuild_destroy(struct traffic_mirror_rebuild * instance)
{
tfe_stream_addr_free(instance->s_c_addr);
free(instance);
}
void traffic_mirror_rebuild_handshake(struct traffic_mirror_rebuild * instance)
{
tcp_send_to_target_group(instance->addr, instance->ethdev, instance->target,
tcp_send_to_target_group(instance->c_s_addr, instance->ethdev, instance->target,
NULL, 0, instance->c_seq, 0, TCP_SYN_FLAG);
tcp_send_to_target_group(instance->addr, instance->ethdev, instance->target,
tcp_send_to_target_group(instance->s_c_addr, instance->ethdev, instance->target,
NULL, 0, instance->s_seq, instance->c_seq + 1, TCP_SYN_FLAG | TCP_ACK_FLAG);
tcp_send_to_target_group(instance->addr, instance->ethdev, instance->target,
tcp_send_to_target_group(instance->c_s_addr, instance->ethdev, instance->target,
NULL, 0, instance->c_seq + 1, instance->s_seq + 1, TCP_ACK_FLAG);
instance->s_seq++;
@@ -270,23 +272,44 @@ void traffic_mirror_rebuild_handshake(struct traffic_mirror_rebuild * instance)
void traffic_mirror_rebuild_data(struct traffic_mirror_rebuild * instance,
const char * data, unsigned int datalen, enum tfe_conn_dir dir)
{
if (data == NULL || datalen == 0)
{
return;
}
if (dir == CONN_DIR_DOWNSTREAM)
{
tcp_send_to_target_group(instance->addr, instance->ethdev, instance->target,
NULL, 0, instance->c_seq, instance->s_seq + 1, TCP_ACK_FLAG);
tcp_send_to_target_group(instance->c_s_addr, instance->ethdev, instance->target,
data, datalen, instance->c_seq, instance->s_seq, TCP_ACK_FLAG);
instance->c_seq += datalen;
}
else
{
tcp_send_to_target_group(instance->addr, instance->ethdev, instance->target,
NULL, 0, instance->s_seq, instance->c_seq + 1, TCP_ACK_FLAG);
tcp_send_to_target_group(instance->s_c_addr, instance->ethdev, instance->target,
data, datalen, instance->s_seq, instance->c_seq, TCP_ACK_FLAG);
instance->s_seq += datalen;
}
}
void traffic_mirror_rebuild_farewell(struct traffic_mirror_rebuild * instance)
{
return;
/* C->S FIN */
tcp_send_to_target_group(instance->c_s_addr, instance->ethdev, instance->target,
NULL, 0, instance->c_seq, instance->s_seq, TCP_FIN_FLAG | TCP_ACK_FLAG);
/* C->S FIN, ACK */
tcp_send_to_target_group(instance->s_c_addr, instance->ethdev, instance->target,
NULL, 0, instance->s_seq, instance->c_seq + 1, TCP_ACK_FLAG);
instance->c_seq += 1;
/* S->C FIN */
tcp_send_to_target_group(instance->s_c_addr, instance->ethdev, instance->target,
NULL, 0, instance->s_seq, instance->c_seq, TCP_FIN_FLAG | TCP_ACK_FLAG);
/* C->S FIN, ACK */
tcp_send_to_target_group(instance->c_s_addr, instance->ethdev, instance->target,
NULL, 0, instance->c_seq, instance->s_seq + 1, TCP_ACK_FLAG);
instance->s_seq += 1;
}