mirror of
https://github.com/wangyu-/udp2raw.git
synced 2025-09-15 19:54:28 +08:00
Compare commits
26 Commits
20170918.0
...
20171024.0
Author | SHA1 | Date | |
---|---|---|---|
|
f34f903317 | ||
|
6e1df4b39f | ||
|
c755a7d7ec | ||
|
6c0642c37e | ||
|
740e10bd04 | ||
|
a549793d82 | ||
|
a989a9f381 | ||
|
54f32f0611 | ||
|
9e173f9513 | ||
|
452661b389 | ||
|
dcde8828c4 | ||
|
fc05e7f080 | ||
|
f096a510b5 | ||
|
8de2506eff | ||
|
3960ca1b36 | ||
|
d778be2bfc | ||
|
0e77b0d5ab | ||
|
545f9796aa | ||
|
32ad8df38d | ||
|
3b0a4c7d08 | ||
|
61d48253f1 | ||
|
e1a97c03b5 | ||
|
6c6b4d2284 | ||
|
3eaf3e908e | ||
|
35603a69e8 | ||
|
4615ab6364 |
13
Dockerfile
Normal file
13
Dockerfile
Normal file
@@ -0,0 +1,13 @@
|
||||
FROM alpine:3.6 as builder
|
||||
|
||||
WORKDIR /
|
||||
|
||||
RUN apk add --no-cache git build-base linux-headers && \
|
||||
git clone https://github.com/wangyu-/udp2raw-tunnel.git && \
|
||||
cd udp2raw-tunnel && \
|
||||
make dynamic
|
||||
|
||||
FROM alpine:3.6
|
||||
RUN apk add --no-cache libstdc++ iptables
|
||||
COPY --from=builder /udp2raw-tunnel/udp2raw_dynamic /bin/
|
||||
ENTRYPOINT [ "/bin/udp2raw_dynamic" ]
|
@@ -94,7 +94,7 @@ You can run udp2raw with a non-root account(for better security).Take a look at
|
||||
### Usage
|
||||
```
|
||||
udp2raw-tunnel
|
||||
git version:adbe7d110f build date:Sep 6 2017 05:37:45
|
||||
git version:6e1df4b39f build date:Oct 24 2017 09:21:15
|
||||
repository: https://github.com/wangyu-/udp2raw-tunnel
|
||||
|
||||
usage:
|
||||
@@ -117,7 +117,9 @@ client options:
|
||||
other options:
|
||||
--conf-file <string> read options from a configuration file instead of command line.
|
||||
check example.conf in repo for format
|
||||
--log-level <number> 0:never 1:fatal 2:error 3:warn
|
||||
--fifo <string> use a fifo(named pipe) for sending commands to the running program,
|
||||
check readme.md in repository for supported commands.
|
||||
--log-level <number> 0:never 1:fatal 2:error 3:warn
|
||||
4:info (default) 5:debug 6:trace
|
||||
--log-position enable file name,function name,line number in log
|
||||
--disable-color disable log color
|
||||
@@ -131,7 +133,7 @@ other options:
|
||||
2:increase seq randomly, about every 3 packets,simply ack last seq
|
||||
3:simulate an almost real seq/ack procedure(default)
|
||||
4:similiar to 3,but do not consider TCP Option Window_Scale,
|
||||
maybe useful when firewall doesnt support TCP Option
|
||||
maybe useful when firewall doesnt support TCP Option
|
||||
--lower-level <string> send packets at OSI level 2, format:'if_name#dest_mac_adress'
|
||||
ie:'eth0#00:23:45:67:89:b9'.or try '--lower-level auto' to obtain
|
||||
the parameter automatically,specify it manually if 'auto' failed
|
||||
|
@@ -2,10 +2,11 @@ cmake_minimum_required(VERSION 3.7)
|
||||
project(udp2raw_tunnel)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set_source_files_properties(lib/aes.c lib/md5.c PROPERTIES LANGUAGE CXX )
|
||||
set_source_files_properties(lib/aes_faster_c/aes.c lib/aes_faster_c/wrapper.c lib/md5.c PROPERTIES LANGUAGE CXX )
|
||||
|
||||
set(SOURCE_FILES
|
||||
lib/aes.c
|
||||
lib/aes_faster_c/aes.c
|
||||
lib/aes_faster_c/wrapper.c
|
||||
lib/md5.c
|
||||
common.cpp
|
||||
encrypt.cpp
|
||||
|
267
common.cpp
267
common.cpp
@@ -7,26 +7,10 @@
|
||||
|
||||
#include "common.h"
|
||||
#include "log.h"
|
||||
#include "misc.h"
|
||||
|
||||
|
||||
|
||||
int about_to_exit=0;
|
||||
|
||||
raw_mode_t raw_mode=mode_faketcp;
|
||||
unordered_map<int, const char*> raw_mode_tostring = {{mode_faketcp, "faketcp"}, {mode_udp, "udp"}, {mode_icmp, "icmp"}};
|
||||
int socket_buf_size=1024*1024;
|
||||
int force_socket_buf=0;
|
||||
|
||||
static int random_number_fd=-1;
|
||||
string iptables_pattern="";
|
||||
int iptables_rule_added=0;
|
||||
int iptables_rule_keeped=0;
|
||||
int iptables_rule_keep_index=0;
|
||||
//int iptables_rule_no_clear=0;
|
||||
|
||||
|
||||
|
||||
program_mode_t program_mode=unset_mode;//0 unset; 1client 2server
|
||||
|
||||
u64_t get_current_time()
|
||||
{
|
||||
@@ -58,167 +42,6 @@ char * my_ntoa(u32_t ip)
|
||||
return inet_ntoa(a);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
int add_iptables_rule(const char * s)
|
||||
{
|
||||
|
||||
iptables_pattern=s;
|
||||
|
||||
string rule="iptables -I INPUT ";
|
||||
rule+=iptables_pattern;
|
||||
rule+=" -j DROP";
|
||||
|
||||
char *output;
|
||||
if(run_command(rule.c_str(),output)==0)
|
||||
{
|
||||
mylog(log_warn,"auto added iptables rule by: %s\n",rule.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
mylog(log_fatal,"auto added iptables failed by: %s\n",rule.c_str());
|
||||
//mylog(log_fatal,"reason : %s\n",strerror(errno));
|
||||
myexit(-1);
|
||||
}
|
||||
iptables_rule_added=1;
|
||||
return 0;
|
||||
}*/
|
||||
string chain[2];
|
||||
string rule_keep[2];
|
||||
string rule_keep_add[2];
|
||||
string rule_keep_del[2];
|
||||
u64_t keep_rule_last_time=0;
|
||||
|
||||
pthread_t keep_thread;
|
||||
int keep_thread_running=0;
|
||||
int iptables_gen_add(const char * s,u32_t const_id)
|
||||
{
|
||||
string dummy="";
|
||||
iptables_pattern=s;
|
||||
chain[0] =dummy+ "udp2rawDwrW_C";
|
||||
rule_keep[0]=dummy+ iptables_pattern+" -j " +chain[0];
|
||||
rule_keep_add[0]=dummy+"iptables -I INPUT "+rule_keep[0];
|
||||
|
||||
char *output;
|
||||
run_command(dummy+"iptables -N "+chain[0],output,show_none);
|
||||
run_command(dummy+"iptables -F "+chain[0],output);
|
||||
run_command(dummy+"iptables -I "+chain[0] + " -j DROP",output);
|
||||
|
||||
rule_keep_del[0]=dummy+"iptables -D INPUT "+rule_keep[0];
|
||||
|
||||
run_command(rule_keep_del[0],output,show_none);
|
||||
run_command(rule_keep_del[0],output,show_none);
|
||||
|
||||
if(run_command(rule_keep_add[0],output)!=0)
|
||||
{
|
||||
mylog(log_fatal,"auto added iptables failed by: %s\n",rule_keep_add[0].c_str());
|
||||
myexit(-1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int iptables_rule_init(const char * s,u32_t const_id,int keep)
|
||||
{
|
||||
iptables_pattern=s;
|
||||
iptables_rule_added=1;
|
||||
iptables_rule_keeped=keep;
|
||||
|
||||
string dummy="";
|
||||
char const_id_str[100];
|
||||
sprintf(const_id_str, "%x", const_id);
|
||||
|
||||
chain[0] =dummy+ "udp2rawDwrW_"+const_id_str+"_C0";
|
||||
chain[1] =dummy+ "udp2rawDwrW_"+const_id_str+"_C1";
|
||||
|
||||
rule_keep[0]=dummy+ iptables_pattern+" -j " +chain[0];
|
||||
rule_keep[1]=dummy+ iptables_pattern+" -j " +chain[1];
|
||||
|
||||
rule_keep_add[0]=dummy+"iptables -I INPUT "+rule_keep[0];
|
||||
rule_keep_add[1]=dummy+"iptables -I INPUT "+rule_keep[1];
|
||||
|
||||
rule_keep_del[0]=dummy+"iptables -D INPUT "+rule_keep[0];
|
||||
rule_keep_del[1]=dummy+"iptables -D INPUT "+rule_keep[1];
|
||||
|
||||
keep_rule_last_time=get_current_time();
|
||||
|
||||
char *output;
|
||||
|
||||
for(int i=0;i<=iptables_rule_keeped;i++)
|
||||
{
|
||||
run_command(dummy+"iptables -N "+chain[i],output);
|
||||
run_command(dummy+"iptables -F "+chain[i],output);
|
||||
run_command(dummy+"iptables -I "+chain[i] + " -j DROP",output);
|
||||
|
||||
if(run_command(rule_keep_add[i],output)!=0)
|
||||
{
|
||||
mylog(log_fatal,"auto added iptables failed by: %s\n",rule_keep_add[i].c_str());
|
||||
myexit(-1);
|
||||
}
|
||||
}
|
||||
mylog(log_warn,"auto added iptables rules\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int keep_iptables_rule() //magic to work on a machine without grep/iptables --check/-m commment
|
||||
{
|
||||
/*
|
||||
if(iptables_rule_keeped==0) return 0;
|
||||
|
||||
|
||||
uint64_t tmp_current_time=get_current_time();
|
||||
if(tmp_current_time-keep_rule_last_time<=iptables_rule_keep_interval)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
keep_rule_last_time=tmp_current_time;
|
||||
}*/
|
||||
|
||||
mylog(log_debug,"keep_iptables_rule begin %llu\n",get_current_time());
|
||||
iptables_rule_keep_index+=1;
|
||||
iptables_rule_keep_index%=2;
|
||||
|
||||
string dummy="";
|
||||
char *output;
|
||||
|
||||
int i=iptables_rule_keep_index;
|
||||
|
||||
run_command(dummy + "iptables -N " + chain[i], output,show_none);
|
||||
|
||||
if (run_command(dummy + "iptables -F " + chain[i], output,show_none) != 0)
|
||||
mylog(log_warn, "iptables -F failed %d\n",i);
|
||||
|
||||
if (run_command(dummy + "iptables -I " + chain[i] + " -j DROP",output,show_none) != 0)
|
||||
mylog(log_warn, "iptables -I failed %d\n",i);
|
||||
|
||||
if (run_command(rule_keep_del[i], output,show_none) != 0)
|
||||
mylog(log_warn, "rule_keep_del failed %d\n",i);
|
||||
|
||||
run_command(rule_keep_del[i], output,show_none); //do it twice,incase it fails for unknown random reason
|
||||
|
||||
if(run_command(rule_keep_add[i], output,show_log)!=0)
|
||||
mylog(log_warn, "rule_keep_del failed %d\n",i);
|
||||
|
||||
mylog(log_debug,"keep_iptables_rule end %llu\n",get_current_time());
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clear_iptables_rule()
|
||||
{
|
||||
char *output;
|
||||
string dummy="";
|
||||
if(!iptables_rule_added) return 0;
|
||||
|
||||
for(int i=0;i<=iptables_rule_keeped;i++ )
|
||||
{
|
||||
run_command(rule_keep_del[i],output);
|
||||
run_command(dummy+"iptables -F "+chain[i],output);
|
||||
run_command(dummy+"iptables -X "+chain[i],output);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void init_random_number_fd()
|
||||
{
|
||||
|
||||
@@ -326,8 +149,7 @@ unsigned short csum(const unsigned short *ptr,int nbytes) {//works both for big
|
||||
return(answer);
|
||||
}
|
||||
|
||||
|
||||
int set_buf_size(int fd)
|
||||
int set_buf_size(int fd,int socket_buf_size,int force_socket_buf)
|
||||
{
|
||||
if(force_socket_buf)
|
||||
{
|
||||
@@ -358,30 +180,6 @@ int set_buf_size(int fd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void myexit(int a)
|
||||
{
|
||||
if(enable_log_color)
|
||||
printf("%s\n",RESET);
|
||||
if(keep_thread_running)
|
||||
{
|
||||
if(pthread_cancel(keep_thread))
|
||||
{
|
||||
mylog(log_warn,"pthread_cancel failed\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
mylog(log_info,"pthread_cancel success\n");
|
||||
}
|
||||
}
|
||||
clear_iptables_rule();
|
||||
exit(a);
|
||||
}
|
||||
void signal_handler(int sig)
|
||||
{
|
||||
about_to_exit=1;
|
||||
// myexit(0);
|
||||
}
|
||||
|
||||
int numbers_to_char(id_t id1,id_t id2,id_t id3,char * &data,int &len)
|
||||
{
|
||||
static char buf[buf_len];
|
||||
@@ -399,7 +197,6 @@ int numbers_to_char(id_t id1,id_t id2,id_t id3,char * &data,int &len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int char_to_numbers(const char * data,int len,id_t &id1,id_t &id2,id_t &id3)
|
||||
{
|
||||
if(len<int(sizeof(id_t)*3)) return -1;
|
||||
@@ -502,6 +299,26 @@ bool larger_than_u16(uint16_t a,uint16_t b)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void myexit(int a)
|
||||
{
|
||||
if(enable_log_color)
|
||||
printf("%s\n",RESET);
|
||||
if(keep_thread_running)
|
||||
{
|
||||
if(pthread_cancel(keep_thread))
|
||||
{
|
||||
mylog(log_warn,"pthread_cancel failed\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
mylog(log_info,"pthread_cancel success\n");
|
||||
}
|
||||
}
|
||||
clear_iptables_rule();
|
||||
exit(a);
|
||||
}
|
||||
|
||||
vector<string> string_to_vec(const char * s,const char * sp) {
|
||||
vector<string> res;
|
||||
string str=s;
|
||||
@@ -739,10 +556,42 @@ vector<string> parse_conf_line(const string& s0)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int create_fifo(char * file)
|
||||
{
|
||||
if(mkfifo (file, 0666)!=0)
|
||||
{
|
||||
if(errno==EEXIST)
|
||||
{
|
||||
mylog(log_warn,"warning fifo file %s exist\n",file);
|
||||
}
|
||||
else
|
||||
{
|
||||
mylog(log_fatal,"create fifo file %s failed\n",file);
|
||||
myexit(-1);
|
||||
}
|
||||
}
|
||||
int fifo_fd=open (file, O_RDWR);
|
||||
if(fifo_fd<0)
|
||||
{
|
||||
mylog(log_fatal,"create fifo file %s failed\n",file);
|
||||
myexit(-1);
|
||||
}
|
||||
struct stat st;
|
||||
if (fstat(fifo_fd, &st)!=0)
|
||||
{
|
||||
mylog(log_fatal,"fstat failed for fifo file %s\n",file);
|
||||
myexit(-1);
|
||||
}
|
||||
|
||||
if(!S_ISFIFO(st.st_mode))
|
||||
{
|
||||
mylog(log_fatal,"%s is not a fifo\n",file);
|
||||
myexit(-1);
|
||||
}
|
||||
|
||||
setnonblocking(fifo_fd);
|
||||
return fifo_fd;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
83
common.h
83
common.h
@@ -21,6 +21,7 @@
|
||||
#include <sys/wait.h>
|
||||
#include <sys/socket.h> //for socket ofcourse
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h> //for exit(0);
|
||||
#include <errno.h> //For errno - the error number
|
||||
#include <netinet/tcp.h> //Provides declarations for tcp header
|
||||
@@ -47,8 +48,11 @@
|
||||
#include <pthread.h>
|
||||
|
||||
#include<unordered_map>
|
||||
#include<vector>
|
||||
#include<string>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
using namespace std;
|
||||
|
||||
|
||||
@@ -58,57 +62,6 @@ typedef long long i64_t;
|
||||
typedef unsigned int u32_t;
|
||||
typedef int i32_t;
|
||||
|
||||
|
||||
const int max_data_len=1600;
|
||||
const int buf_len=max_data_len+400;
|
||||
const u32_t max_handshake_conn_num=10000;
|
||||
const u32_t max_ready_conn_num=1000;
|
||||
const u32_t anti_replay_window_size=4000;
|
||||
const int max_conv_num=10000;
|
||||
|
||||
const u32_t client_handshake_timeout=5000;//unit ms
|
||||
const u32_t client_retry_interval=1000;//ms
|
||||
|
||||
const u32_t server_handshake_timeout=client_handshake_timeout+5000;// this should be longer than clients. client retry initially ,server retry passtively
|
||||
|
||||
const int conv_clear_ratio=10; //conv grabage collecter check 1/10 of all conv one time
|
||||
const int conn_clear_ratio=30;
|
||||
const int conv_clear_min=1;
|
||||
const int conn_clear_min=1;
|
||||
|
||||
const u32_t conv_clear_interval=3000;//ms
|
||||
const u32_t conn_clear_interval=3000;//ms
|
||||
|
||||
|
||||
const i32_t max_fail_time=0;//disable
|
||||
|
||||
const u32_t heartbeat_interval=1000;//ms
|
||||
|
||||
const u32_t timer_interval=400;//ms. this should be smaller than heartbeat_interval and retry interval;
|
||||
|
||||
const uint32_t conv_timeout=120000; //ms. 120 second
|
||||
//const u32_t conv_timeout=30000; //for test
|
||||
|
||||
const u32_t client_conn_timeout=15000;//ms.
|
||||
const u32_t client_conn_uplink_timeout=client_conn_timeout+2000;//ms
|
||||
|
||||
const uint32_t server_conn_timeout=conv_timeout+60000;//ms. this should be 60s+ longer than conv_timeout,so that conv_manager can destruct convs gradually,to avoid latency glicth
|
||||
//const u32_t server_conn_timeout=conv_timeout+10000;//for test
|
||||
|
||||
const u32_t iptables_rule_keep_interval=15;//unit: second;
|
||||
|
||||
extern int about_to_exit;
|
||||
extern pthread_t keep_thread;
|
||||
extern int keep_thread_running;
|
||||
|
||||
enum raw_mode_t{mode_faketcp=0,mode_udp,mode_icmp,mode_end};
|
||||
extern raw_mode_t raw_mode;
|
||||
enum program_mode_t {unset_mode=0,client_mode,server_mode};
|
||||
extern program_mode_t program_mode;
|
||||
extern unordered_map<int, const char*> raw_mode_tostring ;
|
||||
extern int socket_buf_size;
|
||||
extern int force_socket_buf;
|
||||
|
||||
typedef u32_t id_t;
|
||||
|
||||
typedef u64_t iv_t;
|
||||
@@ -117,6 +70,9 @@ typedef u64_t padding_t;
|
||||
|
||||
typedef u64_t anti_replay_seq_t;
|
||||
|
||||
const int max_data_len=1600;
|
||||
const int buf_len=max_data_len+400;
|
||||
|
||||
u64_t get_current_time();
|
||||
u64_t pack_u64(u32_t a,u32_t b);
|
||||
|
||||
@@ -126,7 +82,6 @@ u32_t get_u64_l(u64_t a);
|
||||
|
||||
char * my_ntoa(u32_t ip);
|
||||
|
||||
void myexit(int a);
|
||||
void init_random_number_fd();
|
||||
u64_t get_true_random_number_64();
|
||||
u32_t get_true_random_number();
|
||||
@@ -136,28 +91,20 @@ u64_t hton64(u64_t a);
|
||||
bool larger_than_u16(uint16_t a,uint16_t b);
|
||||
bool larger_than_u32(u32_t a,u32_t b);
|
||||
void setnonblocking(int sock);
|
||||
int set_buf_size(int fd);
|
||||
|
||||
unsigned short csum(const unsigned short *ptr,int nbytes);
|
||||
|
||||
void signal_handler(int sig);
|
||||
int numbers_to_char(id_t id1,id_t id2,id_t id3,char * &data,int &len);
|
||||
int char_to_numbers(const char * data,int len,id_t &id1,id_t &id2,id_t &id3);
|
||||
int set_buf_size(int fd,int socket_buf_size,int force_socket_buf);
|
||||
|
||||
void myexit(int a);
|
||||
|
||||
int add_iptables_rule(const char *);
|
||||
unsigned short csum(const unsigned short *ptr,int nbytes);
|
||||
|
||||
int clear_iptables_rule();
|
||||
|
||||
int iptables_gen_add(const char * s,u32_t const_id);
|
||||
int iptables_rule_init(const char * s,u32_t const_id,int keep);
|
||||
int keep_iptables_rule();
|
||||
int numbers_to_char(id_t id1,id_t id2,id_t id3,char * &data,int &len);
|
||||
int char_to_numbers(const char * data,int len,id_t &id1,id_t &id2,id_t &id3);
|
||||
|
||||
const int show_none=0;
|
||||
const int show_command=0x1;
|
||||
const int show_log=0x2;
|
||||
const int show_all=show_command|show_log;
|
||||
|
||||
int run_command(string command,char * &output,int flag=show_all);
|
||||
//int run_command_no_log(string command,char * &output);
|
||||
int read_file(const char * file,string &output);
|
||||
@@ -175,4 +122,6 @@ int hex_to_u32_with_endian(const string & a,u32_t &output);
|
||||
int hex_to_u32(const string & a,u32_t &output);
|
||||
//extern string iptables_pattern;
|
||||
|
||||
int create_fifo(char * file);
|
||||
|
||||
#endif /* COMMON_H_ */
|
||||
|
748
connection.cpp
Normal file
748
connection.cpp
Normal file
@@ -0,0 +1,748 @@
|
||||
/*
|
||||
* connection.cpp
|
||||
*
|
||||
* Created on: Sep 23, 2017
|
||||
* Author: root
|
||||
*/
|
||||
|
||||
#include "connection.h"
|
||||
#include "encrypt.h"
|
||||
|
||||
|
||||
int disable_anti_replay=0;//if anti_replay windows is diabled
|
||||
|
||||
const int disable_conv_clear=0;//a udp connection in the multiplexer is called conversation in this program,conv for short.
|
||||
|
||||
const int disable_conn_clear=0;//a raw connection is called conn.
|
||||
|
||||
conn_manager_t conn_manager;
|
||||
|
||||
anti_replay_seq_t anti_replay_t::get_new_seq_for_send()
|
||||
{
|
||||
return anti_replay_seq++;
|
||||
}
|
||||
anti_replay_t::anti_replay_t()
|
||||
{
|
||||
max_packet_received=0;
|
||||
anti_replay_seq=get_true_random_number_64()/10;//random first seq
|
||||
//memset(window,0,sizeof(window)); //not necessary
|
||||
}
|
||||
void anti_replay_t::re_init()
|
||||
{
|
||||
max_packet_received=0;
|
||||
//memset(window,0,sizeof(window));
|
||||
}
|
||||
|
||||
int anti_replay_t::is_vaild(u64_t seq)
|
||||
{
|
||||
if(disable_anti_replay) return 1;
|
||||
//if(disabled) return 0;
|
||||
|
||||
if(seq==max_packet_received) return 0;
|
||||
else if(seq>max_packet_received)
|
||||
{
|
||||
if(seq-max_packet_received>=anti_replay_window_size)
|
||||
{
|
||||
memset(window,0,sizeof(window));
|
||||
window[seq%anti_replay_window_size]=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (u64_t i=max_packet_received+1;i<seq;i++)
|
||||
window[i%anti_replay_window_size]=0;
|
||||
window[seq%anti_replay_window_size]=1;
|
||||
}
|
||||
max_packet_received=seq;
|
||||
return 1;
|
||||
}
|
||||
else if(seq<max_packet_received)
|
||||
{
|
||||
if(max_packet_received-seq>=anti_replay_window_size) return 0;
|
||||
else
|
||||
{
|
||||
if (window[seq%anti_replay_window_size]==1) return 0;
|
||||
else
|
||||
{
|
||||
window[seq%anti_replay_window_size]=1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 0; //for complier check
|
||||
}
|
||||
|
||||
|
||||
void server_clear_function(u64_t u64);
|
||||
|
||||
conv_manager_t::conv_manager_t()
|
||||
{
|
||||
clear_it=conv_last_active_time.begin();
|
||||
long long last_clear_time=0;
|
||||
//clear_function=0;
|
||||
}
|
||||
conv_manager_t::~conv_manager_t()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
int conv_manager_t::get_size()
|
||||
{
|
||||
return conv_to_u64.size();
|
||||
}
|
||||
void conv_manager_t::reserve()
|
||||
{
|
||||
u64_to_conv.reserve(10007);
|
||||
conv_to_u64.reserve(10007);
|
||||
conv_last_active_time.reserve(10007);
|
||||
}
|
||||
void conv_manager_t::clear()
|
||||
{
|
||||
if(disable_conv_clear) return ;
|
||||
|
||||
if(program_mode==server_mode)
|
||||
{
|
||||
for(it=conv_to_u64.begin();it!=conv_to_u64.end();it++)
|
||||
{
|
||||
//int fd=int((it->second<<32u)>>32u);
|
||||
server_clear_function( it->second);
|
||||
}
|
||||
}
|
||||
u64_to_conv.clear();
|
||||
conv_to_u64.clear();
|
||||
conv_last_active_time.clear();
|
||||
|
||||
clear_it=conv_last_active_time.begin();
|
||||
|
||||
}
|
||||
u32_t conv_manager_t::get_new_conv()
|
||||
{
|
||||
u32_t conv=get_true_random_number_nz();
|
||||
while(conv_to_u64.find(conv)!=conv_to_u64.end())
|
||||
{
|
||||
conv=get_true_random_number_nz();
|
||||
}
|
||||
return conv;
|
||||
}
|
||||
int conv_manager_t::is_conv_used(u32_t conv)
|
||||
{
|
||||
return conv_to_u64.find(conv)!=conv_to_u64.end();
|
||||
}
|
||||
int conv_manager_t::is_u64_used(u64_t u64)
|
||||
{
|
||||
return u64_to_conv.find(u64)!=u64_to_conv.end();
|
||||
}
|
||||
u32_t conv_manager_t::find_conv_by_u64(u64_t u64)
|
||||
{
|
||||
return u64_to_conv[u64];
|
||||
}
|
||||
u64_t conv_manager_t::find_u64_by_conv(u32_t conv)
|
||||
{
|
||||
return conv_to_u64[conv];
|
||||
}
|
||||
int conv_manager_t::update_active_time(u32_t conv)
|
||||
{
|
||||
return conv_last_active_time[conv]=get_current_time();
|
||||
}
|
||||
int conv_manager_t::insert_conv(u32_t conv,u64_t u64)
|
||||
{
|
||||
u64_to_conv[u64]=conv;
|
||||
conv_to_u64[conv]=u64;
|
||||
conv_last_active_time[conv]=get_current_time();
|
||||
return 0;
|
||||
}
|
||||
int conv_manager_t::erase_conv(u32_t conv)
|
||||
{
|
||||
if(disable_conv_clear) return 0;
|
||||
u64_t u64=conv_to_u64[conv];
|
||||
if(program_mode==server_mode)
|
||||
{
|
||||
server_clear_function(u64);
|
||||
}
|
||||
conv_to_u64.erase(conv);
|
||||
u64_to_conv.erase(u64);
|
||||
conv_last_active_time.erase(conv);
|
||||
return 0;
|
||||
}
|
||||
int conv_manager_t::clear_inactive(char * ip_port)
|
||||
{
|
||||
if(get_current_time()-last_clear_time>conv_clear_interval)
|
||||
{
|
||||
last_clear_time=get_current_time();
|
||||
return clear_inactive0(ip_port);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int conv_manager_t::clear_inactive0(char * ip_port)
|
||||
{
|
||||
if(disable_conv_clear) return 0;
|
||||
|
||||
|
||||
//map<uint32_t,uint64_t>::iterator it;
|
||||
int cnt=0;
|
||||
it=clear_it;
|
||||
int size=conv_last_active_time.size();
|
||||
int num_to_clean=size/conv_clear_ratio+conv_clear_min; //clear 1/10 each time,to avoid latency glitch
|
||||
|
||||
num_to_clean=min(num_to_clean,size);
|
||||
|
||||
u64_t current_time=get_current_time();
|
||||
for(;;)
|
||||
{
|
||||
if(cnt>=num_to_clean) break;
|
||||
if(conv_last_active_time.begin()==conv_last_active_time.end()) break;
|
||||
|
||||
if(it==conv_last_active_time.end())
|
||||
{
|
||||
it=conv_last_active_time.begin();
|
||||
}
|
||||
|
||||
if( current_time -it->second >conv_timeout )
|
||||
{
|
||||
//mylog(log_info,"inactive conv %u cleared \n",it->first);
|
||||
old_it=it;
|
||||
it++;
|
||||
u32_t conv= old_it->first;
|
||||
erase_conv(old_it->first);
|
||||
if(ip_port==0)
|
||||
{
|
||||
mylog(log_info,"conv %x cleared\n",conv);
|
||||
}
|
||||
else
|
||||
{
|
||||
mylog(log_info,"[%s]conv %x cleared\n",ip_port,conv);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
it++;
|
||||
}
|
||||
cnt++;
|
||||
}
|
||||
clear_it=it;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void conn_info_t::recover(const conn_info_t &conn_info)
|
||||
{
|
||||
raw_info=conn_info.raw_info;
|
||||
last_state_time=conn_info.last_state_time;
|
||||
last_hb_recv_time=conn_info.last_hb_recv_time;
|
||||
last_hb_sent_time=conn_info.last_hb_sent_time;
|
||||
my_id=conn_info.my_id;
|
||||
oppsite_id=conn_info.oppsite_id;
|
||||
blob->anti_replay.re_init();
|
||||
|
||||
my_roller=0;//no need to set,but for easier debug,set it to zero
|
||||
oppsite_roller=0;//same as above
|
||||
last_oppsite_roller_time=0;
|
||||
}
|
||||
|
||||
void conn_info_t::re_init()
|
||||
{
|
||||
//send_packet_info.protocol=g_packet_info_send.protocol;
|
||||
if(program_mode==server_mode)
|
||||
state.server_current_state=server_idle;
|
||||
else
|
||||
state.client_current_state=client_idle;
|
||||
last_state_time=0;
|
||||
oppsite_const_id=0;
|
||||
|
||||
timer_fd=0;
|
||||
|
||||
my_roller=0;
|
||||
oppsite_roller=0;
|
||||
last_oppsite_roller_time=0;
|
||||
}
|
||||
conn_info_t::conn_info_t()
|
||||
{
|
||||
blob=0;
|
||||
re_init();
|
||||
}
|
||||
void conn_info_t::prepare()
|
||||
{
|
||||
blob=new blob_t;
|
||||
|
||||
}
|
||||
conn_info_t::conn_info_t(const conn_info_t&b)
|
||||
{
|
||||
//mylog(log_error,"called!!!!!!!!!!!!!\n");
|
||||
*this=b;
|
||||
if(blob!=0)
|
||||
{
|
||||
blob=new blob_t(*b.blob);
|
||||
}
|
||||
}
|
||||
conn_info_t& conn_info_t::operator=(const conn_info_t& b)
|
||||
{
|
||||
mylog(log_fatal,"not allowed\n");
|
||||
myexit(-1);
|
||||
return *this;
|
||||
}
|
||||
conn_info_t::~conn_info_t()
|
||||
{
|
||||
if(program_mode==server_mode)
|
||||
{
|
||||
if(state.server_current_state==server_ready)
|
||||
{
|
||||
assert(blob!=0);
|
||||
assert(oppsite_const_id!=0);
|
||||
//assert(conn_manager.const_id_mp.find(oppsite_const_id)!=conn_manager.const_id_mp.end()); // conn_manager 's deconstuction function erases it
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(blob==0);
|
||||
assert(oppsite_const_id==0);
|
||||
}
|
||||
}
|
||||
//if(oppsite_const_id!=0) //do this at conn_manager 's deconstuction function
|
||||
//conn_manager.const_id_mp.erase(oppsite_const_id);
|
||||
if(blob!=0)
|
||||
delete blob;
|
||||
|
||||
//send_packet_info.protocol=g_packet_info_send.protocol;
|
||||
}
|
||||
|
||||
|
||||
conn_manager_t::conn_manager_t()
|
||||
{
|
||||
ready_num=0;
|
||||
mp.reserve(10007);
|
||||
clear_it=mp.begin();
|
||||
timer_fd_mp.reserve(10007);
|
||||
const_id_mp.reserve(10007);
|
||||
udp_fd_mp.reserve(100007);
|
||||
last_clear_time=0;
|
||||
//current_ready_ip=0;
|
||||
// current_ready_port=0;
|
||||
}
|
||||
int conn_manager_t::exist(u32_t ip,uint16_t port)
|
||||
{
|
||||
u64_t u64=0;
|
||||
u64=ip;
|
||||
u64<<=32u;
|
||||
u64|=port;
|
||||
if(mp.find(u64)!=mp.end())
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
int insert(uint32_t ip,uint16_t port)
|
||||
{
|
||||
uint64_t u64=0;
|
||||
u64=ip;
|
||||
u64<<=32u;
|
||||
u64|=port;
|
||||
mp[u64];
|
||||
return 0;
|
||||
}*/
|
||||
conn_info_t *& conn_manager_t::find_insert_p(u32_t ip,uint16_t port) //be aware,the adress may change after rehash
|
||||
{
|
||||
u64_t u64=0;
|
||||
u64=ip;
|
||||
u64<<=32u;
|
||||
u64|=port;
|
||||
unordered_map<u64_t,conn_info_t*>::iterator it=mp.find(u64);
|
||||
if(it==mp.end())
|
||||
{
|
||||
mp[u64]=new conn_info_t;
|
||||
}
|
||||
return mp[u64];
|
||||
}
|
||||
conn_info_t & conn_manager_t::find_insert(u32_t ip,uint16_t port) //be aware,the adress may change after rehash
|
||||
{
|
||||
u64_t u64=0;
|
||||
u64=ip;
|
||||
u64<<=32u;
|
||||
u64|=port;
|
||||
unordered_map<u64_t,conn_info_t*>::iterator it=mp.find(u64);
|
||||
if(it==mp.end())
|
||||
{
|
||||
mp[u64]=new conn_info_t;
|
||||
}
|
||||
return *mp[u64];
|
||||
}
|
||||
int conn_manager_t::erase(unordered_map<u64_t,conn_info_t*>::iterator erase_it)
|
||||
{
|
||||
if(erase_it->second->state.server_current_state==server_ready)
|
||||
{
|
||||
ready_num--;
|
||||
assert(i32_t(ready_num)!=-1);
|
||||
assert(erase_it->second!=0);
|
||||
assert(erase_it->second->timer_fd !=0);
|
||||
assert(erase_it->second->oppsite_const_id!=0);
|
||||
assert(const_id_mp.find(erase_it->second->oppsite_const_id)!=const_id_mp.end());
|
||||
assert(timer_fd_mp.find(erase_it->second->timer_fd)!=timer_fd_mp.end());
|
||||
|
||||
const_id_mp.erase(erase_it->second->oppsite_const_id);
|
||||
timer_fd_mp.erase(erase_it->second->timer_fd);
|
||||
close(erase_it->second->timer_fd);// close will auto delte it from epoll
|
||||
delete(erase_it->second);
|
||||
mp.erase(erase_it->first);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(erase_it->second->blob==0);
|
||||
assert(erase_it->second->timer_fd ==0);
|
||||
assert(erase_it->second->oppsite_const_id==0);
|
||||
delete(erase_it->second);
|
||||
mp.erase(erase_it->first);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int conn_manager_t::clear_inactive()
|
||||
{
|
||||
if(get_current_time()-last_clear_time>conn_clear_interval)
|
||||
{
|
||||
last_clear_time=get_current_time();
|
||||
return clear_inactive0();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int conn_manager_t::clear_inactive0()
|
||||
{
|
||||
unordered_map<u64_t,conn_info_t*>::iterator it;
|
||||
unordered_map<u64_t,conn_info_t*>::iterator old_it;
|
||||
|
||||
if(disable_conn_clear) return 0;
|
||||
|
||||
//map<uint32_t,uint64_t>::iterator it;
|
||||
int cnt=0;
|
||||
it=clear_it;
|
||||
int size=mp.size();
|
||||
int num_to_clean=size/conn_clear_ratio+conn_clear_min; //clear 1/10 each time,to avoid latency glitch
|
||||
|
||||
mylog(log_trace,"mp.size() %d\n", size);
|
||||
|
||||
num_to_clean=min(num_to_clean,(int)mp.size());
|
||||
u64_t current_time=get_current_time();
|
||||
|
||||
for(;;)
|
||||
{
|
||||
if(cnt>=num_to_clean) break;
|
||||
if(mp.begin()==mp.end()) break;
|
||||
|
||||
if(it==mp.end())
|
||||
{
|
||||
it=mp.begin();
|
||||
}
|
||||
|
||||
if(it->second->state.server_current_state==server_ready &¤t_time - it->second->last_hb_recv_time <=server_conn_timeout)
|
||||
{
|
||||
it++;
|
||||
}
|
||||
else if(it->second->state.server_current_state!=server_ready&& current_time - it->second->last_state_time <=server_handshake_timeout )
|
||||
{
|
||||
it++;
|
||||
}
|
||||
else if(it->second->blob!=0&&it->second->blob->conv_manager.get_size() >0)
|
||||
{
|
||||
assert(it->second->state.server_current_state==server_ready);
|
||||
it++;
|
||||
}
|
||||
else
|
||||
{
|
||||
mylog(log_info,"[%s:%d]inactive conn cleared \n",my_ntoa(it->second->raw_info.recv_info.src_ip),it->second->raw_info.recv_info.src_port);
|
||||
old_it=it;
|
||||
it++;
|
||||
erase(old_it);
|
||||
}
|
||||
cnt++;
|
||||
}
|
||||
clear_it=it;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int send_bare(raw_info_t &raw_info,const char* data,int len)//send function with encryption but no anti replay,this is used when client and server verifys each other
|
||||
//you have to design the protocol carefully, so that you wont be affect by relay attack
|
||||
{
|
||||
if(len<0)
|
||||
{
|
||||
mylog(log_debug,"input_len <0\n");
|
||||
return -1;
|
||||
}
|
||||
packet_info_t &send_info=raw_info.send_info;
|
||||
packet_info_t &recv_info=raw_info.recv_info;
|
||||
|
||||
char send_data_buf[buf_len]; //buf for send data and send hb
|
||||
char send_data_buf2[buf_len];
|
||||
|
||||
|
||||
//static send_bare[buf_len];
|
||||
iv_t iv=get_true_random_number_64();
|
||||
padding_t padding=get_true_random_number_64();
|
||||
|
||||
memcpy(send_data_buf,&iv,sizeof(iv));
|
||||
memcpy(send_data_buf+sizeof(iv),&padding,sizeof(padding));
|
||||
|
||||
send_data_buf[sizeof(iv)+sizeof(padding)]='b';
|
||||
memcpy(send_data_buf+sizeof(iv)+sizeof(padding)+1,data,len);
|
||||
int new_len=len+sizeof(iv)+sizeof(padding)+1;
|
||||
|
||||
if(my_encrypt(send_data_buf,send_data_buf2,new_len,key)!=0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
send_raw0(raw_info,send_data_buf2,new_len);
|
||||
return 0;
|
||||
}
|
||||
int reserved_parse_bare(const char *input,int input_len,char* & data,int & len) // a sub function used in recv_bare
|
||||
{
|
||||
static char recv_data_buf[buf_len];
|
||||
|
||||
if(input_len<0)
|
||||
{
|
||||
mylog(log_debug,"input_len <0\n");
|
||||
return -1;
|
||||
}
|
||||
if(my_decrypt(input,recv_data_buf,input_len,key)!=0)
|
||||
{
|
||||
mylog(log_debug,"decrypt_fail in recv bare\n");
|
||||
return -1;
|
||||
}
|
||||
if(recv_data_buf[sizeof(iv_t)+sizeof(padding_t)]!='b')
|
||||
{
|
||||
mylog(log_debug,"not a bare packet\n");
|
||||
return -1;
|
||||
}
|
||||
len=input_len;
|
||||
data=recv_data_buf+sizeof(iv_t)+sizeof(padding_t)+1;
|
||||
len-=sizeof(iv_t)+sizeof(padding_t)+1;
|
||||
if(len<0)
|
||||
{
|
||||
mylog(log_debug,"len <0\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int recv_bare(raw_info_t &raw_info,char* & data,int & len)//recv function with encryption but no anti replay,this is used when client and server verifys each other
|
||||
//you have to design the protocol carefully, so that you wont be affect by relay attack
|
||||
{
|
||||
packet_info_t &send_info=raw_info.send_info;
|
||||
packet_info_t &recv_info=raw_info.recv_info;
|
||||
|
||||
if(recv_raw0(raw_info,data,len)<0)
|
||||
{
|
||||
//printf("recv_raw_fail in recv bare\n");
|
||||
return -1;
|
||||
}
|
||||
if ((raw_mode == mode_faketcp && (recv_info.syn == 1 || recv_info.ack != 1)))
|
||||
{
|
||||
mylog(log_debug,"unexpect packet type recv_info.syn=%d recv_info.ack=%d \n",recv_info.syn,recv_info.ack);
|
||||
return -1;
|
||||
}
|
||||
return reserved_parse_bare(data,len,data,len);
|
||||
}
|
||||
|
||||
int send_handshake(raw_info_t &raw_info,id_t id1,id_t id2,id_t id3)// a warp for send_bare for sending handshake(this is not tcp handshake) easily
|
||||
{
|
||||
packet_info_t &send_info=raw_info.send_info;
|
||||
packet_info_t &recv_info=raw_info.recv_info;
|
||||
|
||||
char * data;int len;
|
||||
//len=sizeof(id_t)*3;
|
||||
if(numbers_to_char(id1,id2,id3,data,len)!=0) return -1;
|
||||
if(send_bare(raw_info,data,len)!=0) {mylog(log_warn,"send bare fail\n");return -1;}
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
int recv_handshake(packet_info_t &info,id_t &id1,id_t &id2,id_t &id3)
|
||||
{
|
||||
char * data;int len;
|
||||
if(recv_bare(info,data,len)!=0) return -1;
|
||||
|
||||
if(char_to_numbers(data,len,id1,id2,id3)!=0) return -1;
|
||||
|
||||
return 0;
|
||||
}*/
|
||||
|
||||
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.
|
||||
{
|
||||
|
||||
packet_info_t &send_info=conn_info.raw_info.send_info;
|
||||
packet_info_t &recv_info=conn_info.raw_info.recv_info;
|
||||
|
||||
if(type!='h'&&type!='d')
|
||||
{
|
||||
mylog(log_warn,"first byte is not h or d ,%x\n",type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
char send_data_buf[buf_len]; //buf for send data and send hb
|
||||
char send_data_buf2[buf_len];
|
||||
|
||||
|
||||
|
||||
id_t n_tmp_id=htonl(conn_info.my_id);
|
||||
|
||||
memcpy(send_data_buf,&n_tmp_id,sizeof(n_tmp_id));
|
||||
|
||||
n_tmp_id=htonl(conn_info.oppsite_id);
|
||||
|
||||
memcpy(send_data_buf+sizeof(n_tmp_id),&n_tmp_id,sizeof(n_tmp_id));
|
||||
|
||||
anti_replay_seq_t n_seq=hton64(conn_info.blob->anti_replay.get_new_seq_for_send());
|
||||
|
||||
memcpy(send_data_buf+sizeof(n_tmp_id)*2,&n_seq,sizeof(n_seq));
|
||||
|
||||
|
||||
send_data_buf[sizeof(n_tmp_id)*2+sizeof(n_seq)]=type;
|
||||
send_data_buf[sizeof(n_tmp_id)*2+sizeof(n_seq)+1]=conn_info.my_roller;
|
||||
|
||||
memcpy(send_data_buf+2+sizeof(n_tmp_id)*2+sizeof(n_seq),data,len);//data;
|
||||
|
||||
int new_len=len+sizeof(n_seq)+sizeof(n_tmp_id)*2+2;
|
||||
|
||||
if(my_encrypt(send_data_buf,send_data_buf2,new_len,key)!=0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(send_raw0(conn_info.raw_info,send_data_buf2,new_len)!=0) return -1;
|
||||
|
||||
if(after_send_raw0(conn_info.raw_info)!=0) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
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.
|
||||
{
|
||||
packet_info_t &send_info=conn_info.raw_info.send_info;
|
||||
packet_info_t &recv_info=conn_info.raw_info.recv_info;
|
||||
|
||||
char send_data_buf[buf_len];
|
||||
//send_data_buf[0]='d';
|
||||
u32_t n_conv_num=htonl(conv_num);
|
||||
memcpy(send_data_buf,&n_conv_num,sizeof(n_conv_num));
|
||||
|
||||
memcpy(send_data_buf+sizeof(n_conv_num),data,len);
|
||||
int new_len=len+sizeof(n_conv_num);
|
||||
send_safer(conn_info,'d',send_data_buf,new_len);
|
||||
return 0;
|
||||
|
||||
}
|
||||
int 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
|
||||
{
|
||||
static char recv_data_buf[buf_len];
|
||||
|
||||
// char *recv_data_buf=recv_data_buf0; //fix strict alias warning
|
||||
if(my_decrypt(input,recv_data_buf,input_len,key)!=0)
|
||||
{
|
||||
//printf("decrypt fail\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//char *a=recv_data_buf;
|
||||
//id_t h_oppiste_id= ntohl ( *((id_t * )(recv_data_buf)) );
|
||||
id_t h_oppsite_id;
|
||||
memcpy(&h_oppsite_id,recv_data_buf,sizeof(h_oppsite_id));
|
||||
h_oppsite_id=ntohl(h_oppsite_id);
|
||||
|
||||
//id_t h_my_id= ntohl ( *((id_t * )(recv_data_buf+sizeof(id_t))) );
|
||||
id_t h_my_id;
|
||||
memcpy(&h_my_id,recv_data_buf+sizeof(id_t),sizeof(h_my_id));
|
||||
h_my_id=ntohl(h_my_id);
|
||||
|
||||
//anti_replay_seq_t h_seq= ntoh64 ( *((anti_replay_seq_t * )(recv_data_buf +sizeof(id_t) *2 )) );
|
||||
anti_replay_seq_t h_seq;
|
||||
memcpy(&h_seq,recv_data_buf +sizeof(id_t) *2 ,sizeof(h_seq));
|
||||
h_seq=ntoh64(h_seq);
|
||||
|
||||
if(h_oppsite_id!=conn_info.oppsite_id||h_my_id!=conn_info.my_id)
|
||||
{
|
||||
mylog(log_debug,"id and oppsite_id verification failed %x %x %x %x \n",h_oppsite_id,conn_info.oppsite_id,h_my_id,conn_info.my_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (conn_info.blob->anti_replay.is_vaild(h_seq) != 1) {
|
||||
mylog(log_debug,"dropped replay packet\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
//printf("recv _len %d\n ",recv_len);
|
||||
data=recv_data_buf+sizeof(anti_replay_seq_t)+sizeof(id_t)*2;
|
||||
len=input_len-(sizeof(anti_replay_seq_t)+sizeof(id_t)*2 );
|
||||
|
||||
|
||||
if(data[0]!='h'&&data[0]!='d')
|
||||
{
|
||||
mylog(log_debug,"first byte is not h or d ,%x\n",data[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t roller=data[1];
|
||||
|
||||
|
||||
type=data[0];
|
||||
data+=2;
|
||||
len-=2;
|
||||
|
||||
if(len<0)
|
||||
{
|
||||
mylog(log_debug,"len <0 ,%d\n",len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(roller!=conn_info.oppsite_roller)
|
||||
{
|
||||
conn_info.oppsite_roller=roller;
|
||||
conn_info.last_oppsite_roller_time=get_current_time();
|
||||
}
|
||||
conn_info.my_roller++;//increase on a successful recv
|
||||
|
||||
|
||||
if(after_recv_raw0(conn_info.raw_info)!=0) return -1;
|
||||
|
||||
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.
|
||||
{
|
||||
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;
|
||||
static char recv_data_buf[buf_len];
|
||||
|
||||
if(recv_raw0(conn_info.raw_info,recv_data,recv_len)!=0) return -1;
|
||||
|
||||
return parse_safer(conn_info,recv_data,recv_len,type,data,len);
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
int fd=int(u64);
|
||||
int ret;
|
||||
assert(fd!=0);
|
||||
/*
|
||||
epoll_event ev;
|
||||
|
||||
ev.events = EPOLLIN;
|
||||
ev.data.u64 = u64;
|
||||
|
||||
ret = epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, &ev);
|
||||
if (ret!=0)
|
||||
{
|
||||
mylog(log_fatal,"fd:%d epoll delete failed!!!!\n",fd);
|
||||
myexit(-1); //this shouldnt happen
|
||||
}*/ //no need
|
||||
ret= close(fd); //closed fd should be auto removed from epoll
|
||||
|
||||
if (ret!=0)
|
||||
{
|
||||
mylog(log_fatal,"close fd %d failed !!!!\n",fd);
|
||||
myexit(-1); //this shouldnt happen
|
||||
}
|
||||
//mylog(log_fatal,"size:%d !!!!\n",conn_manager.udp_fd_mp.size());
|
||||
assert(conn_manager.udp_fd_mp.find(fd)!=conn_manager.udp_fd_mp.end());
|
||||
conn_manager.udp_fd_mp.erase(fd);
|
||||
}
|
162
connection.h
Normal file
162
connection.h
Normal file
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* connection.h
|
||||
*
|
||||
* Created on: Sep 23, 2017
|
||||
* Author: root
|
||||
*/
|
||||
|
||||
#ifndef CONNECTION_H_
|
||||
#define CONNECTION_H_
|
||||
|
||||
extern int disable_anti_replay;
|
||||
|
||||
#include "connection.h"
|
||||
#include "common.h"
|
||||
#include "log.h"
|
||||
#include "network.h"
|
||||
#include "misc.h"
|
||||
|
||||
|
||||
|
||||
struct anti_replay_t //its for anti replay attack,similar to openvpn/ipsec 's anti replay window
|
||||
{
|
||||
u64_t max_packet_received;
|
||||
char window[anti_replay_window_size];
|
||||
anti_replay_seq_t anti_replay_seq;
|
||||
anti_replay_seq_t get_new_seq_for_send();
|
||||
anti_replay_t();
|
||||
void re_init();
|
||||
|
||||
int is_vaild(u64_t seq);
|
||||
};//anti_replay;
|
||||
|
||||
|
||||
struct conv_manager_t // manage the udp connections
|
||||
{
|
||||
//typedef hash_map map;
|
||||
unordered_map<u64_t,u32_t> u64_to_conv; //conv and u64 are both supposed to be uniq
|
||||
unordered_map<u32_t,u64_t> conv_to_u64;
|
||||
|
||||
unordered_map<u32_t,u64_t> conv_last_active_time;
|
||||
|
||||
unordered_map<u32_t,u64_t>::iterator clear_it;
|
||||
|
||||
unordered_map<u32_t,u64_t>::iterator it;
|
||||
unordered_map<u32_t,u64_t>::iterator old_it;
|
||||
|
||||
//void (*clear_function)(uint64_t u64) ;
|
||||
|
||||
long long last_clear_time;
|
||||
|
||||
conv_manager_t();
|
||||
~conv_manager_t();
|
||||
int get_size();
|
||||
void reserve();
|
||||
void clear();
|
||||
u32_t get_new_conv();
|
||||
int is_conv_used(u32_t conv);
|
||||
int is_u64_used(u64_t u64);
|
||||
u32_t find_conv_by_u64(u64_t u64);
|
||||
u64_t find_u64_by_conv(u32_t conv);
|
||||
int update_active_time(u32_t conv);
|
||||
int insert_conv(u32_t conv,u64_t u64);
|
||||
int erase_conv(u32_t conv);
|
||||
int clear_inactive(char * ip_port=0);
|
||||
int clear_inactive0(char * ip_port);
|
||||
};//g_conv_manager;
|
||||
|
||||
struct blob_t //used in conn_info_t. conv_manager_t and anti_replay_t are costly data structures ,we dont allocate them until its necessary
|
||||
{
|
||||
conv_manager_t conv_manager;
|
||||
anti_replay_t anti_replay;
|
||||
};
|
||||
struct conn_info_t //stores info for a raw connection.for client ,there is only one connection,for server there can be thousand of connection since server can
|
||||
//handle multiple clients
|
||||
{
|
||||
current_state_t state;
|
||||
|
||||
raw_info_t raw_info;
|
||||
u64_t last_state_time;
|
||||
u64_t last_hb_sent_time; //client re-use this for retry
|
||||
u64_t last_hb_recv_time;
|
||||
//long long last_resent_time;
|
||||
|
||||
id_t my_id;
|
||||
id_t oppsite_id;
|
||||
|
||||
|
||||
int timer_fd;
|
||||
id_t oppsite_const_id;
|
||||
|
||||
blob_t *blob;
|
||||
|
||||
uint8_t my_roller;
|
||||
uint8_t oppsite_roller;
|
||||
u64_t last_oppsite_roller_time;
|
||||
|
||||
/*
|
||||
const uint32_t &ip=raw_info.recv_info.src_ip;
|
||||
const uint16_t &port=raw_info.recv_info.src_port;
|
||||
|
||||
*/
|
||||
void recover(const conn_info_t &conn_info);
|
||||
void re_init();
|
||||
conn_info_t();
|
||||
void prepare();
|
||||
conn_info_t(const conn_info_t&b);
|
||||
conn_info_t& operator=(const conn_info_t& b);
|
||||
~conn_info_t();
|
||||
};//g_conn_info;
|
||||
|
||||
struct conn_manager_t //manager for connections. for client,we dont need conn_manager since there is only one connection.for server we use one conn_manager for all connections
|
||||
{
|
||||
|
||||
u32_t ready_num;
|
||||
|
||||
unordered_map<int,conn_info_t *> udp_fd_mp; //a bit dirty to used pointer,but can void unordered_map search
|
||||
unordered_map<int,conn_info_t *> timer_fd_mp;//we can use pointer here since unordered_map.rehash() uses shallow copy
|
||||
|
||||
unordered_map<id_t,conn_info_t *> const_id_mp;
|
||||
|
||||
unordered_map<u64_t,conn_info_t*> mp; //put it at end so that it de-consturcts first
|
||||
|
||||
unordered_map<u64_t,conn_info_t*>::iterator clear_it;
|
||||
|
||||
long long last_clear_time;
|
||||
|
||||
conn_manager_t();
|
||||
int exist(u32_t ip,uint16_t port);
|
||||
/*
|
||||
int insert(uint32_t ip,uint16_t port)
|
||||
{
|
||||
uint64_t u64=0;
|
||||
u64=ip;
|
||||
u64<<=32u;
|
||||
u64|=port;
|
||||
mp[u64];
|
||||
return 0;
|
||||
}*/
|
||||
conn_info_t *& find_insert_p(u32_t ip,uint16_t port); //be aware,the adress may change after rehash
|
||||
conn_info_t & find_insert(u32_t ip,uint16_t port) ; //be aware,the adress may change after rehash
|
||||
|
||||
int erase(unordered_map<u64_t,conn_info_t*>::iterator erase_it);
|
||||
int clear_inactive();
|
||||
int clear_inactive0();
|
||||
|
||||
};
|
||||
|
||||
extern conn_manager_t conn_manager;
|
||||
|
||||
void server_clear_function(u64_t u64);
|
||||
|
||||
int send_bare(raw_info_t &raw_info,const char* data,int len);//send function with encryption but no anti replay,this is used when client and server verifys each other
|
||||
//you have to design the protocol carefully, so that you wont be affect by relay attack
|
||||
int reserved_parse_bare(const char *input,int input_len,char* & data,int & len); // a sub function used in recv_bare
|
||||
int recv_bare(raw_info_t &raw_info,char* & data,int & len);//recv function with encryption but no anti replay,this is used when client and server verifys each other
|
||||
//you have to design the protocol carefully, so that you wont be affect by relay attack
|
||||
int send_handshake(raw_info_t &raw_info,id_t id1,id_t id2,id_t id3);// a warp for send_bare for sending handshake(this is not tcp handshake) easily
|
||||
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 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.
|
||||
#endif /* CONNECTION_H_ */
|
@@ -80,6 +80,10 @@ https://github.com/wangyu-/udp2raw-tunnel/releases
|
||||
|
||||
现在client和server之间建立起了,tunnel。想要在本地连接44.55.66.77:7777,只需要连接 127.0.0.1:3333。来回的所有的udp流量会被经过tunneling发送。在外界看起来是tcp流量,不会有udp流量暴露到公网。
|
||||
|
||||
### MTU设置(重要)
|
||||
|
||||
不论你用udp2raw来加速kcptun还是vpn,为了稳定使用,都需要设置合理的MTU(在kcptun/vpn里设置,而不是在udp2raw里),建议把MTU设置成1200。client和server端都要设置。
|
||||
|
||||
### 提醒
|
||||
如果要在anroid上运行,请看[Android简明教程](/doc/android_guide.md)
|
||||
|
||||
@@ -88,6 +92,7 @@ https://github.com/wangyu-/udp2raw-tunnel/releases
|
||||
如果client和server无法连接,或者连接经常断开,请看一下`--seq-mode`的用法,尝试不同的seq-mode。
|
||||
|
||||
udp2raw可以用非root账号运行,这样更安全。具体方法见:[#26](https://github.com/wangyu-/udp2raw-tunnel/issues/26)
|
||||
|
||||
# 进阶操作说明
|
||||
|
||||
### 命令选项
|
||||
|
@@ -8,7 +8,7 @@
|
||||
##### 摘要
|
||||
udp2raw是一个把udp流量通过raw socket包装成tcp流量的工具。通过用udp2raw配合udp模式的 finalspeed一样可以达到在底层发tcp包,绕过QOS的效果。支持openvz,稳定性也好很多。原理上相当于在finalspeed外面再包了一层tunnel。
|
||||
|
||||
本教程会一步一步演示用udp2raw+finalspeed加速http流量的过程。加速任何其他tcp流量也一样,包括ss。本文避免讨论科学上网,所以只演示加速http流量。
|
||||
本教程会一步一步演示用udp2raw+finalspeed加速http流量的过程。加速任何其他tcp流量也一样,包括$\*\*\*。本文避免讨论科学上网,所以只演示加速http流量。
|
||||
|
||||
udp2raw也支持把udp流量包装成Icmp发送,本教程不做演示。
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
# udp2raw+kcptun 加速tcp流量 Step by Step 教程
|
||||

|
||||
|
||||
本教程会一步一步演示用udp2raw+kcptun加速SSH流量的过程。加速任何其他tcp流量也一样,包括ss;本文避免涉及科学上网,所以演示ssh。
|
||||
本教程会一步一步演示用udp2raw+kcptun加速SSH流量的过程。加速任何其他tcp流量也一样,包括$\*\*\*;本文避免涉及科学上网,所以演示ssh。
|
||||
|
||||
### 环境要求
|
||||
两边的主机都是linux,有root权限。 可以是openwrt路由器或树莓派,也可以是root了的android。
|
||||
|
@@ -16,7 +16,7 @@ static int8_t zero_iv[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0};//this prog
|
||||
* https://crypto.stackexchange.com/questions/5421/using-cbc-with-a-fixed-iv-and-a-random-first-plaintext-block
|
||||
****/
|
||||
|
||||
|
||||
char key[16];//generated from key_string by md5.
|
||||
/*
|
||||
TODO
|
||||
|
||||
|
@@ -12,7 +12,7 @@
|
||||
|
||||
|
||||
const int aes_key_optimize=1; //if enabled,once you used a key for aes,you cant change it anymore
|
||||
|
||||
extern char key[16];
|
||||
|
||||
int my_encrypt(const char *data,char *output,int &len,char * key);
|
||||
int my_decrypt(const char *data,char *output,int &len,char * key);
|
||||
|
2
log.cpp
2
log.cpp
@@ -1,11 +1,11 @@
|
||||
#include "log.h"
|
||||
#include "misc.h"
|
||||
|
||||
int log_level=log_info;
|
||||
|
||||
int enable_log_position=0;
|
||||
int enable_log_color=1;
|
||||
|
||||
|
||||
void log0(const char * file,const char * function,int line,int level,const char* str, ...) {
|
||||
|
||||
if(level>log_level) return ;
|
||||
|
7
makefile
7
makefile
@@ -8,7 +8,7 @@ cc_arm= /toolchains/arm-2014.05/bin/arm-none-linux-gnueabi-g++
|
||||
#cc_bcm2708=/home/wangyu/raspberry/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-g++
|
||||
FLAGS= -std=c++11 -Wall -Wextra -Wno-unused-variable -Wno-unused-parameter -Wno-missing-field-initializers
|
||||
|
||||
COMMON=main.cpp lib/md5.c encrypt.cpp log.cpp network.cpp common.cpp -lpthread
|
||||
COMMON=main.cpp lib/md5.c encrypt.cpp log.cpp network.cpp common.cpp connection.cpp misc.cpp -lpthread
|
||||
SOURCES= $(COMMON) lib/aes_faster_c/aes.c lib/aes_faster_c/wrapper.c
|
||||
SOURCES_TINY_AES= $(COMMON) lib/aes.c
|
||||
SOURCES_AES_ACC=$(COMMON) $(wildcard lib/aes_acc/aes*.c)
|
||||
@@ -30,6 +30,9 @@ debug2: git_version
|
||||
rm -f ${NAME}
|
||||
${cc_local} -o ${NAME} -I. ${SOURCES} ${FLAGS} -lrt -Wformat-nonliteral -ggdb
|
||||
|
||||
dynamic: git_version
|
||||
${cc_local} -o ${NAME}_$@ -I. ${SOURCES} ${FLAGS} -lrt -O3
|
||||
|
||||
mips24kc_be: git_version
|
||||
${cc_mips24kc_be} -o ${NAME}_$@ -I. ${SOURCES} ${FLAGS} -lrt -lgcc_eh -static -O3
|
||||
mips24kc_be_asm_aes: git_version
|
||||
@@ -70,7 +73,7 @@ release: ${TARGETS}
|
||||
|
||||
clean:
|
||||
rm -f ${TAR}
|
||||
rm -f udp2raw udp2raw_cross udp2raw_cmake
|
||||
rm -f udp2raw udp2raw_cross udp2raw_cmake udp2raw_dynamic
|
||||
rm -f git_version.h
|
||||
|
||||
git_version:
|
||||
|
130
misc.h
Normal file
130
misc.h
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* misc.h
|
||||
*
|
||||
* Created on: Sep 23, 2017
|
||||
* Author: root
|
||||
*/
|
||||
|
||||
#ifndef MISC_H_
|
||||
#define MISC_H_
|
||||
|
||||
|
||||
#include "common.h"
|
||||
#include "log.h"
|
||||
#include "network.h"
|
||||
|
||||
|
||||
|
||||
const u32_t max_handshake_conn_num=10000;
|
||||
const u32_t max_ready_conn_num=1000;
|
||||
const u32_t anti_replay_window_size=4000;
|
||||
const int max_conv_num=10000;
|
||||
|
||||
const u32_t client_handshake_timeout=5000;//unit ms
|
||||
const u32_t client_retry_interval=1000;//ms
|
||||
|
||||
const u32_t server_handshake_timeout=client_handshake_timeout+5000;// this should be longer than clients. client retry initially ,server retry passtively
|
||||
|
||||
const int conv_clear_ratio=10; //conv grabage collecter check 1/10 of all conv one time
|
||||
const int conn_clear_ratio=30;
|
||||
const int conv_clear_min=1;
|
||||
const int conn_clear_min=1;
|
||||
|
||||
const u32_t conv_clear_interval=3000;//ms
|
||||
const u32_t conn_clear_interval=3000;//ms
|
||||
|
||||
|
||||
const i32_t max_fail_time=0;//disable
|
||||
|
||||
const u32_t heartbeat_interval=1000;//ms
|
||||
|
||||
const u32_t timer_interval=400;//ms. this should be smaller than heartbeat_interval and retry interval;
|
||||
|
||||
const uint32_t conv_timeout=120000; //ms. 120 second
|
||||
//const u32_t conv_timeout=30000; //for test
|
||||
|
||||
const u32_t client_conn_timeout=10000;//ms.
|
||||
const u32_t client_conn_uplink_timeout=client_conn_timeout+2000;//ms
|
||||
|
||||
const uint32_t server_conn_timeout=conv_timeout+60000;//ms. this should be 60s+ longer than conv_timeout,so that conv_manager can destruct convs gradually,to avoid latency glicth
|
||||
//const u32_t server_conn_timeout=conv_timeout+10000;//for test
|
||||
|
||||
const u32_t iptables_rule_keep_interval=15;//unit: second;
|
||||
|
||||
enum server_current_state_t {server_idle=0,server_handshake1,server_ready}; //server state machine
|
||||
enum client_current_state_t {client_idle=0,client_tcp_handshake,client_handshake1,client_handshake2,client_ready};//client state machine
|
||||
|
||||
enum raw_mode_t{mode_faketcp=0,mode_udp,mode_icmp,mode_end};
|
||||
enum program_mode_t {unset_mode=0,client_mode,server_mode};
|
||||
|
||||
union current_state_t
|
||||
{
|
||||
server_current_state_t server_current_state;
|
||||
client_current_state_t client_current_state;
|
||||
};
|
||||
|
||||
extern char local_ip[100], remote_ip[100],source_ip[100];//local_ip is for -l option,remote_ip for -r option,source for --source-ip
|
||||
extern u32_t local_ip_uint32,remote_ip_uint32,source_ip_uint32;//convert from last line.
|
||||
extern int local_port , remote_port,source_port;//similiar to local_ip remote_ip,buf for port.source_port=0 indicates --source-port is not enabled
|
||||
|
||||
extern int force_source_ip; //if --source-ip is enabled
|
||||
|
||||
extern id_t const_id;//an id used for connection recovery,its generated randomly,it never change since its generated
|
||||
|
||||
extern int udp_fd; //for client only. client use this fd to listen and handle udp connection
|
||||
extern int bind_fd; //bind only,never send or recv. its just a dummy fd for bind,so that other program wont occupy the same port
|
||||
extern int epollfd; //fd for epoll
|
||||
extern int timer_fd; //the general timer fd for client and server.for server this is not the only timer find,every connection has a timer fd.
|
||||
extern int fail_time_counter;//determine if the max_fail_time is reached
|
||||
extern int epoll_trigger_counter;//for debug only
|
||||
extern int debug_flag;//for debug only
|
||||
|
||||
|
||||
extern int simple_rule; //deprecated.
|
||||
extern int keep_rule; //whether to monitor the iptables rule periodly,re-add if losted
|
||||
extern int auto_add_iptables_rule;//if -a is set
|
||||
extern int generate_iptables_rule;//if -g is set
|
||||
extern int generate_iptables_rule_add;// if --gen-add is set
|
||||
|
||||
extern int debug_resend; // debug only
|
||||
|
||||
extern char key_string[1000];// -k option
|
||||
extern char fifo_file[1000];
|
||||
|
||||
|
||||
extern raw_mode_t raw_mode;
|
||||
|
||||
extern program_mode_t program_mode;
|
||||
extern unordered_map<int, const char*> raw_mode_tostring ;
|
||||
|
||||
extern int about_to_exit;
|
||||
|
||||
extern int socket_buf_size;
|
||||
extern int force_socket_buf;
|
||||
|
||||
extern pthread_t keep_thread;
|
||||
extern int keep_thread_running;
|
||||
|
||||
|
||||
int process_lower_level_arg();
|
||||
void print_help();
|
||||
void iptables_rule();
|
||||
void pre_process_arg(int argc, char *argv[]);//mainly for load conf file;
|
||||
int unit_test();
|
||||
int set_timer(int epollfd,int &timer_fd);
|
||||
int set_timer_server(int epollfd,int &timer_fd);
|
||||
int handle_lower_level(raw_info_t &raw_info);
|
||||
|
||||
int add_iptables_rule(const char *);
|
||||
|
||||
int clear_iptables_rule();
|
||||
|
||||
int iptables_gen_add(const char * s,u32_t const_id);
|
||||
int iptables_rule_init(const char * s,u32_t const_id,int keep);
|
||||
int keep_iptables_rule();
|
||||
|
||||
|
||||
|
||||
void signal_handler(int sig);
|
||||
|
||||
#endif /* MISC_H_ */
|
101
network.cpp
101
network.cpp
@@ -7,6 +7,7 @@
|
||||
#include "common.h"
|
||||
#include "network.h"
|
||||
#include "log.h"
|
||||
#include "misc.h"
|
||||
|
||||
int raw_recv_fd=-1;
|
||||
int raw_send_fd=-1;
|
||||
@@ -14,6 +15,7 @@ u32_t link_level_header_len=0;//set it to 14 if SOCK_RAW is used in socket(PF_PA
|
||||
|
||||
int seq_mode=3;
|
||||
int max_seq_mode=4;
|
||||
int random_drop=0;
|
||||
|
||||
int filter_port=-1;
|
||||
|
||||
@@ -1622,6 +1624,12 @@ int recv_raw_tcp_deprecated(packet_info_t &info,char * &payload,int &payloadlen)
|
||||
}*/
|
||||
int send_raw0(raw_info_t &raw_info,const char * payload,int payloadlen)
|
||||
{
|
||||
if (random_drop != 0) {
|
||||
if (get_true_random_number() % 10000 < (u32_t) random_drop) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
packet_info_t &send_info=raw_info.send_info;
|
||||
packet_info_t &recv_info=raw_info.recv_info;
|
||||
mylog(log_trace,"send_raw : from %x %d to %x %d\n",send_info.src_ip,send_info.src_port,send_info.dst_ip,send_info.dst_port);
|
||||
@@ -1772,3 +1780,96 @@ int recv_raw(raw_info_t &raw_info,char *& payload,int & payloadlen)
|
||||
}
|
||||
}*/
|
||||
|
||||
int get_src_adress(u32_t &ip,u32_t remote_ip_uint32,int remote_port) //a trick to get src adress for a dest adress,so that we can use the src address in raw socket as source ip
|
||||
{
|
||||
struct sockaddr_in remote_addr_in={0};
|
||||
|
||||
socklen_t slen = sizeof(sockaddr_in);
|
||||
//memset(&remote_addr_in, 0, sizeof(remote_addr_in));
|
||||
remote_addr_in.sin_family = AF_INET;
|
||||
remote_addr_in.sin_port = htons(remote_port);
|
||||
remote_addr_in.sin_addr.s_addr = remote_ip_uint32;
|
||||
|
||||
|
||||
int new_udp_fd=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if(new_udp_fd<0)
|
||||
{
|
||||
mylog(log_warn,"create udp_fd error\n");
|
||||
return -1;
|
||||
}
|
||||
//set_buf_size(new_udp_fd);
|
||||
|
||||
mylog(log_debug,"created new udp_fd %d\n",new_udp_fd);
|
||||
int ret = connect(new_udp_fd, (struct sockaddr *) &remote_addr_in, slen);
|
||||
if(ret!=0)
|
||||
{
|
||||
mylog(log_warn,"udp fd connect fail\n");
|
||||
close(new_udp_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct sockaddr_in my_addr={0};
|
||||
socklen_t len=sizeof(my_addr);
|
||||
|
||||
if(getsockname(new_udp_fd, (struct sockaddr *) &my_addr, &len)!=0) return -1;
|
||||
|
||||
ip=my_addr.sin_addr.s_addr;
|
||||
|
||||
close(new_udp_fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int try_to_list_and_bind(int bind_fd,u32_t local_ip_uint32,int port) //try to bind to a port,may fail.
|
||||
{
|
||||
int old_bind_fd=bind_fd;
|
||||
|
||||
if(raw_mode==mode_faketcp)
|
||||
{
|
||||
bind_fd=socket(AF_INET,SOCK_STREAM,0);
|
||||
}
|
||||
else if(raw_mode==mode_udp||raw_mode==mode_icmp)
|
||||
{
|
||||
bind_fd=socket(AF_INET,SOCK_DGRAM,0);
|
||||
}
|
||||
if(old_bind_fd!=-1)
|
||||
{
|
||||
close(old_bind_fd);
|
||||
}
|
||||
|
||||
struct sockaddr_in temp_bind_addr={0};
|
||||
//bzero(&temp_bind_addr, sizeof(temp_bind_addr));
|
||||
|
||||
temp_bind_addr.sin_family = AF_INET;
|
||||
temp_bind_addr.sin_port = htons(port);
|
||||
temp_bind_addr.sin_addr.s_addr = local_ip_uint32;
|
||||
|
||||
if (bind(bind_fd, (struct sockaddr*)&temp_bind_addr, sizeof(temp_bind_addr)) !=0)
|
||||
{
|
||||
mylog(log_debug,"bind fail\n");
|
||||
return -1;
|
||||
}
|
||||
if(raw_mode==mode_faketcp)
|
||||
{
|
||||
|
||||
if (listen(bind_fd, SOMAXCONN) != 0) {
|
||||
mylog(log_warn,"listen fail\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int client_bind_to_a_new_port(int bind_fd,u32_t local_ip_uint32)//find a free port and bind to it.
|
||||
{
|
||||
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
|
||||
{
|
||||
if (try_to_list_and_bind(bind_fd,local_ip_uint32,raw_send_port)==0)
|
||||
{
|
||||
return raw_send_port;
|
||||
}
|
||||
}
|
||||
mylog(log_fatal,"bind port fail\n");
|
||||
myexit(-1);
|
||||
return -1;////for compiler check
|
||||
}
|
||||
|
@@ -21,6 +21,8 @@ extern int lower_level_manual;
|
||||
extern char if_name[100];
|
||||
extern unsigned char dest_hw_addr[];
|
||||
|
||||
extern int random_drop;
|
||||
|
||||
extern int ifindex;
|
||||
|
||||
struct icmphdr
|
||||
@@ -90,10 +92,17 @@ int init_raw_socket();
|
||||
void init_filter(int port);
|
||||
|
||||
void remove_filter();
|
||||
|
||||
int init_ifindex(const char * if_name,int &index);
|
||||
|
||||
int find_lower_level_info(u32_t ip,u32_t &dest_ip,string &if_name,string &hw);
|
||||
|
||||
int get_src_adress(u32_t &ip,u32_t remote_ip_uint32,int remote_port); //a trick to get src adress for a dest adress,so that we can use the src address in raw socket as source ip
|
||||
|
||||
int try_to_list_and_bind(int bind_fd,u32_t local_ip_uint32,int port); //try to bind to a port,may fail.
|
||||
|
||||
int client_bind_to_a_new_port(int bind_fd,u32_t local_ip_uint32);//find a free port and bind to it.
|
||||
|
||||
int send_raw_ip(raw_info_t &raw_info,const char * payload,int payloadlen);
|
||||
|
||||
int peek_raw(packet_info_t &peek_info);
|
||||
|
Reference in New Issue
Block a user