mirror of
https://github.com/wangyu-/udp2raw.git
synced 2025-09-16 04:04:27 +08:00
Compare commits
27 Commits
20180830.1
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
165cabb5a3 | ||
|
b51df0089e | ||
|
79bb28fd12 | ||
|
b3e06de4cb | ||
|
b03ae53df6 | ||
|
15c15d5bcb | ||
|
2f0328a41a | ||
|
779ebdd37a | ||
|
5340f0726e | ||
|
e95ee70351 | ||
|
5cc304a261 | ||
|
7636225414 | ||
|
f68c6e211d | ||
|
8c81f7673b | ||
|
c1dfd4e928 | ||
|
7e55b1e132 | ||
|
ee787e0d4a | ||
|
7d481d26b9 | ||
|
168ae1e2ae | ||
|
6230569bbb | ||
|
238e85a5e4 | ||
|
0137dba1fd | ||
|
b6f76827b0 | ||
|
66eb002528 | ||
|
b1f0498472 | ||
|
e5584c73be | ||
|
c855a14ae8 |
@@ -26,12 +26,12 @@ For Windows and MacOS users, use the udp2raw in [this repo](https://github.com/w
|
|||||||
### Send/Receive UDP Packets with ICMP/FakeTCP/UDP headers
|
### Send/Receive UDP Packets with ICMP/FakeTCP/UDP headers
|
||||||
ICMP/FakeTCP headers help you bypass UDP blocking, UDP QOS or improper UDP NAT behavior on some ISPs. In ICMP header mode,udp2raw works like an ICMP tunnel.
|
ICMP/FakeTCP headers help you bypass UDP blocking, UDP QOS or improper UDP NAT behavior on some ISPs. In ICMP header mode,udp2raw works like an ICMP tunnel.
|
||||||
|
|
||||||
UDP headers are also supported. In UDP header mode, it behaves just like a normal UDP tunnel, and you can just make use of the other features (such as encrytion, anti-replay, or connection stalization).
|
UDP headers are also supported. In UDP header mode, it behaves just like a normal UDP tunnel, and you can just make use of the other features (such as encryption, anti-replay, or connection stalization).
|
||||||
|
|
||||||
### Simulated TCP with Real-time/Out-of-Order Delivery
|
### Simulated TCP with Real-time/Out-of-Order Delivery
|
||||||
In FakeTCP header mode,udp2raw simulates 3-way handshake while establishing a connection,simulates seq and ack_seq while data transferring. It also simulates following TCP options: `MSS`, `sackOk`, `TS`, `TS_ack`, `wscale`.Firewalls will regard FakeTCP as a TCP connection, but its essentially UDP: it supports real-time/out-of-order delivery(just as normal UDP does), no congrestion control or re-transmission. So there wont be any TCP over TCP problem when using OpenVPN.
|
In FakeTCP header mode,udp2raw simulates 3-way handshake while establishing a connection,simulates seq and ack_seq while data transferring. It also simulates following TCP options: `MSS`, `sackOk`, `TS`, `TS_ack`, `wscale`.Firewalls will regard FakeTCP as a TCP connection, but its essentially UDP: it supports real-time/out-of-order delivery(just as normal UDP does), no congestion control or re-transmission. So there wont be any TCP over TCP problem when using OpenVPN.
|
||||||
|
|
||||||
### Encrpytion, Anti-Replay
|
### Encryption, Anti-Replay
|
||||||
* Encrypt your traffic with AES-128-CBC.
|
* Encrypt your traffic with AES-128-CBC.
|
||||||
* Protect data integrity by HMAC-SHA1 (or weaker MD5/CRC32).
|
* Protect data integrity by HMAC-SHA1 (or weaker MD5/CRC32).
|
||||||
* Defense replay attack with an anti-replay window, smiliar to IPSec and OpenVPN.
|
* Defense replay attack with an anti-replay window, smiliar to IPSec and OpenVPN.
|
||||||
|
150
client.cpp
150
client.cpp
@@ -105,7 +105,8 @@ int client_on_timer(conn_info_t &conn_info) //for client. called when a timer is
|
|||||||
{
|
{
|
||||||
setnonblocking(bind_fd);
|
setnonblocking(bind_fd);
|
||||||
int ret=connect(bind_fd,(struct sockaddr *)&remote_addr.inner,remote_addr.get_len());
|
int ret=connect(bind_fd,(struct sockaddr *)&remote_addr.inner,remote_addr.get_len());
|
||||||
mylog(log_info,"ret=%d,errno=%s,%d %s\n",ret,get_sock_error(),bind_fd,remote_addr.get_str());
|
mylog(log_debug,"ret=%d,errno=%s, %d %s\n",ret,get_sock_error(),bind_fd,remote_addr.get_str());
|
||||||
|
//mylog(log_info,"ret=%d,errno=,%d %s\n",ret,bind_fd,remote_addr.get_str());
|
||||||
conn_info.state.client_current_state=client_tcp_handshake_dummy;
|
conn_info.state.client_current_state=client_tcp_handshake_dummy;
|
||||||
mylog(log_info,"state changed from client_idle to client_tcp_handshake_dummy\n");
|
mylog(log_info,"state changed from client_idle to client_tcp_handshake_dummy\n");
|
||||||
}
|
}
|
||||||
@@ -306,6 +307,77 @@ int client_on_timer(conn_info_t &conn_info) //for client. called when a timer is
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
int client_on_raw_recv_hs2_or_ready(conn_info_t &conn_info,char type,char *data,int data_len)
|
||||||
|
{
|
||||||
|
packet_info_t &send_info=conn_info.raw_info.send_info;
|
||||||
|
packet_info_t &recv_info=conn_info.raw_info.recv_info;
|
||||||
|
|
||||||
|
if(!recv_info.new_src_ip.equal(send_info.new_dst_ip)||recv_info.src_port!=send_info.dst_port)
|
||||||
|
{
|
||||||
|
mylog(log_warn,"unexpected adress %s %s %d %d,this shouldnt happen.\n",recv_info.new_src_ip.get_str1(),send_info.new_dst_ip.get_str2(),recv_info.src_port,send_info.dst_port);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(conn_info.state.client_current_state==client_handshake2)
|
||||||
|
{
|
||||||
|
mylog(log_info,"changed state from to client_handshake2 to client_ready\n");
|
||||||
|
conn_info.state.client_current_state=client_ready;
|
||||||
|
conn_info.last_hb_sent_time=0;
|
||||||
|
conn_info.last_hb_recv_time=get_current_time();
|
||||||
|
conn_info.last_oppsite_roller_time=conn_info.last_hb_recv_time;
|
||||||
|
client_on_timer(conn_info);
|
||||||
|
}
|
||||||
|
if(data_len>=0&&type=='h')
|
||||||
|
{
|
||||||
|
mylog(log_debug,"[hb]heart beat received,oppsite_roller=%d\n",int(conn_info.oppsite_roller));
|
||||||
|
conn_info.last_hb_recv_time=get_current_time();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if(data_len>= int( sizeof(u32_t))&&type=='d')
|
||||||
|
{
|
||||||
|
mylog(log_trace,"received a data from fake tcp,len:%d\n",data_len);
|
||||||
|
|
||||||
|
if(hb_mode==0)
|
||||||
|
conn_info.last_hb_recv_time=get_current_time();
|
||||||
|
|
||||||
|
u32_t tmp_conv_id;
|
||||||
|
memcpy(&tmp_conv_id,&data[0],sizeof(tmp_conv_id));
|
||||||
|
tmp_conv_id=ntohl(tmp_conv_id);
|
||||||
|
|
||||||
|
if(!conn_info.blob->conv_manager.c.is_conv_used(tmp_conv_id))
|
||||||
|
{
|
||||||
|
mylog(log_info,"unknow conv %d,ignore\n",tmp_conv_id);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
conn_info.blob->conv_manager.c.update_active_time(tmp_conv_id);
|
||||||
|
|
||||||
|
//u64_t u64=conn_info.blob->conv_manager.c.find_data_by_conv(tmp_conv_id);
|
||||||
|
address_t tmp_addr=conn_info.blob->conv_manager.c.find_data_by_conv(tmp_conv_id);
|
||||||
|
|
||||||
|
//sockaddr_in tmp_sockaddr={0};
|
||||||
|
|
||||||
|
//tmp_sockaddr.sin_family = AF_INET;
|
||||||
|
//tmp_sockaddr.sin_addr.s_addr=(u64>>32u);
|
||||||
|
|
||||||
|
//tmp_sockaddr.sin_port= htons(uint16_t((u64<<32u)>>32u));
|
||||||
|
|
||||||
|
|
||||||
|
int ret=sendto(udp_fd,data+sizeof(u32_t),data_len -(sizeof(u32_t)),0,(struct sockaddr *)&tmp_addr.inner,tmp_addr.get_len());
|
||||||
|
|
||||||
|
if(ret<0)
|
||||||
|
{
|
||||||
|
mylog(log_warn,"sento returned %d,%s,%02x,%s\n",ret,get_sock_error(),int(tmp_addr.get_type()),tmp_addr.get_str());
|
||||||
|
//perror("ret<0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mylog(log_warn,"unknown packet,this shouldnt happen.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
int client_on_raw_recv(conn_info_t &conn_info) //called when raw fd received a packet.
|
int client_on_raw_recv(conn_info_t &conn_info) //called when raw fd received a packet.
|
||||||
{
|
{
|
||||||
char* data;int data_len;
|
char* data;int data_len;
|
||||||
@@ -426,74 +498,21 @@ int client_on_raw_recv(conn_info_t &conn_info) //called when raw fd received a p
|
|||||||
}
|
}
|
||||||
else if(conn_info.state.client_current_state==client_handshake2||conn_info.state.client_current_state==client_ready)//received heartbeat or data
|
else if(conn_info.state.client_current_state==client_handshake2||conn_info.state.client_current_state==client_ready)//received heartbeat or data
|
||||||
{
|
{
|
||||||
char type;
|
vector<char> type_vec;
|
||||||
if(recv_safer(conn_info,type,data,data_len)!=0)
|
vector<string> data_vec;
|
||||||
|
recv_safer_multi(conn_info,type_vec,data_vec);
|
||||||
|
if(data_vec.empty())
|
||||||
{
|
{
|
||||||
mylog(log_debug,"recv_safer failed!\n");
|
mylog(log_debug,"recv_safer failed!\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if(!recv_info.new_src_ip.equal(send_info.new_dst_ip)||recv_info.src_port!=send_info.dst_port)
|
|
||||||
|
for(int i=0;i<(int)type_vec.size();i++)
|
||||||
{
|
{
|
||||||
mylog(log_warn,"unexpected adress %s %s %d %d,this shouldnt happen.\n",recv_info.new_src_ip.get_str1(),send_info.new_dst_ip.get_str2(),recv_info.src_port,send_info.dst_port);
|
char type=type_vec[i];
|
||||||
return -1;
|
char *data=(char *)data_vec[i].c_str(); //be careful, do not append data to it
|
||||||
}
|
int data_len=data_vec[i].length();
|
||||||
if(conn_info.state.client_current_state==client_handshake2)
|
client_on_raw_recv_hs2_or_ready(conn_info, type, data,data_len);
|
||||||
{
|
|
||||||
mylog(log_info,"changed state from to client_handshake2 to client_ready\n");
|
|
||||||
conn_info.state.client_current_state=client_ready;
|
|
||||||
conn_info.last_hb_sent_time=0;
|
|
||||||
conn_info.last_hb_recv_time=get_current_time();
|
|
||||||
conn_info.last_oppsite_roller_time=conn_info.last_hb_recv_time;
|
|
||||||
client_on_timer(conn_info);
|
|
||||||
}
|
|
||||||
if(data_len>=0&&type=='h')
|
|
||||||
{
|
|
||||||
mylog(log_debug,"[hb]heart beat received,oppsite_roller=%d\n",int(conn_info.oppsite_roller));
|
|
||||||
conn_info.last_hb_recv_time=get_current_time();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if(data_len>= int( sizeof(u32_t))&&type=='d')
|
|
||||||
{
|
|
||||||
mylog(log_trace,"received a data from fake tcp,len:%d\n",data_len);
|
|
||||||
|
|
||||||
if(hb_mode==0)
|
|
||||||
conn_info.last_hb_recv_time=get_current_time();
|
|
||||||
|
|
||||||
u32_t tmp_conv_id;
|
|
||||||
memcpy(&tmp_conv_id,&data[0],sizeof(tmp_conv_id));
|
|
||||||
tmp_conv_id=ntohl(tmp_conv_id);
|
|
||||||
|
|
||||||
if(!conn_info.blob->conv_manager.c.is_conv_used(tmp_conv_id))
|
|
||||||
{
|
|
||||||
mylog(log_info,"unknow conv %d,ignore\n",tmp_conv_id);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
conn_info.blob->conv_manager.c.update_active_time(tmp_conv_id);
|
|
||||||
|
|
||||||
//u64_t u64=conn_info.blob->conv_manager.c.find_data_by_conv(tmp_conv_id);
|
|
||||||
address_t tmp_addr=conn_info.blob->conv_manager.c.find_data_by_conv(tmp_conv_id);
|
|
||||||
|
|
||||||
//sockaddr_in tmp_sockaddr={0};
|
|
||||||
|
|
||||||
//tmp_sockaddr.sin_family = AF_INET;
|
|
||||||
//tmp_sockaddr.sin_addr.s_addr=(u64>>32u);
|
|
||||||
|
|
||||||
//tmp_sockaddr.sin_port= htons(uint16_t((u64<<32u)>>32u));
|
|
||||||
|
|
||||||
|
|
||||||
int ret=sendto(udp_fd,data+sizeof(u32_t),data_len -(sizeof(u32_t)),0,(struct sockaddr *)&tmp_addr.inner,tmp_addr.get_len());
|
|
||||||
|
|
||||||
if(ret<0)
|
|
||||||
{
|
|
||||||
mylog(log_warn,"sento returned %d,%s,%02x,%s\n",ret,get_sock_error(),int(tmp_addr.get_type()),tmp_addr.get_str());
|
|
||||||
//perror("ret<0");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mylog(log_warn,"unknown packet,this shouldnt happen.\n");
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -513,7 +532,8 @@ int client_on_udp_recv(conn_info_t &conn_info)
|
|||||||
socklen_t udp_new_addr_len = sizeof(address_t::storage_t);
|
socklen_t udp_new_addr_len = sizeof(address_t::storage_t);
|
||||||
if ((recv_len = recvfrom(udp_fd, buf, max_data_len+1, 0,
|
if ((recv_len = recvfrom(udp_fd, buf, max_data_len+1, 0,
|
||||||
(struct sockaddr *) &udp_new_addr_in, &udp_new_addr_len)) == -1) {
|
(struct sockaddr *) &udp_new_addr_in, &udp_new_addr_len)) == -1) {
|
||||||
mylog(log_warn,"recv_from error,%s\n",get_sock_error());
|
mylog(log_debug,"recv_from error,%s\n",get_sock_error());
|
||||||
|
return -1;
|
||||||
//myexit(1);
|
//myexit(1);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
34
common.cpp
34
common.cpp
@@ -404,7 +404,11 @@ char *get_sock_error()
|
|||||||
(LPWSTR)&s, 0, NULL);
|
(LPWSTR)&s, 0, NULL);
|
||||||
sprintf(buf, "%d:%S", e,s);
|
sprintf(buf, "%d:%S", e,s);
|
||||||
int len=strlen(buf);
|
int len=strlen(buf);
|
||||||
if(len>0&&buf[len-1]=='\n') buf[len-1]=0;
|
while(len>0 && (buf[len-1]=='\r'||buf[len-1]=='\n' ))
|
||||||
|
{
|
||||||
|
len--;
|
||||||
|
buf[len]=0;
|
||||||
|
}
|
||||||
LocalFree(s);
|
LocalFree(s);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
@@ -426,13 +430,31 @@ int get_sock_errno()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
u64_t get_current_time_us()
|
||||||
|
{
|
||||||
|
static u64_t value_fix=0;
|
||||||
|
static u64_t largest_value=0;
|
||||||
|
|
||||||
|
u64_t raw_value=(u64_t)(ev_time()*1000*1000);
|
||||||
|
|
||||||
|
u64_t fixed_value=raw_value+value_fix;
|
||||||
|
|
||||||
|
if(fixed_value< largest_value)
|
||||||
|
{
|
||||||
|
value_fix+= largest_value- fixed_value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
largest_value=fixed_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
//printf("<%lld,%lld,%lld>\n",raw_value,value_fix,raw_value + value_fix);
|
||||||
|
return raw_value + value_fix; //new fixed value
|
||||||
|
}
|
||||||
|
|
||||||
u64_t get_current_time()
|
u64_t get_current_time()
|
||||||
{
|
{
|
||||||
timespec tmp_time;
|
return get_current_time_us()/1000;
|
||||||
clock_gettime(CLOCK_MONOTONIC, &tmp_time);
|
|
||||||
return ((u64_t)tmp_time.tv_sec)*1000llu+((u64_t)tmp_time.tv_nsec)/(1000*1000llu);
|
|
||||||
|
|
||||||
//return (u64_t)(ev_time()*1000); //todo change to this later
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u64_t pack_u64(u32_t a,u32_t b)
|
u64_t pack_u64(u32_t a,u32_t b)
|
||||||
|
4
common.h
4
common.h
@@ -159,6 +159,8 @@ const int max_addr_len=100;
|
|||||||
|
|
||||||
extern int force_socket_buf;
|
extern int force_socket_buf;
|
||||||
|
|
||||||
|
extern int g_fix_gro;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
struct ip_port_t
|
struct ip_port_t
|
||||||
{
|
{
|
||||||
@@ -345,6 +347,8 @@ struct not_copy_able_t
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const int huge_data_len=65535+100; //a packet with link level header might be larger than 65535
|
||||||
|
const int huge_buf_len=huge_data_len+100;
|
||||||
|
|
||||||
const int max_data_len=1800;
|
const int max_data_len=1800;
|
||||||
const int buf_len=max_data_len+400;
|
const int buf_len=max_data_len+400;
|
||||||
|
113
connection.cpp
113
connection.cpp
@@ -11,8 +11,6 @@
|
|||||||
|
|
||||||
int disable_anti_replay=0;//if anti_replay windows is diabled
|
int disable_anti_replay=0;//if anti_replay windows is diabled
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const int disable_conn_clear=0;//a raw connection is called conn.
|
const int disable_conn_clear=0;//a raw connection is called conn.
|
||||||
|
|
||||||
conn_manager_t conn_manager;
|
conn_manager_t conn_manager;
|
||||||
@@ -462,12 +460,9 @@ int send_safer(conn_info_t &conn_info,char type,const char* data,int len) //saf
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
char send_data_buf[buf_len]; //buf for send data and send hb
|
char send_data_buf[buf_len]; //buf for send data and send hb
|
||||||
char send_data_buf2[buf_len];
|
char send_data_buf2[buf_len];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
my_id_t n_tmp_id=htonl(conn_info.my_id);
|
my_id_t n_tmp_id=htonl(conn_info.my_id);
|
||||||
|
|
||||||
memcpy(send_data_buf,&n_tmp_id,sizeof(n_tmp_id));
|
memcpy(send_data_buf,&n_tmp_id,sizeof(n_tmp_id));
|
||||||
@@ -488,10 +483,32 @@ int send_safer(conn_info_t &conn_info,char type,const char* data,int len) //saf
|
|||||||
|
|
||||||
int new_len=len+sizeof(n_seq)+sizeof(n_tmp_id)*2+2;
|
int new_len=len+sizeof(n_seq)+sizeof(n_tmp_id)*2+2;
|
||||||
|
|
||||||
|
if(g_fix_gro==0)
|
||||||
|
{
|
||||||
if (my_encrypt(send_data_buf, send_data_buf2, new_len) != 0)
|
if (my_encrypt(send_data_buf, send_data_buf2, new_len) != 0)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (my_encrypt(send_data_buf, send_data_buf2+2, new_len) != 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
write_u16(send_data_buf2,new_len);
|
||||||
|
new_len+=2;
|
||||||
|
if(cipher_mode==cipher_xor)
|
||||||
|
{
|
||||||
|
send_data_buf2[0]^=gro_xor[0];
|
||||||
|
send_data_buf2[1]^=gro_xor[1];
|
||||||
|
}
|
||||||
|
else if(cipher_mode==cipher_aes128cbc||cipher_mode==cipher_aes128cbc)
|
||||||
|
{
|
||||||
|
aes_ecb_encrypt1(send_data_buf2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if(send_raw0(conn_info.raw_info,send_data_buf2,new_len)!=0) return -1;
|
if(send_raw0(conn_info.raw_info,send_data_buf2,new_len)!=0) return -1;
|
||||||
|
|
||||||
@@ -602,19 +619,101 @@ int reserved_parse_safer(conn_info_t &conn_info,const char * input,int input_len
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int recv_safer(conn_info_t &conn_info,char &type,char* &data,int &len)///safer transfer function with anti-replay,when mutually verification is done.
|
int recv_safer_notused(conn_info_t &conn_info,char &type,char* &data,int &len)///safer transfer function with anti-replay,when mutually verification is done.
|
||||||
{
|
{
|
||||||
packet_info_t &send_info=conn_info.raw_info.send_info;
|
packet_info_t &send_info=conn_info.raw_info.send_info;
|
||||||
packet_info_t &recv_info=conn_info.raw_info.recv_info;
|
packet_info_t &recv_info=conn_info.raw_info.recv_info;
|
||||||
|
|
||||||
char * recv_data;int recv_len;
|
char * recv_data;int recv_len;
|
||||||
static char recv_data_buf[buf_len];
|
//static char recv_data_buf[buf_len];
|
||||||
|
|
||||||
if(recv_raw0(conn_info.raw_info,recv_data,recv_len)!=0) return -1;
|
if(recv_raw0(conn_info.raw_info,recv_data,recv_len)!=0) return -1;
|
||||||
|
|
||||||
return reserved_parse_safer(conn_info,recv_data,recv_len,type,data,len);
|
return reserved_parse_safer(conn_info,recv_data,recv_len,type,data,len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int recv_safer_multi(conn_info_t &conn_info,vector<char> &type_arr,vector<string> &data_arr)///safer transfer function with anti-replay,when mutually verification is done.
|
||||||
|
{
|
||||||
|
packet_info_t &send_info=conn_info.raw_info.send_info;
|
||||||
|
packet_info_t &recv_info=conn_info.raw_info.recv_info;
|
||||||
|
|
||||||
|
char * recv_data;int recv_len;
|
||||||
|
assert(type_arr.empty());
|
||||||
|
assert(data_arr.empty());
|
||||||
|
|
||||||
|
if(recv_raw0(conn_info.raw_info,recv_data,recv_len)!=0) return -1;
|
||||||
|
|
||||||
|
char type;
|
||||||
|
char *data;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if(g_fix_gro==0)
|
||||||
|
{
|
||||||
|
int ret = reserved_parse_safer(conn_info, recv_data, recv_len, type, data, len);
|
||||||
|
if(ret==0)
|
||||||
|
{
|
||||||
|
type_arr.push_back(type);
|
||||||
|
data_arr.emplace_back(data,data+len);
|
||||||
|
//std::copy(data,data+len,data_arr[0]);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
char *ori_recv_data=recv_data;
|
||||||
|
int ori_recv_len=recv_len;
|
||||||
|
//mylog(log_debug,"recv_len:%d\n",recv_len);
|
||||||
|
int cnt=0;
|
||||||
|
while(recv_len>=16)
|
||||||
|
{
|
||||||
|
cnt++;
|
||||||
|
int single_len_no_xor;
|
||||||
|
single_len_no_xor=read_u16(recv_data);
|
||||||
|
int single_len;
|
||||||
|
if(cipher_mode==cipher_xor)
|
||||||
|
{
|
||||||
|
recv_data[0]^=gro_xor[0];
|
||||||
|
recv_data[1]^=gro_xor[1];
|
||||||
|
}
|
||||||
|
else if(cipher_mode==cipher_aes128cbc||cipher_mode==cipher_aes128cbc)
|
||||||
|
{
|
||||||
|
aes_ecb_decrypt1(recv_data);
|
||||||
|
}
|
||||||
|
single_len=read_u16(recv_data);
|
||||||
|
recv_len-=2;
|
||||||
|
recv_data+=2;
|
||||||
|
if(single_len > recv_len)
|
||||||
|
{
|
||||||
|
mylog(log_debug,"illegal single_len %d(%d), recv_len %d left,dropped\n",single_len,single_len_no_xor,recv_len);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(single_len> max_data_len )
|
||||||
|
{
|
||||||
|
mylog(log_warn,"single_len %d(%d) > %d, maybe you need to turn down mtu at upper level\n",single_len,single_len_no_xor,max_data_len);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = reserved_parse_safer(conn_info, recv_data, single_len, type, data, len);
|
||||||
|
|
||||||
|
if(ret!=0)
|
||||||
|
{
|
||||||
|
mylog(log_debug,"parse failed, offset= %d,single_len=%d(%d)\n",(int)(recv_data-ori_recv_data),single_len,single_len_no_xor);
|
||||||
|
} else{
|
||||||
|
type_arr.push_back(type);
|
||||||
|
data_arr.emplace_back(data,data+len);
|
||||||
|
//std::copy(data,data+len,data_arr[data_arr.size()-1]);
|
||||||
|
}
|
||||||
|
recv_data+=single_len;
|
||||||
|
recv_len-=single_len;
|
||||||
|
}
|
||||||
|
if(cnt>1)
|
||||||
|
{
|
||||||
|
mylog(log_debug,"got a suspected gro packet, %d packets recovered, recv_len=%d, loop_cnt=%d\n",(int)data_arr.size(),ori_recv_len,cnt);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void server_clear_function(u64_t u64)//used in conv_manager in server mode.for server we have to use one udp fd for one conv(udp connection),
|
void server_clear_function(u64_t u64)//used in conv_manager in server mode.for server we have to use one udp fd for one conv(udp connection),
|
||||||
//so we have to close the fd when conv expires
|
//so we have to close the fd when conv expires
|
||||||
{
|
{
|
||||||
|
@@ -18,8 +18,6 @@ extern int disable_anti_replay;
|
|||||||
|
|
||||||
const int disable_conv_clear=0;//a udp connection in the multiplexer is called conversation in this program,conv for short.
|
const int disable_conv_clear=0;//a udp connection in the multiplexer is called conversation in this program,conv for short.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct anti_replay_t //its for anti replay attack,similar to openvpn/ipsec 's anti replay window
|
struct anti_replay_t //its for anti replay attack,similar to openvpn/ipsec 's anti replay window
|
||||||
{
|
{
|
||||||
u64_t max_packet_received;
|
u64_t max_packet_received;
|
||||||
@@ -346,5 +344,8 @@ int send_handshake(raw_info_t &raw_info,my_id_t id1,my_id_t id2,my_id_t id3);//
|
|||||||
int send_safer(conn_info_t &conn_info,char type,const char* data,int len); //safer transfer function with anti-replay,when mutually verification is done.
|
int send_safer(conn_info_t &conn_info,char type,const char* data,int len); //safer transfer function with anti-replay,when mutually verification is done.
|
||||||
int send_data_safer(conn_info_t &conn_info,const char* data,int len,u32_t conv_num);//a wrap for send_safer for transfer data.
|
int send_data_safer(conn_info_t &conn_info,const char* data,int len,u32_t conv_num);//a wrap for send_safer for transfer data.
|
||||||
//int reserved_parse_safer(conn_info_t &conn_info,const char * input,int input_len,char &type,char* &data,int &len);//subfunction for recv_safer,allow overlap
|
//int reserved_parse_safer(conn_info_t &conn_info,const char * input,int input_len,char &type,char* &data,int &len);//subfunction for recv_safer,allow overlap
|
||||||
int recv_safer(conn_info_t &conn_info,char &type,char* &data,int &len);///safer transfer function with anti-replay,when mutually verification is done.
|
|
||||||
|
//int recv_safer(conn_info_t &conn_info,char &type,char* &data,int &len);///safer transfer function with anti-replay,when mutually verification is done.
|
||||||
|
|
||||||
|
int recv_safer_multi(conn_info_t &conn_info,vector<char> &type_arr,vector<string> &data_arr);//new api for handle gro
|
||||||
#endif /* CONNECTION_H_ */
|
#endif /* CONNECTION_H_ */
|
||||||
|
@@ -8,7 +8,7 @@ the guide on how to build udp2raw
|
|||||||
such as PC,raspberry pi
|
such as PC,raspberry pi
|
||||||
|
|
||||||
##### install git
|
##### install git
|
||||||
run on debian/ubuntun:
|
run on debian/ubuntu:
|
||||||
```
|
```
|
||||||
sudo apt-get install git
|
sudo apt-get install git
|
||||||
```
|
```
|
||||||
@@ -18,7 +18,7 @@ sudo yum install git
|
|||||||
```
|
```
|
||||||
##### clone git code
|
##### clone git code
|
||||||
|
|
||||||
run in any dir:
|
run in any dir:
|
||||||
|
|
||||||
```
|
```
|
||||||
git clone https://github.com/wangyu-/udp2raw-tunnel.git
|
git clone https://github.com/wangyu-/udp2raw-tunnel.git
|
||||||
@@ -26,7 +26,7 @@ cd udp2raw-tunnel
|
|||||||
```
|
```
|
||||||
|
|
||||||
##### install compile tool
|
##### install compile tool
|
||||||
run on debian/ubuntun:
|
run on debian/ubuntu:
|
||||||
```
|
```
|
||||||
sudo apt-get install build-essential
|
sudo apt-get install build-essential
|
||||||
```
|
```
|
||||||
@@ -42,7 +42,7 @@ run 'make',compilation done. the udp2raw file is the just compiled binary
|
|||||||
such as openwrt router,run following instructions on your PC
|
such as openwrt router,run following instructions on your PC
|
||||||
|
|
||||||
##### install git
|
##### install git
|
||||||
run on debian/ubuntun:
|
run on debian/ubuntu:
|
||||||
```
|
```
|
||||||
sudo apt-get install git
|
sudo apt-get install git
|
||||||
```
|
```
|
||||||
|
56
encrypt.cpp
56
encrypt.cpp
@@ -26,6 +26,8 @@ unsigned char hmac_key_decrypt[hmac_key_len + 100]; //key for hmac
|
|||||||
unsigned char cipher_key_encrypt[cipher_key_len + 100]; //key for aes etc.
|
unsigned char cipher_key_encrypt[cipher_key_len + 100]; //key for aes etc.
|
||||||
unsigned char cipher_key_decrypt[cipher_key_len + 100]; //key for aes etc.
|
unsigned char cipher_key_decrypt[cipher_key_len + 100]; //key for aes etc.
|
||||||
|
|
||||||
|
char gro_xor[256+100];//dirty fix for gro
|
||||||
|
|
||||||
unordered_map<int, const char *> auth_mode_tostring = {{auth_none, "none"}, {auth_md5, "md5"}, {auth_crc32, "crc32"},{auth_simple,"simple"},{auth_hmac_sha1,"hmac_sha1"},};
|
unordered_map<int, const char *> auth_mode_tostring = {{auth_none, "none"}, {auth_md5, "md5"}, {auth_crc32, "crc32"},{auth_simple,"simple"},{auth_hmac_sha1,"hmac_sha1"},};
|
||||||
|
|
||||||
unordered_map<int, const char *> cipher_mode_tostring={{cipher_none,"none"},{cipher_aes128cfb,"aes128cfb"},{cipher_aes128cbc,"aes128cbc"},{cipher_xor,"xor"},};
|
unordered_map<int, const char *> cipher_mode_tostring={{cipher_none,"none"},{cipher_aes128cfb,"aes128cfb"},{cipher_aes128cbc,"aes128cbc"},{cipher_xor,"xor"},};
|
||||||
@@ -35,6 +37,8 @@ auth_mode_t auth_mode=auth_md5;
|
|||||||
cipher_mode_t cipher_mode=cipher_aes128cbc;
|
cipher_mode_t cipher_mode=cipher_aes128cbc;
|
||||||
int is_hmac_used=0;
|
int is_hmac_used=0;
|
||||||
|
|
||||||
|
int aes128cfb_old=0;
|
||||||
|
|
||||||
//TODO key negotiation and forward secrecy
|
//TODO key negotiation and forward secrecy
|
||||||
|
|
||||||
int my_init_keys(const char * user_passwd,int is_client)
|
int my_init_keys(const char * user_passwd,int is_client)
|
||||||
@@ -48,9 +52,10 @@ int my_init_keys(const char * user_passwd,int is_client)
|
|||||||
|
|
||||||
md5((uint8_t*)tmp,strlen(tmp),(uint8_t*)normal_key);
|
md5((uint8_t*)tmp,strlen(tmp),(uint8_t*)normal_key);
|
||||||
|
|
||||||
|
|
||||||
if(auth_mode==auth_hmac_sha1)
|
if(auth_mode==auth_hmac_sha1)
|
||||||
is_hmac_used=1;
|
is_hmac_used=1;
|
||||||
if(is_hmac_used)
|
if(is_hmac_used||g_fix_gro||1)
|
||||||
{
|
{
|
||||||
unsigned char salt[400]="";
|
unsigned char salt[400]="";
|
||||||
char salt_text[400]="udp2raw_salt1";
|
char salt_text[400]="udp2raw_salt1";
|
||||||
@@ -82,6 +87,9 @@ int my_init_keys(const char * user_passwd,int is_client)
|
|||||||
assert( hkdf_sha256_expand( pbkdf2_output1,32, (unsigned char *)info_cipher_decrypt,strlen(info_cipher_decrypt), cipher_key_decrypt, cipher_key_len ) ==0);
|
assert( hkdf_sha256_expand( pbkdf2_output1,32, (unsigned char *)info_cipher_decrypt,strlen(info_cipher_decrypt), cipher_key_decrypt, cipher_key_len ) ==0);
|
||||||
assert( hkdf_sha256_expand( pbkdf2_output1,32, (unsigned char *)info_hmac_encrypt,strlen(info_hmac_encrypt), hmac_key_encrypt, hmac_key_len ) ==0);
|
assert( hkdf_sha256_expand( pbkdf2_output1,32, (unsigned char *)info_hmac_encrypt,strlen(info_hmac_encrypt), hmac_key_encrypt, hmac_key_len ) ==0);
|
||||||
assert( hkdf_sha256_expand( pbkdf2_output1,32, (unsigned char *)info_hmac_decrypt,strlen(info_hmac_decrypt), hmac_key_decrypt, hmac_key_len ) ==0);
|
assert( hkdf_sha256_expand( pbkdf2_output1,32, (unsigned char *)info_hmac_decrypt,strlen(info_hmac_decrypt), hmac_key_decrypt, hmac_key_len ) ==0);
|
||||||
|
|
||||||
|
const char *gro_info="gro";
|
||||||
|
assert( hkdf_sha256_expand( pbkdf2_output1,32, (unsigned char *)gro_info,strlen(gro_info), (unsigned char *)gro_xor, 256 ) ==0);
|
||||||
}
|
}
|
||||||
|
|
||||||
print_binary_chars(normal_key,16);
|
print_binary_chars(normal_key,16);
|
||||||
@@ -291,6 +299,40 @@ int de_padding(const char *data ,int &data_len,int padding_num)
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
void aes_ecb_encrypt(const char *data,char *output)
|
||||||
|
{
|
||||||
|
static int first_time=1;
|
||||||
|
char *key=(char*)cipher_key_encrypt;
|
||||||
|
if(aes_key_optimize)
|
||||||
|
{
|
||||||
|
if(first_time==0) key=0;
|
||||||
|
else first_time=0;
|
||||||
|
}
|
||||||
|
AES_ECB_encrypt_buffer((uint8_t*)data,(uint8_t*)key,(uint8_t*)output);
|
||||||
|
}
|
||||||
|
void aes_ecb_encrypt1(char *data)
|
||||||
|
{
|
||||||
|
char buf[16];
|
||||||
|
memcpy(buf,data,16);
|
||||||
|
aes_ecb_encrypt(buf,data);
|
||||||
|
}
|
||||||
|
void aes_ecb_decrypt(const char *data,char *output)
|
||||||
|
{
|
||||||
|
static int first_time=1;
|
||||||
|
char *key=(char*)cipher_key_decrypt;
|
||||||
|
if(aes_key_optimize)
|
||||||
|
{
|
||||||
|
if(first_time==0) key=0;
|
||||||
|
else first_time=0;
|
||||||
|
}
|
||||||
|
AES_ECB_decrypt_buffer((uint8_t*)data,(uint8_t*)key,(uint8_t*)output);
|
||||||
|
}
|
||||||
|
void aes_ecb_decrypt1(char *data)
|
||||||
|
{
|
||||||
|
char buf[16];
|
||||||
|
memcpy(buf,data,16);
|
||||||
|
aes_ecb_decrypt(buf,data);
|
||||||
|
}
|
||||||
int cipher_aes128cbc_encrypt(const char *data,char *output,int &len,char * key)
|
int cipher_aes128cbc_encrypt(const char *data,char *output,int &len,char * key)
|
||||||
{
|
{
|
||||||
static int first_time=1;
|
static int first_time=1;
|
||||||
@@ -312,6 +354,7 @@ int cipher_aes128cbc_encrypt(const char *data,char *output,int &len,char * key)
|
|||||||
int cipher_aes128cfb_encrypt(const char *data,char *output,int &len,char * key)
|
int cipher_aes128cfb_encrypt(const char *data,char *output,int &len,char * key)
|
||||||
{
|
{
|
||||||
static int first_time=1;
|
static int first_time=1;
|
||||||
|
assert(len>=16);
|
||||||
|
|
||||||
char buf[buf_len];
|
char buf[buf_len];
|
||||||
memcpy(buf,data,len);//TODO inefficient code
|
memcpy(buf,data,len);//TODO inefficient code
|
||||||
@@ -320,6 +363,10 @@ int cipher_aes128cfb_encrypt(const char *data,char *output,int &len,char * key)
|
|||||||
if(first_time==0) key=0;
|
if(first_time==0) key=0;
|
||||||
else first_time=0;
|
else first_time=0;
|
||||||
}
|
}
|
||||||
|
if(!aes128cfb_old)
|
||||||
|
{
|
||||||
|
aes_ecb_encrypt(data,buf); //encrypt the first block
|
||||||
|
}
|
||||||
|
|
||||||
AES_CFB_encrypt_buffer((unsigned char *)output,(unsigned char *)buf,len,(unsigned char *)key,(unsigned char *)zero_iv);
|
AES_CFB_encrypt_buffer((unsigned char *)output,(unsigned char *)buf,len,(unsigned char *)key,(unsigned char *)zero_iv);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -363,12 +410,19 @@ int cipher_aes128cbc_decrypt(const char *data,char *output,int &len,char * key)
|
|||||||
int cipher_aes128cfb_decrypt(const char *data,char *output,int &len,char * key)
|
int cipher_aes128cfb_decrypt(const char *data,char *output,int &len,char * key)
|
||||||
{
|
{
|
||||||
static int first_time=1;
|
static int first_time=1;
|
||||||
|
if(len<16) return -1;
|
||||||
|
|
||||||
if(aes_key_optimize)
|
if(aes_key_optimize)
|
||||||
{
|
{
|
||||||
if(first_time==0) key=0;
|
if(first_time==0) key=0;
|
||||||
else first_time=0;
|
else first_time=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
AES_CFB_decrypt_buffer((unsigned char *)output,(unsigned char *)data,len,(unsigned char *)key,(unsigned char *)zero_iv);
|
AES_CFB_decrypt_buffer((unsigned char *)output,(unsigned char *)data,len,(unsigned char *)key,(unsigned char *)zero_iv);
|
||||||
|
|
||||||
|
if(!aes128cfb_old)
|
||||||
|
aes_ecb_decrypt1(output); //decrypt the first block
|
||||||
//if(de_padding(output,len,16)<0) return -1;
|
//if(de_padding(output,len,16)<0) return -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
10
encrypt.h
10
encrypt.h
@@ -12,6 +12,7 @@
|
|||||||
//extern char key[16];
|
//extern char key[16];
|
||||||
|
|
||||||
const int aes_key_optimize=1; //if enabled,once you used a key for aes,you cant change it anymore
|
const int aes_key_optimize=1; //if enabled,once you used a key for aes,you cant change it anymore
|
||||||
|
extern int aes128cfb_old;
|
||||||
|
|
||||||
int my_init_keys(const char *,int);
|
int my_init_keys(const char *,int);
|
||||||
|
|
||||||
@@ -34,10 +35,15 @@ extern cipher_mode_t cipher_mode;
|
|||||||
extern unordered_map<int, const char *> auth_mode_tostring;
|
extern unordered_map<int, const char *> auth_mode_tostring;
|
||||||
extern unordered_map<int, const char *> cipher_mode_tostring;
|
extern unordered_map<int, const char *> cipher_mode_tostring;
|
||||||
|
|
||||||
|
extern char gro_xor[256+100];
|
||||||
|
|
||||||
|
|
||||||
int cipher_decrypt(const char *data,char *output,int &len,char * key);//internal interface ,exposed for test only
|
int cipher_decrypt(const char *data,char *output,int &len,char * key);//internal interface ,exposed for test only
|
||||||
int cipher_encrypt(const char *data,char *output,int &len,char * key);//internal interface ,exposed for test only
|
int cipher_encrypt(const char *data,char *output,int &len,char * key);//internal interface ,exposed for test only
|
||||||
|
|
||||||
|
void aes_ecb_encrypt(const char *data,char *output);
|
||||||
|
void aes_ecb_decrypt(const char *data,char *output);
|
||||||
|
|
||||||
|
void aes_ecb_encrypt1(char *data);
|
||||||
|
void aes_ecb_decrypt1(char *data);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -7,9 +7,8 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
//not used
|
void AES_ECB_encrypt_buffer(const uint8_t* input, const uint8_t* key, uint8_t *output);
|
||||||
//void AES_ECB_encrypt(const uint8_t* input, const uint8_t* key, uint8_t *output, const uint32_t length);
|
void AES_ECB_decrypt_buffer(const uint8_t* input, const uint8_t* key, uint8_t *output);
|
||||||
//void AES_ECB_decrypt(const uint8_t* input, const uint8_t* key, uint8_t *output, const uint32_t length);
|
|
||||||
|
|
||||||
void AES_CBC_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv);
|
void AES_CBC_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv);
|
||||||
void AES_CBC_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv);
|
void AES_CBC_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv);
|
||||||
|
@@ -366,32 +366,25 @@ void AES_CBC_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, co
|
|||||||
decrypt_cbc(rk, length, iv_tmp, input, output);
|
decrypt_cbc(rk, length, iv_tmp, input, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
void AES_ECB_encrypt_buffer(const uint8_t* input, const uint8_t* key, uint8_t* output)
|
||||||
void AES_ECB_encrypt(const uint8_t* input, const uint8_t* key, uint8_t* output, const uint32_t length)
|
|
||||||
{
|
{
|
||||||
uint8_t rk[AES_RKSIZE];
|
static uint8_t rk[AES_RKSIZE];
|
||||||
|
|
||||||
if (key == NULL)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
aeshw_init();
|
aeshw_init();
|
||||||
|
if(key!=NULL)
|
||||||
setkey_enc(rk, key);
|
setkey_enc(rk, key);
|
||||||
encrypt_ecb(AES_NR, rk, input, output);
|
encrypt_ecb(AES_NR, rk, input, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AES_ECB_decrypt(const uint8_t* input, const uint8_t* key, uint8_t *output, const uint32_t length)
|
void AES_ECB_decrypt_buffer(const uint8_t* input, const uint8_t* key, uint8_t *output)
|
||||||
{
|
{
|
||||||
uint8_t rk[AES_RKSIZE];
|
static uint8_t rk[AES_RKSIZE];
|
||||||
|
|
||||||
if (key == NULL)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
aeshw_init();
|
aeshw_init();
|
||||||
|
if(key!=NULL)
|
||||||
setkey_dec(rk, key);
|
setkey_dec(rk, key);
|
||||||
decrypt_ecb(AES_NR, rk, input, output);
|
decrypt_ecb(AES_NR, rk, input, output);
|
||||||
}*/
|
}
|
||||||
|
|
||||||
static void encrypt_cfb( uint8_t* rk,
|
static void encrypt_cfb( uint8_t* rk,
|
||||||
uint32_t length,size_t *iv_off,
|
uint32_t length,size_t *iv_off,
|
||||||
|
@@ -12,15 +12,29 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void AES_ECB_encrypt(const uint8_t* input, const uint8_t* key, uint8_t *output, const uint32_t length)
|
void AES_ECB_encrypt_buffer(const uint8_t* input, const uint8_t* key, uint8_t *output)
|
||||||
{
|
{
|
||||||
printf("AES_ECB_encrypt not implemented\n");
|
static aes_context ctx;
|
||||||
exit(-1);
|
if(key!=0)
|
||||||
|
{
|
||||||
|
aes_init( &ctx);
|
||||||
|
aes_setkey_enc(&ctx,key,AES_KEYSIZE);
|
||||||
}
|
}
|
||||||
void AES_ECB_decrypt(const uint8_t* input, const uint8_t* key, uint8_t *output, const uint32_t length)
|
int ret=aes_crypt_ecb( &ctx, AES_ENCRYPT, (const unsigned char*)input,(unsigned char*) output );
|
||||||
|
assert(ret==0);
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
void AES_ECB_decrypt_buffer(const uint8_t* input, const uint8_t* key, uint8_t *output)
|
||||||
{
|
{
|
||||||
printf("AES_ECB_encrypt not implemented\n");
|
static aes_context ctx;
|
||||||
exit(-1);
|
if(key!=0)
|
||||||
|
{
|
||||||
|
aes_init( &ctx);
|
||||||
|
aes_setkey_dec(&ctx,key,AES_KEYSIZE);
|
||||||
|
}
|
||||||
|
int ret=aes_crypt_ecb( &ctx, AES_DECRYPT, (const unsigned char*)input,(unsigned char*) output );
|
||||||
|
assert(ret==0);
|
||||||
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AES_CBC_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)
|
void AES_CBC_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)
|
||||||
|
5
makefile
5
makefile
@@ -8,6 +8,8 @@ cc_mips24kc_le=/toolchains/lede-sdk-17.01.2-ramips-mt7621_gcc-5.4.0_musl-1.1.16.
|
|||||||
cc_arm= /toolchains/arm-2014.05/bin/arm-none-linux-gnueabi-g++
|
cc_arm= /toolchains/arm-2014.05/bin/arm-none-linux-gnueabi-g++
|
||||||
#cc_arm=/toolchains/lede-sdk-17.01.2-brcm2708-bcm2708_gcc-5.4.0_musl-1.1.16_eabi.Linux-x86_64/staging_dir/toolchain-arm_arm1176jzf-s+vfp_gcc-5.4.0_musl-1.1.16_eabi/bin/arm-openwrt-linux-muslgnueabi-g++
|
#cc_arm=/toolchains/lede-sdk-17.01.2-brcm2708-bcm2708_gcc-5.4.0_musl-1.1.16_eabi.Linux-x86_64/staging_dir/toolchain-arm_arm1176jzf-s+vfp_gcc-5.4.0_musl-1.1.16_eabi/bin/arm-openwrt-linux-muslgnueabi-g++
|
||||||
#cc_bcm2708=/home/wangyu/raspberry/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-g++
|
#cc_bcm2708=/home/wangyu/raspberry/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-g++
|
||||||
|
cc_tmp= /home/wangyu/OpenWrt-SDK-15.05-x86-64_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64/staging_dir/toolchain-x86_64_gcc-4.8-linaro_uClibc-0.9.33.2/bin/x86_64-openwrt-linux-uclibc-g++
|
||||||
|
|
||||||
FLAGS= -std=c++11 -Wall -Wextra -Wno-unused-variable -Wno-unused-parameter -Wno-missing-field-initializers ${OPT}
|
FLAGS= -std=c++11 -Wall -Wextra -Wno-unused-variable -Wno-unused-parameter -Wno-missing-field-initializers ${OPT}
|
||||||
|
|
||||||
COMMON=main.cpp lib/md5.cpp lib/pbkdf2-sha1.cpp lib/pbkdf2-sha256.cpp encrypt.cpp log.cpp network.cpp common.cpp connection.cpp misc.cpp fd_manager.cpp client.cpp server.cpp -lpthread my_ev.cpp -isystem libev
|
COMMON=main.cpp lib/md5.cpp lib/pbkdf2-sha1.cpp lib/pbkdf2-sha256.cpp encrypt.cpp log.cpp network.cpp common.cpp connection.cpp misc.cpp fd_manager.cpp client.cpp server.cpp -lpthread my_ev.cpp -isystem libev
|
||||||
@@ -35,6 +37,9 @@ debug2: git_version
|
|||||||
dynamic: git_version
|
dynamic: git_version
|
||||||
${cc_local} -o ${NAME}_$@ -I. ${SOURCES} ${FLAGS} -lrt -O3
|
${cc_local} -o ${NAME}_$@ -I. ${SOURCES} ${FLAGS} -lrt -O3
|
||||||
|
|
||||||
|
tmp:git_version
|
||||||
|
${cc_tmp} -o ${NAME}_$@ -I. ${SOURCES} ${FLAGS} -lrt -lgcc_eh -static -O3
|
||||||
|
|
||||||
mips24kc_be: git_version
|
mips24kc_be: git_version
|
||||||
${cc_mips24kc_be} -o ${NAME}_$@ -I. ${SOURCES} ${FLAGS} -lrt -lgcc_eh -static -O3
|
${cc_mips24kc_be} -o ${NAME}_$@ -I. ${SOURCES} ${FLAGS} -lrt -lgcc_eh -static -O3
|
||||||
mips24kc_be_asm_aes: git_version
|
mips24kc_be_asm_aes: git_version
|
||||||
|
18
misc.cpp
18
misc.cpp
@@ -144,6 +144,8 @@ void print_help()
|
|||||||
printf(" -g,--gen-rule generate iptables rule then exit,so that you can copy and\n");
|
printf(" -g,--gen-rule generate iptables rule then exit,so that you can copy and\n");
|
||||||
printf(" add it manually.overrides -a\n");
|
printf(" add it manually.overrides -a\n");
|
||||||
printf(" --disable-anti-replay disable anti-replay,not suggested\n");
|
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("\n");
|
//printf("\n");
|
||||||
printf("client options:\n");
|
printf("client options:\n");
|
||||||
@@ -186,7 +188,6 @@ void print_help()
|
|||||||
printf(" --clear clear any iptables rules added by this program.overrides everything\n");
|
printf(" --clear clear any iptables rules added by this program.overrides everything\n");
|
||||||
printf(" --retry-on-error retry on error, allow to start udp2raw before network is initialized\n");
|
printf(" --retry-on-error retry on error, allow to start udp2raw before network is initialized\n");
|
||||||
printf(" -h,--help print this help message\n");
|
printf(" -h,--help print this help message\n");
|
||||||
|
|
||||||
//printf("common options,these options must be same on both side\n");
|
//printf("common options,these options must be same on both side\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -298,6 +299,7 @@ void process_arg(int argc, char *argv[]) //process all options
|
|||||||
{"dev", required_argument, 0, 1},
|
{"dev", required_argument, 0, 1},
|
||||||
{"dns-resolve", no_argument, 0, 1},
|
{"dns-resolve", no_argument, 0, 1},
|
||||||
{"easy-tcp", no_argument, 0, 1},
|
{"easy-tcp", no_argument, 0, 1},
|
||||||
|
{"fix-gro", no_argument, 0, 1},
|
||||||
{NULL, 0, 0, 0}
|
{NULL, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -561,9 +563,16 @@ void process_arg(int argc, char *argv[]) //process all options
|
|||||||
}
|
}
|
||||||
else if(strcmp(long_options[option_index].name,"cipher-mode")==0)
|
else if(strcmp(long_options[option_index].name,"cipher-mode")==0)
|
||||||
{
|
{
|
||||||
|
string s=optarg;
|
||||||
|
if(s=="aes128cfb_0")
|
||||||
|
{
|
||||||
|
s="aes128cfb";
|
||||||
|
aes128cfb_old=1;
|
||||||
|
mylog(log_warn,"aes128cfb_0 is used\n");
|
||||||
|
}
|
||||||
for(i=0;i<cipher_end;i++)
|
for(i=0;i<cipher_end;i++)
|
||||||
{
|
{
|
||||||
if(strcmp(optarg,cipher_mode_tostring[i])==0)
|
if(strcmp(s.c_str(),cipher_mode_tostring[i])==0)
|
||||||
{
|
{
|
||||||
cipher_mode=(cipher_mode_t)i;
|
cipher_mode=(cipher_mode_t)i;
|
||||||
break;
|
break;
|
||||||
@@ -738,6 +747,11 @@ void process_arg(int argc, char *argv[]) //process all options
|
|||||||
use_tcp_dummy_socket=1;
|
use_tcp_dummy_socket=1;
|
||||||
mylog(log_info,"--easy-tcp enabled, now a dummy tcp socket will be created for handshake and block rst\n");
|
mylog(log_info,"--easy-tcp enabled, now a dummy tcp socket will be created for handshake and block rst\n");
|
||||||
}
|
}
|
||||||
|
else if(strcmp(long_options[option_index].name,"fix-gro")==0)
|
||||||
|
{
|
||||||
|
mylog(log_info,"--fix-gro enabled\n");
|
||||||
|
g_fix_gro=1;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mylog(log_warn,"ignored unknown long option ,option_index:%d code:<%x>\n",option_index, optopt);
|
mylog(log_warn,"ignored unknown long option ,option_index:%d code:<%x>\n",option_index, optopt);
|
||||||
|
42
network.cpp
42
network.cpp
@@ -9,6 +9,8 @@
|
|||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
|
|
||||||
|
int g_fix_gro=0;
|
||||||
|
|
||||||
int raw_recv_fd=-1;
|
int raw_recv_fd=-1;
|
||||||
int raw_send_fd=-1;
|
int raw_send_fd=-1;
|
||||||
u32_t link_level_header_len=0;//set it to 14 if SOCK_RAW is used in socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP));
|
u32_t link_level_header_len=0;//set it to 14 if SOCK_RAW is used in socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP));
|
||||||
@@ -41,7 +43,7 @@ const u32_t receive_window_lower_bound=40960;
|
|||||||
const u32_t receive_window_random_range=512;
|
const u32_t receive_window_random_range=512;
|
||||||
const unsigned char wscale=0x05;
|
const unsigned char wscale=0x05;
|
||||||
|
|
||||||
char g_packet_buf[buf_len]; //looks dirty but works well
|
char g_packet_buf[huge_buf_len]; //looks dirty but works well
|
||||||
int g_packet_buf_len=-1;
|
int g_packet_buf_len=-1;
|
||||||
int g_packet_buf_cnt=0;
|
int g_packet_buf_cnt=0;
|
||||||
|
|
||||||
@@ -832,15 +834,40 @@ int pre_recv_raw_packet()
|
|||||||
assert(g_packet_buf_cnt==0);
|
assert(g_packet_buf_cnt==0);
|
||||||
|
|
||||||
g_sockaddr_len=sizeof(g_sockaddr.ll);
|
g_sockaddr_len=sizeof(g_sockaddr.ll);
|
||||||
g_packet_buf_len = recvfrom(raw_recv_fd, g_packet_buf, max_data_len+1, 0 ,(sockaddr*)&g_sockaddr , &g_sockaddr_len);
|
g_packet_buf_len = recvfrom(raw_recv_fd, g_packet_buf, huge_data_len+1, 0 ,(sockaddr*)&g_sockaddr , &g_sockaddr_len);
|
||||||
//assert(g_sockaddr_len==sizeof(g_sockaddr.ll)); //g_sockaddr_len=18, sizeof(g_sockaddr.ll)=20, why its not equal? maybe its bc sll_halen is 6?
|
//assert(g_sockaddr_len==sizeof(g_sockaddr.ll)); //g_sockaddr_len=18, sizeof(g_sockaddr.ll)=20, why its not equal? maybe its bc sll_halen is 6?
|
||||||
|
|
||||||
//assert(g_addr_ll_size==sizeof(g_addr_ll));
|
//assert(g_addr_ll_size==sizeof(g_addr_ll));
|
||||||
|
|
||||||
if(g_packet_buf_len==max_data_len+1)
|
if(g_packet_buf_len==huge_data_len+1)
|
||||||
{
|
{
|
||||||
mylog(log_warn,"huge packet, data_len > %d,dropped\n",max_data_len);
|
if(g_fix_gro==0)
|
||||||
|
{
|
||||||
|
mylog(log_warn,"huge packet, data_len %d > %d,dropped\n",g_packet_buf_len,huge_data_len);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mylog(log_debug,"huge packet, data_len %d > %d,not dropped\n",g_packet_buf_len,huge_data_len);
|
||||||
|
g_packet_buf_len=huge_data_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(g_packet_buf_len> max_data_len+1)
|
||||||
|
{
|
||||||
|
if(g_fix_gro==0)
|
||||||
|
{
|
||||||
|
mylog(log_warn, "huge packet, data_len %d > %d(max_data_len) dropped, maybe you need to turn down mtu at upper level, or you may take a look at --fix-gro\n", g_packet_buf_len,
|
||||||
|
max_data_len);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mylog(log_debug, "huge packet, data_len %d > %d(max_data_len) not dropped\n", g_packet_buf_len,
|
||||||
|
max_data_len);
|
||||||
|
//return -1;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(g_packet_buf_len<0)
|
if(g_packet_buf_len<0)
|
||||||
@@ -1925,9 +1952,8 @@ int recv_raw_tcp(raw_info_t &raw_info,char * &payload,int &payloadlen)
|
|||||||
|
|
||||||
if(tcp_chk!=0)
|
if(tcp_chk!=0)
|
||||||
{
|
{
|
||||||
mylog(log_debug,"tcp_chk:%x\n",tcp_chk);
|
mylog(log_debug,"tcp_chk:%x, tcp checksum failed, ignored\n",tcp_chk);
|
||||||
mylog(log_debug,"tcp header error\n");
|
//return -1;
|
||||||
return -1;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2543,9 +2569,9 @@ int client_bind_to_a_new_port(int &fd,u32_t local_ip_uint32)//find a free port a
|
|||||||
int client_bind_to_a_new_port2(int &fd,const address_t& address)//find a free port and bind to it.
|
int client_bind_to_a_new_port2(int &fd,const address_t& address)//find a free port and bind to it.
|
||||||
{
|
{
|
||||||
address_t tmp=address;
|
address_t tmp=address;
|
||||||
int raw_send_port=10000+get_true_random_number()%(65535-10000);
|
|
||||||
for(int i=0;i<1000;i++)//try 1000 times at max,this should be enough
|
for(int i=0;i<1000;i++)//try 1000 times at max,this should be enough
|
||||||
{
|
{
|
||||||
|
int raw_send_port=10000+get_true_random_number()%(65535-10000);
|
||||||
tmp.set_port(raw_send_port);
|
tmp.set_port(raw_send_port);
|
||||||
if (try_to_list_and_bind2(fd,tmp)==0)
|
if (try_to_list_and_bind2(fd,tmp)==0)
|
||||||
{
|
{
|
||||||
|
@@ -27,11 +27,10 @@ extern int random_drop;
|
|||||||
|
|
||||||
extern int ifindex;
|
extern int ifindex;
|
||||||
|
|
||||||
extern char g_packet_buf[buf_len];
|
extern char g_packet_buf[huge_buf_len];
|
||||||
extern int g_packet_buf_len;
|
extern int g_packet_buf_len;
|
||||||
extern int g_packet_buf_cnt;
|
extern int g_packet_buf_cnt;
|
||||||
|
|
||||||
|
|
||||||
struct my_iphdr
|
struct my_iphdr
|
||||||
{
|
{
|
||||||
#ifdef UDP2RAW_LITTLE_ENDIAN
|
#ifdef UDP2RAW_LITTLE_ENDIAN
|
||||||
|
26
server.cpp
26
server.cpp
@@ -411,7 +411,10 @@ int server_on_raw_recv_handshake1(conn_info_t &conn_info,char * ip_port,char * d
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
int server_on_recv_safer_multi(conn_info_t &conn_info,char type,char *data,int data_len)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
int server_on_raw_recv_multi() //called when server received an raw packet
|
int server_on_raw_recv_multi() //called when server received an raw packet
|
||||||
{
|
{
|
||||||
char dummy_buf[buf_len];
|
char dummy_buf[buf_len];
|
||||||
@@ -590,13 +593,24 @@ int server_on_raw_recv_multi() //called when server received an raw packet
|
|||||||
}
|
}
|
||||||
if(conn_info.state.server_current_state==server_ready)
|
if(conn_info.state.server_current_state==server_ready)
|
||||||
{
|
{
|
||||||
char type;
|
vector<char> type_vec;
|
||||||
//mylog(log_info,"before recv_safer\n");
|
vector<string> data_vec;
|
||||||
if (recv_safer(conn_info,type, data, data_len) != 0) {
|
recv_safer_multi(conn_info,type_vec,data_vec);
|
||||||
|
if(data_vec.empty())
|
||||||
|
{
|
||||||
|
mylog(log_debug,"recv_safer failed!\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
//mylog(log_info,"after recv_safer\n");
|
|
||||||
return server_on_raw_recv_ready(conn_info,ip_port,type,data,data_len);
|
for(int i=0;i<(int)type_vec.size();i++)
|
||||||
|
{
|
||||||
|
char type=type_vec[i];
|
||||||
|
char *data=(char *)data_vec[i].c_str(); //be careful, do not append data to it
|
||||||
|
int data_len=data_vec[i].length();
|
||||||
|
server_on_raw_recv_ready(conn_info,ip_port,type,data,data_len);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(conn_info.state.server_current_state==server_idle)
|
if(conn_info.state.server_current_state==server_idle)
|
||||||
|
Reference in New Issue
Block a user