Compare commits

..

102 Commits

Author SHA1 Message Date
wangyu
32166d65ae bug fix 2017-08-13 08:18:23 +08:00
wangyu
2af94823e3 better makefile 2017-08-13 02:14:50 +08:00
root
00a3955de0 Merge branch 'master' of https://github.com/wangyu-/udp2raw-tunnel 2017-08-12 19:21:31 +08:00
root
0266163b12 fixed a makefile problem 2017-08-12 19:21:24 +08:00
wangyu-
df55271c08 Update README.zh-cn.md 2017-08-12 03:56:39 -07:00
wangyu-
facf7e4049 Update README.md 2017-08-12 03:54:20 -07:00
wangyu-
81209ba25e Update README.md 2017-08-12 03:07:22 -07:00
wangyu-
8c833776da Update README.md 2017-08-11 23:36:48 -07:00
wangyu-
aede2a8680 Update README.md 2017-08-11 23:15:54 -07:00
wangyu-
b0636445e3 Update README.md 2017-08-11 22:55:41 -07:00
wangyu-
f8715a1d1d Update README.md 2017-08-11 22:48:04 -07:00
wangyu-
6205aa6b8f Update README.zh-cn.md 2017-08-11 21:46:38 -07:00
wangyu-
ae0509d7d2 Update README.md 2017-08-11 21:44:52 -07:00
wangyu
2fa2666479 make cross2 cross3 2017-08-12 11:36:14 +08:00
wangyu-
fdbf1e082f Update README.md 2017-08-11 17:24:51 -07:00
wangyu
d502de0c7c Merge branch 'master' of https://github.com/wangyu-/udp2raw-tunnel 2017-08-12 07:13:30 +08:00
wangyu
8487d7c624 updated image 2017-08-12 07:12:54 +08:00
wangyu-
83b00e79ad Add files via upload 2017-08-11 08:40:23 -07:00
wangyu-
36ed28064a Create 111 2017-08-11 08:39:43 -07:00
wangyu-
746aefa70a Update README.md 2017-08-11 06:54:39 -07:00
wangyu-
a69cbf23da Merge pull request #4 from t123yh/patch-1
Update README.md
2017-08-11 21:50:00 +08:00
Tian Yunhao
fc4d178657 Update README.md 2017-08-11 20:36:37 +08:00
wangyu-
ccab523ddf Update README.zh-cn.md 2017-08-11 02:46:33 -07:00
wangyu-
4eb72f6139 Update README.md 2017-08-11 02:45:29 -07:00
wangyu-
6296322e22 Update README.zh-cn.md 2017-08-11 02:41:07 -07:00
wangyu-
3a0c512e43 Update README.md 2017-08-11 02:39:46 -07:00
wangyu-
e01d7059ad Update README.zh-cn.md 2017-08-11 02:26:25 -07:00
wangyu-
5e6d977247 Update README.md 2017-08-11 02:25:14 -07:00
wangyu-
c08bd12ea0 Update README.md 2017-08-11 01:55:26 -07:00
wangyu-
ebdb08873a Update README.md 2017-08-11 01:54:39 -07:00
wangyu-
46b0a00b3e Update README.md 2017-08-11 01:53:03 -07:00
wangyu-
d1934dda4c Update README.md 2017-08-11 01:52:29 -07:00
wangyu-
81e599e84c Update README.zh-cn.md 2017-08-11 01:50:25 -07:00
wangyu-
fadf5a25c2 Update README.zh-cn.md 2017-08-11 01:49:56 -07:00
wangyu-
9f25a61dad Update README.md 2017-08-11 01:47:20 -07:00
wangyu-
165dc193f0 Update README.md 2017-08-11 01:45:53 -07:00
wangyu-
e732ce2a8a Update README.md 2017-08-11 01:33:20 -07:00
wangyu-
d7cae0be18 Update README.md 2017-08-11 01:32:55 -07:00
wangyu
c1b8eb23a2 english build_guide 2017-08-11 16:30:22 +08:00
wangyu
1bbe19cdee Merge branch 'master' of https://github.com/wangyu-/udp2raw-tunnel 2017-08-11 16:17:43 +08:00
wangyu
b16b37c879 fixed cmake 2017-08-11 16:17:26 +08:00
wangyu-
9479c95510 Update README.md 2017-08-10 23:49:55 -07:00
wangyu-
90b1897d4a Update README.md 2017-08-10 23:49:24 -07:00
wangyu-
3fa1a99046 Update README.zh-cn.md 2017-08-10 23:47:36 -07:00
wangyu-
eb59012b7b Update README.md 2017-08-10 23:31:42 -07:00
wangyu-
1a2cd767c0 Update README.zh-cn.md 2017-08-10 23:06:34 -07:00
wangyu-
8f04c82788 Update README.md 2017-08-10 22:53:01 -07:00
wangyu-
1b9f2a1e0e Update README.md 2017-08-10 22:51:50 -07:00
wangyu-
7592729abc Update README.md 2017-08-10 22:42:00 -07:00
wangyu
e890a6344c reverted extern c syntax,fixed a makefile problem 2017-08-11 12:25:04 +08:00
wangyu-
bc6358aa0a Merge pull request #3 from BroncoTc/master
merged pull request "add cmake support and fix compile errors“
2017-08-11 11:39:05 +08:00
broncotc
ed6416a30d add cmake support and fix compile errors 2017-08-11 10:45:40 +08:00
wangyu-
9378cee8d1 Update kcptun_step_by_step.md 2017-08-10 08:46:05 -07:00
wangyu-
0b3fb41f6f Update kcptun_step_by_step.md 2017-08-10 08:45:45 -07:00
wangyu-
41489af1d1 Update build_guide.zh-cn.md 2017-08-10 07:15:10 -07:00
wangyu
3a1bacc11e Merge branch 'master' of https://github.com/wangyu-/udp2raw-tunnel 2017-08-10 22:08:18 +08:00
wangyu-
06d7638c5f Update README.zh-cn.md 2017-08-10 07:08:21 -07:00
wangyu
380971fe2b modified makefile 2017-08-10 22:08:09 +08:00
wangyu-
709258b260 Update build_guide.zh-cn.md 2017-08-10 07:04:45 -07:00
wangyu-
c3a8305e49 Update build_guide.zh-cn.md 2017-08-10 07:03:57 -07:00
wangyu-
5c08d65d91 Update build_guide.zh-cn.md 2017-08-10 07:03:38 -07:00
wangyu-
6f9ab92c1d Create build_guide.zh-cn.md 2017-08-10 06:20:51 -07:00
wangyu-
2f57fa6670 Update openvpn_guide.md 2017-08-10 05:39:06 -07:00
wangyu-
d104074328 Update README.zh-cn.md 2017-08-10 03:21:34 -07:00
wangyu-
7c280ab335 Update README.md 2017-08-10 03:20:35 -07:00
wangyu-
eb8567b693 Update README.zh-cn.md 2017-08-10 00:05:47 -07:00
wangyu-
fec382ebab Update README.zh-cn.md 2017-08-09 23:46:03 -07:00
wangyu-
4d319f54ff Update README.zh-cn.md 2017-08-09 23:44:41 -07:00
wangyu-
a58618c73c Update README.zh-cn.md 2017-08-09 23:39:53 -07:00
wangyu-
456da000f4 Update README.zh-cn.md 2017-08-09 23:37:30 -07:00
wangyu-
91e229616c Update README.md 2017-08-09 20:49:44 -07:00
wangyu
2251947278 Merge branch 'master' of https://github.com/wangyu-/udp2raw-tunnel 2017-08-09 21:30:10 +08:00
wangyu
c48c619002 added mtu warning 2017-08-09 21:29:54 +08:00
wangyu-
0cac945a26 Update kcptun_step_by_step.md 2017-08-09 06:04:18 -07:00
wangyu-
97738ab3ce Update finalspeed_step_by_step.md 2017-08-09 06:03:25 -07:00
wangyu-
a6bb0b50cf Update finalspeed_step_by_step.md 2017-08-09 06:02:30 -07:00
wangyu-
e7530fa7f9 Update README.zh-cn.md 2017-08-09 05:15:03 -07:00
wangyu-
cec1257474 Update README.zh-cn.md 2017-08-08 19:09:51 -07:00
wangyu
c97f09f534 Merge branch 'master' of https://github.com/wangyu-/udp2raw-tunnel 2017-08-09 09:18:41 +08:00
wangyu
92581be9a1 generates udp2raw_binaries.tar.gz in makefile 2017-08-09 09:18:27 +08:00
wangyu-
58ab1f6b15 Update README.zh-cn.md 2017-08-08 08:57:07 -07:00
wangyu-
1b0d4f6d08 Update README.zh-cn.md 2017-08-08 01:24:34 -07:00
wangyu
91a015b8a8 Merge branch 'master' of https://github.com/wangyu-/udp2raw-tunnel 2017-08-08 15:49:28 +08:00
wangyu
ce2e6a094d added send-direction failure direction,x86 binary 2017-08-08 15:49:11 +08:00
wangyu-
59af4a0135 Update README.md 2017-08-07 18:54:55 -07:00
wangyu-
b5c6176079 Add files via upload 2017-08-08 09:54:31 +08:00
wangyu-
83abc1def4 Update kcptun_step_by_step.md 2017-08-07 16:05:27 -07:00
wangyu
307399b00a added option lower-level 2017-08-07 23:42:09 +08:00
wangyu-
44852270ef Create openvpn_guide.md 2017-08-06 22:03:13 -07:00
wangyu-
ae153ceacc Update finalspeed_step_by_step.md 2017-08-06 19:43:18 -07:00
wangyu-
da6aafba12 Update README.md 2017-08-06 19:33:25 -07:00
wangyu-
e50d368440 Update finalspeed_step_by_step.md 2017-08-06 09:28:26 -07:00
wangyu-
801ecfd0ee Update README.zh-cn.md 2017-08-06 08:28:11 -07:00
wangyu-
45b7ab6285 Update README.zh-cn.md ,tcptun_step_by_step.md,finalspeed_step_by_step.md 2017-08-06 23:18:16 +08:00
wangyu-
8271cce383 Update README.zh-cn.md 2017-08-06 00:43:44 -07:00
wangyu
00dcec9896 Merge branch 'master' of https://github.com/wangyu-/udp2raw-tunnel 2017-08-06 14:50:50 +08:00
wangyu
6be7034bcb chinese readme 2017-08-06 14:50:27 +08:00
wangyu-
9593528dd4 Update README.md 2017-08-05 23:21:09 -07:00
wangyu-
9884544e34 Update README.md 2017-08-05 23:11:36 -07:00
wangyu-
858928a17f Update README.md 2017-08-05 23:10:26 -07:00
wangyu-
dc6c328d57 Update README.md 2017-08-06 13:12:23 +08:00
wangyu-
716c183886 Update README.md 2017-08-05 06:48:55 -07:00
44 changed files with 1049 additions and 113 deletions

19
CMakeLists.txt Normal file
View File

@@ -0,0 +1,19 @@
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
lib/aes.c
lib/md5.c
common.cpp
encrypt.cpp
log.cpp
main.cpp
network.cpp
)
set(CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-unused-variable -Wno-unused-parameter -static")
#set(CMAKE_LINK_LIBRARY_FLAG "-lrt")
add_executable(udp2raw_tunnel ${SOURCE_FILES})
target_link_libraries(udp2raw_tunnel rt)

191
README.md
View File

@@ -1,14 +1,187 @@
# udp2raw-tunnel
udp2raw tunnel (udp to tcp with fake tcp header)
# Udp2raw-tunnel
![image0](images/image0.PNG)
#usage
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.
client:
-A INPUT -s 44.55.66.77/32 -p tcp -m tcp --sport 9999 -j DROP
[简体中文](/doc/README.zh-cn.md)
# Features
### Send / Receive UDP Packet with fake-tcp/icmp headers
Fake-tcp/icmp headers help you bypass UDP blocking, UDP QOS or improper UDP NAT behavior on some ISPs. Raw packets with UDP headers are also supported.In UDP header mode,it behaves just like a normal UDP tunnel,and you can just make use of the other features.
./raw -l 127.0.0.1:6666 -r44.55.66.77:9999 -c --source-ip 192.168.1.100
### 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.
server:
-A INPUT -p tcp -m tcp --dport 9999 -j DROP
### Encrpytion, Anti-Replay, Anti-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.
./raw -l44.55.66.77:9999 -r 127.0.0.1:5555 -s
### 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.
For example, if you use UDP2RAW + OpenVPN, OpenVPN won't lose connection after any reconnect, **even if the network cable is re-plugged or the WiFi access point is changed**.
### Other Features
* **Multiplexing** One client can handle multiple UDP connections, all of which share the same raw connection.
* **Multiple Clients** One server can have multiple clients.
* **NAT Support** All of the 3 modes work in NAT environments.
* **OpenVZ Support** Tested on BandwagonHost.
* **OpenWRT Support** No dependencies, easy to build. Binary for ar71xx are included in release.
### Keywords
* 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
# Getting Started
### Prerequisites
A Linux host (including desktop Linux, OpenWRT router, or Raspberry PI) with root access.
If you want to use it on MICRO$OFT Windows, you can use VMware or Hyper-V (both bridged mode and <del>NAT mode</del> are supported).
### Installing
Download binary release from https://github.com/wangyu-/udp2raw-tunnel/releases
### Running
Assume your UDP is blocked or being QOS-ed or just poorly supported. Assume your server ip is 44.55.66.77, you have a service listening on udp port 7777.
```bash
# Run at client side
./udp2raw_amd64 -c -l0.0.0.0:3333 -r44.55.66.77:4096 -a -k "passwd" --raw-mode faketcp
# Run at server side:
./udp2raw_amd64 -s -l0.0.0.0:4096 -r 127.0.0.1:7777 -a -k "passwd" --raw-mode faketcp
```
Now,an encrypted raw tunnel has been established between client and server through TCP port 4096. Connecting to UDP port 3333 at the client side is equivalent to connecting to port 7777 at the server side. No UDP traffic will be exposed.
# Advanced Topic
### Usage
```
udp2raw-tunnel
version: Aug 5 2017 21:03:54
repository: https://github.com/wangyu-/udp2raw-tunnel
usage:
run as client : ./this_program -c -l local_listen_ip:local_port -r server_ip:server_port [options]
run as server : ./this_program -s -l server_listen_ip:server_port -r remote_ip:remote_port [options]
common options,these options must be same on both side:
--raw-mode <string> avaliable values:faketcp(default),udp,icmp
-k,--key <string> password to gen symetric key,default:"secret key"
--auth-mode <string> avaliable values:aes128cbc(default),xor,none
--cipher-mode <string> avaliable values:md5(default),crc32,simple,none
-a,--auto-rule auto add (and delete) iptables rule
-g,--gen-rule generate iptables rule then exit
--disable-anti-replay disable anti-replay,not suggested
client options:
--source-ip <ip> force source-ip for raw socket
--source-port <port> force source-port for raw socket,tcp/udp only
this option disables port changing while re-connecting
other options:
--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
--disable-bpf disable the kernel space filter,most time its not necessary
unless you suspect there is a bug
--sock-buf <number> buf size for socket,>=10 and <=10240,unit:kbyte,default:1024
--seqmode <number> seq increase mode for faketcp:
0:dont increase
1:increase every packet
2:increase randomly, about every 3 packets (default)
-h,--help print this help message
```
### IPTABLES rule
This program sends packets via raw socket. In FakeTCP mode, Linux kernel TCP packet processing has to be blocked by a iptables rule on both sides, otherwise the kernel will automatically send RST for an unrecongized TCP packet and you will sustain from stability / peformance problems. You can use `-a` option to let the program automatically add / delete iptables rule on start / exit. You can also use the `-g` option to generate iptables rule and add it manually.
### `cipher-mode` and `auth-mode`
It is suggested to use `aes128cbc` + `md5` to obtain maximum security. If you want to run the program on a router, you can try `xor` + `simple`, which can fool packet inspection by firewalls the most of time, but it cannot protect you from serious attacks. Mode none is only for debugging purpose. It is not recommended to set the cipher-mode or auth-mode to none.
### seq-mode
The FakeTCP mode does not behave 100% like a real tcp connection. ISPs may be able to distinguish the simulated tcp traffic from the real TCP traffic (though it's costly). seq-mode can help you change the seq increase behavior slightly. If you experience connection problems, try to change the value.
# Peformance Test
#### Test method:
iperf3 TCP via OpenVPN + udp2raw
(iperf3 UDP mode is not used because of a bug mentioned in this issue: https://github.com/esnet/iperf/issues/296 . Instead, we package the TCP traffic into UDP by OpenVPN to test the performance. Read [Application](https://github.com/wangyu-/udp2raw-tunnel#application) for details.
#### iperf3 command:
```
iperf3 -c 10.222.2.1 -P40
iperf3 -c 10.222.2.1 -P40 -R
```
#### Environments
* **Client** Vultr $2.5/monthly plan (single core 2.4GHz cpu, 512MB RAM, Tokyo, Japan)
* **Server** BandwagonHost $3.99/annually plan (single core 2.0GHz cpu, 128MB RAM, Los Angeles, USA)
### Test1
raw_mode: faketcp cipher_mode: xor  auth_mode: simple
![image4](images/image4.PNG)
(reverse speed was simliar and not uploaded)
### Test2
raw_mode: faketcp cipher_mode: aes128cbc  auth_mode: md5
![image5](images/image5.PNG)
(reverse speed was simliar and not uploaded)
# Application
### tunneling any traffic via raw traffic by using udp2raw +openvpn
![image_vpn](images/openvpn.PNG)
1. bypasses UDP block/UDP QOS
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)
### 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)
### speed-up tcp connection via raw traffic by using udp2raw+finalspeed
finalspeed is a tcp connection speed-up program similiar to kcptun,it speeds-up tcp connection by using kcp protocol on-top of udp or tcp.but its tcp mode doesnt support openvz,you can bypass this problem if you use udp2raw+finalspeed together,and icmp mode also becomes avaliable.
# How to build
read [build_guide](/doc/build_guide.md)
# Other
### Easier installation on ArchLinux
```
yaourt -S udp2raw-tunnel # or
pacaur -S udp2raw-tunnel
```
# Related work
### kcptun-raw
udp2raw was inspired by kcptun-raw,which modified kcptun to support tcp mode.
https://github.com/Chion82/kcptun-raw
### relayRawSocket
kcptun-raw was inspired by relayRawSocket. A simple udp to raw tunnel,wrote in python
https://github.com/linhua55/some_kcptun_tools/tree/master/relayRawSocket
### kcpraw
another project of kcptun with tcp mode
https://github.com/ccsexyz/kcpraw
### icmptunnel
Transparently tunnel your IP traffic through ICMP echo and reply packets.
https://github.com/DhavalKapil/icmptunnel

View File

@@ -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;

View File

@@ -42,6 +42,7 @@
#include <arpa/inet.h>
#include <stdarg.h>
#include <assert.h>
#include <linux/if_packet.h>
@@ -58,7 +59,7 @@ typedef int i32_t;
const int max_data_len=1600;
const int buf_len=max_data_len+200;
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=1000;
@@ -70,7 +71,7 @@ const u32_t client_retry_interval=1000;
const u32_t server_handshake_timeout=10000;// this should be much 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=10;
const int conn_clear_ratio=30;
const int conv_clear_min=5;
const int conn_clear_min=1;
@@ -88,6 +89,7 @@ const u32_t timer_interval=400;//this should be smaller than heartbeat_interval
const u32_t conv_timeout=30000; //for test
const u32_t client_conn_timeout=10000;
const u32_t client_conn_uplink_timeout=client_conn_timeout+2000;
//const uint32_t server_conn_timeout=conv_timeout+60000;//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

175
doc/README.zh-cn.md Normal file
View File

@@ -0,0 +1,175 @@
Udp2raw-tunnel
![image2](/images/image2.PNG)
加密、防重放攻击的、信道复用的udp tunnel利用raw socket中转udp流量.同时有心跳保活,且在断线重连后保持上层连接不掉线的功能。
[English](/README.md)
[udp2raw+kcptun step_by_step教程](kcptun_step_by_step.md)
[udp2raw+finalspeed step_by_step教程](finalspeed_step_by_step.md)
如果你需要加速跨国网游、网页浏览解决方案在另一个repo
https://github.com/wangyu-/UDPspeeder
# 功能特性
### 把udp流量伪装成tcp /icmp
用raw socket给udp包加上tcp/icmp包头可以突破udp流量限制或Udp QOS。或者在udp nat有问题的环境下提升稳定性。  另外也支持用raw 发udp包这样流量不会被伪装只会被加密。
### 模拟TCP3次握手
模拟TCP3次握手模拟seq ack过程。另外还模拟了一些tcp optionMSS,sackOk,TS,TS_ack,wscale用来使流量看起来更像是由普通的linux tcp协议栈发送的。
### 心跳保活、自动重连,连接快速恢复,单向链路失效检测
心跳保活、自动重连udp2raw重连可以恢复上次的连接重连后上层连接继续有效底层掉线上层不掉线。有效解决上层连接断开的问题。 (功能借鉴自[kcptun-raw](https://github.com/Chion82/kcptun-raw)**就算你拔掉网线重插或者重新拨号获得新ip上层应用也不会断线**
Client能用单倍的超时时间检测到单向链路的失效不管是上行还是下行只要有一个方向失效就能被client检测到。重连只需要client发起就可以立即被server处理不需要等到server端的连接超时后。
对于有大量client的情况对于不同client,server发送的心跳是错开时间发送的不会因为短时间发送大量的心跳而造成拥塞和延迟抖动。
### 加密 防重放攻击 防中间人攻击
用aes128cbc加密md5/crc32做数据完整校验。用类似ipsec/openvpn的 replay windows机制来防止重放攻击。
设计目标是即使攻击者可以监听到tunnel的所有包可以选择性丢弃tunnel的任意包可以重放任意包攻击者也没办法获得tunnel承载的任何数据也没办法向tunnel的数据流中通过包构造/包重放插入任何数据。client和server互相认证对方无法被中间人攻击。
### 其他特性
信道复用client的udp端支持多个连接。
server支持多个client也能正确处理多个连接的重连和连接恢复。
NAT 穿透 tcp icmp udp模式都支持nat穿透。
支持Openvz配合finalspeed使用可以在openvz上用tcp模式的finalspeed
支持Openwrt没有编译依赖容易编译到任何平台上。release中提供了ar71xx版本的binary
epoll纯异步高并发除了回收过期连接外所有操作的时间复杂度都跟连接数无关。回收过期连接的操做也是柔和进行的不会因为消耗太多cpu时间造成延迟抖动。
### 关键词
突破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
# 简明操作说明
### 环境要求
Linux主机有root权限。主机上最好安装了iptables命令(apt/yum很容易安装)。在windows和mac上可以开虚拟机桥接模式和<del>NAT模式</del>经测试都可用)。
### 安装
下载编译好的二进制文件,解压到任意目录。
https://github.com/wangyu-/udp2raw-tunnel/releases
### 运行
假设你有一个serverip为44.55.66.77有一个服务监听在udp 7777端口。 假设你本地的主机到44.55.66.77的UDP流量被屏蔽了或者被qos了
```
在client端运行:
./udp2raw_amd64 -c -l0.0.0.0:3333 -r44.55.66.77:4096 -a -k "passwd" --raw-mode faketcp
在server端运行:
./udp2raw_amd64 -s -l0.0.0.0:4096 -r 127.0.0.1:7777 -a -k "passwd" --raw-mode faketcp
```
现在client和server之间建立起了tunnel。想要在本地连接44.55.66.77:7777只需要连接 127.0.0.1:3333。来回的所有的udp流量会被经过tunneling发送。在外界看起来是tcp流量不会有udp流量暴露到公网。
# 进阶操作说明
### 命令选项
```
udp2raw-tunnel
version: Aug 5 2017 21:03:54
repository: https://github.com/wangyu-/udp2raw-tunnel
usage:
run as client : ./this_program -c -l local_listen_ip:local_port -r server_ip:server_port [options]
run as server : ./this_program -s -l server_listen_ip:server_port -r remote_ip:remote_port [options]
common options,these options must be same on both side:
--raw-mode <string> avaliable values:faketcp(default),udp,icmp
-k,--key <string> password to gen symetric key,default:"secret key"
--auth-mode <string> avaliable values:aes128cbc(default),xor,none
--cipher-mode <string> avaliable values:md5(default),crc32,simple,none
-a,--auto-rule auto add (and delete) iptables rule
-g,--gen-rule generate iptables rule then exit
--disable-anti-replay disable anti-replay,not suggested
client options:
--source-ip <ip> force source-ip for raw socket
--source-port <port> force source-port for raw socket,tcp/udp only
this option disables port changing while re-connecting
other options:
--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
--disable-bpf disable the kernel space filter,most time its not necessary
unless you suspect there is a bug
--sock-buf <number> buf size for socket,>=10 and <=10240,unit:kbyte,default:1024
--seqmode <number> seq increase mode for faketcp:
0:dont increase
1:increase every packet
2:increase randomly, about every 3 packets (default)
-h,--help print this help message
```
### iptables 规则
用raw收发tcp包本质上绕过了linux内核的tcp协议栈。linux碰到raw socket发来的包会不认识如果一直收到不认识的包会回复大量RST造成不稳定或性能问题。所以强烈建议添加iptables规则屏蔽Linux内核的对指定端口的处理。用-a选项udp2raw会在启动的时候自动帮你加上Iptables规则退出的时候再自动删掉。如果长期使用可以用-g选项来生成相应的Iptables规则再自己手动添加这样规则不会在udp2raw退出时被删掉可以避免停掉udp2raw后内核向对端回复RST。
用raw收发udp包也类似只是内核回复的是icmp unreachable。而用raw 收发icmp内核会自动回复icmp echo。都需要相应的iptables规则。
### cipher-mode 和 auth-mode
如果要最大的安全性建议用aes128cbc+md5。如果要运行再路由器上建议xor+simple。但是注意xor+simple只能骗过防火墙的包检测不能防止真正的攻击者。
### seq-mode
facktcp模式并没有模拟tcp的全部。所以理论上有办法把faketcp和真正的tcp流量区分开来虽然大部分ISP不太可能做这种程度的包检测。seq-mode可以改变一些seq ack的行为。如果遇到了连接问题可以尝试更改。在我这边的移动线路用3种模式都没问题。
# 性能测试
iperf3 的UDP模式有BUG所以这里用iperf3的tcp模式配合Openvpn测试udp2raw的性能。iperf3 udp issue ,https://github.com/esnet/iperf/issues/296
openvpn关掉了自带的加密。
#### iperf3 命令:
```
iperf3 -c 10.222.2.1 -P40
iperf3 -c 10.222.2.1 -P40 -R
```
#### client主机
vultr 2.5美元每月套餐(single core 2.4ghz cpu,512m ram,日本东京机房),
#### server主机
bandwagonhost 3.99美元每年套餐(single core 2.0ghz cpu,128m ram,美国洛杉矶机房)
### 测试1
raw_mode: faketcp cipher_mode: xor  auth_mode: simple
![image4](/images/image4.PNG)
(反向的速度几乎一样,所以只发正向测试的图)
测试中cpu被打满。其中有30%的cpu是被openvpn占的。 如果不用Openvpn中转实际达到100+Mb/S 应该没问题。
### 测试2
raw_mode: faketcp cipher_mode: aes128cbc  auth_mode: md5
![image5](/images/image5.PNG)
(反向的速度几乎一样,所以只发正向测试的图)
测试中cpu被打满。绝大多数cpu都是被udp2raw占用的主要消耗在aes加密。即使不用Openvpn速度也不会快很多了。
# 应用
### 中转 kcptun
[udp2raw+kcptun step_by_step教程](kcptun_step_by_step.md)
### 中转 finalspeed
[udp2raw+finalspeed step_by_step教程](finalspeed_step_by_step.md)
# 如何自己编译
[编译教程](build_guide.zh-cn.md)
# 相关repo
### kcptun-raw
udp2raw was inspired by kcptun-raw,which modified kcptun to support tcp mode.
https://github.com/Chion82/kcptun-raw
### relayRawSocket
kcptun-raw was inspired by relayRawSocket. A simple udp to raw tunnel,wrote in python
https://github.com/linhua55/some_kcptun_tools/tree/master/relayRawSocket
### kcpraw
another project of kcptun with tcp mode
https://github.com/ccsexyz/kcpraw
### icmptunnel
Transparently tunnel your IP traffic through ICMP echo and reply packets.
https://github.com/DhavalKapil/icmptunnel

74
doc/build_guide.md Normal file
View File

@@ -0,0 +1,74 @@
# udp2raw build guide
the guide on how to build udp2raw to you own platform
## linux platform which supports local compile
such as PC,raspberry pi
##### install git
run on debian/ubuntun
```
sudo apt-get install git
```
run on redhat/centos:
```
sudo yum install git
```
##### clone git code
run in any dir
```
git clone https://github.com/wangyu-/udp2raw-tunnel.git
cd udp2raw-tunnel
```
##### install compile tool
run on debian/ubuntun
```
sudo apt-get install build-essential
```
run on redhat/centos:
```
sudo yum groupinstall 'Development Tools'
```
run 'make'compilation done. the udp2raw file is the just compiled binary
## platform which needs cross-compile
such as openwrt router,run following instructions on your PC
##### install git
run on debian/ubuntun
```
sudo apt-get install git
```
run on redhat/centos:
```
sudo yum install git
```
##### download cross compile tool chain
find it on downloads.openwrt.org according to your openwrt version and cpu model.
for example, my tplink wdr4310 runs chaos_calmer 15.05,its with ar71xx cpudownload the following package.
```
http://downloads.openwrt.org/chaos_calmer/15.05/ar71xx/generic/OpenWrt-SDK-15.05-ar71xx-generic_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64.tar.bz2
```
unzip it to any dir,such as /home/wangyu/OpenWrt-SDK-ar71xx-for-linux-x86_64-gcc-4.8-linaro_uClibc-0.9.33.2
cd into staging_dir toolchain-xxxxx bin .find the soft link with g++ suffix. in my case ,its mips-openwrt-linux-g++ ,check for its full path:
```
/home/wangyu/Desktop/OpenWrt-SDK-15.05-ar71xx-generic_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-g++
```
##### compile
modify first line of makefile to:
```
cc_cross=/home/wangyu/Desktop/OpenWrt-SDK-15.05-ar71xx-generic_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-g++
```
run 'make cross'the just generated udp2raw_cross is the binary,compile done. copy it to your router to run.

72
doc/build_guide.zh-cn.md Normal file
View File

@@ -0,0 +1,72 @@
# udp2raw编译方法
本文演示怎么把udp2raw编译到自己所需的平台。
## 可以本地编译的linux平台
比如电脑、树莓派
##### 首先安装git
debian/ubuntun执行
```
sudo apt-get install git
```
redhat/centos执行:
```
sudo yum install git
```
##### 用git把源码clone至本地
在任意目录执行:
```
git clone https://github.com/wangyu-/udp2raw-tunnel.git
cd udp2raw-tunnel
```
##### 安装g++ make 等工具
debian/ubuntun执行
```
sudo apt-get install build-essential
```
redhat/centos执行:
```
sudo yum groupinstall 'Development Tools'
```
然后运行make编译完成。 生成的udp2raw就是编译好的bianry。
## 需要交叉编译的平台
比如各种openwrt路由器
##### 首先安装git
debian/ubuntun执行
```
sudo apt-get install git
```
redhat/centos执行:
```
sudo yum install git
```
##### 下载安装交叉编译工具包
去downloads.openwrt.org上找到自己的openwrt版本和cpu型号对应的SDK。通常openwrt版本号不一样也问题不大最主要是cpu型号。
比如我的tplink wdr4310运行的是chaos_calmer 15.05,ar71xx cpu应该下载这个包
```
http://downloads.openwrt.org/chaos_calmer/15.05/ar71xx/generic/OpenWrt-SDK-15.05-ar71xx-generic_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64.tar.bz2
```
解压到本地任意目录,比如:/home/wangyu/OpenWrt-SDK-ar71xx-for-linux-x86_64-gcc-4.8-linaro_uClibc-0.9.33.2
让后依次进入staging_dir toolchain-xxxxx bin 目录找到后缀是g++的软链,比如我的是mips-openwrt-linux-g++ ,记下这个文件的完整路径:
```
/home/wangyu/Desktop/OpenWrt-SDK-15.05-ar71xx-generic_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-g++
```
##### 编译
把makefile的第一行 cross_cc=后面的内容改成你刚才记下的完整路径:
```
cc_cross=/home/wangyu/Desktop/OpenWrt-SDK-15.05-ar71xx-generic_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-g++
```
执行make cross目录下生成udp2raw_cross文件。编译完成。

View File

@@ -0,0 +1,69 @@
# udp2raw+finalspeed 加速tcp流量 Step by Step 教程
![image](finalspeed_step_by_step/Capture0.PNG)
##### 背景
国内有些ISP会对UDP做QOS或屏蔽这时候加速协议对TCP发包模式的支持就很重要。finalspeed虽然本身支持在底层用TCP发包但是其依赖的libpcap不支持openvz架构即使不是openvz架构的主机也存在不稳定的问题。
##### 摘要
udp2raw是一个把udp流量通过raw socket包装成tcp流量的工具。通过用udp2raw配合udp模式的 finalspeed一样可以达到在底层发tcp包绕过QOS的效果。支持openvz,稳定性也好很多。原理上相当于在finalspeed外面再包了一层tunnel。
本教程会一步一步演示用udp2raw+kcptun加速http流量的过程。加速任何其他tcp流量也一样。
udp2raw也支持把udp流量包装成Icmp发送本教程不做演示。
### 环境要求
服务器主机是linux有root权限。  可以是openvz架构的vps。 也可以是openwrt路由器。
本地主机是windows,本地有openwrt路由器或树莓派或安装了linux虚拟机网卡设置为桥接模式
(如果嫌给虚拟机安装linux麻烦可以下载别人提供好的linux虚拟机镜像比如https://www.kali.org/downloads/ ,不过我没有测试过这个镜像,我用的是debian 7)
### 安装
下载好udp2raw的压缩包解压分别解压到服务器和本地的虚拟机。
https://github.com/xtaci/kcptun/releases
在服务器端安装好finalspeed服务端在本地windows安装好finalspeed的客户端。服务端我以前是用91yun的一键安装脚本安装的没装过的可以去网上搜一键安装脚本。
### 运行
1.先在服务器主机运行如下命令确定finalspeed服务端已经正常启动了。
```
netstat -nlp|grep java
```
![image](finalspeed_step_by_step/Capture5.PNG)
如果显示了150端口就表示服务端启动好了。
2.在服务器启动udp2raw server
```
./udp2raw_amd64 -s -l0.0.0.0:8855 -r 127.0.0.1:150 -a -k "passwd" --raw-mode faketcp
```
![image](finalspeed_step_by_step/Capture2.PNG)
3.在本地的虚拟机上启动udp2raw client ,假设服务器ip是45.66.77.88
```
./udp2raw_amd64 -c -r45.66.77.88:8855 -l0.0.0.0:150 --raw-mode faketcp -a -k"passwd"
```
如果一切正常client端会显示client_ready:
![image](finalspeed_step_by_step/Capture3.PNG)
记下红框中的ip,这是虚拟机的网卡ip
在server端也会显示server_reay
![image](finalspeed_step_by_step/Capture4.PNG)
4.在本地windows,按图配置好finalspeed的客户端。注意192.168.205.8改成你刚才记下来的IP带宽也要按实际的填。传输协议要选UDP.
![image](finalspeed_step_by_step/Capture.PNG)
5.所有准备工作已经完成了在本地访问本地的8012端口相当于访问服务器的80端口。
来试一下通过http://127.0.0.1:8012/ 下载文件 1.5M/s
![image](finalspeed_step_by_step/Capture6.PNG)
再试一下直接通过服务器的ip访问http://45.66.77.88:80/ 速度只有600K/s
![image](finalspeed_step_by_step/Capture7.PNG)
教程就到这里了用来加速其他的tcp服务也是一样的只要再第三步那里设置其他的端口。

View File

@@ -0,0 +1 @@
11

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

View File

@@ -0,0 +1,59 @@
# udp2raw+kcptun 加速tcp流量 Step by Step 教程
![image](kcptun_step_by_step/Capture00.PNG)
本教程会一步一步演示用udp2raw+kcptun加速SSH流量的过程。加速任何其他tcp流量也一样包括ss本文避免涉及科学上网所以演示ssh。
### 环境要求
两边的主机都是linux有root权限。 可以是openwrt路由器或树莓派windows上桥接模式的虚拟机也可用
### 安装
下载好kcptun和udp2raw的压缩包解压分别解压到client端和server端。
https://github.com/xtaci/kcptun/releases
https://github.com/wangyu-/udp2raw-tunnel/releases
解压好后,如图:
![image](kcptun_step_by_step/Capture0.PNG)
### 运行
1.在远程服务器运行 udp2raw_amd64 server模式
```
./udp2raw_amd64 -s -l0.0.0.0:8855 -r 127.0.0.1:4000 -k "passwd" --raw-mode faketcp -a
```
![image](kcptun_step_by_step/Capture.PNG)
2.在本地运行udp2raw_amd64 client模式假设server ip是45.66.77.88
```
./udp2raw_amd64 -c -r45.66.77.88:8855 -l0.0.0.0:4000 --raw-mode faketcp -a -k"passwd"
```
如果一切正常client端输出如下显示client_ready
![image](kcptun_step_by_step/Capture2.PNG)
server端也会有类似输出,显示server_ready
![image](kcptun_step_by_step/Capture3.PNG)
3.在远程服务器运行 kcp server
```
./server_linux_amd64 -t "127.0.0.1:22" -l ":4000" -mode fast2 -mtu 1300
```
-mtu 1300很重要或者设置成更小。
![image](kcptun_step_by_step/Capture6.PNG)
4.在本地运行
```
./client_linux_amd64 -r "127.0.0.1:4000" -l ":3322" -mode fast2 -mtu 1300
```
-mtu 1300很重要或者设置成更小。
![image](kcptun_step_by_step/Capture7.PNG)
5.所有准备工作已经做好,在本地运行
```
ssh -p 3322 root@127.0.0.1
```
已经连进去了而且是经过kcptun加速的
![image](kcptun_step_by_step/Capture8.PNG)

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

91
doc/openvpn_guide.md Normal file
View File

@@ -0,0 +1,91 @@
# 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
```
client
dev tun100
proto udp
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
```

View File

@@ -1,11 +1,11 @@
#include <lib/aes.h>
#include <lib/md5.h>
#include "lib/aes.h"
#include "lib/md5.h"
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <encrypt.h>
#include <common.h>
#include "encrypt.h"
#include "common.h"
#include "log.h"
//static uint64_t seq=1;

View File

@@ -29,10 +29,6 @@ enum cipher_mode_t {cipher_none=0,cipher_aes128cbc,cipher_xor,cipher_end};
extern auth_mode_t auth_mode;
extern cipher_mode_t cipher_mode;
struct a
{
char * buf[buf_len];
};
extern unordered_map<int, const char *> auth_mode_tostring;
extern unordered_map<int, const char *> cipher_mode_tostring;

BIN
images/image0.PNG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

BIN
images/image1.PNG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
images/image2.PNG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

BIN
images/image4.PNG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
images/image5.PNG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
images/openvpn.PNG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

1
images/speedtest/111 Normal file
View File

@@ -0,0 +1 @@

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

View File

@@ -1,4 +1,4 @@
#include <log.h>
#include "log.h"
int log_level=log_info;

2
log.h
View File

@@ -44,7 +44,7 @@
#include <sys/timerfd.h>
#include <set>
#include <encrypt.h>
#include "encrypt.h"
#include <inttypes.h>
#include <sys/ioctl.h>

168
main.cpp
View File

@@ -38,6 +38,8 @@ int disable_anti_replay=0;
char key_string[1000]= "secret key";
char key[16];//,key2[16];
int mtu_warn=1375;
//uint64_t current_time_rough=0;
@@ -291,6 +293,11 @@ struct conn_info_t
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;
@@ -305,8 +312,13 @@ struct conn_info_t
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;
}
conn_info_t()
void re_init()
{
//send_packet_info.protocol=g_packet_info_send.protocol;
if(program_mode==server_mode)
@@ -315,8 +327,17 @@ struct conn_info_t
state.client_current_state=client_idle;
last_state_time=0;
oppsite_const_id=0;
blob=0;
timer_fd=0;
my_roller=0;
oppsite_roller=0;
last_oppsite_roller_time=0;
}
conn_info_t()
{
blob=0;
re_init();
}
void prepare()
{
@@ -537,7 +558,7 @@ int TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
////////==========================type divider=======================================================
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 *data,int data_len);
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 DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD;
@@ -676,15 +697,15 @@ int recv_handshake(packet_info_t &info,id_t &id1,id_t &id2,id_t &id3)
return 0;
}*/
int send_safer(conn_info_t &conn_info,const char* data,int len)
int send_safer(conn_info_t &conn_info,char type,const char* data,int len)
{
packet_info_t &send_info=conn_info.raw_info.send_info;
packet_info_t &recv_info=conn_info.raw_info.recv_info;
if(data[0]!='h'&&data[0]!='d')
if(type!='h'&&type!='d')
{
mylog(log_warn,"first byte is not h or d ,%x\n",data[0]);
mylog(log_warn,"first byte is not h or d ,%x\n",type);
return -1;
}
@@ -693,6 +714,8 @@ int send_safer(conn_info_t &conn_info,const char* data,int len)
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));
@@ -706,9 +729,12 @@ int send_safer(conn_info_t &conn_info,const char* data,int len)
memcpy(send_data_buf+sizeof(n_tmp_id)*2,&n_seq,sizeof(n_seq));
memcpy(send_data_buf+sizeof(n_tmp_id)*2+sizeof(n_seq),data,len);//data;
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;
int new_len=len+sizeof(n_seq)+sizeof(n_tmp_id)*2;
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)
{
@@ -727,17 +753,17 @@ int send_data_safer(conn_info_t &conn_info,const char* data,int len,u32_t conv_n
packet_info_t &recv_info=conn_info.raw_info.recv_info;
char send_data_buf[buf_len];
send_data_buf[0]='d';
//send_data_buf[0]='d';
u32_t n_conv_num=htonl(conv_num);
memcpy(send_data_buf+1,&n_conv_num,sizeof(n_conv_num));
memcpy(send_data_buf,&n_conv_num,sizeof(n_conv_num));
memcpy(send_data_buf+1+sizeof(n_conv_num),data,len);
int new_len=len+1+sizeof(n_conv_num);
send_safer(conn_info,send_data_buf,new_len);
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* &data,int &len)//allow overlap
int parse_safer(conn_info_t &conn_info,const char * input,int input_len,char &type,char* &data,int &len)//allow overlap
{
static char recv_data_buf0[buf_len];
@@ -779,17 +805,32 @@ int parse_safer(conn_info_t &conn_info,const char * input,int input_len,char* &d
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* &data,int &len)
int recv_safer(conn_info_t &conn_info,char &type,char* &data,int &len)
{
packet_info_t &send_info=conn_info.raw_info.send_info;
packet_info_t &recv_info=conn_info.raw_info.recv_info;
@@ -799,7 +840,7 @@ int recv_safer(conn_info_t &conn_info,char* &data,int &len)
if(recv_raw0(conn_info.raw_info,recv_data,recv_len)!=0) return -1;
return parse_safer(conn_info,recv_data,recv_len,data,len);
return parse_safer(conn_info,recv_data,recv_len,type,data,len);
}
int try_to_list_and_bind(int port)
@@ -928,6 +969,8 @@ int client_on_timer(conn_info_t &conn_info) //for client
conn_info.blob->conv_manager.clear_inactive();
mylog(log_trace,"timer!\n");
mylog(log_trace,"roller my %d,oppsite %d,%lld\n",int(conn_info.my_roller),int(conn_info.oppsite_roller),conn_info.last_oppsite_roller_time);
mylog(log_trace,"<client_on_timer,send_info.ts_ack= %u>\n",send_info.ts_ack);
if(conn_info.state.client_current_state==client_idle)
@@ -1112,7 +1155,7 @@ int client_on_timer(conn_info_t &conn_info) //for client
{
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 from client_ready\n");
mylog(log_info,"state back to client_idle from client_ready bc of server-->client direction timeout\n");
return 0;
}
@@ -1121,9 +1164,16 @@ int client_on_timer(conn_info_t &conn_info) //for client
return 0;
}
if(get_current_time()- conn_info.last_oppsite_roller_time>client_conn_uplink_timeout)
{
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 from client_ready bc of client-->server direction timeout\n");
}
mylog(log_debug,"heartbeat sent <%x,%x>\n",conn_info.oppsite_id,conn_info.my_id);
send_safer(conn_info,(char *)"h",1);/////////////send
send_safer(conn_info,'h',"",0);/////////////send
conn_info.last_hb_sent_time=get_current_time();
return 0;
@@ -1164,7 +1214,7 @@ int server_on_timer_multi(conn_info_t &conn_info,char * ip_port)
return 0;
}
send_safer(conn_info,(char *)"h",1); /////////////send
send_safer(conn_info,'h',"",0); /////////////send
conn_info.last_hb_sent_time=get_current_time();
@@ -1280,7 +1330,8 @@ int client_on_raw_recv(conn_info_t &conn_info)
}
else if(conn_info.state.client_current_state==client_handshake2||conn_info.state.client_current_state==client_ready)//received heartbeat or data
{
if(recv_safer(conn_info,data,data_len)!=0)
char type;
if(recv_safer(conn_info,type,data,data_len)!=0)
{
mylog(log_debug,"recv_safer failed!\n");
return -1;
@@ -1296,21 +1347,22 @@ int client_on_raw_recv(conn_info_t &conn_info)
conn_info.state.client_current_state=client_ready;
conn_info.last_hb_sent_time=0;
conn_info.last_hb_recv_time=get_current_time();
conn_info.last_oppsite_roller_time=conn_info.last_hb_recv_time;
client_on_timer(conn_info);
}
if(data_len==1&&data[0]=='h')
if(data_len==0&&type=='h')
{
mylog(log_debug,"[hb]heart beat received\n");
conn_info.last_hb_recv_time=get_current_time();
return 0;
}
else if(data_len>= int( sizeof(u32_t)+1 )&&data[0]=='d')
else if(data_len>= int( sizeof(u32_t))&&type=='d')
{
mylog(log_trace,"received a data from fake tcp,len:%d\n",data_len);
conn_info.last_hb_recv_time=get_current_time();
u32_t tmp_conv_id= ntohl(* ((u32_t *)&data[1]));
u32_t tmp_conv_id= ntohl(* ((u32_t *)&data[0]));
if(!conn_info.blob->conv_manager.is_conv_used(tmp_conv_id))
{
@@ -1331,7 +1383,7 @@ int client_on_raw_recv(conn_info_t &conn_info)
tmp_sockaddr.sin_port= htons(uint16_t((u64<<32u)>>32u));
int ret=sendto(udp_fd,data+1+sizeof(u32_t),data_len -(1+sizeof(u32_t)),0,(struct sockaddr *)&tmp_sockaddr,sizeof(tmp_sockaddr));
int ret=sendto(udp_fd,data+sizeof(u32_t),data_len -(sizeof(u32_t)),0,(struct sockaddr *)&tmp_sockaddr,sizeof(tmp_sockaddr));
if(ret<0)
{
@@ -1365,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;
@@ -1491,10 +1546,13 @@ int server_on_raw_recv_multi()
}
if(conn_info.state.server_current_state==server_ready)
{
if (recv_safer(conn_info, data, data_len) != 0) {
char type;
//mylog(log_info,"before recv_safer\n");
if (recv_safer(conn_info,type, data, data_len) != 0) {
return -1;
}
return server_on_raw_recv_ready(conn_info,ip_port,data,data_len);
//mylog(log_info,"after recv_safer\n");
return server_on_raw_recv_ready(conn_info,ip_port,type,data,data_len);
}
return 0;
}
@@ -1572,7 +1630,7 @@ int server_on_raw_recv_handshake1(conn_info_t &conn_info,char * ip_port,char * d
}
return 0;
}
int server_on_raw_recv_ready(conn_info_t &conn_info,char * ip_port,char *data,int data_len)
int server_on_raw_recv_ready(conn_info_t &conn_info,char * ip_port,char type,char *data,int data_len)
{
raw_info_t &raw_info = conn_info.raw_info;
@@ -1590,15 +1648,15 @@ int server_on_raw_recv_ready(conn_info_t &conn_info,char * ip_port,char *data,in
return 0;
}*/
if (data[0] == 'h' && data_len == 1) {
u32_t tmp = ntohl(*((u32_t *) &data[1 + sizeof(u32_t)]));
if (type == 'h' && data_len == 0) {
//u32_t tmp = ntohl(*((u32_t *) &data[sizeof(u32_t)]));
mylog(log_debug,"[%s][hb]received hb \n",ip_port);
conn_info.last_hb_recv_time = get_current_time();
return 0;
} else if (data[0] == 'd' && data_len >=int( sizeof(u32_t) + 1))
} else if (type== 'd' && data_len >=int( sizeof(u32_t) ))
{
u32_t tmp_conv_id = ntohl(*((u32_t *) &data[1]));
u32_t tmp_conv_id = ntohl(*((u32_t *) &data[0]));
conn_info.last_hb_recv_time = get_current_time();
@@ -1671,8 +1729,8 @@ int server_on_raw_recv_ready(conn_info_t &conn_info,char * ip_port,char *data,in
int fd = int((u64 << 32u) >> 32u);
mylog(log_trace, "[%s]received a data from fake tcp,len:%d\n",ip_port, data_len);
int ret = send(fd, data + 1 + sizeof(u32_t),
data_len - (1 + sizeof(u32_t)), 0);
int ret = send(fd, data + sizeof(u32_t),
data_len - ( sizeof(u32_t)), 0);
mylog(log_trace, "[%s]%d byte sent ,fd :%d\n ",ip_port, ret, fd);
if (ret < 0) {
@@ -1724,7 +1782,7 @@ int server_on_raw_recv_pre_ready(conn_info_t &conn_info,char * ip_port,u32_t tmp
conn_info.last_hb_recv_time = get_current_time();
conn_info.last_hb_sent_time = conn_info.last_hb_recv_time;//=get_current_time()
send_safer(conn_info, (char *) "h", 1); /////////////send
send_safer(conn_info, 'h',"", 0); /////////////send
mylog(log_info, "[%s]changed state to server_ready\n",ip_port);
conn_info.blob->anti_replay.re_init();
@@ -1783,7 +1841,7 @@ int server_on_raw_recv_pre_ready(conn_info_t &conn_info,char * ip_port,u32_t tmp
//ori_conn_info.state.server_current_state=server_ready;
ori_conn_info.recover(conn_info);
send_safer(ori_conn_info, (char *) "h", 1);
send_safer(ori_conn_info, 'h',"", 0);
//ori_conn_info.blob->anti_replay.re_init();
@@ -1981,12 +2039,17 @@ int client_event_loop()
int recv_len;
struct sockaddr_in udp_new_addr_in;
if ((recv_len = recvfrom(udp_fd, buf, buf_len, 0,
(struct sockaddr *) &udp_new_addr_in, &slen)) == -1) {
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, &udp_new_addr_len)) == -1) {
mylog(log_error,"recv_from error,this shouldnt happen at client\n");
myexit(1);
};
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);
}
mylog(log_trace,"Received packet from %s:%d,len: %d\n", inet_ntoa(udp_new_addr_in.sin_addr),
ntohs(udp_new_addr_in.sin_port),recv_len);
@@ -2250,16 +2313,22 @@ int server_event_loop()
u32_t conv_id=conn_info.blob->conv_manager.find_conv_by_u64(fd);
int recv_len=recv(fd,buf,buf_len,0);
int recv_len=recv(fd,buf,max_data_len,0);
mylog(log_trace,"received a packet from udp_fd,len:%d\n",recv_len);
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;
}
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);
}
//conn_info.conv_manager->update_active_time(conv_id); server dosnt update from upd side,only update from raw side. (client updates at both side)
if(conn_info.state.server_current_state==server_ready)
@@ -2351,6 +2420,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 +2614,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;

View File

@@ -1,16 +1,39 @@
ccmips=mips-openwrt-linux-g++
FLAGS=-Wall -Wextra -Wno-unused-variable -Wno-unused-parameter
FLAGS2= -O3
cc_cross=/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_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
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
all:
sudo killall udp2raw||true
sleep 0.2
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} ${FLAGS2}
${ccmips} main.cpp -o udp2raw_ar71xx -lrt -I. -Ilib lib/aes.c lib/md5.c encrypt.cpp log.cpp network.cpp common.cpp -std=c++11 ${FLAGS} ${FLAGS2}
rm -f udp2raw
${cc_local} -o udp2raw -I. ${SOURCES} ${FLAGS} -lrt -static -O3
fast:
sudo killall udp2raw||true
sleep 0.2
g++ main.cpp -o udp2raw_amd64 -ggdb -I. -Ilib lib/aes.c lib/md5.c encrypt.cpp log.cpp network.cpp common.cpp -lrt -std=c++11 ${FLAGS}
rm -f udp2raw
${cc_local} -o udp2raw -I. ${SOURCES} ${FLAGS} -lrt
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
rm -f udp2raw
${cc_local} -o udp2raw -I. ${SOURCES} ${FLAGS} -lrt -Wformat-nonliteral -D MY_DEBUG
ar71xx:
${cc_ar71xx} -o udp2raw_ar71xx -I. ${SOURCES} ${FLAGS} -lrt -lgcc_eh -static -O3
bcm2708:
${cc_bcm2708} -o udp2raw_bcm2708 -I. ${SOURCES} ${FLAGS} -lrt -static -O3
amd64:
${cc_local} -o udp2raw_amd64 -I. ${SOURCES} ${FLAGS} -lrt -static -O3
x86:
${cc_local} -o udp2raw_x86 -I. ${SOURCES} ${FLAGS} -lrt -m32 -static -O3
cross:
${cc_cross} -o udp2raw_cross -I. ${SOURCES} ${FLAGS} -lrt -static -lgcc_eh -O3
cross2:
${cc_cross} -o udp2raw_cross -I. ${SOURCES} ${FLAGS} -lrt -O3
release: amd64 x86 ar71xx bcm2708
tar -zcvf ${TAR}
clean:
rm -f ${TAR}

View File

@@ -20,7 +20,15 @@ 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 short g_ip_id_counter=0;
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 +164,48 @@ packet_info_t::packet_info_t()
int init_raw_socket()
{
raw_send_fd = socket(AF_INET , SOCK_RAW , IPPROTO_TCP);
g_ip_id_counter=get_true_random_number()%65535;
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);
}
if(raw_send_fd == -1) {
mylog(log_fatal,"Failed to create raw_send_fd\n");
//perror("Failed to create raw_send_fd");
myexit(1);
}
}
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 +224,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,9 +288,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 +318,19 @@ 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;
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 (g_ip_id_counter++); //Id of this packet
}
else
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
iph->ttl = 64;
@@ -291,32 +340,65 @@ 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)
{ static char peek_raw_buf[buf_len];
char *ip_begin=peek_raw_buf+link_level_header_len;
struct sockaddr saddr;
socklen_t saddr_size;
int recv_len = recvfrom(raw_recv_fd, peek_raw_buf,buf_len, MSG_PEEK ,&saddr , &saddr_size);//change buf_len to something smaller,we only need header here
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 \n",recv_len,int(sizeof(iphdr)));
mylog(log_trace,"%s\n ",strerror(errno));
return -1;
}
peek_info.src_ip=iph->saddr;
@@ -328,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;
@@ -367,11 +456,9 @@ int recv_raw_ip(raw_info_t &raw_info,char * &payload,int &payloadlen)
iphdr * iph;
struct sockaddr saddr;
socklen_t saddr_size;
saddr_size = sizeof(saddr);
socklen_t saddr_size = sizeof(saddr);
int flag=0;
int recv_len = recvfrom(raw_recv_fd, recv_raw_ip_buf, buf_len, flag ,&saddr , &saddr_size);
int recv_len = recvfrom(raw_recv_fd, recv_raw_ip_buf, max_data_len, flag ,&saddr , &saddr_size);
if(recv_len<0)
{
@@ -402,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;
}
@@ -426,7 +514,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;
}
@@ -908,7 +996,7 @@ int recv_raw_udp(raw_info_t &raw_info, char *&payload, int &payloadlen)
}
udphdr *udph=(struct udphdr*)ip_payload;
if(ntohs(udph->len)!=ip_payloadlen)
if(int(ntohs(udph->len))!=ip_payloadlen)
{
mylog(log_debug,"udp length error %d %d \n",ntohs(udph->len),ip_payloadlen);
@@ -1104,7 +1192,7 @@ int recv_raw_tcp_deprecated(packet_info_t &info,char * &payload,int &payloadlen)
mylog(log_trace,"raw!\n");
size = recvfrom(raw_recv_fd, buf, buf_len, 0 ,&saddr , &saddr_size);
size = recvfrom(raw_recv_fd, buf, max_data_len, 0 ,&saddr , &saddr_size);
if(buf[12]!=8||buf[13]!=0)
{

View File

@@ -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);