udp2raw/doc/README.zh-cn.md
2017-11-21 14:46:14 -06:00

291 lines
16 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Udp2raw-tunnel
![image2](/images/image0.PNG)
udp2raw tunnel通过raw socket给UDP包加上TCP或ICMP header进而绕过UDP屏蔽或QoS或在UDP不稳定的环境下提升稳定性。可以有效防止在使用kcptun或者finalspeed的情况下udp端口被运营商限速。
支持心跳保活、自动重连,重连后会恢复上次连接,在底层掉线的情况下可以保持上层不掉线。同时有加密、防重放攻击、信道复用的功能。
[English](/README.md)
[udp2raw+kcptun step_by_step教程](kcptun_step_by_step.md)
[udp2raw+finalspeed step_by_step教程](finalspeed_step_by_step.md)
**提示:**
udp2raw不是加速器只是一个帮助你绕过UDP限制的工具。如果你需要UDP加速器请看UDPspeeder。
UDPspeeder的repo:
https://github.com/wangyu-/UDPspeeder
# 支持的平台
Linux主机有root权限。可以是PC、android手机/平板、openwrt路由器、树莓派。主机上最好安装了iptables命令(apt/yum很容易安装)。
Release中提供了`amd64`、`x86`、`arm`、`mips_be`、`mips_le`的预编译binary.
##### 对于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。
如果你的网络不允许桥接也是有办法用的具体方法请看wiki。
##### 对于ios和游戏主机用户
可以把udp2raw运行在局域网的其他机器上。最好的办法是买个能刷OpenWrt/LEDE/梅林的路由器把udp2raw运行在路由器上。
# 功能特性
### 把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 window机制来防止重放攻击。
设计目标是即使攻击者可以监听到tunnel的所有包可以选择性丢弃tunnel的任意包可以重放任意包攻击者也没办法获得tunnel承载的任何数据也没办法向tunnel的数据流中通过包构造/包重放插入任何数据。
### 其他特性
信道复用client的udp端支持多个连接。
server支持多个client也能正确处理多个连接的重连和连接恢复。
NAT 穿透 tcp icmp udp模式都支持nat穿透。
支持Openvz配合finalspeed使用可以在openvz上用tcp模式的finalspeed
支持Openwrt没有编译依赖容易编译到任何平台上。
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
# 简明操作说明
### 安装
下载编译好的二进制文件,解压到任意目录。
https://github.com/wangyu-/udp2raw-tunnel/releases
### 运行
假设你有一个serverip为44.55.66.77有一个服务监听在udp 7777端口。 假设你本地的主机到44.55.66.77的UDP流量被屏蔽了或者被qos了
```
在server端运行:
./udp2raw_amd64 -s -l0.0.0.0:4096 -r 127.0.0.1:7777 -a -k "passwd" --raw-mode faketcp
在client端运行:
./udp2raw_amd64 -c -l0.0.0.0:3333 -r44.55.66.77:4096 -a -k "passwd" --raw-mode faketcp
```
###### Server端输出:
![](/images/output_server.PNG)
###### Client端输出:
![](/images/output_client.PNG)
现在client和server之间建立起了tunnel。想要在本地连接44.55.66.77:7777只需要连接 127.0.0.1:3333。来回的所有的udp流量会被经过tunneling发送。在外界看起来是tcp流量不会有udp流量暴露到公网。
### MTU设置(重要)
不论你用udp2raw来加速kcptun还是vpn,为了稳定使用,都需要设置合理的MTU在kcptun/vpn里设置而不是在udp2raw里建议把MTU设置成1200。client和server端都要设置。
### 提醒
如果要在anroid上运行请看[Android简明教程](/doc/android_guide.md)
如果要在梅林固件的路由器上使用,添加`--lower-level auto` `--keep-rule`
如果client和server无法连接或者连接经常断开请看一下`--seq-mode`的用法尝试不同的seq-mode。
udp2raw可以用非root账号运行这样更安全。具体方法见[#26](https://github.com/wangyu-/udp2raw-tunnel/issues/26)
# 进阶操作说明
### 命令选项
```
udp2raw-tunnel
git version:6e1df4b39f build date:Oct 24 2017 09:21:15
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"
--cipher-mode <string> avaliable values:aes128cbc(default),xor,none
--auth-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,so that you can copy and
add it manually.overrides -a
--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:
--conf-file <string> read options from a configuration file instead of command line.
check example.conf in repo for format
--fifo <string> use a fifo(named pipe) for sending commands to the running program,
check readme.md in repository for supported commands.
--log-level <number> 0:never 1:fatal 2:error 3:warn
4:info (default) 5:debug 6:trace
--log-position enable file name,function name,line number in log
--disable-color disable log color
--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
--force-sock-buf bypass system limitation while setting sock-buf
--seq-mode <number> seq increase mode for faketcp:
0:static header,do not increase seq and ack_seq
1:increase seq for every packet,simply ack last seq
2:increase seq randomly, about every 3 packets,simply ack last seq
3:simulate an almost real seq/ack procedure(default)
4:similiar to 3,but do not consider TCP Option Window_Scale,
maybe useful when firewall doesnt support TCP Option
--lower-level <string> send packets at OSI level 2, format:'if_name#dest_mac_adress'
ie:'eth0#00:23:45:67:89:b9'.or try '--lower-level auto' to obtain
the parameter automatically,specify it manually if 'auto' failed
--gen-add generate iptables rule and add it permanently,then exit.overrides -g
--keep-rule monitor iptables and auto re-add if necessary.implys -a
--clear clear any iptables rules added by this program.overrides everything
-h,--help print this help message
```
### iptables 规则,`-a`和`-g`
用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种模式都没问题。
### `--keep-rule`
定期主动检查iptables如果udp2raw添加的iptables规则丢了就重新添加。在一些iptables可能会被其他程序清空的情况下(比如梅林固件和openwrt的路由器)格外有用。
### `--fifo`
指定一个fifo(named pipe)来向运行中的程序发送命令,例如`--fifo fifo.file`
在client端,可以用`echo reconnect >fifo.file`来强制client换端口重连上层不断线.对Server目前没有效果。
### `--lower-level`
大部分udp2raw不能连通的情况都是设置了不兼容的iptables造成的。--lower-level选项允许绕过本地iptables。在一些iptables不好改动的情况下尤其有效比如你用的是梅林固件iptables全是固件自己生成的
##### 格式
`if_name#dest_mac_adress`,例如 `eth0#00:23:45:67:89:b9` 。`eth0`换成你的出口网卡名。`00:23:45:67:89:b9`换成网关的mac地址如果client和server在同一个局域网内可能不需要网关这时候直接用对方主机的mac地址这个属于罕见的应用场景可以忽略
可以用`--lower-level auto`自动获取参数,如果获取参数失败,再手动填写。
##### client端获得--lower-level参数的办法
在client 端,运行`traceroute <server_ip>`,记下第一跳的地址,这个就是`网关ip`。再运行`arp -s <网关ip>`可以同时查到出口网卡名和mac。
![](/images/lower_level.PNG)
如果traceroute第一跳结果是`* * *`说明网关屏蔽了对traceroute的应答。需要用`ip route`或`route`查询网关:
![](/images/route.PNG)
##### server端获得--lower-level参数的办法
如果client有公网ip就`traceroute <client_ip>`。下一步和client端的方法一样。
如果client没有公网ip就`traceroute google.com` 或`traceroute baidu.com`。下一步和client端的方法一样。
server端也可以用`--lower-level auto` 来尝试自动获得参数,如果无法连接再手动填写。
##### 注意
如果用了`--lower-level`选项。server虽然还可以bind在0.0.0.0,但是因为你显式指定了网络接口,就只能工作在这一个网络接口了。
如果`arps -s`命令查询不到首先再试几次。如果还是查询不到那么可能是因为你用的是pppoe方式的拨号宽带查询不到是正常的。这种情况下`if_name`填pppoe产生的虚拟interface通常名字叫`pppXXXX`,从`ifconfig`命令的输出里找一下;`des_mac_adress`填`00:00:00:00:00:00`,例如`ppp0#00:00:00:00:00:00`
### `--conf-file`
为了避免将密码等私密信息暴露给`ps`命令,你也可以使用 `配置文件` 来存储参数。
比如,将以上服务端参数改写成配置文件
`server.conf`:
```
-s
# 你可以像这样添加注释
# 注意,只有整行注释才能在配置文件里使用
# 注释必须独占一行
-l 0.0.0.0:4096
-r 127.0.0.1:7777
-a
-k passwd
--raw-mode faketcp
```
注意,当写入配置文件的时候,密码等参数两边的引号必须去除。
然后就可以使用下面的方式启动服务端
```bash
./udp2raw_amd64 --conf-file server.conf
```
# 性能测试
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