12 Commits
v4.4 ... v4.5

Author SHA1 Message Date
arraykeys@gmail.com
2d1c1449aa Merge branch 'master' of https://github.com/snail007/goproxy.git 2018-03-13 10:29:50 +08:00
arraykeys@gmail.com
f348298acd v4.5 2018-03-13 10:29:26 +08:00
arraykeys@gmail.com
ad47104fc7 v4.5 2018-03-13 10:04:18 +08:00
snail007
4d4fb64b59 Update mux_bridge.go 2018-03-12 19:27:37 +08:00
arraykeys@gmail.com
9ce3a6e468 Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com> 2018-03-12 18:15:14 +08:00
arraykeys@gmail.com
34e9e362b9 Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com> 2018-03-12 17:31:35 +08:00
arraykeys@gmail.com
f87cbf73e8 Merge branch 'dev' of https://github.com/snail007/goproxy.git into dev 2018-03-12 13:59:47 +08:00
arraykeys@gmail.com
362ada2ebb v4.5
Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com>
2018-03-12 13:59:25 +08:00
snail007
b4b7221dab Merge pull request #44 from snail007/dev
Update README_ZH.md
2018-03-10 17:00:50 +08:00
snail007
2d8dc56f4e Update README_ZH.md 2018-03-10 17:00:03 +08:00
arraykeys@gmail.com
1cf4313d12 Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com> 2018-03-09 17:16:21 +08:00
arraykeys@gmail.com
7bb8f19b90 Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com> 2018-03-09 16:02:05 +08:00
22 changed files with 437 additions and 234 deletions

View File

@ -1,4 +1,10 @@
proxy更新日志 proxy更新日志
v4.5
1.优化了mux内网穿透连接管理逻辑,增强了稳定性.
2.mux内网穿透增加了tcp和kcp协议支持,之前是tls,现在支持三种协议tcp,tls,kcp.
3.keygen参数增加了用法: proxy keygen usage.
4.http(s)/socks5代理,tls增加了自签名证书支持.
5.建议升级.
v4.4 v4.4
1.增加了协议转换sps功能代理协议转换使用的是sps子命令(socks+https的缩写) 1.增加了协议转换sps功能代理协议转换使用的是sps子命令(socks+https的缩写)
sps本身不提供代理功能只是接受代理请求"转换并转发"给已经存在的http(s)代理 sps本身不提供代理功能只是接受代理请求"转换并转发"给已经存在的http(s)代理

View File

@ -34,7 +34,8 @@ Proxy is a high performance HTTP, HTTPS, HTTPS, websocket, TCP, UDP, Socks5 prox
- ...   - ...  
This page is the v4.4 manual, and the other version of the manual can be checked by the following link. This page is the v4.5 manual, and the other version of the manual can be checked by the following link.
- [v4.4 manual](https://github.com/snail007/goproxy/tree/v4.4)
- [v4.3 manual](https://github.com/snail007/goproxy/tree/v4.3) - [v4.3 manual](https://github.com/snail007/goproxy/tree/v4.3)
- [v4.2 manual](https://github.com/snail007/goproxy/tree/v4.2) - [v4.2 manual](https://github.com/snail007/goproxy/tree/v4.2)
- [v4.0-4.1 manual](https://github.com/snail007/goproxy/tree/v4.1) - [v4.0-4.1 manual](https://github.com/snail007/goproxy/tree/v4.1)
@ -148,7 +149,7 @@ If the installation fails or your VPS is not a linux64 system, please follow the
Download address: https://github.com/snail007/goproxy/releases Download address: https://github.com/snail007/goproxy/releases
```shell ```shell
cd /root/proxy/ cd /root/proxy/
wget https://github.com/snail007/goproxy/releases/download/v4.4/proxy-linux-amd64.tar.gz wget https://github.com/snail007/goproxy/releases/download/v4.5/proxy-linux-amd64.tar.gz
``` ```
#### **2.Download the automatic installation script** #### **2.Download the automatic installation script**
```shell ```shell
@ -281,13 +282,13 @@ Local HTTP (S) proxy use 28080 port,excute:
`./proxy http -T ssh -P "2.2.2.2:22" -u user -S user.key -t tcp -p ":28080"` `./proxy http -T ssh -P "2.2.2.2:22" -u user -S user.key -t tcp -p ":28080"`
#### **1.8.KCP protocol transmission** #### **1.8.KCP protocol transmission**
The KCP protocol requires a -B parameter to set a password which can encrypt and decrypt data. The KCP protocol requires a --kcp-key parameter to set a password which can encrypt and decrypt data.
Http first level proxy(VPS,IP:22.22.22.22) Http first level proxy(VPS,IP:22.22.22.22)
`./proxy http -t kcp -p ":38080" -B mypassword` `./proxy http -t kcp -p ":38080" --kcp-key mypassword`
Http second level proxy(os is Linux) Http second level proxy(os is Linux)
`./proxy http -t tcp -p ":8080" -T kcp -P "22.22.22.22:38080" -B mypassword` `./proxy http -t tcp -p ":8080" -T kcp -P "22.22.22.22:38080" --kcp-key mypassword`
Then access to the local 8080 port is access to the proxy's port 38080 on the VPS, and the data is transmitted through the KCP protocol. Then access to the local 8080 port is access to the proxy's port 38080 on the VPS, and the data is transmitted through the KCP protocol.
#### **1.9.HTTP reverse proxy** #### **1.9.HTTP reverse proxy**
Proxy supports not only set up a proxy through in other software, to provide services for other software, but support the request directly to the website domain to proxy monitor IP when proxy monitors 80 and 443 ports, then proxy will automatically access to the HTTP proxy access website for you.   Proxy supports not only set up a proxy through in other software, to provide services for other software, but support the request directly to the website domain to proxy monitor IP when proxy monitors 80 and 443 ports, then proxy will automatically access to the HTTP proxy access website for you.  
@ -657,13 +658,13 @@ ip: user's IP, for example: 192.168.1.200
If there is no -a or -F or --auth-url parameters, it means to turn off the authentication. If there is no -a or -F or --auth-url parameters, it means to turn off the authentication.
#### **5.8.KCP protocol transmission** #### **5.8.KCP protocol transmission**
The KCP protocol requires a -B parameter which can set a password to encrypt and decrypt data.   The KCP protocol requires a --kcp-key parameter which can set a password to encrypt and decrypt data.  
HTTP first level proxy(VPS,IP:22.22.22.22) HTTP first level proxy(VPS,IP:22.22.22.22)
`./proxy socks -t kcp -p ":38080" -B mypassword` `./proxy socks -t kcp -p ":38080" --kcp-key mypassword`
HTTP two level proxy(local os is Linux) HTTP two level proxy(local os is Linux)
`./proxy socks -t tcp -p ":8080" -T kcp -P "22.22.22.22:38080" -B mypassword` `./proxy socks -t tcp -p ":8080" -T kcp -P "22.22.22.22:38080" --kcp-key mypassword`
Then access to the local 8080 port is access to the proxy port 38080 on the VPS, and the data is transmitted through the KCP protocol. Then access to the local 8080 port is access to the proxy port 38080 on the VPS, and the data is transmitted through the KCP protocol.
#### **5.9.Custom DNS** #### **5.9.Custom DNS**
@ -692,7 +693,7 @@ command
Suppose there is a KCP HTTP (s) proxy (password: demo123): 127.0.0.1:8080. Now we turn it into a common proxy that supports HTTP (s) and Socks5 at the same time. The local port after transformation is 18080. Suppose there is a KCP HTTP (s) proxy (password: demo123): 127.0.0.1:8080. Now we turn it into a common proxy that supports HTTP (s) and Socks5 at the same time. The local port after transformation is 18080.
command command
`./proxy sps -S http -T kcp -P 127.0.0.1:8080 -t tcp -p :18080 -B demo123` `./proxy sps -S http -T kcp -P 127.0.0.1:8080 -t tcp -p :18080 --kcp-key demo123`
#### **6.3.SOCKS5 to HTTP(S) + SOCKS5** #### **6.3.SOCKS5 to HTTP(S) + SOCKS5**
Suppose there is a common Socks5 proxy: 127.0.0.1:8080, now we turn it into a common proxy that supports HTTP (s) and Socks5 at the same time, and the local port after transformation is 18080. Suppose there is a common Socks5 proxy: 127.0.0.1:8080, now we turn it into a common proxy that supports HTTP (s) and Socks5 at the same time, and the local port after transformation is 18080.
@ -705,7 +706,7 @@ command
Suppose there is a KCP Socks5 proxy (password: demo123): 127.0.0.1:8080, now we turn it into a common proxy that support HTTP (s) and Socks5 at the same time, and the local port after transformation is 18080. Suppose there is a KCP Socks5 proxy (password: demo123): 127.0.0.1:8080, now we turn it into a common proxy that support HTTP (s) and Socks5 at the same time, and the local port after transformation is 18080.
command command
`./proxy sps -S socks -T kcp -P 127.0.0.1:8080 -t tcp -p :18080 -B demo123`   `./proxy sps -S socks -T kcp -P 127.0.0.1:8080 -t tcp -p :18080 --kcp-key demo123`  
#### **6.4.Chain style connection** #### **6.4.Chain style connection**
It is mentioned above that multiple SPS nodes can be connected to build encrypted channels, assuming you have the following VPS and a PC. It is mentioned above that multiple SPS nodes can be connected to build encrypted channels, assuming you have the following VPS and a PC.

View File

@ -35,7 +35,8 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5代理服务
- ... - ...
本页是v4.4手册,其他版本手册请点击下面链接查看. 本页是v4.5手册,其他版本手册请点击下面链接查看.
- [v4.4手册](https://github.com/snail007/goproxy/tree/v4.4)
- [v4.3手册](https://github.com/snail007/goproxy/tree/v4.3) - [v4.3手册](https://github.com/snail007/goproxy/tree/v4.3)
- [v4.2手册](https://github.com/snail007/goproxy/tree/v4.2) - [v4.2手册](https://github.com/snail007/goproxy/tree/v4.2)
- [v4.0-v4.1手册](https://github.com/snail007/goproxy/tree/v4.1) - [v4.0-v4.1手册](https://github.com/snail007/goproxy/tree/v4.1)
@ -146,7 +147,7 @@ curl -L https://raw.githubusercontent.com/snail007/goproxy/master/install_auto.s
下载地址:https://github.com/snail007/goproxy/releases 下载地址:https://github.com/snail007/goproxy/releases
```shell ```shell
cd /root/proxy/ cd /root/proxy/
wget https://github.com/snail007/goproxy/releases/download/v4.4/proxy-linux-amd64.tar.gz wget https://github.com/snail007/goproxy/releases/download/v4.5/proxy-linux-amd64.tar.gz
``` ```
#### **2.下载自动安装脚本** #### **2.下载自动安装脚本**
```shell ```shell
@ -187,7 +188,8 @@ http,tcp,udp代理过程会和上级通讯,为了安全我们采用加密通讯,
在linux上并安装了openssl命令可以直接通过下面的命令生成证书和key文件. 在linux上并安装了openssl命令可以直接通过下面的命令生成证书和key文件.
`./proxy keygen` `./proxy keygen`
默认会在当前程序目录下面生成证书文件proxy.crt和key文件proxy.key。 默认会在当前程序目录下面生成证书文件proxy.crt和key文件proxy.key。
更多用法:`proxy keygen usage`
### **后台运行** ### **后台运行**
默认执行proxy之后,如果要保持proxy运行,不能关闭命令行. 默认执行proxy之后,如果要保持proxy运行,不能关闭命令行.
如果想在后台运行proxy,命令行可以关闭,只需要在命令最后加上--daemon参数即可. 如果想在后台运行proxy,命令行可以关闭,只需要在命令最后加上--daemon参数即可.
@ -281,13 +283,13 @@ target:用户访问的URL,比如:http://demo.com:80/1.html或https://www.baidu.c
`./proxy http -T ssh -P "2.2.2.2:22" -u user -S user.key -t tcp -p ":28080"` `./proxy http -T ssh -P "2.2.2.2:22" -u user -S user.key -t tcp -p ":28080"`
#### **1.8.KCP协议传输** #### **1.8.KCP协议传输**
KCP协议需要-B参数设置一个密码用于加密解密数据 KCP协议需要--kcp-key参数设置一个密码用于加密解密数据
一级HTTP代理(VPS,IP:22.22.22.22) 一级HTTP代理(VPS,IP:22.22.22.22)
`./proxy http -t kcp -p ":38080" -B mypassword` `./proxy http -t kcp -p ":38080" --kcp-key mypassword`
二级HTTP代理(本地Linux) 二级HTTP代理(本地Linux)
`./proxy http -t tcp -p ":8080" -T kcp -P "22.22.22.22:38080" -B mypassword` `./proxy http -t tcp -p ":8080" -T kcp -P "22.22.22.22:38080" --kcp-key mypassword`
那么访问本地的8080端口就是访问VPS上面的代理端口38080,数据通过kcp协议传输. 那么访问本地的8080端口就是访问VPS上面的代理端口38080,数据通过kcp协议传输.
#### **1.9 HTTP(S)反向代理** #### **1.9 HTTP(S)反向代理**
@ -386,16 +388,16 @@ VPS(IP:22.22.22.33)执行:
#### **2.4.加密二级TCP代理** #### **2.4.加密二级TCP代理**
VPS(IP:22.22.22.33)执行: VPS(IP:22.22.22.33)执行:
`./proxy tcp -t tcp -p ":33080" -T tcp -P "127.0.0.1:8080" -C proxy.crt -K proxy.key` `./proxy tcp -t tls -p ":33080" -T tcp -P "127.0.0.1:8080" -C proxy.crt -K proxy.key`
本地执行: 本地执行:
`./proxy tcp -p ":23080" -T tls -P "22.22.22.33:33080" -C proxy.crt -K proxy.key` `./proxy tcp -p ":23080" -T tls -P "22.22.22.33:33080" -C proxy.crt -K proxy.key`
那么访问本地23080端口就是通过加密TCP隧道访问22.22.22.33的8080端口. 那么访问本地23080端口就是通过加密TCP隧道访问22.22.22.33的8080端口.
#### **2.5.加密三级TCP代理** #### **2.5.加密三级TCP代理**
一级TCP代理VPS_01,IP:22.22.22.22 一级TCP代理VPS_01,IP:22.22.22.22
`./proxy tcp -t tcp -p ":38080" -T tcp -P "66.66.66.66:8080" -C proxy.crt -K proxy.key` `./proxy tcp -t tls -p ":38080" -T tcp -P "66.66.66.66:8080" -C proxy.crt -K proxy.key`
二级TCP代理VPS_02,IP:33.33.33.33 二级TCP代理VPS_02,IP:33.33.33.33
`./proxy tcp -t tcp -p ":28080" -T tls -P "22.22.22.22:38080" -C proxy.crt -K proxy.key` `./proxy tcp -t tls -p ":28080" -T tls -P "22.22.22.22:38080" -C proxy.crt -K proxy.key`
三级TCP代理(本地) 三级TCP代理(本地)
`./proxy tcp -p ":8080" -T tls -P "33.33.33.33:28080" -C proxy.crt -K proxy.key` `./proxy tcp -p ":8080" -T tls -P "33.33.33.33:28080" -C proxy.crt -K proxy.key`
那么访问本地8080端口就是通过加密TCP隧道访问66.66.66.66的8080端口. 那么访问本地8080端口就是通过加密TCP隧道访问66.66.66.66的8080端口.
@ -428,16 +430,16 @@ VPS(IP:22.22.22.33)执行:
#### **3.4.加密二级UDP代理** #### **3.4.加密二级UDP代理**
VPS(IP:22.22.22.33)执行: VPS(IP:22.22.22.33)执行:
`./proxy tcp -t tcp -p ":33080" -T udp -P "8.8.8.8:53" -C proxy.crt -K proxy.key` `./proxy tcp -t tls -p ":33080" -T udp -P "8.8.8.8:53" -C proxy.crt -K proxy.key`
本地执行: 本地执行:
`./proxy udp -p ":5353" -T tls -P "22.22.22.33:33080" -C proxy.crt -K proxy.key` `./proxy udp -p ":5353" -T tls -P "22.22.22.33:33080" -C proxy.crt -K proxy.key`
那么访问本地UDP:5353端口就是通过加密TCP隧道,通过VPS访问8.8.8.8的UDP:53端口. 那么访问本地UDP:5353端口就是通过加密TCP隧道,通过VPS访问8.8.8.8的UDP:53端口.
#### **3.5.加密三级UDP代理** #### **3.5.加密三级UDP代理**
一级TCP代理VPS_01,IP:22.22.22.22 一级TCP代理VPS_01,IP:22.22.22.22
`./proxy tcp -t tcp -p ":38080" -T udp -P "8.8.8.8:53" -C proxy.crt -K proxy.key` `./proxy tcp -t tls -p ":38080" -T udp -P "8.8.8.8:53" -C proxy.crt -K proxy.key`
二级TCP代理VPS_02,IP:33.33.33.33 二级TCP代理VPS_02,IP:33.33.33.33
`./proxy tcp -t tcp -p ":28080" -T tls -P "22.22.22.22:38080" -C proxy.crt -K proxy.key` `./proxy tcp -t tls -p ":28080" -T tls -P "22.22.22.22:38080" -C proxy.crt -K proxy.key`
三级TCP代理(本地) 三级TCP代理(本地)
`./proxy udp -p ":5353" -T tls -P "33.33.33.33:28080" -C proxy.crt -K proxy.key` `./proxy udp -p ":5353" -T tls -P "33.33.33.33:28080" -C proxy.crt -K proxy.key`
那么访问本地5353端口就是通过加密TCP隧道,通过VPS_01访问8.8.8.8的53端口. 那么访问本地5353端口就是通过加密TCP隧道,通过VPS_01访问8.8.8.8的53端口.
@ -661,13 +663,13 @@ ip:用户的IP,比如:192.168.1.200
如果没有-a或-F或--auth-url参数,就是关闭认证. 如果没有-a或-F或--auth-url参数,就是关闭认证.
#### **5.8.KCP协议传输** #### **5.8.KCP协议传输**
KCP协议需要-B参数设置一个密码用于加密解密数据 KCP协议需要--kcp-key参数设置一个密码用于加密解密数据
一级HTTP代理(VPS,IP:22.22.22.22) 一级HTTP代理(VPS,IP:22.22.22.22)
`./proxy socks -t kcp -p ":38080" -B mypassword` `./proxy socks -t kcp -p ":38080" --kcp-key mypassword`
二级HTTP代理(本地Linux) 二级HTTP代理(本地Linux)
`./proxy socks -t tcp -p ":8080" -T kcp -P "22.22.22.22:38080" -B mypassword` `./proxy socks -t tcp -p ":8080" -T kcp -P "22.22.22.22:38080" --kcp-key mypassword`
那么访问本地的8080端口就是访问VPS上面的代理端口38080,数据通过kcp协议传输. 那么访问本地的8080端口就是访问VPS上面的代理端口38080,数据通过kcp协议传输.
#### **5.9.自定义DNS** #### **5.9.自定义DNS**
@ -695,7 +697,7 @@ KCP协议需要-B参数设置一个密码用于加密解密数据
假设已经存在一个kcp的http(s)代理密码是demo123127.0.0.1:8080,现在我们把它转为同时支持http(s)和socks5的普通代理,转换后的本地端口为18080。 假设已经存在一个kcp的http(s)代理密码是demo123127.0.0.1:8080,现在我们把它转为同时支持http(s)和socks5的普通代理,转换后的本地端口为18080。
命令如下: 命令如下:
`./proxy sps -S http -T kcp -P 127.0.0.1:8080 -t tcp -p :18080 -B demo123` `./proxy sps -S http -T kcp -P 127.0.0.1:8080 -t tcp -p :18080 --kcp-key demo123`
#### **6.3 SOCKS5转HTTP(S)+SOCKS5** #### **6.3 SOCKS5转HTTP(S)+SOCKS5**
假设已经存在一个普通的socks5代理127.0.0.1:8080,现在我们把它转为同时支持http(s)和socks5的普通代理,转换后的本地端口为18080。 假设已经存在一个普通的socks5代理127.0.0.1:8080,现在我们把它转为同时支持http(s)和socks5的普通代理,转换后的本地端口为18080。
@ -708,7 +710,7 @@ KCP协议需要-B参数设置一个密码用于加密解密数据
假设已经存在一个kcp的socks5代理密码是demo123127.0.0.1:8080,现在我们把它转为同时支持http(s)和socks5的普通代理,转换后的本地端口为18080。 假设已经存在一个kcp的socks5代理密码是demo123127.0.0.1:8080,现在我们把它转为同时支持http(s)和socks5的普通代理,转换后的本地端口为18080。
命令如下: 命令如下:
`./proxy sps -S socks -T kcp -P 127.0.0.1:8080 -t tcp -p :18080 -B demo123` `./proxy sps -S socks -T kcp -P 127.0.0.1:8080 -t tcp -p :18080 --kcp-key demo123`
#### **6.4 链式连接** #### **6.4 链式连接**
上面提过多个sps结点可以层级连接构建加密通道假设有如下vps和家里的pc电脑。 上面提过多个sps结点可以层级连接构建加密通道假设有如下vps和家里的pc电脑。

View File

@ -73,6 +73,7 @@ func initConfig() (err error) {
//########http######### //########http#########
http := app.Command("http", "proxy on http mode") http := app.Command("http", "proxy on http mode")
httpArgs.Parent = http.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').String() httpArgs.Parent = http.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').String()
httpArgs.CaCertFile = http.Flag("ca", "ca cert file for tls").Default("").String()
httpArgs.CertFile = http.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String() httpArgs.CertFile = http.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
httpArgs.KeyFile = http.Flag("key", "key file for tls").Short('K').Default("proxy.key").String() httpArgs.KeyFile = http.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
httpArgs.LocalType = http.Flag("local-type", "local protocol type <tls|tcp|kcp>").Default("tcp").Short('t').Enum("tls", "tcp", "kcp") httpArgs.LocalType = http.Flag("local-type", "local protocol type <tls|tcp|kcp>").Default("tcp").Short('t').Enum("tls", "tcp", "kcp")
@ -126,31 +127,34 @@ func initConfig() (err error) {
//########mux-server######### //########mux-server#########
muxServer := app.Command("server", "proxy on mux server mode") muxServer := app.Command("server", "proxy on mux server mode")
muxServerArgs.Parent = muxServer.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').String() muxServerArgs.Parent = muxServer.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').String()
muxServerArgs.ParentType = muxServer.Flag("parent-type", "parent protocol type <tls|tcp|kcp>").Default("tls").Short('T').Enum("tls", "tcp", "kcp")
muxServerArgs.CertFile = muxServer.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String() muxServerArgs.CertFile = muxServer.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
muxServerArgs.KeyFile = muxServer.Flag("key", "key file for tls").Short('K').Default("proxy.key").String() muxServerArgs.KeyFile = muxServer.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
muxServerArgs.Timeout = muxServer.Flag("timeout", "tcp timeout with milliseconds").Short('t').Default("2000").Int() muxServerArgs.Timeout = muxServer.Flag("timeout", "tcp timeout with milliseconds").Short('i').Default("2000").Int()
muxServerArgs.IsUDP = muxServer.Flag("udp", "proxy on udp mux server mode").Default("false").Bool() muxServerArgs.IsUDP = muxServer.Flag("udp", "proxy on udp mux server mode").Default("false").Bool()
muxServerArgs.Key = muxServer.Flag("k", "client key").Default("default").String() muxServerArgs.Key = muxServer.Flag("k", "client key").Default("default").String()
muxServerArgs.Route = muxServer.Flag("route", "local route to client's network, such as: PROTOCOL://LOCAL_IP:LOCAL_PORT@[CLIENT_KEY]CLIENT_LOCAL_HOST:CLIENT_LOCAL_PORT").Short('r').Default("").Strings() muxServerArgs.Route = muxServer.Flag("route", "local route to client's network, such as: PROTOCOL://LOCAL_IP:LOCAL_PORT@[CLIENT_KEY]CLIENT_LOCAL_HOST:CLIENT_LOCAL_PORT").Short('r').Default("").Strings()
muxServerArgs.IsCompress = muxServer.Flag("c", "compress data when tcp mode").Default("false").Bool() muxServerArgs.IsCompress = muxServer.Flag("c", "compress data when tcp|tls mode").Default("false").Bool()
muxServerArgs.SessionCount = muxServer.Flag("session-count", "session count which connect to bridge").Short('n').Default("10").Int() muxServerArgs.SessionCount = muxServer.Flag("session-count", "session count which connect to bridge").Short('n').Default("10").Int()
//########mux-client######### //########mux-client#########
muxClient := app.Command("client", "proxy on mux client mode") muxClient := app.Command("client", "proxy on mux client mode")
muxClientArgs.Parent = muxClient.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').String() muxClientArgs.Parent = muxClient.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').String()
muxClientArgs.ParentType = muxClient.Flag("parent-type", "parent protocol type <tls|tcp|kcp>").Default("tls").Short('T').Enum("tls", "tcp", "kcp")
muxClientArgs.CertFile = muxClient.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String() muxClientArgs.CertFile = muxClient.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
muxClientArgs.KeyFile = muxClient.Flag("key", "key file for tls").Short('K').Default("proxy.key").String() muxClientArgs.KeyFile = muxClient.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
muxClientArgs.Timeout = muxClient.Flag("timeout", "tcp timeout with milliseconds").Short('t').Default("2000").Int() muxClientArgs.Timeout = muxClient.Flag("timeout", "tcp timeout with milliseconds").Short('i').Default("2000").Int()
muxClientArgs.Key = muxClient.Flag("k", "key same with server").Default("default").String() muxClientArgs.Key = muxClient.Flag("k", "key same with server").Default("default").String()
muxClientArgs.IsCompress = muxClient.Flag("c", "compress data when tcp mode").Default("false").Bool() muxClientArgs.IsCompress = muxClient.Flag("c", "compress data when tcp|tls mode").Default("false").Bool()
muxClientArgs.SessionCount = muxClient.Flag("session-count", "session count which connect to bridge").Short('n').Default("10").Int() muxClientArgs.SessionCount = muxClient.Flag("session-count", "session count which connect to bridge").Short('n').Default("10").Int()
//########mux-bridge######### //########mux-bridge#########
muxBridge := app.Command("bridge", "proxy on mux bridge mode") muxBridge := app.Command("bridge", "proxy on mux bridge mode")
muxBridgeArgs.CertFile = muxBridge.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String() muxBridgeArgs.CertFile = muxBridge.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
muxBridgeArgs.KeyFile = muxBridge.Flag("key", "key file for tls").Short('K').Default("proxy.key").String() muxBridgeArgs.KeyFile = muxBridge.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
muxBridgeArgs.Timeout = muxBridge.Flag("timeout", "tcp timeout with milliseconds").Short('t').Default("2000").Int() muxBridgeArgs.Timeout = muxBridge.Flag("timeout", "tcp timeout with milliseconds").Short('i').Default("2000").Int()
muxBridgeArgs.Local = muxBridge.Flag("local", "local ip:port to listen").Short('p').Default(":33080").String() muxBridgeArgs.Local = muxBridge.Flag("local", "local ip:port to listen").Short('p').Default(":33080").String()
muxBridgeArgs.LocalType = muxBridge.Flag("local-type", "local protocol type <tls|tcp|kcp>").Default("tls").Short('t').Enum("tls", "tcp", "kcp")
//########tunnel-server######### //########tunnel-server#########
tunnelServer := app.Command("tserver", "proxy on tunnel server mode") tunnelServer := app.Command("tserver", "proxy on tunnel server mode")
@ -186,6 +190,7 @@ func initConfig() (err error) {
socksArgs.UDPParent = socks.Flag("udp-parent", "udp parent address, such as: \"23.32.32.19:33090\"").Default("").Short('X').String() socksArgs.UDPParent = socks.Flag("udp-parent", "udp parent address, such as: \"23.32.32.19:33090\"").Default("").Short('X').String()
socksArgs.UDPLocal = socks.Flag("udp-local", "udp local ip:port to listen").Short('x').Default(":33090").String() socksArgs.UDPLocal = socks.Flag("udp-local", "udp local ip:port to listen").Short('x').Default(":33090").String()
socksArgs.CertFile = socks.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String() socksArgs.CertFile = socks.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
socksArgs.CaCertFile = socks.Flag("ca", "ca cert file for tls").Default("").String()
socksArgs.KeyFile = socks.Flag("key", "key file for tls").Short('K').Default("proxy.key").String() socksArgs.KeyFile = socks.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
socksArgs.SSHUser = socks.Flag("ssh-user", "user for ssh").Short('u').Default("").String() socksArgs.SSHUser = socks.Flag("ssh-user", "user for ssh").Short('u').Default("").String()
socksArgs.SSHKeyFile = socks.Flag("ssh-key", "private key file for ssh").Short('S').Default("").String() socksArgs.SSHKeyFile = socks.Flag("ssh-key", "private key file for ssh").Short('S').Default("").String()
@ -210,6 +215,7 @@ func initConfig() (err error) {
spsArgs.Parent = sps.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').String() spsArgs.Parent = sps.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').String()
spsArgs.CertFile = sps.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String() spsArgs.CertFile = sps.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
spsArgs.KeyFile = sps.Flag("key", "key file for tls").Short('K').Default("proxy.key").String() spsArgs.KeyFile = sps.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
spsArgs.CaCertFile = sps.Flag("ca", "ca cert file for tls").Default("").String()
spsArgs.Timeout = sps.Flag("timeout", "tcp timeout milliseconds when connect to real server or parent proxy").Short('i').Default("2000").Int() spsArgs.Timeout = sps.Flag("timeout", "tcp timeout milliseconds when connect to real server or parent proxy").Short('i').Default("2000").Int()
spsArgs.ParentType = sps.Flag("parent-type", "parent protocol type <tls|tcp|kcp>").Short('T').Enum("tls", "tcp", "kcp") spsArgs.ParentType = sps.Flag("parent-type", "parent protocol type <tls|tcp|kcp>").Short('T').Enum("tls", "tcp", "kcp")
spsArgs.LocalType = sps.Flag("local-type", "local protocol type <tls|tcp|kcp>").Default("tcp").Short('t').Enum("tls", "tcp", "kcp") spsArgs.LocalType = sps.Flag("local-type", "local protocol type <tls|tcp|kcp>").Default("tcp").Short('t').Enum("tls", "tcp", "kcp")
@ -264,6 +270,15 @@ func initConfig() (err error) {
*kcpArgs.Crypt = "aes" *kcpArgs.Crypt = "aes"
kcpArgs.Block, _ = kcp.NewAESBlockCrypt(pass) kcpArgs.Block, _ = kcp.NewAESBlockCrypt(pass)
} }
//attach kcp config
tcpArgs.KCP = kcpArgs
httpArgs.KCP = kcpArgs
socksArgs.KCP = kcpArgs
spsArgs.KCP = kcpArgs
muxBridgeArgs.KCP = kcpArgs
muxServerArgs.KCP = kcpArgs
muxClientArgs.KCP = kcpArgs
flags := log.Ldate flags := log.Ldate
if *debug { if *debug {
flags |= log.Lshortfile | log.Lmicroseconds flags |= log.Lshortfile | log.Lmicroseconds

View File

@ -5,7 +5,7 @@ if [ -e /tmp/proxy ]; then
fi fi
mkdir /tmp/proxy mkdir /tmp/proxy
cd /tmp/proxy cd /tmp/proxy
wget https://github.com/snail007/goproxy/releases/download/v4.4/proxy-linux-amd64.tar.gz wget https://github.com/snail007/goproxy/releases/download/v4.5/proxy-linux-amd64.tar.gz
# #install proxy # #install proxy
tar zxvf proxy-linux-amd64.tar.gz tar zxvf proxy-linux-amd64.tar.gz

View File

@ -8,7 +8,7 @@ import (
"syscall" "syscall"
) )
const APP_VERSION = "4.4" const APP_VERSION = "4.5"
func main() { func main() {
err := initConfig() err := initConfig()

View File

@ -1,5 +1,5 @@
#!/bin/bash #!/bin/bash
VER="4.4" VER="4.5"
RELEASE="release-${VER}" RELEASE="release-${VER}"
rm -rf .cert rm -rf .cert
mkdir .cert mkdir .cert

View File

@ -26,6 +26,7 @@ const (
type MuxServerArgs struct { type MuxServerArgs struct {
Parent *string Parent *string
ParentType *string
CertFile *string CertFile *string
KeyFile *string KeyFile *string
CertBytes []byte CertBytes []byte
@ -39,9 +40,11 @@ type MuxServerArgs struct {
Mgr *MuxServerManager Mgr *MuxServerManager
IsCompress *bool IsCompress *bool
SessionCount *int SessionCount *int
KCP kcpcfg.KCPConfigArgs
} }
type MuxClientArgs struct { type MuxClientArgs struct {
Parent *string Parent *string
ParentType *string
CertFile *string CertFile *string
KeyFile *string KeyFile *string
CertBytes []byte CertBytes []byte
@ -50,16 +53,18 @@ type MuxClientArgs struct {
Timeout *int Timeout *int
IsCompress *bool IsCompress *bool
SessionCount *int SessionCount *int
KCP kcpcfg.KCPConfigArgs
} }
type MuxBridgeArgs struct { type MuxBridgeArgs struct {
Parent *string
CertFile *string CertFile *string
KeyFile *string KeyFile *string
CertBytes []byte CertBytes []byte
KeyBytes []byte KeyBytes []byte
Local *string Local *string
LocalType *string
Timeout *int Timeout *int
IsCompress *bool IsCompress *bool
KCP kcpcfg.KCPConfigArgs
} }
type TunnelServerArgs struct { type TunnelServerArgs struct {
Parent *string Parent *string
@ -115,6 +120,8 @@ type HTTPArgs struct {
Parent *string Parent *string
CertFile *string CertFile *string
KeyFile *string KeyFile *string
CaCertFile *string
CaCertBytes []byte
CertBytes []byte CertBytes []byte
KeyBytes []byte KeyBytes []byte
Local *string Local *string
@ -164,6 +171,8 @@ type SocksArgs struct {
LocalType *string LocalType *string
CertFile *string CertFile *string
KeyFile *string KeyFile *string
CaCertFile *string
CaCertBytes []byte
CertBytes []byte CertBytes []byte
KeyBytes []byte KeyBytes []byte
SSHKeyFile *string SSHKeyFile *string
@ -194,6 +203,8 @@ type SPSArgs struct {
Parent *string Parent *string
CertFile *string CertFile *string
KeyFile *string KeyFile *string
CaCertFile *string
CaCertBytes []byte
CertBytes []byte CertBytes []byte
KeyBytes []byte KeyBytes []byte
Local *string Local *string

View File

@ -41,6 +41,12 @@ func (s *HTTP) CheckArgs() {
} }
if *s.cfg.ParentType == "tls" || *s.cfg.LocalType == "tls" { if *s.cfg.ParentType == "tls" || *s.cfg.LocalType == "tls" {
s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile) s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
if *s.cfg.CaCertFile != "" {
s.cfg.CaCertBytes, err = ioutil.ReadFile(*s.cfg.CaCertFile)
if err != nil {
log.Fatalf("read ca file error,ERR:%s", err)
}
}
} }
if *s.cfg.ParentType == "ssh" { if *s.cfg.ParentType == "ssh" {
if *s.cfg.SSHUser == "" { if *s.cfg.SSHUser == "" {
@ -128,7 +134,7 @@ func (s *HTTP) Start(args interface{}) (err error) {
if *s.cfg.LocalType == TYPE_TCP { if *s.cfg.LocalType == TYPE_TCP {
err = sc.ListenTCP(s.callback) err = sc.ListenTCP(s.callback)
} else if *s.cfg.LocalType == TYPE_TLS { } else if *s.cfg.LocalType == TYPE_TLS {
err = sc.ListenTls(s.cfg.CertBytes, s.cfg.KeyBytes, s.callback) err = sc.ListenTls(s.cfg.CertBytes, s.cfg.KeyBytes, s.cfg.CaCertBytes, s.callback)
} else if *s.cfg.LocalType == TYPE_KCP { } else if *s.cfg.LocalType == TYPE_KCP {
err = sc.ListenKCP(s.cfg.KCP, s.callback) err = sc.ListenKCP(s.cfg.KCP, s.callback)
} }
@ -321,7 +327,7 @@ func (s *HTTP) InitOutConnPool() {
*s.cfg.CheckParentInterval, *s.cfg.CheckParentInterval,
*s.cfg.ParentType, *s.cfg.ParentType,
s.cfg.KCP, s.cfg.KCP,
s.cfg.CertBytes, s.cfg.KeyBytes, s.cfg.CertBytes, s.cfg.KeyBytes, s.cfg.CaCertBytes,
s.Resolve(*s.cfg.Parent), s.Resolve(*s.cfg.Parent),
*s.cfg.Timeout, *s.cfg.Timeout,
*s.cfg.PoolSize, *s.cfg.PoolSize,

View File

@ -9,6 +9,7 @@ import (
"snail007/proxy/utils" "snail007/proxy/utils"
"strconv" "strconv"
"strings" "strings"
"sync"
"time" "time"
"github.com/xtaci/smux" "github.com/xtaci/smux"
@ -18,12 +19,14 @@ type MuxBridge struct {
cfg MuxBridgeArgs cfg MuxBridgeArgs
clientControlConns utils.ConcurrentMap clientControlConns utils.ConcurrentMap
router utils.ClientKeyRouter router utils.ClientKeyRouter
l *sync.Mutex
} }
func NewMuxBridge() Service { func NewMuxBridge() Service {
b := &MuxBridge{ b := &MuxBridge{
cfg: MuxBridgeArgs{}, cfg: MuxBridgeArgs{},
clientControlConns: utils.NewConcurrentMap(), clientControlConns: utils.NewConcurrentMap(),
l: &sync.Mutex{},
} }
b.router = utils.NewClientKeyRouter(&b.clientControlConns, 50000) b.router = utils.NewClientKeyRouter(&b.clientControlConns, 50000)
return b return b
@ -36,7 +39,9 @@ func (s *MuxBridge) CheckArgs() {
if *s.cfg.CertFile == "" || *s.cfg.KeyFile == "" { if *s.cfg.CertFile == "" || *s.cfg.KeyFile == "" {
log.Fatalf("cert and key file required") log.Fatalf("cert and key file required")
} }
s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile) if *s.cfg.LocalType == TYPE_TLS {
s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
}
} }
func (s *MuxBridge) StopService() { func (s *MuxBridge) StopService() {
@ -48,86 +53,103 @@ func (s *MuxBridge) Start(args interface{}) (err error) {
host, port, _ := net.SplitHostPort(*s.cfg.Local) host, port, _ := net.SplitHostPort(*s.cfg.Local)
p, _ := strconv.Atoi(port) p, _ := strconv.Atoi(port)
sc := utils.NewServerChannel(host, p) sc := utils.NewServerChannel(host, p)
if *s.cfg.LocalType == TYPE_TCP {
err = sc.ListenTls(s.cfg.CertBytes, s.cfg.KeyBytes, func(inConn net.Conn) { err = sc.ListenTCP(s.handler)
reader := bufio.NewReader(inConn) } else if *s.cfg.LocalType == TYPE_TLS {
err = sc.ListenTls(s.cfg.CertBytes, s.cfg.KeyBytes, nil, s.handler)
var err error } else if *s.cfg.LocalType == TYPE_KCP {
var connType uint8 err = sc.ListenKCP(s.cfg.KCP, s.handler)
var key string }
err = utils.ReadPacket(reader, &connType, &key)
if err != nil {
log.Printf("read error,ERR:%s", err)
return
}
switch connType {
case CONN_SERVER:
var serverID string
err = utils.ReadPacketData(reader, &serverID)
if err != nil {
log.Printf("read error,ERR:%s", err)
return
}
log.Printf("server connection %s %s connected", serverID, key)
session, err := smux.Server(inConn, nil)
if err != nil {
utils.CloseConn(&inConn)
log.Printf("server session error,ERR:%s", err)
return
}
for {
stream, err := session.AcceptStream()
if err != nil {
session.Close()
utils.CloseConn(&inConn)
return
}
go s.callback(stream, serverID, key)
}
case CONN_CLIENT:
log.Printf("client connection %s connected", key)
session, err := smux.Client(inConn, nil)
if err != nil {
utils.CloseConn(&inConn)
log.Printf("client session error,ERR:%s", err)
return
}
keyInfo := strings.Split(key, "-")
groupKey := keyInfo[0]
index := keyInfo[1]
if !s.clientControlConns.Has(groupKey) {
item := utils.NewConcurrentMap()
s.clientControlConns.Set(groupKey, &item)
}
_group, _ := s.clientControlConns.Get(groupKey)
group := _group.(*utils.ConcurrentMap)
group.Set(index, session)
// s.clientControlConns.Set(key, session)
go func() {
for {
if session.IsClosed() {
group.Remove(index)
if group.IsEmpty() {
s.clientControlConns.Remove(groupKey)
}
break
}
time.Sleep(time.Second * 5)
}
}()
//log.Printf("set client session,key: %s", key)
}
})
if err != nil { if err != nil {
return return
} }
log.Printf("proxy on mux bridge mode %s", (*sc.Listener).Addr()) log.Printf("%s bridge on %s", *s.cfg.LocalType, (*sc.Listener).Addr())
return return
} }
func (s *MuxBridge) Clean() { func (s *MuxBridge) Clean() {
s.StopService() s.StopService()
} }
func (s *MuxBridge) handler(inConn net.Conn) {
reader := bufio.NewReader(inConn)
var err error
var connType uint8
var key string
err = utils.ReadPacket(reader, &connType, &key)
if err != nil {
log.Printf("read error,ERR:%s", err)
return
}
switch connType {
case CONN_SERVER:
var serverID string
err = utils.ReadPacketData(reader, &serverID)
if err != nil {
log.Printf("read error,ERR:%s", err)
return
}
log.Printf("server connection %s %s connected", serverID, key)
session, err := smux.Server(inConn, nil)
if err != nil {
utils.CloseConn(&inConn)
log.Printf("server session error,ERR:%s", err)
return
}
for {
stream, err := session.AcceptStream()
if err != nil {
session.Close()
utils.CloseConn(&inConn)
return
}
go s.callback(stream, serverID, key)
}
case CONN_CLIENT:
log.Printf("client connection %s connected", key)
session, err := smux.Client(inConn, nil)
if err != nil {
utils.CloseConn(&inConn)
log.Printf("client session error,ERR:%s", err)
return
}
keyInfo := strings.Split(key, "-")
if len(keyInfo) != 2 {
utils.CloseConn(&inConn)
log.Printf("client key format error,key:%s", key)
return
}
groupKey := keyInfo[0]
index := keyInfo[1]
s.l.Lock()
defer s.l.Unlock()
if !s.clientControlConns.Has(groupKey) {
item := utils.NewConcurrentMap()
s.clientControlConns.Set(groupKey, &item)
}
_group, _ := s.clientControlConns.Get(groupKey)
group := _group.(*utils.ConcurrentMap)
group.Set(index, session)
// s.clientControlConns.Set(key, session)
go func() {
for {
if session.IsClosed() {
s.l.Lock()
defer s.l.Unlock()
if sess, ok := group.Get(index); ok && sess.(*smux.Session).IsClosed() {
group.Remove(index)
}
if group.IsEmpty() {
s.clientControlConns.Remove(groupKey)
}
break
}
time.Sleep(time.Second * 5)
}
}()
//log.Printf("set client session,key: %s", key)
}
}
func (s *MuxBridge) callback(inConn net.Conn, serverID, key string) { func (s *MuxBridge) callback(inConn net.Conn, serverID, key string) {
try := 20 try := 20
for { for {
@ -140,12 +162,22 @@ func (s *MuxBridge) callback(inConn net.Conn, serverID, key string) {
} }
_group, ok := s.clientControlConns.Get(key) _group, ok := s.clientControlConns.Get(key)
if !ok { if !ok {
log.Printf("client %s session not exists for server stream %s", key, serverID) log.Printf("client %s session not exists for server stream %s, retrying...", key, serverID)
time.Sleep(time.Second * 3) time.Sleep(time.Second * 3)
continue continue
} }
group := _group.(*utils.ConcurrentMap) group := _group.(*utils.ConcurrentMap)
index := group.Keys()[rand.Intn(group.Count())] keys := group.Keys()
keysLen := len(keys)
i := 0
if keysLen > 0 {
i = rand.Intn(keysLen)
} else {
log.Printf("client %s session empty for server stream %s, retrying...", key, serverID)
time.Sleep(time.Second * 3)
continue
}
index := keys[i]
log.Printf("select client : %s-%s", key, index) log.Printf("select client : %s-%s", key, index)
session, _ := group.Get(index) session, _ := group.Get(index)
stream, err := session.(*smux.Session).OpenStream() stream, err := session.(*smux.Session).OpenStream()

View File

@ -36,7 +36,9 @@ func (s *MuxClient) CheckArgs() {
if *s.cfg.CertFile == "" || *s.cfg.KeyFile == "" { if *s.cfg.CertFile == "" || *s.cfg.KeyFile == "" {
log.Fatalf("cert and key file required") log.Fatalf("cert and key file required")
} }
s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile) if *s.cfg.ParentType == "tls" {
s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
}
} }
func (s *MuxClient) StopService() { func (s *MuxClient) StopService() {
@ -45,8 +47,12 @@ func (s *MuxClient) Start(args interface{}) (err error) {
s.cfg = args.(MuxClientArgs) s.cfg = args.(MuxClientArgs)
s.CheckArgs() s.CheckArgs()
s.InitService() s.InitService()
log.Printf("proxy on mux client mode, compress %v", *s.cfg.IsCompress) log.Printf("client started")
for i := 1; i <= *s.cfg.SessionCount; i++ { count := 1
if *s.cfg.SessionCount > 0 {
count = *s.cfg.SessionCount
}
for i := 1; i <= count; i++ {
log.Printf("session worker[%d] started", i) log.Printf("session worker[%d] started", i)
go func(i int) { go func(i int) {
defer func() { defer func() {
@ -56,14 +62,12 @@ func (s *MuxClient) Start(args interface{}) (err error) {
} }
}() }()
for { for {
var _conn tls.Conn conn, err := s.getParentConn()
_conn, err = utils.TlsConnectHost(*s.cfg.Parent, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes)
if err != nil { if err != nil {
log.Printf("connection err: %s, retrying...", err) log.Printf("connection err: %s, retrying...", err)
time.Sleep(time.Second * 3) time.Sleep(time.Second * 3)
continue continue
} }
conn := net.Conn(&_conn)
_, err = conn.Write(utils.BuildPacket(CONN_CLIENT, fmt.Sprintf("%s-%d", *s.cfg.Key, i))) _, err = conn.Write(utils.BuildPacket(CONN_CLIENT, fmt.Sprintf("%s-%d", *s.cfg.Key, i)))
if err != nil { if err != nil {
conn.Close() conn.Close()
@ -119,7 +123,20 @@ func (s *MuxClient) Start(args interface{}) (err error) {
func (s *MuxClient) Clean() { func (s *MuxClient) Clean() {
s.StopService() s.StopService()
} }
func (s *MuxClient) getParentConn() (conn net.Conn, err error) {
if *s.cfg.ParentType == "tls" {
var _conn tls.Conn
_conn, err = utils.TlsConnectHost(*s.cfg.Parent, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes, nil)
if err == nil {
conn = net.Conn(&_conn)
}
} else if *s.cfg.ParentType == "kcp" {
conn, err = utils.ConnectKCPHost(*s.cfg.Parent, s.cfg.KCP)
} else {
conn, err = utils.ConnectHost(*s.cfg.Parent, *s.cfg.Timeout)
}
return
}
func (s *MuxClient) ServeUDP(inConn *smux.Stream, localAddr, ID string) { func (s *MuxClient) ServeUDP(inConn *smux.Stream, localAddr, ID string) {
for { for {

View File

@ -43,7 +43,7 @@ func (s *MuxServerManager) Start(args interface{}) (err error) {
s.cfg = args.(MuxServerArgs) s.cfg = args.(MuxServerArgs)
s.CheckArgs() s.CheckArgs()
if *s.cfg.Parent != "" { if *s.cfg.Parent != "" {
log.Printf("use tls parent %s", *s.cfg.Parent) log.Printf("use %s parent %s", *s.cfg.ParentType, *s.cfg.Parent)
} else { } else {
log.Fatalf("parent required") log.Fatalf("parent required")
} }
@ -88,6 +88,8 @@ func (s *MuxServerManager) Start(args interface{}) (err error) {
Mgr: s, Mgr: s,
IsCompress: s.cfg.IsCompress, IsCompress: s.cfg.IsCompress,
SessionCount: s.cfg.SessionCount, SessionCount: s.cfg.SessionCount,
KCP: s.cfg.KCP,
ParentType: s.cfg.ParentType,
}) })
if err != nil { if err != nil {
@ -105,7 +107,9 @@ func (s *MuxServerManager) CheckArgs() {
if *s.cfg.CertFile == "" || *s.cfg.KeyFile == "" { if *s.cfg.CertFile == "" || *s.cfg.KeyFile == "" {
log.Fatalf("cert and key file required") log.Fatalf("cert and key file required")
} }
s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile) if *s.cfg.ParentType == "tls" {
s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
}
} }
func (s *MuxServerManager) InitService() { func (s *MuxServerManager) InitService() {
} }
@ -152,7 +156,7 @@ func (s *MuxServer) Start(args interface{}) (err error) {
if err != nil { if err != nil {
return return
} }
log.Printf("proxy on udp mux server mode %s", (*s.sc.UDPListener).LocalAddr()) log.Printf("server on %s", (*s.sc.UDPListener).LocalAddr())
} else { } else {
err = s.sc.ListenTCP(func(inConn net.Conn) { err = s.sc.ListenTCP(func(inConn net.Conn) {
defer func() { defer func() {
@ -201,7 +205,7 @@ func (s *MuxServer) Start(args interface{}) (err error) {
if err != nil { if err != nil {
return return
} }
log.Printf("proxy on mux server mode %s, compress %v", (*s.sc.Listener).Addr(), *s.cfg.IsCompress) log.Printf("server on %s", (*s.sc.Listener).Addr())
} }
return return
} }
@ -209,7 +213,11 @@ func (s *MuxServer) Clean() {
} }
func (s *MuxServer) GetOutConn() (outConn net.Conn, ID string, err error) { func (s *MuxServer) GetOutConn() (outConn net.Conn, ID string, err error) {
outConn, err = s.GetConn(fmt.Sprintf("%d", rand.Intn(*s.cfg.SessionCount))) i := 1
if *s.cfg.SessionCount > 0 {
i = rand.Intn(*s.cfg.SessionCount)
}
outConn, err = s.GetConn(fmt.Sprintf("%d", i))
if err != nil { if err != nil {
log.Printf("connection err: %s", err) log.Printf("connection err: %s", err)
return return
@ -240,12 +248,11 @@ func (s *MuxServer) GetConn(index string) (conn net.Conn, err error) {
var session *smux.Session var session *smux.Session
_session, ok := s.sessions.Get(index) _session, ok := s.sessions.Get(index)
if !ok { if !ok {
var _conn tls.Conn var c net.Conn
_conn, err = utils.TlsConnectHost(*s.cfg.Parent, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes) c, err = s.getParentConn()
if err != nil { if err != nil {
return return
} }
c := net.Conn(&_conn)
_, err = c.Write(utils.BuildPacket(CONN_SERVER, *s.cfg.Key, s.cfg.Mgr.serverID)) _, err = c.Write(utils.BuildPacket(CONN_SERVER, *s.cfg.Key, s.cfg.Mgr.serverID))
if err != nil { if err != nil {
c.Close() c.Close()
@ -266,10 +273,34 @@ func (s *MuxServer) GetConn(index string) (conn net.Conn, err error) {
if err != nil { if err != nil {
session.Close() session.Close()
s.sessions.Remove(index) s.sessions.Remove(index)
} else {
go func() {
for {
if session.IsClosed() {
s.sessions.Remove(index)
break
}
time.Sleep(time.Second * 5)
}
}()
} }
return return
} }
func (s *MuxServer) getParentConn() (conn net.Conn, err error) {
if *s.cfg.ParentType == "tls" {
var _conn tls.Conn
_conn, err = utils.TlsConnectHost(*s.cfg.Parent, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes, nil)
if err == nil {
conn = net.Conn(&_conn)
}
} else if *s.cfg.ParentType == "kcp" {
conn, err = utils.ConnectKCPHost(*s.cfg.Parent, s.cfg.KCP)
} else {
conn, err = utils.ConnectHost(*s.cfg.Parent, *s.cfg.Timeout)
}
return
}
func (s *MuxServer) UDPConnDeamon() { func (s *MuxServer) UDPConnDeamon() {
go func() { go func() {
defer func() { defer func() {

View File

@ -37,16 +37,28 @@ func NewSocks() Service {
func (s *Socks) CheckArgs() { func (s *Socks) CheckArgs() {
var err error var err error
if *s.cfg.LocalType == "tls" { if *s.cfg.LocalType == "tls" || (*s.cfg.Parent != "" && *s.cfg.ParentType == "tls") {
s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile) s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
if *s.cfg.CaCertFile != "" {
s.cfg.CaCertBytes, err = ioutil.ReadFile(*s.cfg.CaCertFile)
if err != nil {
log.Fatalf("read ca file error,ERR:%s", err)
}
}
} }
if *s.cfg.Parent != "" { if *s.cfg.Parent != "" {
if *s.cfg.ParentType == "" { if *s.cfg.ParentType == "" {
log.Fatalf("parent type unkown,use -T <tls|tcp|ssh|kcp>") log.Fatalf("parent type unkown,use -T <tls|tcp|ssh|kcp>")
} }
if *s.cfg.ParentType == "tls" { // if *s.cfg.ParentType == "tls" {
s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile) // s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
} // if *s.cfg.CaCertFile != "" {
// s.cfg.CaCertBytes, err = ioutil.ReadFile(*s.cfg.CaCertFile)
// if err != nil {
// log.Fatalf("read ca file error,ERR:%s", err)
// }
// }
// }
if *s.cfg.ParentType == "ssh" { if *s.cfg.ParentType == "ssh" {
if *s.cfg.SSHUser == "" { if *s.cfg.SSHUser == "" {
log.Fatalf("ssh user required") log.Fatalf("ssh user required")
@ -138,7 +150,7 @@ func (s *Socks) Start(args interface{}) (err error) {
if *s.cfg.LocalType == TYPE_TCP { if *s.cfg.LocalType == TYPE_TCP {
err = sc.ListenTCP(s.socksConnCallback) err = sc.ListenTCP(s.socksConnCallback)
} else if *s.cfg.LocalType == TYPE_TLS { } else if *s.cfg.LocalType == TYPE_TLS {
err = sc.ListenTls(s.cfg.CertBytes, s.cfg.KeyBytes, s.socksConnCallback) err = sc.ListenTls(s.cfg.CertBytes, s.cfg.KeyBytes, nil, s.socksConnCallback)
} else if *s.cfg.LocalType == TYPE_KCP { } else if *s.cfg.LocalType == TYPE_KCP {
err = sc.ListenKCP(s.cfg.KCP, s.socksConnCallback) err = sc.ListenKCP(s.cfg.KCP, s.socksConnCallback)
} }
@ -471,7 +483,7 @@ func (s *Socks) getOutConn(methodBytes, reqBytes []byte, host string) (outConn n
case "tcp": case "tcp":
if *s.cfg.ParentType == "tls" { if *s.cfg.ParentType == "tls" {
var _outConn tls.Conn var _outConn tls.Conn
_outConn, err = utils.TlsConnectHost(s.Resolve(*s.cfg.Parent), *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes) _outConn, err = utils.TlsConnectHost(s.Resolve(*s.cfg.Parent), *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes, nil)
outConn = net.Conn(&_outConn) outConn = net.Conn(&_outConn)
} else if *s.cfg.ParentType == "kcp" { } else if *s.cfg.ParentType == "kcp" {
outConn, err = utils.ConnectKCPHost(s.Resolve(*s.cfg.Parent), s.cfg.KCP) outConn, err = utils.ConnectKCPHost(s.Resolve(*s.cfg.Parent), s.cfg.KCP)

View File

@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"errors" "errors"
"fmt" "fmt"
"io/ioutil"
"log" "log"
"net" "net"
"runtime/debug" "runtime/debug"
@ -34,6 +35,13 @@ func (s *SPS) CheckArgs() {
} }
if *s.cfg.ParentType == TYPE_TLS || *s.cfg.LocalType == TYPE_TLS { if *s.cfg.ParentType == TYPE_TLS || *s.cfg.LocalType == TYPE_TLS {
s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile) s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
if *s.cfg.CaCertFile != "" {
var err error
s.cfg.CaCertBytes, err = ioutil.ReadFile(*s.cfg.CaCertFile)
if err != nil {
log.Fatalf("read ca file error,ERR:%s", err)
}
}
} }
} }
func (s *SPS) InitService() { func (s *SPS) InitService() {
@ -47,7 +55,7 @@ func (s *SPS) InitOutConnPool() {
0, 0,
*s.cfg.ParentType, *s.cfg.ParentType,
s.cfg.KCP, s.cfg.KCP,
s.cfg.CertBytes, s.cfg.KeyBytes, s.cfg.CertBytes, s.cfg.KeyBytes, nil,
*s.cfg.Parent, *s.cfg.Parent,
*s.cfg.Timeout, *s.cfg.Timeout,
0, 0,
@ -75,7 +83,7 @@ func (s *SPS) Start(args interface{}) (err error) {
if *s.cfg.LocalType == TYPE_TCP { if *s.cfg.LocalType == TYPE_TCP {
err = sc.ListenTCP(s.callback) err = sc.ListenTCP(s.callback)
} else if *s.cfg.LocalType == TYPE_TLS { } else if *s.cfg.LocalType == TYPE_TLS {
err = sc.ListenTls(s.cfg.CertBytes, s.cfg.KeyBytes, s.callback) err = sc.ListenTls(s.cfg.CertBytes, s.cfg.KeyBytes, nil, s.callback)
} else if *s.cfg.LocalType == TYPE_KCP { } else if *s.cfg.LocalType == TYPE_KCP {
err = sc.ListenKCP(s.cfg.KCP, s.callback) err = sc.ListenKCP(s.cfg.KCP, s.callback)
} }

View File

@ -56,7 +56,7 @@ func (s *TCP) Start(args interface{}) (err error) {
if *s.cfg.LocalType == TYPE_TCP { if *s.cfg.LocalType == TYPE_TCP {
err = sc.ListenTCP(s.callback) err = sc.ListenTCP(s.callback)
} else if *s.cfg.LocalType == TYPE_TLS { } else if *s.cfg.LocalType == TYPE_TLS {
err = sc.ListenTls(s.cfg.CertBytes, s.cfg.KeyBytes, s.callback) err = sc.ListenTls(s.cfg.CertBytes, s.cfg.KeyBytes, nil, s.callback)
} else if *s.cfg.LocalType == TYPE_KCP { } else if *s.cfg.LocalType == TYPE_KCP {
err = sc.ListenKCP(s.cfg.KCP, s.callback) err = sc.ListenKCP(s.cfg.KCP, s.callback)
} }
@ -172,7 +172,7 @@ func (s *TCP) InitOutConnPool() {
*s.cfg.CheckParentInterval, *s.cfg.CheckParentInterval,
*s.cfg.ParentType, *s.cfg.ParentType,
s.cfg.KCP, s.cfg.KCP,
s.cfg.CertBytes, s.cfg.KeyBytes, s.cfg.CertBytes, s.cfg.KeyBytes, nil,
*s.cfg.Parent, *s.cfg.Parent,
*s.cfg.Timeout, *s.cfg.Timeout,
*s.cfg.PoolSize, *s.cfg.PoolSize,

View File

@ -51,7 +51,7 @@ func (s *TunnelBridge) Start(args interface{}) (err error) {
p, _ := strconv.Atoi(port) p, _ := strconv.Atoi(port)
sc := utils.NewServerChannel(host, p) sc := utils.NewServerChannel(host, p)
err = sc.ListenTls(s.cfg.CertBytes, s.cfg.KeyBytes, func(inConn net.Conn) { err = sc.ListenTls(s.cfg.CertBytes, s.cfg.KeyBytes, nil, func(inConn net.Conn) {
//log.Printf("connection from %s ", inConn.RemoteAddr()) //log.Printf("connection from %s ", inConn.RemoteAddr())
reader := bufio.NewReader(inConn) reader := bufio.NewReader(inConn)

View File

@ -161,7 +161,7 @@ func (s *TunnelClient) GetInConn(typ uint8, data ...string) (outConn net.Conn, e
} }
func (s *TunnelClient) GetConn() (conn net.Conn, err error) { func (s *TunnelClient) GetConn() (conn net.Conn, err error) {
var _conn tls.Conn var _conn tls.Conn
_conn, err = utils.TlsConnectHost(*s.cfg.Parent, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes) _conn, err = utils.TlsConnectHost(*s.cfg.Parent, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes, nil)
if err == nil { if err == nil {
conn = net.Conn(&_conn) conn = net.Conn(&_conn)
} }

View File

@ -174,7 +174,7 @@ func (s *TunnelServerManager) GetOutConn(typ uint8) (outConn net.Conn, ID string
} }
func (s *TunnelServerManager) GetConn() (conn net.Conn, err error) { func (s *TunnelServerManager) GetConn() (conn net.Conn, err error) {
var _conn tls.Conn var _conn tls.Conn
_conn, err = utils.TlsConnectHost(*s.cfg.Parent, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes) _conn, err = utils.TlsConnectHost(*s.cfg.Parent, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes, nil)
if err == nil { if err == nil {
conn = net.Conn(&_conn) conn = net.Conn(&_conn)
} }
@ -280,7 +280,7 @@ func (s *TunnelServer) GetOutConn(typ uint8) (outConn net.Conn, ID string, err e
} }
func (s *TunnelServer) GetConn() (conn net.Conn, err error) { func (s *TunnelServer) GetConn() (conn net.Conn, err error) {
var _conn tls.Conn var _conn tls.Conn
_conn, err = utils.TlsConnectHost(*s.cfg.Parent, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes) _conn, err = utils.TlsConnectHost(*s.cfg.Parent, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes, nil)
if err == nil { if err == nil {
conn = net.Conn(&_conn) conn = net.Conn(&_conn)
} }

View File

@ -210,7 +210,7 @@ func (s *UDP) InitOutConnPool() {
*s.cfg.CheckParentInterval, *s.cfg.CheckParentInterval,
*s.cfg.ParentType, *s.cfg.ParentType,
kcpcfg.KCPConfigArgs{}, kcpcfg.KCPConfigArgs{},
s.cfg.CertBytes, s.cfg.KeyBytes, s.cfg.CertBytes, s.cfg.KeyBytes, nil,
*s.cfg.Parent, *s.cfg.Parent,
*s.cfg.Timeout, *s.cfg.Timeout,
*s.cfg.PoolSize, *s.cfg.PoolSize,

View File

@ -86,14 +86,14 @@ func ioCopy(dst io.ReadWriter, src io.ReadWriter) (err error) {
} }
} }
} }
func TlsConnectHost(host string, timeout int, certBytes, keyBytes []byte) (conn tls.Conn, err error) { func TlsConnectHost(host string, timeout int, certBytes, keyBytes, caCertBytes []byte) (conn tls.Conn, err error) {
h := strings.Split(host, ":") h := strings.Split(host, ":")
port, _ := strconv.Atoi(h[1]) port, _ := strconv.Atoi(h[1])
return TlsConnect(h[0], port, timeout, certBytes, keyBytes) return TlsConnect(h[0], port, timeout, certBytes, keyBytes, caCertBytes)
} }
func TlsConnect(host string, port, timeout int, certBytes, keyBytes []byte) (conn tls.Conn, err error) { func TlsConnect(host string, port, timeout int, certBytes, keyBytes, caCertBytes []byte) (conn tls.Conn, err error) {
conf, err := getRequestTlsConfig(certBytes, keyBytes) conf, err := getRequestTlsConfig(certBytes, keyBytes, caCertBytes)
if err != nil { if err != nil {
return return
} }
@ -103,8 +103,24 @@ func TlsConnect(host string, port, timeout int, certBytes, keyBytes []byte) (con
} }
return *tls.Client(_conn, conf), err return *tls.Client(_conn, conf), err
} }
func getRequestTlsConfig(certBytes, keyBytes []byte) (conf *tls.Config, err error) { func getRequestTlsConfig(certBytes, keyBytes, caCertBytes []byte) (conf *tls.Config, err error) {
block, _ := pem.Decode(certBytes)
var cert tls.Certificate
cert, err = tls.X509KeyPair(certBytes, keyBytes)
if err != nil {
return
}
serverCertPool := x509.NewCertPool()
caBytes := certBytes
if caCertBytes != nil {
caBytes = caCertBytes
}
ok := serverCertPool.AppendCertsFromPEM(caBytes)
if !ok {
err = errors.New("failed to parse root certificate")
}
block, _ := pem.Decode(caBytes)
if block == nil { if block == nil {
panic("failed to parse certificate PEM") panic("failed to parse certificate PEM")
} }
@ -112,34 +128,24 @@ func getRequestTlsConfig(certBytes, keyBytes []byte) (conf *tls.Config, err erro
if x509Cert == nil { if x509Cert == nil {
panic("failed to parse block") panic("failed to parse block")
} }
var cert tls.Certificate
cert, err = tls.X509KeyPair(certBytes, keyBytes)
if err != nil {
return
}
serverCertPool := x509.NewCertPool()
ok := serverCertPool.AppendCertsFromPEM(certBytes)
if !ok {
err = errors.New("failed to parse root certificate")
}
conf = &tls.Config{ conf = &tls.Config{
RootCAs: serverCertPool, RootCAs: serverCertPool,
Certificates: []tls.Certificate{cert}, Certificates: []tls.Certificate{cert},
InsecureSkipVerify: false, InsecureSkipVerify: true,
ServerName: x509Cert.Subject.CommonName, ServerName: x509Cert.Subject.CommonName,
// VerifyPeerCertificate: func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { VerifyPeerCertificate: func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
// opts := x509.VerifyOptions{ opts := x509.VerifyOptions{
// Roots: serverCertPool, Roots: serverCertPool,
// } }
// for _, rawCert := range rawCerts { for _, rawCert := range rawCerts {
// cert, _ := x509.ParseCertificate(rawCert) cert, _ := x509.ParseCertificate(rawCert)
// _, err := cert.Verify(opts) _, err := cert.Verify(opts)
// if err != nil { if err != nil {
// return err return err
// } }
// } }
// return nil return nil
// }, },
} }
return return
} }
@ -165,22 +171,19 @@ func ConnectKCPHost(hostAndPort string, config kcpcfg.KCPConfigArgs) (conn net.C
return NewCompStream(kcpconn), err return NewCompStream(kcpconn), err
} }
func ListenTls(ip string, port int, certBytes, keyBytes []byte) (ln *net.Listener, err error) { func ListenTls(ip string, port int, certBytes, keyBytes, caCertBytes []byte) (ln *net.Listener, err error) {
block, _ := pem.Decode(certBytes)
if block == nil {
panic("failed to parse certificate PEM")
}
x509Cert, _ := x509.ParseCertificate(block.Bytes)
if x509Cert == nil {
panic("failed to parse block")
}
var cert tls.Certificate var cert tls.Certificate
cert, err = tls.X509KeyPair(certBytes, keyBytes) cert, err = tls.X509KeyPair(certBytes, keyBytes)
if err != nil { if err != nil {
return return
} }
clientCertPool := x509.NewCertPool() clientCertPool := x509.NewCertPool()
ok := clientCertPool.AppendCertsFromPEM(certBytes) caBytes := certBytes
if caCertBytes != nil {
caBytes = caCertBytes
}
ok := clientCertPool.AppendCertsFromPEM(caBytes)
if !ok { if !ok {
err = errors.New("failed to parse root certificate") err = errors.New("failed to parse root certificate")
} }
@ -188,21 +191,6 @@ func ListenTls(ip string, port int, certBytes, keyBytes []byte) (ln *net.Listene
ClientCAs: clientCertPool, ClientCAs: clientCertPool,
Certificates: []tls.Certificate{cert}, Certificates: []tls.Certificate{cert},
ClientAuth: tls.RequireAndVerifyClientCert, ClientAuth: tls.RequireAndVerifyClientCert,
ServerName: x509Cert.Subject.CommonName,
// VerifyPeerCertificate: func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
// opts := x509.VerifyOptions{
// Roots: clientCertPool,
// }
// for _, rawCert := range rawCerts {
// cert, _ := x509.ParseCertificate(rawCert)
// _, err := cert.Verify(opts)
// fmt.Println("SERVER ERR:", err)
// if err != nil {
// return err
// }
// }
// return nil
// },
} }
_ln, err := tls.Listen("tcp", fmt.Sprintf("%s:%d", ip, port), config) _ln, err := tls.Listen("tcp", fmt.Sprintf("%s:%d", ip, port), config)
if err == nil { if err == nil {
@ -245,27 +233,95 @@ func CloseConn(conn *net.Conn) {
} }
} }
func Keygen() (err error) { func Keygen() (err error) {
cmd := exec.Command("sh", "-c", "openssl genrsa -out proxy.key 2048")
out, err := cmd.CombinedOutput()
if err != nil {
log.Printf("err:%s", err)
return
}
fmt.Println(string(out))
CList := []string{"AD", "AE", "AF", "AG", "AI", "AL", "AM", "AO", "AR", "AT", "AU", "AZ", "BB", "BD", "BE", "BF", "BG", "BH", "BI", "BJ", "BL", "BM", "BN", "BO", "BR", "BS", "BW", "BY", "BZ", "CA", "CF", "CG", "CH", "CK", "CL", "CM", "CN", "CO", "CR", "CS", "CU", "CY", "CZ", "DE", "DJ", "DK", "DO", "DZ", "EC", "EE", "EG", "ES", "ET", "FI", "FJ", "FR", "GA", "GB", "GD", "GE", "GF", "GH", "GI", "GM", "GN", "GR", "GT", "GU", "GY", "HK", "HN", "HT", "HU", "ID", "IE", "IL", "IN", "IQ", "IR", "IS", "IT", "JM", "JO", "JP", "KE", "KG", "KH", "KP", "KR", "KT", "KW", "KZ", "LA", "LB", "LC", "LI", "LK", "LR", "LS", "LT", "LU", "LV", "LY", "MA", "MC", "MD", "MG", "ML", "MM", "MN", "MO", "MS", "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA", "NE", "NG", "NI", "NL", "NO", "NP", "NR", "NZ", "OM", "PA", "PE", "PF", "PG", "PH", "PK", "PL", "PR", "PT", "PY", "QA", "RO", "RU", "SA", "SB", "SC", "SD", "SE", "SG", "SI", "SK", "SL", "SM", "SN", "SO", "SR", "ST", "SV", "SY", "SZ", "TD", "TG", "TH", "TJ", "TM", "TN", "TO", "TR", "TT", "TW", "TZ", "UA", "UG", "US", "UY", "UZ", "VC", "VE", "VN", "YE", "YU", "ZA", "ZM", "ZR", "ZW"} CList := []string{"AD", "AE", "AF", "AG", "AI", "AL", "AM", "AO", "AR", "AT", "AU", "AZ", "BB", "BD", "BE", "BF", "BG", "BH", "BI", "BJ", "BL", "BM", "BN", "BO", "BR", "BS", "BW", "BY", "BZ", "CA", "CF", "CG", "CH", "CK", "CL", "CM", "CN", "CO", "CR", "CS", "CU", "CY", "CZ", "DE", "DJ", "DK", "DO", "DZ", "EC", "EE", "EG", "ES", "ET", "FI", "FJ", "FR", "GA", "GB", "GD", "GE", "GF", "GH", "GI", "GM", "GN", "GR", "GT", "GU", "GY", "HK", "HN", "HT", "HU", "ID", "IE", "IL", "IN", "IQ", "IR", "IS", "IT", "JM", "JO", "JP", "KE", "KG", "KH", "KP", "KR", "KT", "KW", "KZ", "LA", "LB", "LC", "LI", "LK", "LR", "LS", "LT", "LU", "LV", "LY", "MA", "MC", "MD", "MG", "ML", "MM", "MN", "MO", "MS", "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA", "NE", "NG", "NI", "NL", "NO", "NP", "NR", "NZ", "OM", "PA", "PE", "PF", "PG", "PH", "PK", "PL", "PR", "PT", "PY", "QA", "RO", "RU", "SA", "SB", "SC", "SD", "SE", "SG", "SI", "SK", "SL", "SM", "SN", "SO", "SR", "ST", "SV", "SY", "SZ", "TD", "TG", "TH", "TJ", "TM", "TN", "TO", "TR", "TT", "TW", "TZ", "UA", "UG", "US", "UY", "UZ", "VC", "VE", "VN", "YE", "YU", "ZA", "ZM", "ZR", "ZW"}
domainSubfixList := []string{".com", ".edu", ".gov", ".int", ".mil", ".net", ".org", ".biz", ".info", ".pro", ".name", ".museum", ".coop", ".aero", ".xxx", ".idv", ".ac", ".ad", ".ae", ".af", ".ag", ".ai", ".al", ".am", ".an", ".ao", ".aq", ".ar", ".as", ".at", ".au", ".aw", ".az", ".ba", ".bb", ".bd", ".be", ".bf", ".bg", ".bh", ".bi", ".bj", ".bm", ".bn", ".bo", ".br", ".bs", ".bt", ".bv", ".bw", ".by", ".bz", ".ca", ".cc", ".cd", ".cf", ".cg", ".ch", ".ci", ".ck", ".cl", ".cm", ".cn", ".co", ".cr", ".cu", ".cv", ".cx", ".cy", ".cz", ".de", ".dj", ".dk", ".dm", ".do", ".dz", ".ec", ".ee", ".eg", ".eh", ".er", ".es", ".et", ".eu", ".fi", ".fj", ".fk", ".fm", ".fo", ".fr", ".ga", ".gd", ".ge", ".gf", ".gg", ".gh", ".gi", ".gl", ".gm", ".gn", ".gp", ".gq", ".gr", ".gs", ".gt", ".gu", ".gw", ".gy", ".hk", ".hm", ".hn", ".hr", ".ht", ".hu", ".id", ".ie", ".il", ".im", ".in", ".io", ".iq", ".ir", ".is", ".it", ".je", ".jm", ".jo", ".jp", ".ke", ".kg", ".kh", ".ki", ".km", ".kn", ".kp", ".kr", ".kw", ".ky", ".kz", ".la", ".lb", ".lc", ".li", ".lk", ".lr", ".ls", ".lt", ".lu", ".lv", ".ly", ".ma", ".mc", ".md", ".mg", ".mh", ".mk", ".ml", ".mm", ".mn", ".mo", ".mp", ".mq", ".mr", ".ms", ".mt", ".mu", ".mv", ".mw", ".mx", ".my", ".mz", ".na", ".nc", ".ne", ".nf", ".ng", ".ni", ".nl", ".no", ".np", ".nr", ".nu", ".nz", ".om", ".pa", ".pe", ".pf", ".pg", ".ph", ".pk", ".pl", ".pm", ".pn", ".pr", ".ps", ".pt", ".pw", ".py", ".qa", ".re", ".ro", ".ru", ".rw", ".sa", ".sb", ".sc", ".sd", ".se", ".sg", ".sh", ".si", ".sj", ".sk", ".sl", ".sm", ".sn", ".so", ".sr", ".st", ".sv", ".sy", ".sz", ".tc", ".td", ".tf", ".tg", ".th", ".tj", ".tk", ".tl", ".tm", ".tn", ".to", ".tp", ".tr", ".tt", ".tv", ".tw", ".tz", ".ua", ".ug", ".uk", ".um", ".us", ".uy", ".uz", ".va", ".vc", ".ve", ".vg", ".vi", ".vn", ".vu", ".wf", ".ws", ".ye", ".yt", ".yu", ".yr", ".za", ".zm", ".zw"} domainSubfixList := []string{".com", ".edu", ".gov", ".int", ".mil", ".net", ".org", ".biz", ".info", ".pro", ".name", ".museum", ".coop", ".aero", ".xxx", ".idv", ".ac", ".ad", ".ae", ".af", ".ag", ".ai", ".al", ".am", ".an", ".ao", ".aq", ".ar", ".as", ".at", ".au", ".aw", ".az", ".ba", ".bb", ".bd", ".be", ".bf", ".bg", ".bh", ".bi", ".bj", ".bm", ".bn", ".bo", ".br", ".bs", ".bt", ".bv", ".bw", ".by", ".bz", ".ca", ".cc", ".cd", ".cf", ".cg", ".ch", ".ci", ".ck", ".cl", ".cm", ".cn", ".co", ".cr", ".cu", ".cv", ".cx", ".cy", ".cz", ".de", ".dj", ".dk", ".dm", ".do", ".dz", ".ec", ".ee", ".eg", ".eh", ".er", ".es", ".et", ".eu", ".fi", ".fj", ".fk", ".fm", ".fo", ".fr", ".ga", ".gd", ".ge", ".gf", ".gg", ".gh", ".gi", ".gl", ".gm", ".gn", ".gp", ".gq", ".gr", ".gs", ".gt", ".gu", ".gw", ".gy", ".hk", ".hm", ".hn", ".hr", ".ht", ".hu", ".id", ".ie", ".il", ".im", ".in", ".io", ".iq", ".ir", ".is", ".it", ".je", ".jm", ".jo", ".jp", ".ke", ".kg", ".kh", ".ki", ".km", ".kn", ".kp", ".kr", ".kw", ".ky", ".kz", ".la", ".lb", ".lc", ".li", ".lk", ".lr", ".ls", ".lt", ".lu", ".lv", ".ly", ".ma", ".mc", ".md", ".mg", ".mh", ".mk", ".ml", ".mm", ".mn", ".mo", ".mp", ".mq", ".mr", ".ms", ".mt", ".mu", ".mv", ".mw", ".mx", ".my", ".mz", ".na", ".nc", ".ne", ".nf", ".ng", ".ni", ".nl", ".no", ".np", ".nr", ".nu", ".nz", ".om", ".pa", ".pe", ".pf", ".pg", ".ph", ".pk", ".pl", ".pm", ".pn", ".pr", ".ps", ".pt", ".pw", ".py", ".qa", ".re", ".ro", ".ru", ".rw", ".sa", ".sb", ".sc", ".sd", ".se", ".sg", ".sh", ".si", ".sj", ".sk", ".sl", ".sm", ".sn", ".so", ".sr", ".st", ".sv", ".sy", ".sz", ".tc", ".td", ".tf", ".tg", ".th", ".tj", ".tk", ".tl", ".tm", ".tn", ".to", ".tp", ".tr", ".tt", ".tv", ".tw", ".tz", ".ua", ".ug", ".uk", ".um", ".us", ".uy", ".uz", ".va", ".vc", ".ve", ".vg", ".vi", ".vn", ".vu", ".wf", ".ws", ".ye", ".yt", ".yu", ".yr", ".za", ".zm", ".zw"}
C := CList[int(RandInt(4))%len(CList)] C := CList[int(RandInt(4))%len(CList)]
ST := RandString(int(RandInt(4) % 10)) ST := RandString(int(RandInt(4) % 10))
O := RandString(int(RandInt(4) % 10)) O := RandString(int(RandInt(4) % 10))
CN := strings.ToLower(RandString(int(RandInt(4)%10)) + domainSubfixList[int(RandInt(4))%len(domainSubfixList)]) CN := strings.ToLower(RandString(int(RandInt(4)%10)) + domainSubfixList[int(RandInt(4))%len(domainSubfixList)])
cmdStr := fmt.Sprintf("openssl req -new -key proxy.key -x509 -days 36500 -out proxy.crt -subj /C=%s/ST=%s/O=%s/CN=%s", C, ST, O, CN) //log.Printf("C: %s, ST: %s, O: %s, CN: %s", C, ST, O, CN)
cmd = exec.Command("sh", "-c", cmdStr) var out []byte
out, err = cmd.CombinedOutput() if len(os.Args) == 3 && os.Args[2] == "ca" {
if err != nil { cmd := exec.Command("sh", "-c", "openssl genrsa -out ca.key 2048")
log.Printf("err:%s", err) out, err = cmd.CombinedOutput()
return if err != nil {
log.Printf("err:%s", err)
return
}
fmt.Println(string(out))
cmdStr := fmt.Sprintf("openssl req -new -key ca.key -x509 -days 36500 -out ca.crt -subj /C=%s/ST=%s/O=%s/CN=%s", C, ST, O, "*."+CN)
cmd = exec.Command("sh", "-c", cmdStr)
out, err = cmd.CombinedOutput()
if err != nil {
log.Printf("err:%s", err)
return
}
fmt.Println(string(out))
} else if len(os.Args) == 5 && os.Args[2] == "ca" && os.Args[3] != "" && os.Args[4] != "" {
certBytes, _ := ioutil.ReadFile("ca.crt")
block, _ := pem.Decode(certBytes)
if block == nil || certBytes == nil {
panic("failed to parse ca certificate PEM")
}
x509Cert, _ := x509.ParseCertificate(block.Bytes)
if x509Cert == nil {
panic("failed to parse block")
}
name := os.Args[3]
days := os.Args[4]
cmd := exec.Command("sh", "-c", "openssl genrsa -out "+name+".key 2048")
out, err = cmd.CombinedOutput()
if err != nil {
log.Printf("err:%s", err)
return
}
fmt.Println(string(out))
cmdStr := fmt.Sprintf("openssl req -new -key %s.key -out %s.csr -subj /C=%s/ST=%s/O=%s/CN=%s", name, name, C, ST, O, CN)
fmt.Printf("%s", cmdStr)
cmd = exec.Command("sh", "-c", cmdStr)
out, err = cmd.CombinedOutput()
if err != nil {
log.Printf("err:%s", err)
return
}
fmt.Println(string(out))
cmdStr = fmt.Sprintf("openssl x509 -req -days %s -in %s.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out %s.crt", days, name, name)
fmt.Printf("%s", cmdStr)
cmd = exec.Command("sh", "-c", cmdStr)
out, err = cmd.CombinedOutput()
if err != nil {
log.Printf("err:%s", err)
return
}
fmt.Println(string(out))
} else if len(os.Args) == 3 && os.Args[2] == "usage" {
fmt.Println(`proxy keygen //generate proxy.crt and proxy.key
proxy keygen ca //generate ca.crt and ca.key
proxy keygen ca client0 30 //generate client0.crt client0.key and use ca.crt sign it with 30 days
`)
} else if len(os.Args) == 2 {
cmd := exec.Command("sh", "-c", "openssl genrsa -out proxy.key 2048")
out, err = cmd.CombinedOutput()
if err != nil {
log.Printf("err:%s", err)
return
}
fmt.Println(string(out))
cmdStr := fmt.Sprintf("openssl req -new -key proxy.key -x509 -days 36500 -out proxy.crt -subj /C=%s/ST=%s/O=%s/CN=%s", C, ST, O, CN)
cmd = exec.Command("sh", "-c", cmdStr)
out, err = cmd.CombinedOutput()
if err != nil {
log.Printf("err:%s", err)
return
}
fmt.Println(string(out))
} }
fmt.Println(string(out))
return return
} }
func GetAllInterfaceAddr() ([]net.IP, error) { func GetAllInterfaceAddr() ([]net.IP, error) {

View File

@ -42,8 +42,8 @@ func NewServerChannelHost(host string) ServerChannel {
func (sc *ServerChannel) SetErrAcceptHandler(fn func(err error)) { func (sc *ServerChannel) SetErrAcceptHandler(fn func(err error)) {
sc.errAcceptHandler = fn sc.errAcceptHandler = fn
} }
func (sc *ServerChannel) ListenTls(certBytes, keyBytes []byte, fn func(conn net.Conn)) (err error) { func (sc *ServerChannel) ListenTls(certBytes, keyBytes, caCertBytes []byte, fn func(conn net.Conn)) (err error) {
sc.Listener, err = ListenTls(sc.ip, sc.port, certBytes, keyBytes) sc.Listener, err = ListenTls(sc.ip, sc.port, certBytes, keyBytes, caCertBytes)
if err == nil { if err == nil {
go func() { go func() {
defer func() { defer func() {
@ -142,15 +142,19 @@ func (sc *ServerChannel) ListenUDP(fn func(packet []byte, localAddr, srcAddr *ne
func (sc *ServerChannel) ListenKCP(config kcpcfg.KCPConfigArgs, fn func(conn net.Conn)) (err error) { func (sc *ServerChannel) ListenKCP(config kcpcfg.KCPConfigArgs, fn func(conn net.Conn)) (err error) {
lis, err := kcp.ListenWithOptions(fmt.Sprintf("%s:%d", sc.ip, sc.port), config.Block, *config.DataShard, *config.ParityShard) lis, err := kcp.ListenWithOptions(fmt.Sprintf("%s:%d", sc.ip, sc.port), config.Block, *config.DataShard, *config.ParityShard)
if err == nil { if err == nil {
if err := lis.SetDSCP(*config.DSCP); err != nil { if err = lis.SetDSCP(*config.DSCP); err != nil {
log.Println("SetDSCP:", err) log.Println("SetDSCP:", err)
return
} }
if err := lis.SetReadBuffer(*config.SockBuf); err != nil { if err = lis.SetReadBuffer(*config.SockBuf); err != nil {
log.Println("SetReadBuffer:", err) log.Println("SetReadBuffer:", err)
return
} }
if err := lis.SetWriteBuffer(*config.SockBuf); err != nil { if err = lis.SetWriteBuffer(*config.SockBuf); err != nil {
log.Println("SetWriteBuffer:", err) log.Println("SetWriteBuffer:", err)
return
} }
sc.Listener = new(net.Listener)
*sc.Listener = lis *sc.Listener = lis
go func() { go func() {
defer func() { defer func() {

View File

@ -491,25 +491,27 @@ func (req *HTTPRequest) addPortIfNot() (newHost string) {
} }
type OutPool struct { type OutPool struct {
Pool ConnPool Pool ConnPool
dur int dur int
typ string typ string
certBytes []byte certBytes []byte
keyBytes []byte keyBytes []byte
kcp kcpcfg.KCPConfigArgs caCertBytes []byte
address string kcp kcpcfg.KCPConfigArgs
timeout int address string
timeout int
} }
func NewOutPool(dur int, typ string, kcp kcpcfg.KCPConfigArgs, certBytes, keyBytes []byte, address string, timeout int, InitialCap int, MaxCap int) (op OutPool) { func NewOutPool(dur int, typ string, kcp kcpcfg.KCPConfigArgs, certBytes, keyBytes, caCertBytes []byte, address string, timeout int, InitialCap int, MaxCap int) (op OutPool) {
op = OutPool{ op = OutPool{
dur: dur, dur: dur,
typ: typ, typ: typ,
certBytes: certBytes, certBytes: certBytes,
keyBytes: keyBytes, keyBytes: keyBytes,
kcp: kcp, caCertBytes: caCertBytes,
address: address, kcp: kcp,
timeout: timeout, address: address,
timeout: timeout,
} }
var err error var err error
op.Pool, err = NewConnPool(poolConfig{ op.Pool, err = NewConnPool(poolConfig{
@ -543,7 +545,7 @@ func NewOutPool(dur int, typ string, kcp kcpcfg.KCPConfigArgs, certBytes, keyByt
func (op *OutPool) getConn() (conn interface{}, err error) { func (op *OutPool) getConn() (conn interface{}, err error) {
if op.typ == "tls" { if op.typ == "tls" {
var _conn tls.Conn var _conn tls.Conn
_conn, err = TlsConnectHost(op.address, op.timeout, op.certBytes, op.keyBytes) _conn, err = TlsConnectHost(op.address, op.timeout, op.certBytes, op.keyBytes, op.caCertBytes)
if err == nil { if err == nil {
conn = net.Conn(&_conn) conn = net.Conn(&_conn)
} }