Compare commits

...

13 Commits

Author SHA1 Message Date
wangyu-
2c67c319b7 fix last commit 2018-02-24 18:07:16 -06:00
wangyu-
86a78b223e Merge branch 'master' of https://github.com/wangyu-/udp2raw-tunnel 2018-02-24 17:26:42 -06:00
wangyu-
0c2060028a --max-rst-allowed --max-rst-to-show 2018-02-24 17:26:29 -06:00
wangyu-
1f313f1c07 Update kcptun_step_by_step.md 2018-02-23 16:39:41 +08:00
wangyu-
af2513cbc0 Update README.md 2018-02-22 04:09:08 +08:00
wangyu-
65b2d7bc1c Update README.zh-cn.md 2018-02-22 04:02:02 +08:00
wangyu-
a02c22cb3d Update README.md 2018-02-22 03:50:42 +08:00
wangyu-
5a6a2682bc Update README.md 2018-02-22 03:32:43 +08:00
wangyu-
a170650210 Update README.md 2018-02-22 03:32:32 +08:00
wangyu-
b0f62e35cc Update README.zh-cn.md 2018-02-22 03:30:27 +08:00
wangyu-
96b57df4e2 Update README.zh-cn.md 2018-02-21 14:07:32 +08:00
wangyu-
0f756e3166 added guide for running udp2raw client on windows/mac 2018-02-21 13:48:28 +08:00
wangyu-
7cb65ec45d handle truncated packet 2018-02-20 06:10:18 -06:00
11 changed files with 142 additions and 35 deletions

View File

@@ -11,6 +11,8 @@ When used alone,udp2raw tunnels only UDP traffic. Nevertheless,if you used udp2r
[简体中文](/doc/README.zh-cn.md)(内容更丰富)
[udp2raw wiki](https://github.com/wangyu-/udp2raw-tunnel/wiki)
# Support Platforms
Linux host (including desktop Linux,Android phone/tablet,OpenWRT router,or Raspberry PI) with root access.
@@ -51,22 +53,6 @@ For example, if you use udp2raw + OpenVPN, OpenVPN won't lose connection after a
### Keywords
`Bypass UDP QoS` `Bypass UDP Blocking` `Bypass OpenVPN TCP over TCP problem` `OpenVPN over ICMP` `UDP to ICMP tunnel` `UDP to TCP tunnel` `UDP over ICMP` `UDP over TCP`
# Frequently Asked Questions
### Q: What is the advantage of using udp2raw FakeTCP mode,why not use a TCP-based VPN(such as OpenVPN TCP mode)?
Answer: **TCP doesnt allow real-time/out-of-order delivery**. **If you use OpenVPN TCP mode to turn UDP traffic into TCP,there will be latency issue**:the loss of a single packet blocks all following packet until re-transmission is done. This will cause unacceptable delay for gaming and voice chatting.
**TCP also has re-transmission and congestion control which cant be disabled.** UDP programs usualy want to control packet sending rate by themselves. If you use OpenVPN TCP mode this cant be done because of the congestion control of underlying TCP protocol. Further more,with the re-transmission of underlying TCP,**if you send too many udp packets via an OpenVPN TCP connection,the connection will become completely unusable for a while**(It will eventually recover as most of the re-transmission is done,but it wont be very soon).
Those issues exist for almost all TCP-based VPNs.
For udp2raw there is no underlying TCP protocol,udp2raw just add TCP headers to UDP packets directly by using raw socket. It supports real-time/out-of-order delivery,there is no re-transmission and congestion control. **Udp2raw doesnt have all above issues**.
### Q: Is udp2raw designed for replacing VPN?
Answer: No. Udp2raw is designed for bypassing UDP restrictions. It doesnt have all of the features a VPN has(such as transparently redirect all traffic).
Instead of replacing VPN,udp2raw can be used with any UDP-based VPN together to grant UDP-based VPN the ablity of bypassing UDP restrictions,while not having the performance issue involved by a TCP-based VPN. Check [this link](https://github.com/wangyu-/udp2raw-tunnel#tunneling-any-traffic-via-raw-traffic-by-using-udp2raw-openvpn) for more info.
# Getting Started
### Installing
Download binary release from https://github.com/wangyu-/udp2raw-tunnel/releases
@@ -242,7 +228,7 @@ raw_mode: faketcp cipher_mode: aes128cbc  auth_mode: md5
4. Supports almost any UDP-based VPN
More details at [openvpn+udp2raw_guide](/doc/openvpn_guide.md)
More details at [openvpn+udp2raw_guide](https://github.com/wangyu-/udp2raw-tunnel/wiki/udp2raw-openvpn-config-guide)
## Speed-up tcp connection via raw traffic by using udp2raw+kcptun
kcptun is a tcp connection speed-up program,it speeds-up tcp connection by using kcp protocol on-top of udp.by using udp2raw,you can use kcptun while udp is QoSed or blocked.
(kcptun, https://github.com/xtaci/kcptun)
@@ -287,3 +273,9 @@ https://arxiv.org/abs/1103.0463
http://korz.cs.yale.edu/2009/tng/papers/pfldnet10.pdf
https://pdfs.semanticscholar.org/9e6f/e2306f4385b4eb5416d1fcab16e9361d6ba3.pdf
# wiki
Check wiki for more info:
https://github.com/wangyu-/udp2raw-tunnel/wiki

View File

@@ -85,7 +85,7 @@ struct ip_port_t
typedef u64_t fd64_t;
const int max_data_len=1600;
const int max_data_len=1800;
const int buf_len=max_data_len+400;
u64_t get_current_time();

View File

@@ -228,6 +228,10 @@ conv_manager_t::~conv_manager_t()
void conn_info_t::recover(const conn_info_t &conn_info)
{
raw_info=conn_info.raw_info;
raw_info.rst_received=0;
raw_info.disabled=0;
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;
@@ -238,6 +242,7 @@ conv_manager_t::~conv_manager_t()
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()
@@ -642,7 +647,7 @@ int send_data_safer(conn_info_t &conn_info,const char* data,int len,u32_t conv_n
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
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
{
static char recv_data_buf[buf_len];
@@ -738,7 +743,7 @@ int recv_safer(conn_info_t &conn_info,char &type,char* &data,int &len)///safer t
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);
return reserved_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),

View File

@@ -154,12 +154,12 @@ 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 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 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.
#endif /* CONNECTION_H_ */

View File

@@ -10,6 +10,8 @@ udp2raw tunnel通过raw socket给UDP包加上TCP或ICMP header进而绕过
[udp2raw+finalspeed step_by_step教程](finalspeed_step_by_step.md)
[udp2raw wiki](https://github.com/wangyu-/udp2raw-tunnel/wiki)
**提示:**
udp2raw不是加速器只是一个帮助你绕过UDP限制的工具。如果你需要UDP加速器请看UDPspeeder。
@@ -24,13 +26,15 @@ Release中提供了`amd64`、`x86`、`arm`、`mips_be`、`mips_le`的预编译bi
##### 对于windows和mac用户
在虚拟机中可以稳定使用udp2raw跑在Linux里其他应用照常跑在window里确保虚拟机网卡工作在桥接模式。可以使用[这个](https://github.com/wangyu-/udp2raw-tunnel/releases/download/20171108.0/lede-17.01.2-x86_virtual_machine_image.zip)虚拟机镜像大小只有7.5mb免去在虚拟机里装系统的麻烦虚拟机自带ssh server可以scp拷贝文件可以ssh进去可以复制粘贴root密码123456
可以把udp2raw运行在虚拟机上(网络必须是桥接模式)
如果你的网络不允许桥接也是有办法用的具体方法请看wiki。
另外可以参考:
https://github.com/wangyu-/udp2raw-tunnel/wiki/在windows-mac上运行udp2raw客户端带图形界面
##### 对于ios和游戏主机用户
可以把udp2raw运行在局域网的其他机器上。最好的办法是买个能刷OpenWrt/LEDE/梅林的路由器把udp2raw运行在路由器上。
可以把udp2raw运行在局域网的其他机器/虚拟机上。最好的办法是买个能刷OpenWrt/LEDE/梅林的路由器把udp2raw运行在路由器上。
# 功能特性
### 把udp流量伪装成tcp /icmp
@@ -290,3 +294,9 @@ Transparently tunnel your IP traffic through ICMP echo and reply packets.
https://github.com/DhavalKapil/icmptunnel
# wiki
更多内容请看 wiki:
https://github.com/wangyu-/udp2raw-tunnel/wiki

View File

@@ -6,7 +6,9 @@
### 环境要求
两边的主机都是linux有root权限。 可以是openwrt路由器或树莓派也可以是root了的android。
(windowsmac可以用release里发布的预装了udp2raw的openwrt_x86虚拟机镜像容量4.4mb,开机即用)
windows/mac上运行udp2raw可以参考这个教程
https://github.com/wangyu-/udp2raw-tunnel/wiki/在windows-mac上运行udp2raw客户端带图形界面
### 安装

View File

@@ -10,11 +10,13 @@
char hb_buf[buf_len];
int on_epoll_recv_event=0; //TODO, just a flag to help detect epoll infinite shoot
int server_on_raw_recv_pre_ready(conn_info_t &conn_info,char * ip_port,u32_t tmp_oppsite_const_id);
int server_on_raw_recv_ready(conn_info_t &conn_info,char * ip_port,char type,char *data,int data_len);
int server_on_raw_recv_handshake1(conn_info_t &conn_info,char * ip_port,char * data, int data_len);
int client_on_timer(conn_info_t &conn_info) //for client. called when a timer is ready in epoll
{
//keep_iptables_rule();
@@ -28,9 +30,19 @@ int client_on_timer(conn_info_t &conn_info) //for client. called when a timer is
mylog(log_trace,"<client_on_timer,send_info.ts_ack= %u>\n",send_info.ts_ack);
if(raw_info.disabled)
{
conn_info.state.client_current_state=client_idle;
conn_info.my_id=get_true_random_number_nz();
mylog(log_info,"state back to client_idle\n");
}
if(conn_info.state.client_current_state==client_idle)
{
raw_info.rst_received=0;
raw_info.disabled=0;
fail_time_counter++;
if(max_fail_time>0&&fail_time_counter>max_fail_time)
{
@@ -41,6 +53,8 @@ int client_on_timer(conn_info_t &conn_info) //for client. called when a timer is
conn_info.blob->anti_replay.re_init();
conn_info.my_id = get_true_random_number_nz(); ///todo no need to do this everytime
u32_t new_ip=0;
if(!force_source_ip&&get_src_adress(new_ip,remote_ip_uint32,remote_port)==0)
{
@@ -610,13 +624,15 @@ int server_on_raw_recv_multi() //called when server received an raw packet
conn_info_t &conn_info=conn_manager.find_insert(ip,port);
conn_info.raw_info=tmp_raw_info;
raw_info_t &raw_info=conn_info.raw_info;
packet_info_t &send_info=conn_info.raw_info.send_info;
packet_info_t &recv_info=conn_info.raw_info.recv_info;
//conn_info.ip_port.ip=ip;
//conn_info.ip_port.port=port;
packet_info_t &send_info=conn_info.raw_info.send_info;
packet_info_t &recv_info=conn_info.raw_info.recv_info;
raw_info_t &raw_info=conn_info.raw_info;
send_info.src_ip=recv_info.dst_ip;
send_info.src_port=recv_info.dst_port;
@@ -645,6 +661,8 @@ int server_on_raw_recv_multi() //called when server received an raw packet
}
conn_info_t & conn_info=conn_manager.find_insert(ip,port);//insert if not exist
packet_info_t &send_info=conn_info.raw_info.send_info;
packet_info_t &recv_info=conn_info.raw_info.recv_info;
@@ -1294,12 +1312,18 @@ int client_event_loop()
int recv_len;
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,
if ((recv_len = recvfrom(udp_fd, buf, max_data_len+1, 0,
(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);
};
if(recv_len==max_data_len+1)
{
mylog(log_warn,"huge packet, data_len > %d,dropped\n",max_data_len);
continue;
}
if(recv_len>=mtu_warn)
{
mylog(log_warn,"huge packet,data len=%d (>=%d).strongly suggested to set a smaller mtu at upper level,to get rid of this warn\n ",recv_len,mtu_warn);
@@ -1473,6 +1497,8 @@ int server_event_loop()
}
mylog(log_info,"fifo_file=%s\n",fifo_file);
}
while(1)////////////////////////
{
@@ -1639,10 +1665,16 @@ int server_event_loop()
int fd=fd_manager.to_fd(fd64);
int recv_len=recv(fd,buf,max_data_len,0);
int recv_len=recv(fd,buf,max_data_len+1,0);
mylog(log_trace,"received a packet from udp_fd,len:%d\n",recv_len);
if(recv_len==max_data_len+1)
{
mylog(log_warn,"huge packet, data_len > %d,dropped\n",max_data_len);
continue;
}
if(recv_len<0)
{
mylog(log_debug,"udp fd,recv_len<0 continue,%s\n",strerror(errno));
@@ -1718,7 +1750,7 @@ int main(int argc, char *argv[])
if(geteuid() != 0)
{
mylog(log_error,"root check failed, it seems like you are using a non-root account. we can try to continue, but it may fail. If you want to run udp2raw as non-root, you have to add iptables rule manually, and grant udp2raw CAP_NET_RAW capability, check README.md in repo for more info.\n");
mylog(log_warn,"root check failed, it seems like you are using a non-root account. we can try to continue, but it may fail. If you want to run udp2raw as non-root, you have to add iptables rule manually, and grant udp2raw CAP_NET_RAW capability, check README.md in repo for more info.\n");
}
else
{

View File

@@ -18,6 +18,10 @@ int hb_len=1200;
int mtu_warn=1375;//if a packet larger than mtu warn is receviced,there will be a warning
int max_rst_to_show=15;
int max_rst_allowed=-1;
fd_manager_t fd_manager;
@@ -268,6 +272,8 @@ void process_arg(int argc, char *argv[]) //process all options
{"hb-mode", required_argument, 0, 1},
{"hb-len", required_argument, 0, 1},
{"mtu-warn", required_argument, 0, 1},
{"max-rst-to-show", required_argument, 0, 1},
{"max-rst-allowed", required_argument, 0, 1},
{NULL, 0, 0, 0}
};
@@ -628,6 +634,18 @@ void process_arg(int argc, char *argv[]) //process all options
assert(mtu_warn>0);
mylog(log_info,"mtu_warn=%d \n",mtu_warn);
}
else if(strcmp(long_options[option_index].name,"max-rst-to-show")==0)
{
sscanf(optarg,"%d",&max_rst_to_show);
assert(max_rst_to_show>=-1);
mylog(log_info,"max_rst_to_show=%d \n",max_rst_to_show);
}
else if(strcmp(long_options[option_index].name,"max-rst-allowed")==0)
{
sscanf(optarg,"%d",&max_rst_allowed);
assert(max_rst_allowed>=-1);
mylog(log_info,"max_rst_allowed=%d \n",max_rst_allowed);
}
else
{
mylog(log_warn,"ignored unknown long option ,option_index:%d code:<%x>\n",option_index, optopt);

4
misc.h
View File

@@ -17,6 +17,10 @@ extern int hb_mode;
extern int hb_len;
extern int mtu_warn;
extern int max_rst_allowed;
extern int max_rst_to_show;
const u32_t max_handshake_conn_num=10000;
const u32_t max_ready_conn_num=1000;
const u32_t anti_replay_window_size=4000;

View File

@@ -566,6 +566,13 @@ int send_raw_ip(raw_info_t &raw_info,const char * payload,int payloadlen)
const packet_info_t &recv_info=raw_info.recv_info;
char send_raw_ip_buf[buf_len];
if(raw_info.disabled)
{
mylog(log_debug,"[%s,%d]connection disabled, no packet will be sent\n",my_ntoa(recv_info.src_ip),recv_info.src_port);
assert(max_rst_allowed>=0);
return 0;
}
struct iphdr *iph = (struct iphdr *) send_raw_ip_buf;
memset(iph,0,sizeof(iphdr));
@@ -704,7 +711,13 @@ int recv_raw_ip(raw_info_t &raw_info,char * &payload,int &payloadlen)
struct sockaddr_ll 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 ,(sockaddr*)&saddr , &saddr_size);
int recv_len = recvfrom(raw_recv_fd, recv_raw_ip_buf, max_data_len+1, flag ,(sockaddr*)&saddr , &saddr_size);
if(recv_len==max_data_len+1)
{
mylog(log_warn,"huge packet, data_len > %d,dropped\n",max_data_len);
return -1;
}
if(recv_len<0)
{
@@ -1439,7 +1452,37 @@ int recv_raw_tcp(raw_info_t &raw_info,char * &payload,int &payloadlen)
if(tcph->rst==1)
{
mylog(log_error,"[%s,%d]rst==1\n",my_ntoa(recv_info.src_ip),recv_info.src_port);
raw_info.rst_received++;
if(max_rst_to_show>0)
{
if(raw_info.rst_received < max_rst_to_show)
{
mylog(log_warn,"[%s,%d]rst==1,cnt=%d\n",my_ntoa(recv_info.src_ip),recv_info.src_port,(int)raw_info.rst_received);
}
else if(raw_info.rst_received == max_rst_to_show)
{
mylog(log_warn,"[%s,%d]rst==1,cnt=%d >=max_rst_to_show, this log will be muted for current connection\n",my_ntoa(recv_info.src_ip),recv_info.src_port,(int)raw_info.rst_received);
}
else
{
mylog(log_debug,"[%s,%d]rst==1,cnt=%d\n",my_ntoa(recv_info.src_ip),recv_info.src_port,(int)raw_info.rst_received);
}
}
else if(max_rst_to_show==0)
{
mylog(log_debug,"[%s,%d]rst==1,cnt=%d\n",my_ntoa(recv_info.src_ip),recv_info.src_port,(int)raw_info.rst_received);
}
else
{
mylog(log_warn,"[%s,%d]rst==1,cnt=%d\n",my_ntoa(recv_info.src_ip),recv_info.src_port,(int)raw_info.rst_received);
}
if(max_rst_allowed>=0 && raw_info.rst_received==max_rst_allowed+1 )
{
mylog(log_warn,"[%s,%d]connection disabled because of rst_received=%d > max_rst_allow=%d\n",my_ntoa(recv_info.src_ip),recv_info.src_port,(int)raw_info.rst_received,(int)max_rst_allowed );
raw_info.disabled=1;
}
}
/* if(recv_info.has_ts)

View File

@@ -77,12 +77,13 @@ struct raw_info_t
{
packet_info_t send_info;
packet_info_t recv_info;
//int last_send_len;
//int last_recv_len;
u32_t reserved_send_seq;
//uint32_t first_seq,first_ack_seq;
int rst_received=0;
bool disabled=0;
};//g_raw_info;