Compare commits

...

28 Commits

Author SHA1 Message Date
wangyu
fb5546f83b Merge branch 'master' of https://github.com/wangyu-/udp2raw-tunnel 2017-08-15 15:48:42 +08:00
wangyu
bb67509179 added lower-level option in help page 2017-08-15 15:48:19 +08:00
wangyu-
4bc4d618db Update README.zh-cn.md 2017-08-14 23:04:51 -07:00
wangyu
9f4c452cf6 Merge branch 'master' of https://github.com/wangyu-/udp2raw-tunnel 2017-08-15 13:04:55 +08:00
wangyu
455dcc1e84 trival 2017-08-15 13:04:21 +08:00
wangyu
cee22ec3dc zero out every sockaddr 2017-08-15 13:03:22 +08:00
wangyu-
0612b73e7e Update README.md 2017-08-14 05:32:54 -07:00
wangyu-
84697a35c9 Update README.md 2017-08-14 05:29:52 -07:00
wangyu-
78bf036e04 Update README.zh-cn.md 2017-08-14 05:24:00 -07:00
wangyu-
3ee73b048e Update README.md 2017-08-14 04:03:57 -07:00
wangyu-
8220cf30fb Update README.zh-cn.md 2017-08-14 03:50:34 -07:00
wangyu-
a061af0b89 Update README.zh-cn.md 2017-08-14 03:44:56 -07:00
wangyu-
746cda08d2 Update README.md 2017-08-14 03:28:31 -07:00
wangyu-
06f5541b2a Update README.zh-cn.md 2017-08-14 03:11:25 -07:00
wangyu-
97b73b06c9 Update README.zh-cn.md 2017-08-14 03:09:36 -07:00
wangyu-
f7319680d9 Update README.zh-cn.md 2017-08-14 03:07:43 -07:00
wangyu-
6dd52326b4 Update README.zh-cn.md 2017-08-14 03:04:16 -07:00
wangyu-
1ebef723bf Update README.zh-cn.md 2017-08-14 02:29:09 -07:00
wangyu-
744bf2dece Update README.zh-cn.md 2017-08-14 00:56:20 -07:00
wangyu-
7538204bd1 Update README.zh-cn.md 2017-08-14 00:54:44 -07:00
wangyu-
ae6dd0b196 Update README.md 2017-08-13 20:32:11 -07:00
wangyu-
fc515c770f Update README.md 2017-08-13 20:31:24 -07:00
wangyu-
491c322148 Update README.md 2017-08-13 07:31:25 -07:00
wangyu
80f1070546 Merge branch 'master' of https://github.com/wangyu-/udp2raw-tunnel 2017-08-13 21:28:05 +08:00
wangyu
5a4e3302e2 added comment about security of zero iv + nonce first data block 2017-08-13 21:27:53 +08:00
wangyu-
e76ad81a04 Update README.zh-cn.md 2017-08-13 05:57:20 -07:00
wangyu
7ac0d3561d improve makefile 2017-08-13 10:30:14 +08:00
wangyu
32166d65ae bug fix 2017-08-13 08:18:23 +08:00
6 changed files with 91 additions and 55 deletions

View File

@@ -1,7 +1,7 @@
# Udp2raw-tunnel
![image0](images/image0.PNG)
An Encrpyted,Anti-Replay,Multiplexed UDP Tunnel which can help you Bypass UDP Block or QoS by tunneling UDP traffic through Fake-TCP or ICMP by using raw socket.It aslo acts as a Connection Stablizer.
A UDP Tunnel which tunnels UDP via FakeTCP/UDP/ICMP Traffic by using Raw Socket,helps you Bypass UDP FireWalls(or Unstable UDP Environment).Its Encrpyted,Anti-Replay and Multiplexed.It aslo acts as a Connection Stablizer.
[简体中文](/doc/README.zh-cn.md)
# Features
@@ -11,11 +11,11 @@ Fake-tcp/icmp headers help you bypass UDP blocking, UDP QOS or improper UDP NAT
### Simulate TCP Handshake
Simulates the 3-way handshake, along with seq and ack_seq. TCP options MSS, sackOk, TS, TS_ack, wscale are also simulated. Real-time delivery guaranteed, no TCP over TCP problem when using OpenVPN.
### Encrpytion, Anti-Replay, Anti-MITM
### Encrpytion, Anti-Replay, No MITM
* Encrypt your traffic with AES-128-CBC.
* Protect data integrity by MD5 or CRC32.
* Defense replay attack with an anti-replay window, smiliar to IPSec and OpenVPN.
* Authenticate mutually, no more MITM attacks.
* Authenticate mutually, no MITM attacks.
### Failure Dectection & Stablization (Connection Recovery)
Conection failures are detected by heartbeats. If timed-out,client will automatically change port number and reconnect. If reconnection is successful, the previous connection will be recovered, and all existing UDP conversations will stay vaild.
@@ -185,3 +185,12 @@ https://github.com/ccsexyz/kcpraw
Transparently tunnel your IP traffic through ICMP echo and reply packets.
https://github.com/DhavalKapil/icmptunnel
### Tcp Minion
Tcp Minion is a project which modifid the code of tcp stack in kernel,and implemented real-time out-order udp packet delivery through this modified tcp stack.I failed to find the implementation,but there are some papers avaliable:
https://arxiv.org/abs/1103.0463
http://korz.cs.yale.edu/2009/tng/papers/pfldnet10.pdf
https://pdfs.semanticscholar.org/9e6f/e2306f4385b4eb5416d1fcab16e9361d6ba3.pdf

View File

@@ -1,6 +1,8 @@
Udp2raw-tunnel
![image2](/images/image2.PNG)
加密、防重放攻击的、信道复用的udp tunnel利用raw socket中转udp流量.同时有心跳保活,且在断线重连后保持上层连接不掉线的功能。
udp2raw tunnel通过raw socket给UDP包加上TCP或ICMP header进而绕过UDP屏蔽或QoS或在UDP不稳定的环境下提升稳定性。支持心跳保活、自动重连重连后会恢复上次连接在底层掉线的情况下可以保持上层不掉线。同时有加密、防重放攻击、信道复用的功能。
**欢迎任何形式的转载**
[English](/README.md)
@@ -26,7 +28,7 @@ Client能用单倍的超时时间检测到单向链路的失效不管是上
对于有大量client的情况对于不同client,server发送的心跳是错开时间发送的不会因为短时间发送大量的心跳而造成拥塞和延迟抖动。
### 加密 防重放攻击 防中间人攻击
用aes128cbc加密md5/crc32做数据完整校验。用类似ipsec/openvpn的 replay windows机制来防止重放攻击。
用aes128cbc加密md5/crc32做数据完整校验。用类似ipsec/openvpn的 replay window机制来防止重放攻击。
设计目标是即使攻击者可以监听到tunnel的所有包可以选择性丢弃tunnel的任意包可以重放任意包攻击者也没办法获得tunnel承载的任何数据也没办法向tunnel的数据流中通过包构造/包重放插入任何数据。client和server互相认证对方无法被中间人攻击。
@@ -49,7 +51,7 @@ epoll纯异步高并发除了回收过期连接外所有操作的时间
# 简明操作说明
### 环境要求
Linux主机有root权限。主机上最好安装了iptables命令(apt/yum很容易安装)。在windows和mac上可以开虚拟机桥接模式和<del>NAT模式</del>测试可用)。
Linux主机有root权限。主机上最好安装了iptables命令(apt/yum很容易安装)。在windows和mac上可以开虚拟机udp2raw跑在linux里其他应用照常跑在windows上桥接模式测试可用)。
### 安装
下载编译好的二进制文件,解压到任意目录。

View File

@@ -11,8 +11,11 @@
//static uint64_t seq=1;
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 use zero iv,you should make sure first block of data contains a random/nonce data
/****
* important!
* why zero iv + nonce first data block is secure?
* https://crypto.stackexchange.com/questions/5421/using-cbc-with-a-fixed-iv-and-a-random-first-plaintext-block
****/
unordered_map<int, const char *> auth_mode_tostring = {{auth_none, "none"}, {auth_md5, "md5"}, {auth_crc32, "crc32"},{auth_simple,"simple"}};
unordered_map<int, const char *> cipher_mode_tostring={{cipher_none,"none"},{cipher_aes128cbc,"aes128cbc"},{cipher_xor,"xor"}};

View File

@@ -860,8 +860,8 @@ int try_to_list_and_bind(int port)
close(old_bind_fd);
}
struct sockaddr_in temp_bind_addr;
bzero(&temp_bind_addr, sizeof(temp_bind_addr));
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);
@@ -1375,7 +1375,7 @@ int client_on_raw_recv(conn_info_t &conn_info)
u64_t u64=conn_info.blob->conv_manager.find_u64_by_conv(tmp_conv_id);
sockaddr_in tmp_sockaddr;
sockaddr_in tmp_sockaddr={0};
tmp_sockaddr.sin_family = AF_INET;
tmp_sockaddr.sin_addr.s_addr=(u64>>32u);
@@ -1417,10 +1417,13 @@ int server_on_raw_recv_multi()
{
recv(raw_recv_fd, 0,0, 0 );//
//struct sockaddr saddr;
//socklen_t saddr_size;
//socklen_t saddr_size=sizeof(saddr);
///recvfrom(raw_recv_fd, 0,0, 0 ,&saddr , &saddr_size);//
mylog(log_trace,"peek_raw failed\n");
return -1;
}else
{
mylog(log_trace,"peek_raw success\n");
}
u32_t ip=peek_info.src_ip;uint16_t port=peek_info.src_port;
@@ -1544,9 +1547,11 @@ int server_on_raw_recv_multi()
if(conn_info.state.server_current_state==server_ready)
{
char type;
//mylog(log_info,"before recv_safer\n");
if (recv_safer(conn_info,type, data, data_len) != 0) {
return -1;
}
//mylog(log_info,"after recv_safer\n");
return server_on_raw_recv_ready(conn_info,ip_port,type,data,data_len);
}
return 0;
@@ -1663,10 +1668,10 @@ int server_on_raw_recv_ready(conn_info_t &conn_info,char * ip_port,char type,cha
tmp_conv_id);
return 0;
}
struct sockaddr_in remote_addr_in;
struct sockaddr_in remote_addr_in={0};
socklen_t slen = sizeof(sockaddr_in);
memset(&remote_addr_in, 0, sizeof(remote_addr_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_address_uint32;
@@ -1857,10 +1862,10 @@ int server_on_raw_recv_pre_ready(conn_info_t &conn_info,char * ip_port,u32_t tmp
int get_src_adress(u32_t &ip)
{
struct sockaddr_in remote_addr_in;
struct sockaddr_in remote_addr_in={0};
socklen_t slen = sizeof(sockaddr_in);
memset(&remote_addr_in, 0, sizeof(remote_addr_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_address_uint32;
@@ -1883,7 +1888,7 @@ int get_src_adress(u32_t &ip)
return -1;
}
struct sockaddr_in my_addr;
struct sockaddr_in my_addr={0};
unsigned int len=sizeof(my_addr);
if(getsockname(new_udp_fd, (struct sockaddr *) &my_addr, &len)!=0) return -1;
@@ -1945,10 +1950,10 @@ int client_event_loop()
int yes = 1;
//setsockopt(udp_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
struct sockaddr_in local_me;
struct sockaddr_in local_me={0};
socklen_t slen = sizeof(sockaddr_in);
memset(&local_me, 0, sizeof(local_me));
//memset(&local_me, 0, sizeof(local_me));
local_me.sin_family = AF_INET;
local_me.sin_port = htons(local_port);
local_me.sin_addr.s_addr = local_address_uint32;
@@ -2033,9 +2038,10 @@ int client_event_loop()
{
int recv_len;
struct sockaddr_in udp_new_addr_in;
struct sockaddr_in udp_new_addr_in={0};
socklen_t udp_new_addr_len = sizeof(sockaddr_in);
if ((recv_len = recvfrom(udp_fd, buf, max_data_len, 0,
(struct sockaddr *) &udp_new_addr_in, &slen)) == -1) {
(struct sockaddr *) &udp_new_addr_in, &udp_new_addr_len)) == -1) {
mylog(log_error,"recv_from error,this shouldnt happen at client\n");
myexit(1);
};
@@ -2131,8 +2137,8 @@ int server_event_loop()
bind_fd=socket(AF_INET,SOCK_DGRAM,0);
}
struct sockaddr_in temp_bind_addr;
bzero(&temp_bind_addr, sizeof(temp_bind_addr));
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(local_port);
@@ -2313,7 +2319,8 @@ int server_event_loop()
if(recv_len<0)
{
mylog(log_debug,"udp fd,recv_len<0 continue\n");
mylog(log_debug,"udp fd,recv_len<0 continue,%s\n",strerror(errno));
continue;
}
@@ -2388,6 +2395,8 @@ void print_help()
printf(" 1:increase every packet\n");
printf(" 2:increase randomly, about every 3 packets (default)\n");
// printf("\n");
printf(" --lower-level <string> send packet at OSI level 2, format:'if_name#gateway_mac_adress'\n");
printf(" ie:'eth0#00:23:45:67:89:b9'.Beta.\n");
printf(" -h,--help print this help message\n");
//printf("common options,these options must be same on both side\n");

View File

@@ -2,34 +2,38 @@ cc_cross=/home/wangyu/OpenWrt-SDK-ar71xx-for-linux-x86_64-gcc-4.8-linaro_uClibc-
cc_local=g++
cc_ar71xx=/home/wangyu/OpenWrt-SDK-ar71xx-for-linux-x86_64-gcc-4.8-linaro_uClibc-0.9.33.2/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-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
FLAGS= -std=c++11 -Wall -Wextra -Wno-unused-variable -Wno-unused-parameter -Wno-missing-field-initializers
SOURCES=main.cpp lib/aes.c lib/md5.c encrypt.cpp log.cpp network.cpp common.cpp
TAR=udp2raw_binaries.tar.gz udp2raw_amd64 udp2raw_x86 udp2raw_ar71xx udp2raw_bcm2708
NAME=udp2raw
TAR=${NAME}_binaries.tar.gz ${NAME}_amd64 ${NAME}_x86 ${NAME}_ar71xx ${NAME}_bcm2708
all:
rm -f udp2raw
${cc_local} -o udp2raw -I. ${SOURCES} ${FLAGS} -lrt -static -O3
rm -f ${NAME}
${cc_local} -o ${NAME} -I. ${SOURCES} ${FLAGS} -lrt -static -O3
fast:
rm -f udp2raw
${cc_local} -o udp2raw -I. ${SOURCES} ${FLAGS} -lrt
rm -f ${NAME}
${cc_local} -o ${NAME} -I. ${SOURCES} ${FLAGS} -lrt
debug:
rm -f udp2raw
${cc_local} -o udp2raw -I. ${SOURCES} ${FLAGS} -lrt -Wformat-nonliteral -D MY_DEBUG
rm -f ${NAME}
${cc_local} -o ${NAME} -I. ${SOURCES} ${FLAGS} -lrt -Wformat-nonliteral -D MY_DEBUG
ar71xx:
${cc_ar71xx} -o udp2raw_ar71xx -I. ${SOURCES} ${FLAGS} -lrt -lgcc_eh -static -O3
${cc_ar71xx} -o ${NAME}_ar71xx -I. ${SOURCES} ${FLAGS} -lrt -lgcc_eh -static -O3
bcm2708:
${cc_bcm2708} -o udp2raw_bcm2708 -I. ${SOURCES} ${FLAGS} -lrt -static -O3
${cc_bcm2708} -o ${NAME}_bcm2708 -I. ${SOURCES} ${FLAGS} -lrt -static -O3
amd64:
${cc_local} -o ${NAME}_amd64 -I. ${SOURCES} ${FLAGS} -lrt -static -O3
x86:
${cc_local} -o ${NAME}_x86 -I. ${SOURCES} ${FLAGS} -lrt -m32 -static -O3
cross:
${cc_cross} -o udp2raw_cross -I. ${SOURCES} ${FLAGS} -lrt -static -lgcc_eh -O3
${cc_cross} -o ${NAME}_cross -I. ${SOURCES} ${FLAGS} -lrt -O3
cross2:
${cc_cross} -o udp2raw_cross -I. ${SOURCES} ${FLAGS} -lrt -O3
${cc_cross} -o ${NAME}_cross -I. ${SOURCES} ${FLAGS} -lrt -static -lgcc_eh -O3
release: ar71xx bcm2708
${cc_local} -o udp2raw_amd64 -I. ${SOURCES} ${FLAGS} -lrt -static -O3
${cc_local} -o udp2raw_x86 -I. ${SOURCES} ${FLAGS} -lrt -m32 -static -O3
release: amd64 x86 ar71xx bcm2708
tar -zcvf ${TAR}
clean:

View File

@@ -24,6 +24,8 @@ int lower_level=0;
int ifindex=-1;
char if_name[100]="";
unsigned short g_ip_id_counter=0;
unsigned char oppsite_hw_addr[6]=
{0xff,0xff,0xff,0xff,0xff,0xff};
//{0x00,0x23,0x45,0x67,0x89,0xb9};
@@ -162,6 +164,7 @@ packet_info_t::packet_info_t()
int init_raw_socket()
{
g_ip_id_counter=get_true_random_number()%65535;
if(lower_level==0)
{
raw_send_fd = socket(AF_INET , SOCK_RAW , IPPROTO_TCP);
@@ -306,7 +309,6 @@ int init_ifindex(char * if_name)
return 0;
}
int send_raw_ip(raw_info_t &raw_info,const char * payload,int payloadlen)
{
const packet_info_t &send_info=raw_info.send_info;
@@ -316,19 +318,18 @@ int send_raw_ip(raw_info_t &raw_info,const char * payload,int payloadlen)
struct iphdr *iph = (struct iphdr *) send_raw_ip_buf;
memset(iph,0,sizeof(iphdr));
static unsigned short ip_id=1;
iph->ihl = sizeof(iphdr)/4; //we dont use ip options,so the length is just sizeof(iphdr)
iph->version = 4;
iph->tos = 0;
if(lower_level)
{
iph->id=0;
//iph->id = htons (ip_id++); //Id of this packet
//iph->id=0;
iph->id = htons (g_ip_id_counter++); //Id of this packet
}
else
iph->id = 0; //Id of this packet ,kernel will auto fill this if id is zero ,or really?????// todo //seems like there is a problem
iph->id = htons (g_ip_id_counter++); //Id of this packet
//iph->id = 0; //Id of this packet ,kernel will auto fill this if id is zero ,or really?????// todo //seems like there is a problem
iph->frag_off = htons(0x4000); //DF set,others are zero
// iph->frag_off = htons(0x0000); //DF set,others are zero
@@ -353,7 +354,7 @@ int send_raw_ip(raw_info_t &raw_info,const char * payload,int payloadlen)
int ret;
if(lower_level==0)
{
struct sockaddr_in sin;
struct sockaddr_in sin={0};
sin.sin_family = AF_INET;
//sin.sin_port = htons(info.dst_port); //dont need this
sin.sin_addr.s_addr = send_info.dst_ip;
@@ -363,8 +364,8 @@ int send_raw_ip(raw_info_t &raw_info,const char * payload,int payloadlen)
else
{
struct sockaddr_ll addr;
memset(&addr,0,sizeof(addr));
struct sockaddr_ll addr={0};
//memset(&addr,0,sizeof(addr));
addr.sll_family=AF_PACKET;
addr.sll_ifindex=ifindex;
@@ -389,13 +390,15 @@ int send_raw_ip(raw_info_t &raw_info,const char * payload,int payloadlen)
int peek_raw(packet_info_t &peek_info)
{ static char peek_raw_buf[buf_len];
char *ip_begin=peek_raw_buf+link_level_header_len;
struct sockaddr saddr;
socklen_t saddr_size;
struct sockaddr saddr={0};
socklen_t saddr_size=sizeof(saddr);
int recv_len = recvfrom(raw_recv_fd, peek_raw_buf,max_data_len, MSG_PEEK ,&saddr , &saddr_size);//change max_data_len to something smaller,we only need header here
iphdr * iph = (struct iphdr *) (ip_begin);
//mylog(log_info,"recv_len %d\n",recv_len);
if(recv_len<int(sizeof(iphdr)))
{
mylog(log_trace,"failed here %d %d\n",recv_len,int(sizeof(iphdr)));
mylog(log_trace,"%s\n ",strerror(errno));
return -1;
}
peek_info.src_ip=iph->saddr;
@@ -407,10 +410,17 @@ int peek_raw(packet_info_t &peek_info)
{
case mode_faketcp:
{
if(iph->protocol!=IPPROTO_TCP) return -1;
if(iph->protocol!=IPPROTO_TCP)
{
mylog(log_trace,"failed here");
return -1;
}
struct tcphdr *tcph=(tcphdr *)payload;
if(recv_len<int( iphdrlen+sizeof(tcphdr) ))
{
mylog(log_trace,"failed here");
return -1;
}
peek_info.src_port=ntohs(tcph->source);
peek_info.syn=tcph->syn;
break;
@@ -445,11 +455,9 @@ int recv_raw_ip(raw_info_t &raw_info,char * &payload,int &payloadlen)
static char recv_raw_ip_buf[buf_len];
iphdr * iph;
struct sockaddr saddr;
socklen_t saddr_size;
saddr_size = sizeof(saddr);
struct sockaddr saddr={0};
socklen_t saddr_size = sizeof(saddr);
int flag=0;
int recv_len = recvfrom(raw_recv_fd, recv_raw_ip_buf, max_data_len, flag ,&saddr , &saddr_size);
if(recv_len<0)
@@ -481,6 +489,7 @@ int recv_raw_ip(raw_info_t &raw_info,char * &payload,int &payloadlen)
if(bind_address_uint32!=0 &&recv_info.dst_ip!=bind_address_uint32)
{
mylog(log_trace,"bind adress doenst match, dropped\n");
//printf(" bind adress doenst match, dropped\n");
return -1;
}