Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support TCP SPA feature #515

Open
wants to merge 3 commits into
base: unified
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions common.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@ extern int force_socket_buf;

extern int g_fix_gro;

extern int g_tcp_spa;

/*
struct ip_port_t
{
Expand Down
1 change: 1 addition & 0 deletions git_version.h
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
const char *gitversion = "e42f0e573221c5e0146c02fd5d71f32aa93c7221";
8 changes: 7 additions & 1 deletion misc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,9 @@ void print_help() {
printf(" --disable-anti-replay disable anti-replay,not suggested\n");
printf(" --fix-gro try to fix huge packet caused by GRO. this option is at an early stage.\n");
printf(" make sure client and server are at same version.\n");

printf(" --tcp-spa TCP SPA mode to avoid port scanning.\n");
printf(" when enable on server mode, will check SYN's option.\n");

// printf("\n");
printf("client options:\n");
printf(" --source-ip <ip> force source-ip for raw socket\n");
Expand Down Expand Up @@ -296,6 +298,7 @@ void process_arg(int argc, char *argv[]) // process all options
{"no-pcap-mutex", no_argument, 0, 1},
#endif
{"fix-gro", no_argument, 0, 1},
{"tcp-spa", no_argument, 0, 1},
{NULL, 0, 0, 0}};

process_log_level(argc, argv);
Expand Down Expand Up @@ -677,6 +680,9 @@ void process_arg(int argc, char *argv[]) // process all options
} else if (strcmp(long_options[option_index].name, "fix-gro") == 0) {
mylog(log_info, "--fix-gro enabled\n");
g_fix_gro = 1;
} else if (strcmp(long_options[option_index].name, "tcp-spa") == 0) {
mylog(log_info, "--tcp-spa enabled\n");
g_tcp_spa = 1;
} else {
mylog(log_warn, "ignored unknown long option ,option_index:%d code:<%x>\n", option_index, optopt);
}
Expand Down
71 changes: 70 additions & 1 deletion network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,40 @@ tcpdump -i eth1 ip and icmp -dd
*/
#endif

//tcp option for SPA
int g_tcp_spa = 0;
typedef struct tcpopt_data {
uint8_t opcode;
uint8_t opsize;
uint16_t reserve;
uint32_t csum;
}tcpopt_data_t;

#define TCPOPT_SPA 233

#define HASH_PRIME 16777619
#define HASH_OFFSET 2166136261U

//FNV-1a from GPT
uint32_t checksum(uint32_t timestamp, const char* key) {
uint32_t hash = HASH_OFFSET;
const char* ptr = key;
size_t key_len = strlen(key);

for (size_t i = 0; i < key_len; i++) {
hash ^= (uint32_t)ptr[i];
hash *= HASH_PRIME;
}

for (uint32_t i = 0; i < sizeof(uint32_t); i++) {
hash ^= (uint32_t)(timestamp & 0xFF);
hash *= HASH_PRIME;
timestamp >>= 8;
}
return hash;
}
//--------------

packet_info_t::packet_info_t() {
src_port = 0;
dst_port = 0;
Expand Down Expand Up @@ -1679,6 +1713,16 @@ int send_raw_tcp(raw_info_t &raw_info, const char *payload, int payloadlen) { /
send_raw_tcp_buf[i++] = 0x03;
send_raw_tcp_buf[i++] = 0x03;
send_raw_tcp_buf[i++] = wscale;

if(g_tcp_spa && tcph->ack == 0) {
tcph->doff = 12;
tcpopt_data_t opt = {TCPOPT_SPA, sizeof(tcpopt_data_t), 0, 0};
uint32_t csum = checksum(ts, key_string);
opt.csum = htonl(csum);
memcpy(&send_raw_tcp_buf[i], &opt, opt.opsize);
i += opt.opsize;
}

} else {
tcph->doff = 8;
int i = sizeof(my_tcphdr);
Expand Down Expand Up @@ -2113,6 +2157,8 @@ int parse_tcp_option(char *option_begin, char *option_end, packet_info_t &recv_i
recv_info.has_ts = 0;
recv_info.ts = 0;

tcpopt_data_t *opt = NULL;

char *ptr = option_begin;
// char *option_end=tcp_begin+tcp_hdr_len;
while (ptr < option_end) {
Expand Down Expand Up @@ -2143,6 +2189,14 @@ int parse_tcp_option(char *option_begin, char *option_end, packet_info_t &recv_i

// return 0;//we currently only parse ts, so just return after its found
ptr += 10;
} else if (recv_info.syn == 1 && recv_info.ack == 0
&& g_tcp_spa && (unsigned char)*ptr == TCPOPT_SPA) {
if (ptr + sizeof(tcpopt_data_t) > option_end) {
mylog(log_trace, "ptr+8>option_end for TCPOPT_SPA\n");
return -2;
}
opt = (tcpopt_data_t*)ptr;
ptr += sizeof(tcpopt_data_t);
} else {
if (ptr + 1 >= option_end) {
mylog(log_trace, "invaild option ptr+1==option_end\n");
Expand All @@ -2160,7 +2214,18 @@ int parse_tcp_option(char *option_begin, char *option_end, packet_info_t &recv_i
// printf("!");
}
// printf("\n");
if(recv_info.syn == 1 && recv_info.ack == 0 && g_tcp_spa) {
if(opt == NULL) {
mylog(log_trace, "No found spa opt, pkt drop\n");
return -2;
}

uint32_t csum = checksum(htonl(recv_info.ts), key_string);
if(opt->csum != htonl(csum)){
mylog(log_trace, "SPA csum match failed\n");
return -2;
}
}
return 0;
}
int recv_raw_tcp(raw_info_t &raw_info, char *&payload, int &payloadlen) {
Expand Down Expand Up @@ -2294,7 +2359,8 @@ int recv_raw_tcp(raw_info_t &raw_info, char *&payload, int &payloadlen) {
}
printf("<%d %d>\n",recv_info.ts,recv_info.ts_ack);
*/
parse_tcp_option(tcp_option, option_end, recv_info);

//parse_tcp_option(tcp_option, option_end, recv_info);

recv_info.ack = tcph->ack;
recv_info.syn = tcph->syn;
Expand All @@ -2304,6 +2370,9 @@ int recv_raw_tcp(raw_info_t &raw_info, char *&payload, int &payloadlen) {

recv_info.seq = ntohl(tcph->seq);

if(-2 == parse_tcp_option(tcp_option, option_end, recv_info))
return -1;

// recv_info.last_last_ack_seq=recv_info.last_ack_seq;
// recv_info.last_ack_seq=recv_info.ack_seq;
u32_t last_ack_seq = recv_info.ack_seq;
Expand Down
Binary file added udp2raw
Binary file not shown.