mirror of
https://github.com/wangyu-/udp2raw.git
synced 2025-01-19 14:29:34 +08:00
added option lower-level
This commit is contained in:
parent
44852270ef
commit
307399b00a
@ -10,8 +10,8 @@ Which can help you bypass udp blocking or udp QOS or just poorly supported udp N
|
||||
encrypt your traffic with aes128cbc,protects data integrity by md5 or crc32,protect replay attack with an anti-replay window smiliar to ipsec/openvpn.
|
||||
### Simulated TCP Handshake
|
||||
simulated 3-way handshake,simluated seq ack_seq. Simluated tcp options:MSS,sackOk,TS,TS_ack,wscale. Provides real-time delivery ,no tcp over tcp problem when using openvpn.
|
||||
### Connnection Recover
|
||||
After connection timeouts,the client will re-connect.if re-connection is successful,the previous connection will be recovered,and all existed udp conversations will stay vaild.
|
||||
### Connnection Failure Dectection & Recover
|
||||
Conection failure detection by hearbeat. After hearbeat timeouts,client will auto change port and re-connect.if re-connection is successful,the previous connection will be recovered,and all existed udp conversations will stay vaild.
|
||||
### Other Features
|
||||
Multiplexing ,one client supports multi udp connections,all of those traffic will share one raw connection
|
||||
|
||||
@ -118,6 +118,8 @@ raw_mode: faketcp cipher_mode: aes128cbc auth_mode: md5
|
||||
2. no TCP ovr tcp problem (tcp over tcp problem http://sites.inka.de/bigred/devel/tcp-tcp.html ,https://community.openvpn.net/openvpn/ticket/2 )
|
||||
|
||||
3. openvpn over icmp also becomes a choice
|
||||
|
||||
more details at [openvpn+udp2raw_guide](/doc/openvpn_guide.md)
|
||||
### tunneling kcptun
|
||||
make kcptun support tcp mode.
|
||||
(kcptun, https://github.com/xtaci/kcptun)
|
||||
|
@ -198,12 +198,12 @@ int set_buf_size(int fd)
|
||||
{
|
||||
if(setsockopt(fd, SOL_SOCKET, SO_SNDBUFFORCE, &socket_buf_size, sizeof(socket_buf_size))<0)
|
||||
{
|
||||
mylog(log_fatal,"SO_SNDBUFFORCE fail\n");
|
||||
mylog(log_fatal,"SO_SNDBUFFORCE fail,fd %d\n",fd);
|
||||
myexit(1);
|
||||
}
|
||||
if(setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &socket_buf_size, sizeof(socket_buf_size))<0)
|
||||
{
|
||||
mylog(log_fatal,"SO_RCVBUFFORCE fail\n");
|
||||
mylog(log_fatal,"SO_RCVBUFFORCE fail,fd %d\n",fd);
|
||||
myexit(1);
|
||||
}
|
||||
return 0;
|
||||
|
1
common.h
1
common.h
@ -42,6 +42,7 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
#include <linux/if_packet.h>
|
||||
|
||||
|
||||
|
||||
|
@ -18,10 +18,12 @@ Udp2raw-tunnel
|
||||
### 模拟TCP3次握手
|
||||
模拟TCP3次握手,模拟seq ack过程。另外还模拟了一些tcp option:MSS,sackOk,TS,TS_ack,wscale,用来使流量看起来更像是由普通的linux tcp协议栈发送的。
|
||||
|
||||
### 连接快速恢复
|
||||
### 连接保持,连接快速恢复
|
||||
心跳机制检查连接是否中断,一旦心跳超时。client会立即换raw socket的端口重连,重连成功后会恢复之前中断的连接。虽然raw端的端口变了,但是udp端的所有连接都会继续有效。udp这边感觉不到raw端的重连,只会感觉到短暂断流,这跟普通的短暂丢包是类似的,不会导致上层应用重连。
|
||||
|
||||
另一个优化是,重连只需要client发起,就可以立即被server处理,不需要等到server端的连接超时后。
|
||||
另一个优化是,重连只需要client发起,就可以立即被server处理,不需要等到server端的连接超时后。这个在单向连接失效的情况下有用。
|
||||
|
||||
另外,对于有大量client的情况,对于不同client,server发送的心跳是错开时间发送的,不会因为短时间发送大量的心跳而造成拥塞和延迟抖动。
|
||||
|
||||
### 其他特性
|
||||
信道复用,client的udp端支持多个连接。
|
||||
@ -32,7 +34,10 @@ NAT 穿透 ,tcp icmp udp模式都支持nat穿透。
|
||||
|
||||
支持Openvz,配合finalspeed使用,可以在openvz上用tcp模式的finalspeed
|
||||
|
||||
支持Openwrt,没有编译以来,容易编译到任何平台上。release中提供了ar71xx版本的binary
|
||||
支持Openwrt,没有编译依赖,容易编译到任何平台上。release中提供了ar71xx版本的binary
|
||||
|
||||
单进程,纯异步,无锁,高并发,除了回收过期连接外,所有操作的时间复杂度都跟连接数无关。回收过期连接这个操作是个批量操作,会定期进行,但是会保证一次回收的数量不超过总数的1/10(可配置),不会造成延迟抖动。
|
||||
|
||||
### 关键词
|
||||
突破udp qos,突破udp屏蔽,openvpn tcp over tcp problem,openvpn over icmp,udp to icmp tunnel,udp to tcp tunnel,udp via icmp,udp via tcp
|
||||
|
||||
|
@ -1 +1,88 @@
|
||||
# udp2raw+openvpn config guide
|
||||
![image_vpn](/images/openvpn.PNG)
|
||||
|
||||
![image4](/images/image4.PNG)
|
||||
# udp2raw command
|
||||
#### run at server side
|
||||
```
|
||||
./udp2raw_amd64 -s -l0.0.0.0:8855 -r 127.0.0.1:7777 -k "passwd" --raw-mode faketcp -a
|
||||
```
|
||||
#### run at client side
|
||||
assume server ip is 45.66.77.88
|
||||
```
|
||||
./udp2raw_amd64 -s -l0.0.0.0:3333 -r 45.66.77.88:8855 -k "passwd" --raw-mode faketcp -a
|
||||
```
|
||||
|
||||
|
||||
# openvpn config
|
||||
|
||||
#### client side config
|
||||
```
|
||||
|
||||
remote 127.0.0.1 3333
|
||||
resolv-retry infinite
|
||||
nobind
|
||||
persist-key
|
||||
persist-tun
|
||||
|
||||
ca /root/add-on/openvpn/ca.crt
|
||||
cert /root/add-on/openvpn/client.crt
|
||||
key /root/add-on/openvpn/client.key
|
||||
|
||||
keepalive 3 20
|
||||
verb 3
|
||||
mute 20
|
||||
|
||||
comp-lzo no
|
||||
cipher none ##### disable openvpn 's cipher and auth for maxmized peformance.
|
||||
auth none ##### you can enable openvpn's cipher and auth,if you dont care about peformance,oryou dont trust udp2raw 's encryption
|
||||
|
||||
fragment 1200 ##### very important you can turn it up a bit. but,the lower the safer
|
||||
mssfix 1200 ##### very important
|
||||
|
||||
sndbuf 2000000 ##### important
|
||||
rcvbuf 2000000 ##### important
|
||||
txqueuelen 4000 ##### suggested
|
||||
```
|
||||
|
||||
|
||||
#### server side config
|
||||
```
|
||||
local 0.0.0.0
|
||||
port 7777
|
||||
proto udp
|
||||
dev tun
|
||||
|
||||
ca /etc/openvpn/easy-rsa/2.0/keys/ca.crt
|
||||
cert /etc/openvpn/easy-rsa/2.0/keys/server.crt
|
||||
key /etc/openvpn/easy-rsa/2.0/keys/server.key
|
||||
dh /etc/openvpn/easy-rsa/2.0/keys/dh1024.pem
|
||||
|
||||
server 10.222.2.0 255.255.255.0
|
||||
ifconfig 10.222.2.1 10.222.2.6
|
||||
|
||||
client-to-client
|
||||
duplicate-cn
|
||||
keepalive 10 60
|
||||
|
||||
max-clients 50
|
||||
|
||||
persist-key
|
||||
persist-tun
|
||||
|
||||
status /etc/openvpn/openvpn-status.log
|
||||
|
||||
verb 3
|
||||
mute 20
|
||||
|
||||
comp-lzo no
|
||||
cipher none ##### disable openvpn 's cipher and auth for maxmized peformance.
|
||||
auth none ##### you can enable openvpn's cipher and auth,if you dont care about peformance,oryou dont trust udp2raw 's encryption
|
||||
|
||||
fragment 1200 ##### very important you can turn it up a bit. but,the lower the safer
|
||||
mssfix 1200 ##### very important
|
||||
|
||||
sndbuf 2000000 ##### important
|
||||
rcvbuf 2000000 ##### important
|
||||
txqueuelen 4000 ##### suggested
|
||||
```
|
||||
|
20
main.cpp
20
main.cpp
@ -38,6 +38,7 @@ int disable_anti_replay=0;
|
||||
char key_string[1000]= "secret key";
|
||||
char key[16];//,key2[16];
|
||||
|
||||
|
||||
//uint64_t current_time_rough=0;
|
||||
|
||||
|
||||
@ -2351,6 +2352,7 @@ void process_arg(int argc, char *argv[])
|
||||
{"gen-rule", no_argument, 0, 'g'},
|
||||
{"debug", no_argument, 0, 1},
|
||||
{"clear", no_argument, 0, 1},
|
||||
{"lower-level", required_argument, 0, 1},
|
||||
{"sock-buf", required_argument, 0, 1},
|
||||
{"seq-mode", required_argument, 0, 1},
|
||||
{NULL, 0, 0, 0}
|
||||
@ -2544,6 +2546,24 @@ void process_arg(int argc, char *argv[])
|
||||
else if(strcmp(long_options[option_index].name,"log-level")==0)
|
||||
{
|
||||
}
|
||||
else if(strcmp(long_options[option_index].name,"lower-level")==0)
|
||||
{
|
||||
if(strchr(optarg,'#')==0)
|
||||
{
|
||||
mylog(log_fatal,"lower-level parameter invaild,should be if_name#mac_adress ,ie eth0#00:23:45:67:89:b9\n");
|
||||
myexit(-1);
|
||||
}
|
||||
lower_level=1;
|
||||
u32_t hw[6];
|
||||
memset(hw,0,sizeof(hw));
|
||||
sscanf(optarg,"%[^#]#%x:%x:%x:%x:%x:%x",if_name,&hw[0],&hw[1],&hw[2],&hw[3],&hw[4],&hw[5]);
|
||||
|
||||
mylog(log_warn,"make sure this is correct: ifname=<%s> gateway_hw_hd=<%x:%x:%x:%x:%x:%x> \n",if_name,hw[0],hw[1],hw[2],hw[3],hw[4],hw[5]);
|
||||
for(int i=0;i<6;i++)
|
||||
{
|
||||
oppsite_hw_addr[i]=uint8_t(hw[i]);
|
||||
}
|
||||
}
|
||||
else if(strcmp(long_options[option_index].name,"disable-color")==0)
|
||||
{
|
||||
//enable_log_color=0;
|
||||
|
13
makefile
13
makefile
@ -4,13 +4,18 @@ FLAGS2= -O3
|
||||
all:
|
||||
sudo killall udp2raw||true
|
||||
sleep 0.2
|
||||
g++ main.cpp -o udp2raw_amd64 -static -ggdb -I. lib/aes.c lib/md5.c encrypt.cpp log.cpp network.cpp common.cpp -lrt -std=c++11 ${FLAGS} ${FLAGS2}
|
||||
${ccmips} main.cpp -o udp2raw_ar71xx -lrt -I. lib/aes.c lib/md5.c encrypt.cpp log.cpp network.cpp common.cpp -std=c++11 ${FLAGS} ${FLAGS2}
|
||||
g++ main.cpp -o udp2raw -static -ggdb -I. lib/aes.c lib/md5.c encrypt.cpp log.cpp network.cpp common.cpp -lrt -std=c++11 ${FLAGS} ${FLAGS2}
|
||||
# ${ccmips} main.cpp -o udp2raw_ar71xx -lrt -I. lib/aes.c lib/md5.c encrypt.cpp log.cpp network.cpp common.cpp -std=c++11 ${FLAGS} ${FLAGS2}
|
||||
fast:
|
||||
sudo killall udp2raw||true
|
||||
sleep 0.2
|
||||
g++ main.cpp -o udp2raw_amd64 -ggdb -I. lib/aes.c lib/md5.c encrypt.cpp log.cpp network.cpp common.cpp -lrt -std=c++11 ${FLAGS}
|
||||
g++ main.cpp -o udp2raw -ggdb -I. lib/aes.c lib/md5.c encrypt.cpp log.cpp network.cpp common.cpp -lrt -std=c++11 ${FLAGS}
|
||||
|
||||
|
||||
debug:
|
||||
g++ main.cpp -o udp2raw_amd64 -static -ggdb -I. -Ilib lib/aes.c lib/md5.c encrypt.cpp log.cpp network.cpp common.cpp -lrt -std=c++11 ${FLAGS} -Wformat-nonliteral -D MY_DEBUG
|
||||
g++ main.cpp -o udp2raw -static -ggdb -I. -Ilib lib/aes.c lib/md5.c encrypt.cpp log.cpp network.cpp common.cpp -lrt -std=c++11 ${FLAGS} -Wformat-nonliteral -D MY_DEBUG
|
||||
|
||||
release:
|
||||
g++ main.cpp -o udp2raw_amd64 -static -ggdb -I. lib/aes.c lib/md5.c encrypt.cpp log.cpp network.cpp common.cpp -lrt -std=c++11 ${FLAGS} ${FLAGS2}
|
||||
${ccmips} main.cpp -o udp2raw_ar71xx -lrt -I. lib/aes.c lib/md5.c encrypt.cpp log.cpp network.cpp common.cpp -std=c++11 ${FLAGS} ${FLAGS2}
|
||||
|
||||
|
121
network.cpp
121
network.cpp
@ -20,7 +20,13 @@ int disable_bpf_filter=0; //for test only,most time no need to disable this
|
||||
|
||||
u32_t bind_address_uint32=0;
|
||||
|
||||
int lower_level=0;
|
||||
int ifindex=-1;
|
||||
char if_name[100]="";
|
||||
|
||||
unsigned char oppsite_hw_addr[6]=
|
||||
{0xff,0xff,0xff,0xff,0xff,0xff};
|
||||
//{0x00,0x23,0x45,0x67,0x89,0xb9};
|
||||
|
||||
struct sock_filter code_tcp_old[] = {
|
||||
{ 0x28, 0, 0, 0x0000000c },//0
|
||||
@ -156,20 +162,47 @@ packet_info_t::packet_info_t()
|
||||
int init_raw_socket()
|
||||
{
|
||||
|
||||
if(lower_level==0)
|
||||
{
|
||||
raw_send_fd = socket(AF_INET , SOCK_RAW , IPPROTO_TCP);
|
||||
|
||||
|
||||
if(raw_send_fd == -1) {
|
||||
mylog(log_fatal,"Failed to create raw_send_fd\n");
|
||||
//perror("Failed to create raw_send_fd");
|
||||
myexit(1);
|
||||
}
|
||||
|
||||
int one = 1;
|
||||
const int *val = &one;
|
||||
if (setsockopt (raw_send_fd, IPPROTO_IP, IP_HDRINCL, val, sizeof (one)) < 0) {
|
||||
mylog(log_fatal,"Error setting IP_HDRINCL %d\n",errno);
|
||||
//perror("Error setting IP_HDRINCL");
|
||||
myexit(2);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
raw_send_fd = socket(PF_PACKET , SOCK_DGRAM , htons(ETH_P_IP));
|
||||
|
||||
if(raw_send_fd == -1) {
|
||||
mylog(log_fatal,"Failed to create raw_send_fd\n");
|
||||
//perror("Failed to create raw_send_fd");
|
||||
myexit(1);
|
||||
}
|
||||
init_ifindex(if_name);
|
||||
|
||||
}
|
||||
|
||||
if(setsockopt(raw_send_fd, SOL_SOCKET, SO_SNDBUFFORCE, &socket_buf_size, sizeof(socket_buf_size))<0)
|
||||
{
|
||||
mylog(log_fatal,"SO_SNDBUFFORCE fail\n");
|
||||
myexit(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//raw_fd = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL));
|
||||
|
||||
raw_recv_fd= socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
|
||||
@ -188,13 +221,7 @@ int init_raw_socket()
|
||||
|
||||
//IP_HDRINCL to tell the kernel that headers are included in the packet
|
||||
|
||||
int one = 1;
|
||||
const int *val = &one;
|
||||
if (setsockopt (raw_send_fd, IPPROTO_IP, IP_HDRINCL, val, sizeof (one)) < 0) {
|
||||
mylog(log_fatal,"Error setting IP_HDRINCL %d\n",errno);
|
||||
//perror("Error setting IP_HDRINCL");
|
||||
myexit(2);
|
||||
}
|
||||
|
||||
|
||||
setnonblocking(raw_send_fd); //not really necessary
|
||||
setnonblocking(raw_recv_fd);
|
||||
@ -258,8 +285,26 @@ void remove_filter()
|
||||
//exit(-1);
|
||||
}
|
||||
}
|
||||
int init_ifindex(char * if_name)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
size_t if_name_len=strlen(if_name);
|
||||
if (if_name_len<sizeof(ifr.ifr_name)) {
|
||||
memcpy(ifr.ifr_name,if_name,if_name_len);
|
||||
ifr.ifr_name[if_name_len]=0;
|
||||
} else {
|
||||
mylog(log_fatal,"interface name is too long\n");
|
||||
myexit(-1);
|
||||
}
|
||||
if (ioctl(raw_send_fd,SIOCGIFINDEX,&ifr)==-1) {
|
||||
|
||||
|
||||
mylog(log_fatal,"SIOCGIFINDEX fail ,%s\n",strerror(errno));
|
||||
myexit(-1);
|
||||
}
|
||||
ifindex=ifr.ifr_ifindex;
|
||||
mylog(log_info,"ifname:%s ifindex:%d\n",if_name,ifindex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int send_raw_ip(raw_info_t &raw_info,const char * payload,int payloadlen)
|
||||
@ -271,17 +316,20 @@ 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));
|
||||
|
||||
struct sockaddr_in sin;
|
||||
sin.sin_family = AF_INET;
|
||||
//sin.sin_port = htons(info.dst_port); //dont need this
|
||||
sin.sin_addr.s_addr = send_info.dst_ip;
|
||||
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;
|
||||
|
||||
// iph->id = htonl (ip_id++); //Id of this packet
|
||||
// iph->id = 0; //Id of this packet ,kernel will auto fill this if id is zero
|
||||
if(lower_level)
|
||||
{
|
||||
iph->id=0;
|
||||
//iph->id = htons (ip_id++); //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->frag_off = htons(0x4000); //DF set,others are zero
|
||||
// iph->frag_off = htons(0x0000); //DF set,others are zero
|
||||
iph->ttl = 64;
|
||||
@ -291,20 +339,51 @@ int send_raw_ip(raw_info_t &raw_info,const char * payload,int payloadlen)
|
||||
iph->daddr = send_info.dst_ip;
|
||||
|
||||
uint16_t ip_tot_len=sizeof (struct iphdr)+payloadlen;
|
||||
// iph->tot_len = htons(ip_tot_len); //this is not necessary ,kernel will always auto fill this //http://man7.org/linux/man-pages/man7/raw.7.html
|
||||
//iph->tot_len = ip_tot_len;
|
||||
if(lower_level)iph->tot_len = htons(ip_tot_len); //this is not necessary ,kernel will always auto fill this //http://man7.org/linux/man-pages/man7/raw.7.html
|
||||
else
|
||||
iph->tot_len = 0;
|
||||
|
||||
memcpy(send_raw_ip_buf+sizeof(iphdr) , payload, payloadlen);
|
||||
|
||||
//iph->check = csum ((unsigned short *) send_raw_ip_buf, ip_tot_len); //this is not necessary ,kernel will always auto fill this
|
||||
if(lower_level) iph->check =
|
||||
csum ((unsigned short *) send_raw_ip_buf, iph->ihl*4); //this is not necessary ,kernel will always auto fill this
|
||||
else
|
||||
iph->check=0;
|
||||
|
||||
int ret = sendto(raw_send_fd, send_raw_ip_buf, ip_tot_len , 0, (struct sockaddr *) &sin, sizeof (sin));
|
||||
int ret;
|
||||
if(lower_level==0)
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
sin.sin_family = AF_INET;
|
||||
//sin.sin_port = htons(info.dst_port); //dont need this
|
||||
sin.sin_addr.s_addr = send_info.dst_ip;
|
||||
ret = sendto(raw_send_fd, send_raw_ip_buf, ip_tot_len , 0, (struct sockaddr *) &sin, sizeof (sin));
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
struct sockaddr_ll addr;
|
||||
memset(&addr,0,sizeof(addr));
|
||||
|
||||
addr.sll_family=AF_PACKET;
|
||||
addr.sll_ifindex=ifindex;
|
||||
addr.sll_halen=ETHER_ADDR_LEN;
|
||||
addr.sll_protocol=htons(ETH_P_IP);
|
||||
memcpy(addr.sll_addr,oppsite_hw_addr,ETHER_ADDR_LEN);
|
||||
ret = sendto(raw_send_fd, send_raw_ip_buf, ip_tot_len , 0, (struct sockaddr *) &addr, sizeof (addr));
|
||||
}
|
||||
if(ret==-1)
|
||||
{
|
||||
mylog(log_debug,"sendto failed\n");
|
||||
|
||||
mylog(log_trace,"sendto failed\n");
|
||||
//perror("why?");
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
//mylog(log_info,"sendto succ\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int peek_raw(packet_info_t &peek_info)
|
||||
@ -426,7 +505,7 @@ int recv_raw_ip(raw_info_t &raw_info,char * &payload,int &payloadlen)
|
||||
|
||||
if(ip_chk!=0)
|
||||
{
|
||||
mylog(log_debug,"ip header error %d\n",ip_chk);
|
||||
mylog(log_debug,"ip header error %x\n",ip_chk);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,10 @@ extern int filter_port;
|
||||
extern u32_t bind_address_uint32;
|
||||
extern int disable_bpf_filter;
|
||||
|
||||
extern int lower_level;
|
||||
extern char if_name[100];
|
||||
extern unsigned char oppsite_hw_addr[];
|
||||
|
||||
struct icmphdr
|
||||
{
|
||||
uint8_t type;
|
||||
@ -76,6 +80,7 @@ int init_raw_socket();
|
||||
void init_filter(int port);
|
||||
|
||||
void remove_filter();
|
||||
int init_ifindex(char * if_name);
|
||||
|
||||
|
||||
int send_raw_ip(raw_info_t &raw_info,const char * payload,int payloadlen);
|
||||
|
Loading…
x
Reference in New Issue
Block a user