Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8bafb88bc4 | ||
|
|
dc82b94c6b | ||
|
|
cf6043b0de | ||
|
|
ce1095d6de | ||
|
|
9f08170cd3 | ||
|
|
5c66f5f5d2 | ||
|
|
1a9c3244a3 | ||
|
|
00688bbf33 | ||
|
|
787cc56ed4 | ||
|
|
3984083e23 | ||
|
|
a91790b16d | ||
|
|
b2549e8d48 | ||
|
|
768e5dd6c0 | ||
|
|
7899f1ec00 | ||
|
|
ef93946fb1 | ||
|
|
675061fd63 | ||
|
|
4b212eee0d |
@ -1,4 +1,11 @@
|
||||
proxy更新日志
|
||||
v3.2
|
||||
1.内网穿透功能server端-r参数增加了协议和key设置.
|
||||
2.手册增加了对-r参数的详细说明.
|
||||
3.修复了普通模式也检查证书文件的bug.
|
||||
4.增加了Socks5支持,目前只支持TCP协议,不支持UDP协议.
|
||||
5.Socks5上级代理支持ssh中转,linux服务器不需要任何服务端,本地一个proxy即可开心上网.
|
||||
6.http(s)代理增加了ssh中转支持,linux服务器不需要任何服务端,本地一个proxy即可开心上网.
|
||||
|
||||
v3.1
|
||||
1.优化了内网穿透功能,bridge,client和server只需要启动一个即可。
|
||||
|
||||
119
README.md
@ -11,8 +11,9 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp代理服务器,支
|
||||
- 智能HTTP代理,会自动判断访问的网站是否屏蔽,如果被屏蔽那么就会使用上级代理(前提是配置了上级代理)访问网站;如果访问的网站没有被屏蔽,为了加速访问,代理会直接访问网站,不使用上级代理.
|
||||
- 域名黑白名单,更加自由的控制网站的访问方式。
|
||||
- 跨平台性,无论你是widows,linux,还是mac,甚至是树莓派,都可以很好的运行proxy.
|
||||
- 多协议支持,支持HTTP,TCP,UDP,Websocket代理.
|
||||
- 多协议支持,支持HTTP(S),TCP,UDP,Websocket,SOCKS5代理.
|
||||
- 支持内网穿透,协议支持TCP和UDP.
|
||||
- HTTP(S),SOCKS5代理支持SSH中转,上级Linux服务器不需要任何服务端,本地一个proxy即可开心上网.
|
||||
|
||||
### Why need these?
|
||||
- 当由于安全因素或者限制,我们不能顺畅的访问我们在其它地方的服务,我们可以通过多个相连的proxy节点建立起一个安全的隧道,顺畅的访问我们的服务.
|
||||
@ -24,7 +25,8 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp代理服务器,支
|
||||
- ...
|
||||
|
||||
### 手册目录
|
||||
本页是最新v3.1手册,其他版本手册请点击下面链接查看.
|
||||
本页是最新v3.2手册,其他版本手册请点击下面链接查看.
|
||||
- [v3.1手册](https://github.com/snail007/goproxy/tree/v3.1)
|
||||
- [v3.0手册](https://github.com/snail007/goproxy/tree/v3.0)
|
||||
- [v2.x手册](https://github.com/snail007/goproxy/tree/v2.2)
|
||||
|
||||
@ -50,7 +52,7 @@ wget https://github.com/reddec/monexec/releases/download/v0.1.1/monexec_0.1.1_li
|
||||
下载地址:https://github.com/snail007/goproxy/releases
|
||||
```shell
|
||||
cd /root/proxy/
|
||||
wget https://github.com/snail007/goproxy/releases/download/v3.1/proxy-linux-amd64.tar.gz
|
||||
wget https://github.com/snail007/goproxy/releases/download/v3.1fix/proxy-linux-amd64.tar.gz
|
||||
```
|
||||
**3.下载自动安装脚本**
|
||||
```shell
|
||||
@ -91,8 +93,9 @@ http,tcp,udp代理过程会和上级通讯,为了安全我们采用加密通讯,
|
||||
**1.2.普通二级HTTP代理**
|
||||
使用本地端口8090,假设上级HTTP代理是`22.22.22.22:8080`
|
||||
`./proxy http -t tcp -p "0.0.0.0:8090" -T tcp -P "22.22.22.22:8080" `
|
||||
默认开启了连接池,如果为了网络情况很好,-L可以关闭连接池,0就是连接池大小,0为关闭.
|
||||
`./proxy http -t tcp -p "0.0.0.0:8090" -T tcp -P "22.22.22.22:8080" -L 0`
|
||||
默认关闭了连接池,如果要加快访问速度,-L可以开启连接池,10就是连接池大小,0为关闭,
|
||||
开启连接池在网络不好的情况下,稳定不是很好.
|
||||
`./proxy http -t tcp -p "0.0.0.0:8090" -T tcp -P "22.22.22.22:8080" -L 10`
|
||||
我们还可以指定网站域名的黑白名单文件,一行一个域名,怕匹配规则是最右批评匹配,比如:baidu.com,匹配的是*.*.baidu.com,黑名单的域名域名直接走上级代理,白名单的域名不走上级代理.
|
||||
`./proxy http -p "0.0.0.0:8090" -T tcp -P "22.22.22.22:8080" -b blocked.txt -d direct.txt`
|
||||
|
||||
@ -129,7 +132,20 @@ http,tcp,udp代理过程会和上级通讯,为了安全我们采用加密通讯,
|
||||
默认情况下,proxy会智能判断一个网站域名是否无法访问,如果无法访问才走上级HTTP代理.通过--always可以使全部HTTP代理流量强制走上级HTTP代理.
|
||||
`./proxy http --always -t tls -p ":28080" -T tls -P "22.22.22.22:38080" -C proxy.crt -K proxy.key`
|
||||
|
||||
**1.7.查看帮助**
|
||||
**1.7.HTTP(S)通过SSH中转**
|
||||
说明:ssh中转的原理是利用了ssh的转发功能,就是你连接上ssh之后,可以通过ssh代理访问目标地址.
|
||||
假设有:vps
|
||||
- IP是2.2.2.2, ssh端口是22, ssh用户名是:user, ssh用户密码是:demo
|
||||
- 用户user的ssh私钥名称是user.key
|
||||
|
||||
***1.7.1 ssh用户名和密码的方式***
|
||||
本地HTTP(S)代理28080端口,执行:
|
||||
`./proxy http -T ssh -P "2.2.2.2:22" -u user -A demo -t tcp -p ":28080"`
|
||||
***1.7.2 ssh用户名和密钥的方式***
|
||||
本地HTTP(S)代理28080端口,执行:
|
||||
`./proxy http -T ssh -P "2.2.2.2:22" -u user -S user.key -t tcp -p ":28080"`
|
||||
|
||||
**1.8.查看帮助**
|
||||
`./proxy help http`
|
||||
|
||||
|
||||
@ -242,7 +258,7 @@ VPS(IP:22.22.22.33)执行:
|
||||
`./proxy tserver -r ":28080@:80" -P "127.0.0.1:33080" -C proxy.crt -K proxy.key`
|
||||
|
||||
1. 在公司机器A上面执行
|
||||
`./proxy tclient -C proxy.crt -K proxy.key`
|
||||
`./proxy tclient -P "22.22.22.22:33080" -C proxy.crt -K proxy.key`
|
||||
|
||||
1. 完成
|
||||
|
||||
@ -261,10 +277,10 @@ VPS(IP:22.22.22.33)执行:
|
||||
步骤:
|
||||
1. 在vps上执行,确保vps的80端口没被其它程序占用.
|
||||
`./proxy tbridge -p ":33080" -C proxy.crt -K proxy.key`
|
||||
`./proxy tserver -r ":80@:80" -P ":33080" -C proxy.crt -K proxy.key`
|
||||
`./proxy tserver -r ":80@:80" -P "22.22.22.22:33080" -C proxy.crt -K proxy.key`
|
||||
|
||||
1. 在自己笔记本上面执行
|
||||
`./proxy tclient -C proxy.crt -K proxy.key`
|
||||
`./proxy tclient -P "22.22.22.22:33080" -C proxy.crt -K proxy.key`
|
||||
|
||||
1. 完成
|
||||
|
||||
@ -309,10 +325,10 @@ VPS(IP:22.22.22.33)执行:
|
||||
|
||||
**4.6、高级用法二**
|
||||
提示:
|
||||
如果同时有多个client连接到同一个bridge,需要指定不同的key,可以通过--k参数设定,--k可以是任意唯一字符串,
|
||||
如果同时有多个client连接到同一个bridge,需要指定不同的key,可以通过--k参数设定,--k可以是任意唯一字符串,
|
||||
只要在同一个bridge上唯一即可.
|
||||
server连接到bridge的时候,如果同时有多个client连接到同一个bridge,需要使用--k参数选择client.
|
||||
暴露多个端口重复-r参数即可.-r格式是:"本地IP:本地端口@clientHOST:client端口"
|
||||
server连接到bridge的时候,如果同时有多个client连接到同一个bridge,需要使用--k参数选择client.
|
||||
暴露多个端口重复-r参数即可.-r格式是:"本地IP:本地端口@clientHOST:client端口".
|
||||
|
||||
背景:
|
||||
- 公司机器A提供了web服务80端口,ftp服务21端口
|
||||
@ -332,14 +348,89 @@ server连接到bridge的时候,如果同时有多个client连接到同一个brid
|
||||
|
||||
1. 完成
|
||||
|
||||
**4.7.查看帮助**
|
||||
**4.7.tserver的-r参数**
|
||||
-r完整格式是:`PROTOCOL://LOCAL_IP:LOCAL_PORT@[CLIENT_KEY]CLIENT_LOCAL_HOST:CLIENT_LOCAL_PORT`
|
||||
|
||||
4.7.1.协议PROTOCOL:tcp或者udp.
|
||||
比如: `-r "udp://:10053@:53" -r "tcp://:10800@:1080" -r ":8080@:80"`
|
||||
如果指定了--udp参数,PROTOCOL默认为udp,那么:`-r ":8080@:80"`默认为udp;
|
||||
如果没有指定--udp参数,PROTOCOL默认为tcp,那么:`-r ":8080@:80"`默认为tcp;
|
||||
|
||||
4.7.2.CLIENT_KEY:默认是default.
|
||||
比如: -r "udp://:10053@[test1]:53" -r "tcp://:10800@[test2]:1080" -r ":8080@:80"
|
||||
如果指定了--k参数,比如--k test,那么:`-r ":8080@:80"`CLIENT_KEY默认为test;
|
||||
如果没有指定--k参数,那么:`-r ":8080@:80"`CLIENT_KEY默认为default;
|
||||
|
||||
4.7.3.LOCAL_IP为空默认是:`0.0.0.0`,CLIENT_LOCAL_HOST为空默认是:`127.0.0.1`;
|
||||
|
||||
**4.8.查看帮助**
|
||||
`./proxy help tbridge`
|
||||
`./proxy help tserver`
|
||||
`./proxy help tserver`
|
||||
|
||||
### 5.SOCKS5代理
|
||||
提示:SOCKS5代理,只支持TCP协议,不支持UDP协议,不支持用户名密码认证.
|
||||
**5.1.普通SOCKS5代理**
|
||||
`./proxy socks -t tcp -p "0.0.0.0:38080"`
|
||||
|
||||
**5.2.普通二级SOCKS5代理**
|
||||
使用本地端口8090,假设上级SOCKS5代理是`22.22.22.22:8080`
|
||||
`./proxy socks -t tcp -p "0.0.0.0:8090" -T tcp -P "22.22.22.22:8080" `
|
||||
我们还可以指定网站域名的黑白名单文件,一行一个域名,怕匹配规则是最右批评匹配,比如:baidu.com,匹配的是*.*.baidu.com,黑名单的域名域名直接走上级代理,白名单的域名不走上级代理.
|
||||
`./proxy socks -p "0.0.0.0:8090" -T tcp -P "22.22.22.22:8080" -b blocked.txt -d direct.txt`
|
||||
|
||||
**5.3.SOCKS二级代理(加密)**
|
||||
一级SOCKS代理(VPS,IP:22.22.22.22)
|
||||
`./proxy socks -t tls -p ":38080" -C proxy.crt -K proxy.key`
|
||||
|
||||
二级SOCKS代理(本地Linux)
|
||||
`./proxy socks -t tcp -p ":8080" -T tls -P "22.22.22.22:38080" -C proxy.crt -K proxy.key`
|
||||
那么访问本地的8080端口就是访问VPS上面的代理端口38080.
|
||||
|
||||
二级SOCKS代理(本地windows)
|
||||
`./proxy.exe socks -t tcp -p ":8080" -T tls -P "22.22.22.22:38080" -C proxy.crt -K proxy.key`
|
||||
然后设置你的windos系统中,需要通过代理上网的程序的代理为socks5模式,地址为:127.0.0.1,端口为:8080,程序即可通过加密通道通过vps上网。
|
||||
|
||||
**5.4.SOCKS三级代理(加密)**
|
||||
一级SOCKS代理VPS_01,IP:22.22.22.22
|
||||
`./proxy socks -t tls -p ":38080" -C proxy.crt -K proxy.key`
|
||||
二级SOCKS代理VPS_02,IP:33.33.33.33
|
||||
`./proxy socks -t tls -p ":28080" -T tls -P "22.22.22.22:38080" -C proxy.crt -K proxy.key`
|
||||
三级SOCKS代理(本地)
|
||||
`./proxy socks -t tcp -p ":8080" -T tls -P "33.33.33.33:28080" -C proxy.crt -K proxy.key`
|
||||
那么访问本地的8080端口就是访问一级SOCKS代理上面的代理端口38080.
|
||||
|
||||
**5.5.SOCKS代理流量强制走上级SOCKS代理**
|
||||
默认情况下,proxy会智能判断一个网站域名是否无法访问,如果无法访问才走上级SOCKS代理.通过--always可以使全部SOCKS代理流量强制走上级SOCKS代理.
|
||||
`./proxy socks --always -t tls -p ":28080" -T tls -P "22.22.22.22:38080" -C proxy.crt -K proxy.key`
|
||||
|
||||
**5.6.SOCKS通过SSH中转**
|
||||
说明:ssh中转的原理是利用了ssh的转发功能,就是你连接上ssh之后,可以通过ssh代理访问目标地址.
|
||||
假设有:vps
|
||||
- IP是2.2.2.2, ssh端口是22, ssh用户名是:user, ssh用户密码是:demo
|
||||
- 用户user的ssh私钥名称是user.key
|
||||
|
||||
***5.6.1 ssh用户名和密码的方式***
|
||||
本地SOCKS5代理28080端口,执行:
|
||||
`./proxy socks -T ssh -P "2.2.2.2:22" -u user -A demo -t tcp -p ":28080"`
|
||||
***5.6.2 ssh用户名和密钥的方式***
|
||||
本地SOCKS5代理28080端口,执行:
|
||||
`./proxy socks -T ssh -P "2.2.2.2:22" -u user -S user.key -t tcp -p ":28080"`
|
||||
|
||||
那么访问本地的28080端口就是通过VPS访问目标地址.
|
||||
|
||||
**5.7.查看帮助**
|
||||
`./proxy help socks`
|
||||
|
||||
### TODO
|
||||
- socks5代理支持.
|
||||
- SOCKS5增加用户名密码认证
|
||||
|
||||
### 如何使用源码?
|
||||
cd进入你的go src目录,然后git clone https://github.com/snail007/goproxy.git ./proxy 即可.
|
||||
编译直接:go build
|
||||
运行: go run *.go
|
||||
utils是工具包,service是具体的每个服务类.
|
||||
|
||||
### License
|
||||
Proxy is licensed under GPLv3 license.
|
||||
### Contact
|
||||
|
||||
82
config.go
@ -2,7 +2,6 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"proxy/services"
|
||||
@ -24,7 +23,7 @@ func initConfig() (err error) {
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
args := services.Args{}
|
||||
|
||||
//define args
|
||||
tcpArgs := services.TCPArgs{}
|
||||
httpArgs := services.HTTPArgs{}
|
||||
@ -32,18 +31,18 @@ func initConfig() (err error) {
|
||||
tunnelClientArgs := services.TunnelClientArgs{}
|
||||
tunnelBridgeArgs := services.TunnelBridgeArgs{}
|
||||
udpArgs := services.UDPArgs{}
|
||||
|
||||
socksArgs := services.SocksArgs{}
|
||||
//build srvice args
|
||||
app = kingpin.New("proxy", "happy with proxy")
|
||||
app.Author("snail").Version(APP_VERSION)
|
||||
args.Parent = app.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').String()
|
||||
certTLS := app.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
|
||||
keyTLS := app.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
|
||||
|
||||
//########http#########
|
||||
http := app.Command("http", "proxy on http mode")
|
||||
httpArgs.LocalType = http.Flag("local-type", "parent protocol type <tls|tcp>").Default("tcp").Short('t').Enum("tls", "tcp")
|
||||
httpArgs.ParentType = http.Flag("parent-type", "parent protocol type <tls|tcp>").Short('T').Enum("tls", "tcp")
|
||||
httpArgs.Parent = http.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').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.LocalType = http.Flag("local-type", "local protocol type <tls|tcp>").Default("tcp").Short('t').Enum("tls", "tcp")
|
||||
httpArgs.ParentType = http.Flag("parent-type", "parent protocol type <tls|tcp|ssh>").Short('T').Enum("tls", "tcp", "ssh")
|
||||
httpArgs.Always = http.Flag("always", "always use parent proxy").Default("false").Bool()
|
||||
httpArgs.Timeout = http.Flag("timeout", "tcp timeout milliseconds when connect to real server or parent proxy").Default("2000").Int()
|
||||
httpArgs.HTTPTimeout = http.Flag("http-timeout", "check domain if blocked , http request timeout milliseconds when connect to host").Default("3000").Int()
|
||||
@ -55,9 +54,16 @@ func initConfig() (err error) {
|
||||
httpArgs.PoolSize = http.Flag("pool-size", "conn pool size , which connect to parent proxy, zero: means turn off pool").Short('L').Default("0").Int()
|
||||
httpArgs.CheckParentInterval = http.Flag("check-parent-interval", "check if proxy is okay every interval seconds,zero: means no check").Short('I').Default("3").Int()
|
||||
httpArgs.Local = http.Flag("local", "local ip:port to listen").Short('p').Default(":33080").String()
|
||||
httpArgs.SSHUser = http.Flag("ssh-user", "user for ssh").Short('u').Default("").String()
|
||||
httpArgs.SSHKeyFile = http.Flag("ssh-key", "private key file for ssh").Short('S').Default("").String()
|
||||
httpArgs.SSHKeyFileSalt = http.Flag("ssh-keysalt", "salt of ssh private key").Short('s').Default("").String()
|
||||
httpArgs.SSHPassword = http.Flag("ssh-password", "password for ssh").Short('A').Default("").String()
|
||||
|
||||
//########tcp#########
|
||||
tcp := app.Command("tcp", "proxy on tcp mode")
|
||||
tcpArgs.Parent = tcp.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').String()
|
||||
tcpArgs.CertFile = tcp.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
|
||||
tcpArgs.KeyFile = tcp.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
|
||||
tcpArgs.Timeout = tcp.Flag("timeout", "tcp timeout milliseconds when connect to real server or parent proxy").Short('t').Default("2000").Int()
|
||||
tcpArgs.ParentType = tcp.Flag("parent-type", "parent protocol type <tls|tcp|udp>").Short('T').Enum("tls", "tcp", "udp")
|
||||
tcpArgs.IsTLS = tcp.Flag("tls", "proxy on tls mode").Default("false").Bool()
|
||||
@ -67,6 +73,9 @@ func initConfig() (err error) {
|
||||
|
||||
//########udp#########
|
||||
udp := app.Command("udp", "proxy on udp mode")
|
||||
udpArgs.Parent = udp.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').String()
|
||||
udpArgs.CertFile = udp.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
|
||||
udpArgs.KeyFile = udp.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
|
||||
udpArgs.Timeout = udp.Flag("timeout", "tcp timeout milliseconds when connect to parent proxy").Short('t').Default("2000").Int()
|
||||
udpArgs.ParentType = udp.Flag("parent-type", "parent protocol type <tls|tcp|udp>").Short('T').Enum("tls", "tcp", "udp")
|
||||
udpArgs.PoolSize = udp.Flag("pool-size", "conn pool size , which connect to parent proxy, zero: means turn off pool").Short('L').Default("0").Int()
|
||||
@ -75,36 +84,49 @@ func initConfig() (err error) {
|
||||
|
||||
//########tunnel-server#########
|
||||
tunnelServer := app.Command("tserver", "proxy on tunnel server mode")
|
||||
tunnelServerArgs.Parent = tunnelServer.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').String()
|
||||
tunnelServerArgs.CertFile = tunnelServer.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
|
||||
tunnelServerArgs.KeyFile = tunnelServer.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
|
||||
tunnelServerArgs.Timeout = tunnelServer.Flag("timeout", "tcp timeout with milliseconds").Short('t').Default("2000").Int()
|
||||
tunnelServerArgs.IsUDP = tunnelServer.Flag("udp", "proxy on udp tunnel server mode").Default("false").Bool()
|
||||
tunnelServerArgs.Key = tunnelServer.Flag("k", "client key").Default("default").String()
|
||||
//tunnelServerArgs.Remote = tunnelServer.Flag("remote", "client's network host:port").Short('R').Default("").String()
|
||||
//tunnelServerArgs.Local = tunnelServer.Flag("local", "local ip:port to listen").Short('p').Default(":33080").String()
|
||||
tunnelServerArgs.Route = tunnelServer.Flag("route", "local route to client's network, such as :localip:localport@clienthost:clientport").Short('r').Default("").Strings()
|
||||
tunnelServerArgs.Route = tunnelServer.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()
|
||||
|
||||
//########tunnel-client#########
|
||||
tunnelClient := app.Command("tclient", "proxy on tunnel client mode")
|
||||
tunnelClientArgs.Parent = tunnelClient.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').String()
|
||||
tunnelClientArgs.CertFile = tunnelClient.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
|
||||
tunnelClientArgs.KeyFile = tunnelClient.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
|
||||
tunnelClientArgs.Timeout = tunnelClient.Flag("timeout", "tcp timeout with milliseconds").Short('t').Default("2000").Int()
|
||||
tunnelClientArgs.Key = tunnelClient.Flag("k", "key same with server").Default("default").String()
|
||||
|
||||
//########tunnel-bridge#########
|
||||
tunnelBridge := app.Command("tbridge", "proxy on tunnel bridge mode")
|
||||
tunnelBridgeArgs.CertFile = tunnelBridge.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
|
||||
tunnelBridgeArgs.KeyFile = tunnelBridge.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
|
||||
tunnelBridgeArgs.Timeout = tunnelBridge.Flag("timeout", "tcp timeout with milliseconds").Short('t').Default("2000").Int()
|
||||
tunnelBridgeArgs.Local = tunnelBridge.Flag("local", "local ip:port to listen").Short('p').Default(":33080").String()
|
||||
|
||||
//########ssh#########
|
||||
socks := app.Command("socks", "proxy on ssh mode")
|
||||
socksArgs.Parent = socks.Flag("parent", "parent ssh address, such as: \"23.32.32.19:22\"").Default("").Short('P').String()
|
||||
socksArgs.ParentType = socks.Flag("parent-type", "parent protocol type <tls|tcp|ssh>").Default("tcp").Short('T').Enum("tls", "tcp", "ssh")
|
||||
socksArgs.LocalType = socks.Flag("local-type", "local protocol type <tls|tcp>").Default("tcp").Short('t').Enum("tls", "tcp")
|
||||
socksArgs.Local = socks.Flag("local", "local ip:port to listen").Short('p').Default(":33080").String()
|
||||
socksArgs.CertFile = socks.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").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.SSHKeyFile = socks.Flag("ssh-key", "private key file for ssh").Short('S').Default("").String()
|
||||
socksArgs.SSHKeyFileSalt = socks.Flag("ssh-keysalt", "salt of ssh private key").Short('s').Default("").String()
|
||||
socksArgs.SSHPassword = socks.Flag("ssh-password", "password for ssh").Short('A').Default("").String()
|
||||
socksArgs.Always = socks.Flag("always", "always use parent proxy").Default("false").Bool()
|
||||
socksArgs.Timeout = socks.Flag("timeout", "tcp timeout milliseconds when connect to real server or parent proxy").Default("5000").Int()
|
||||
socksArgs.Interval = socks.Flag("interval", "check domain if blocked every interval seconds").Default("10").Int()
|
||||
socksArgs.Blocked = socks.Flag("blocked", "blocked domain file , one domain each line").Default("blocked").Short('b').String()
|
||||
socksArgs.Direct = socks.Flag("direct", "direct domain file , one domain each line").Default("direct").Short('d').String()
|
||||
//parse args
|
||||
serviceName := kingpin.MustParse(app.Parse(os.Args[1:]))
|
||||
|
||||
if *certTLS != "" && *keyTLS != "" {
|
||||
args.CertBytes, args.KeyBytes = tlsBytes(*certTLS, *keyTLS)
|
||||
}
|
||||
|
||||
//common args
|
||||
httpArgs.Args = args
|
||||
tcpArgs.Args = args
|
||||
udpArgs.Args = args
|
||||
tunnelBridgeArgs.Args = args
|
||||
tunnelClientArgs.Args = args
|
||||
tunnelServerArgs.Args = args
|
||||
poster()
|
||||
//regist services and run service
|
||||
services.Regist("http", services.NewHTTP(), httpArgs)
|
||||
@ -113,9 +135,10 @@ func initConfig() (err error) {
|
||||
services.Regist("tserver", services.NewTunnelServerManager(), tunnelServerArgs)
|
||||
services.Regist("tclient", services.NewTunnelClient(), tunnelClientArgs)
|
||||
services.Regist("tbridge", services.NewTunnelBridge(), tunnelBridgeArgs)
|
||||
services.Regist("socks", services.NewSocks(), socksArgs)
|
||||
service, err = services.Run(serviceName)
|
||||
if err != nil {
|
||||
log.Fatalf("run service [%s] fail, ERR:%s", service, err)
|
||||
log.Fatalf("run service [%s] fail, ERR:%s", serviceName, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -132,16 +155,3 @@ func poster() {
|
||||
|
||||
v%s`+" by snail , blog : http://www.host900.com/\n\n", APP_VERSION)
|
||||
}
|
||||
func tlsBytes(cert, key string) (certBytes, keyBytes []byte) {
|
||||
certBytes, err := ioutil.ReadFile(cert)
|
||||
if err != nil {
|
||||
log.Fatalf("err : %s", err)
|
||||
return
|
||||
}
|
||||
keyBytes, err = ioutil.ReadFile(key)
|
||||
if err != nil {
|
||||
log.Fatalf("err : %s", err)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -1,40 +0,0 @@
|
||||
这里以vps centos 64位为例子
|
||||
Linux 部分
|
||||
1.Putty工具(或其他工具)
|
||||
root登入
|
||||
2.下载批量命令文件install_auto.sh(64位的话直接执行这个命令即可)
|
||||
#curl -L https://raw.githubusercontent.com/snail007/goproxy/master/install_auto.sh | bash
|
||||
注意
|
||||
这里的install_auto.sh 源码可以下载修改proxy版本,保存后执行.
|
||||
<img src="https://github.com/snail007/goproxy/blob/master/docs/images/image001.png?raw=true"/>
|
||||
3.修改/etc/proxy/proxy.toml配置文件
|
||||
<img src="https://github.com/snail007/goproxy/blob/master/docs/images/image002.png?raw=true"/>
|
||||
<img src="https://github.com/snail007/goproxy/blob/master/docs/images/image003.png?raw=true"/>
|
||||
<img src="https://github.com/snail007/goproxy/blob/master/docs/images/image004.png?raw=true"/>
|
||||
#/usr/bin/proxyd status
|
||||
如果未运行那么执行调试命令:/usr/bin/proxy
|
||||
如果一切正常,可以使用proxyd命令管理proxy,执行 proxyd 可以查看用法.
|
||||
后台启动proxy: proxyd start
|
||||
4.下载证书加密文件/etc/proxy/proxy.crt和/etc/proxy/proxy.key到windows
|
||||
Windows部分
|
||||
5.https://github.com/snail007/goproxy/releases 下载对应windows版本
|
||||
<img src="https://github.com/snail007/goproxy/blob/master/docs/images/image005.jpg?raw=true"/>
|
||||
<img src="https://github.com/snail007/goproxy/blob/master/docs/images/image006.png?raw=true"/>
|
||||
我的是d:盘
|
||||
6.修改windows下的proxy.toml vps服务ip和上面设置的端口哦
|
||||
<img src="https://github.com/snail007/goproxy/blob/master/docs/images/image007.png?raw=true"/>
|
||||
然后运行proxy.exe即可.
|
||||
这时候浏览器代理服务器就是127.0.0.1:9501啦,完毕!
|
||||
|
||||
要隐藏windows命令用工具下载RunHiddenConsole.exe 写个bat文件都放proxy目录下就行
|
||||
Start.bat
|
||||
|
||||
@echo off
|
||||
echo Starting
|
||||
RunHiddenConsole D:/proxy/proxy.exe
|
||||
|
||||
Stop.bat
|
||||
@echo off
|
||||
echo Stopping
|
||||
taskkill /F /IM proxy.exe > nul
|
||||
exit
|
||||
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 11 KiB |
@ -6,7 +6,7 @@ fi
|
||||
mkdir /tmp/proxy
|
||||
cd /tmp/proxy
|
||||
wget https://github.com/reddec/monexec/releases/download/v0.1.1/monexec_0.1.1_linux_amd64.tar.gz
|
||||
wget https://github.com/snail007/goproxy/releases/download/v3.1/proxy-linux-amd64.tar.gz
|
||||
wget https://github.com/snail007/goproxy/releases/download/v3.1fix/proxy-linux-amd64.tar.gz
|
||||
|
||||
# install monexec
|
||||
tar zxvf monexec_0.1.1_linux_amd64.tar.gz
|
||||
|
||||
2
main.go
@ -9,7 +9,7 @@ import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
const APP_VERSION = "3.0"
|
||||
const APP_VERSION = "3.2"
|
||||
|
||||
func main() {
|
||||
err := initConfig()
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#!/bin/bash
|
||||
VER="3.1"
|
||||
VER="3.2"
|
||||
RELEASE="release-${VER}"
|
||||
rm -rf .cert
|
||||
mkdir .cert
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
package services
|
||||
|
||||
import "golang.org/x/crypto/ssh"
|
||||
|
||||
// tcp := app.Command("tcp", "proxy on tcp mode")
|
||||
// t := tcp.Flag("tcp-timeout", "tcp timeout milliseconds when connect to real server or parent proxy").Default("2000").Int()
|
||||
|
||||
@ -13,32 +15,43 @@ const (
|
||||
CONN_CLIENT = uint8(3)
|
||||
)
|
||||
|
||||
type Args struct {
|
||||
type TunnelServerArgs struct {
|
||||
Parent *string
|
||||
CertFile *string
|
||||
KeyFile *string
|
||||
CertBytes []byte
|
||||
KeyBytes []byte
|
||||
}
|
||||
type TunnelServerArgs struct {
|
||||
Args
|
||||
Local *string
|
||||
IsUDP *bool
|
||||
Key *string
|
||||
Remote *string
|
||||
Timeout *int
|
||||
Route *[]string
|
||||
Local *string
|
||||
IsUDP *bool
|
||||
Key *string
|
||||
Remote *string
|
||||
Timeout *int
|
||||
Route *[]string
|
||||
}
|
||||
type TunnelClientArgs struct {
|
||||
Args
|
||||
Key *string
|
||||
Timeout *int
|
||||
Parent *string
|
||||
CertFile *string
|
||||
KeyFile *string
|
||||
CertBytes []byte
|
||||
KeyBytes []byte
|
||||
Key *string
|
||||
Timeout *int
|
||||
}
|
||||
type TunnelBridgeArgs struct {
|
||||
Args
|
||||
Local *string
|
||||
Timeout *int
|
||||
Parent *string
|
||||
CertFile *string
|
||||
KeyFile *string
|
||||
CertBytes []byte
|
||||
KeyBytes []byte
|
||||
Local *string
|
||||
Timeout *int
|
||||
}
|
||||
type TCPArgs struct {
|
||||
Args
|
||||
Parent *string
|
||||
CertFile *string
|
||||
KeyFile *string
|
||||
CertBytes []byte
|
||||
KeyBytes []byte
|
||||
Local *string
|
||||
ParentType *string
|
||||
IsTLS *bool
|
||||
@ -48,7 +61,11 @@ type TCPArgs struct {
|
||||
}
|
||||
|
||||
type HTTPArgs struct {
|
||||
Args
|
||||
Parent *string
|
||||
CertFile *string
|
||||
KeyFile *string
|
||||
CertBytes []byte
|
||||
KeyBytes []byte
|
||||
Local *string
|
||||
Always *bool
|
||||
HTTPTimeout *int
|
||||
@ -62,15 +79,46 @@ type HTTPArgs struct {
|
||||
Timeout *int
|
||||
PoolSize *int
|
||||
CheckParentInterval *int
|
||||
SSHKeyFile *string
|
||||
SSHKeyFileSalt *string
|
||||
SSHPassword *string
|
||||
SSHUser *string
|
||||
SSHKeyBytes []byte
|
||||
SSHAuthMethod ssh.AuthMethod
|
||||
}
|
||||
type UDPArgs struct {
|
||||
Args
|
||||
Parent *string
|
||||
CertFile *string
|
||||
KeyFile *string
|
||||
CertBytes []byte
|
||||
KeyBytes []byte
|
||||
Local *string
|
||||
ParentType *string
|
||||
Timeout *int
|
||||
PoolSize *int
|
||||
CheckParentInterval *int
|
||||
}
|
||||
type SocksArgs struct {
|
||||
Parent *string
|
||||
ParentType *string
|
||||
Local *string
|
||||
LocalType *string
|
||||
CertFile *string
|
||||
KeyFile *string
|
||||
CertBytes []byte
|
||||
KeyBytes []byte
|
||||
SSHKeyFile *string
|
||||
SSHKeyFileSalt *string
|
||||
SSHPassword *string
|
||||
SSHUser *string
|
||||
SSHKeyBytes []byte
|
||||
SSHAuthMethod ssh.AuthMethod
|
||||
Timeout *int
|
||||
Always *bool
|
||||
Interval *int
|
||||
Blocked *string
|
||||
Direct *string
|
||||
}
|
||||
|
||||
func (a *TCPArgs) Protocol() string {
|
||||
if *a.IsTLS {
|
||||
|
||||
114
services/http.go
@ -3,11 +3,15 @@ package services
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"proxy/utils"
|
||||
"runtime/debug"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
type HTTP struct {
|
||||
@ -15,6 +19,7 @@ type HTTP struct {
|
||||
cfg HTTPArgs
|
||||
checker utils.Checker
|
||||
basicAuth utils.BasicAuth
|
||||
sshClient *ssh.Client
|
||||
}
|
||||
|
||||
func NewHTTP() Service {
|
||||
@ -25,11 +30,53 @@ func NewHTTP() Service {
|
||||
basicAuth: utils.BasicAuth{},
|
||||
}
|
||||
}
|
||||
func (s *HTTP) CheckArgs() {
|
||||
var err error
|
||||
if *s.cfg.Parent != "" && *s.cfg.ParentType == "" {
|
||||
log.Fatalf("parent type unkown,use -T <tls|tcp|ssh>")
|
||||
}
|
||||
if *s.cfg.ParentType == "tls" || *s.cfg.LocalType == "tls" {
|
||||
s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
|
||||
}
|
||||
if *s.cfg.ParentType == "ssh" {
|
||||
if *s.cfg.SSHUser == "" {
|
||||
log.Fatalf("ssh user required")
|
||||
}
|
||||
if *s.cfg.SSHKeyFile == "" && *s.cfg.SSHPassword == "" {
|
||||
log.Fatalf("ssh password or key required")
|
||||
}
|
||||
|
||||
if *s.cfg.SSHPassword != "" {
|
||||
s.cfg.SSHAuthMethod = ssh.Password(*s.cfg.SSHPassword)
|
||||
} else {
|
||||
var SSHSigner ssh.Signer
|
||||
s.cfg.SSHKeyBytes, err = ioutil.ReadFile(*s.cfg.SSHKeyFile)
|
||||
if err != nil {
|
||||
log.Fatalf("read key file ERR: %s", err)
|
||||
}
|
||||
if *s.cfg.SSHKeyFileSalt != "" {
|
||||
SSHSigner, err = ssh.ParsePrivateKeyWithPassphrase(s.cfg.SSHKeyBytes, []byte(*s.cfg.SSHKeyFileSalt))
|
||||
} else {
|
||||
SSHSigner, err = ssh.ParsePrivateKey(s.cfg.SSHKeyBytes)
|
||||
}
|
||||
if err != nil {
|
||||
log.Fatalf("parse ssh private key fail,ERR: %s", err)
|
||||
}
|
||||
s.cfg.SSHAuthMethod = ssh.PublicKeys(SSHSigner)
|
||||
}
|
||||
}
|
||||
}
|
||||
func (s *HTTP) InitService() {
|
||||
s.InitBasicAuth()
|
||||
if *s.cfg.Parent != "" {
|
||||
s.checker = utils.NewChecker(*s.cfg.HTTPTimeout, int64(*s.cfg.Interval), *s.cfg.Blocked, *s.cfg.Direct)
|
||||
}
|
||||
if *s.cfg.ParentType == "ssh" {
|
||||
err := s.ConnectSSH()
|
||||
if err != nil {
|
||||
log.Fatalf("init service fail, ERR: %s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
func (s *HTTP) StopService() {
|
||||
if s.outPool.Pool != nil {
|
||||
@ -38,13 +85,12 @@ func (s *HTTP) StopService() {
|
||||
}
|
||||
func (s *HTTP) Start(args interface{}) (err error) {
|
||||
s.cfg = args.(HTTPArgs)
|
||||
s.CheckArgs()
|
||||
if *s.cfg.Parent != "" {
|
||||
log.Printf("use %s parent %s", *s.cfg.ParentType, *s.cfg.Parent)
|
||||
s.InitOutConnPool()
|
||||
}
|
||||
|
||||
s.InitService()
|
||||
|
||||
host, port, _ := net.SplitHostPort(*s.cfg.Local)
|
||||
p, _ := strconv.Atoi(port)
|
||||
sc := utils.NewServerChannel(host, p)
|
||||
@ -95,8 +141,9 @@ func (s *HTTP) callback(inConn net.Conn) {
|
||||
//log.Printf("blocked ? : %v, %s , fail:%d ,success:%d", useProxy, address, n, m)
|
||||
}
|
||||
log.Printf("use proxy : %v, %s", useProxy, address)
|
||||
//os.Exit(0)
|
||||
|
||||
err = s.OutToTCP(useProxy, address, &inConn, &req)
|
||||
|
||||
if err != nil {
|
||||
if *s.cfg.Parent == "" {
|
||||
log.Printf("connect to %s fail, ERR:%s", address, err)
|
||||
@ -118,9 +165,13 @@ func (s *HTTP) OutToTCP(useProxy bool, address string, inConn *net.Conn, req *ut
|
||||
var outConn net.Conn
|
||||
var _outConn interface{}
|
||||
if useProxy {
|
||||
_outConn, err = s.outPool.Pool.Get()
|
||||
if err == nil {
|
||||
outConn = _outConn.(net.Conn)
|
||||
if *s.cfg.ParentType == "ssh" {
|
||||
outConn, err = s.getSSHConn(address)
|
||||
} else {
|
||||
_outConn, err = s.outPool.Pool.Get()
|
||||
if err == nil {
|
||||
outConn = _outConn.(net.Conn)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
outConn, err = utils.ConnectHost(address, *s.cfg.Timeout)
|
||||
@ -134,20 +185,61 @@ func (s *HTTP) OutToTCP(useProxy bool, address string, inConn *net.Conn, req *ut
|
||||
outAddr := outConn.RemoteAddr().String()
|
||||
outLocalAddr := outConn.LocalAddr().String()
|
||||
|
||||
if req.IsHTTPS() && !useProxy {
|
||||
req.HTTPSReply()
|
||||
if req.IsHTTPS() && (!useProxy || *s.cfg.ParentType == "ssh") {
|
||||
//https无上级或者上级非代理,proxy需要响应connect请求,并直连目标
|
||||
err = req.HTTPSReply()
|
||||
} else {
|
||||
outConn.Write(req.HeadBuf)
|
||||
//https或者http,上级是代理,proxy需要转发
|
||||
_, err = outConn.Write(req.HeadBuf)
|
||||
if err != nil {
|
||||
log.Printf("write to %s , err:%s", *s.cfg.Parent, err)
|
||||
utils.CloseConn(inConn)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
utils.IoBind((*inConn), outConn, func(err error) {
|
||||
log.Printf("conn %s - %s - %s -%s released [%s]", inAddr, inLocalAddr, outLocalAddr, outAddr, req.Host)
|
||||
log.Printf("conn %s - %s - %s - %s released [%s]", inAddr, inLocalAddr, outLocalAddr, outAddr, req.Host)
|
||||
utils.CloseConn(inConn)
|
||||
utils.CloseConn(&outConn)
|
||||
}, func(n int, d bool) {}, 0)
|
||||
log.Printf("conn %s - %s - %s - %s connected [%s]", inAddr, inLocalAddr, outLocalAddr, outAddr, req.Host)
|
||||
|
||||
return
|
||||
}
|
||||
func (s *HTTP) OutToUDP(inConn *net.Conn) (err error) {
|
||||
|
||||
func (s *HTTP) getSSHConn(host string) (outConn net.Conn, err error) {
|
||||
maxTryCount := 1
|
||||
tryCount := 0
|
||||
RETRY:
|
||||
if tryCount >= maxTryCount {
|
||||
return
|
||||
}
|
||||
outConn, err = s.sshClient.Dial("tcp", host)
|
||||
//log.Printf("s.sshClient.Dial, host:%s)", host)
|
||||
if err != nil {
|
||||
log.Printf("connect ssh fail, ERR: %s, retrying...", err)
|
||||
s.sshClient.Close()
|
||||
e := s.ConnectSSH()
|
||||
if e == nil {
|
||||
tryCount++
|
||||
time.Sleep(time.Second * 3)
|
||||
goto RETRY
|
||||
} else {
|
||||
err = e
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
func (s *HTTP) ConnectSSH() (err error) {
|
||||
config := ssh.ClientConfig{
|
||||
User: *s.cfg.SSHUser,
|
||||
Auth: []ssh.AuthMethod{s.cfg.SSHAuthMethod},
|
||||
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
|
||||
return nil
|
||||
},
|
||||
}
|
||||
s.sshClient, err = ssh.Dial("tcp", *s.cfg.Parent, &config)
|
||||
return
|
||||
}
|
||||
func (s *HTTP) InitOutConnPool() {
|
||||
|
||||
304
services/socks.go
Normal file
@ -0,0 +1,304 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"proxy/utils"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
type Socks struct {
|
||||
cfg SocksArgs
|
||||
checker utils.Checker
|
||||
basicAuth utils.BasicAuth
|
||||
sshClient *ssh.Client
|
||||
}
|
||||
|
||||
func NewSocks() Service {
|
||||
return &Socks{
|
||||
cfg: SocksArgs{},
|
||||
checker: utils.Checker{},
|
||||
basicAuth: utils.BasicAuth{},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Socks) CheckArgs() {
|
||||
var err error
|
||||
if *s.cfg.Parent != "" {
|
||||
if *s.cfg.ParentType == "" {
|
||||
log.Fatalf("parent type unkown,use -T <tls|tcp|ssh>")
|
||||
}
|
||||
if *s.cfg.ParentType == "tls" || *s.cfg.LocalType == "tls" {
|
||||
s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
|
||||
}
|
||||
if *s.cfg.ParentType == "ssh" {
|
||||
if *s.cfg.SSHUser == "" {
|
||||
log.Fatalf("ssh user required")
|
||||
}
|
||||
if *s.cfg.SSHKeyFile == "" && *s.cfg.SSHPassword == "" {
|
||||
log.Fatalf("ssh password or key required")
|
||||
}
|
||||
|
||||
if *s.cfg.SSHPassword != "" {
|
||||
s.cfg.SSHAuthMethod = ssh.Password(*s.cfg.SSHPassword)
|
||||
} else {
|
||||
var SSHSigner ssh.Signer
|
||||
s.cfg.SSHKeyBytes, err = ioutil.ReadFile(*s.cfg.SSHKeyFile)
|
||||
if err != nil {
|
||||
log.Fatalf("read key file ERR: %s", err)
|
||||
}
|
||||
if *s.cfg.SSHKeyFileSalt != "" {
|
||||
SSHSigner, err = ssh.ParsePrivateKeyWithPassphrase(s.cfg.SSHKeyBytes, []byte(*s.cfg.SSHKeyFileSalt))
|
||||
} else {
|
||||
SSHSigner, err = ssh.ParsePrivateKey(s.cfg.SSHKeyBytes)
|
||||
}
|
||||
if err != nil {
|
||||
log.Fatalf("parse ssh private key fail,ERR: %s", err)
|
||||
}
|
||||
s.cfg.SSHAuthMethod = ssh.PublicKeys(SSHSigner)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
func (s *Socks) InitService() {
|
||||
s.checker = utils.NewChecker(*s.cfg.Timeout, int64(*s.cfg.Interval), *s.cfg.Blocked, *s.cfg.Direct)
|
||||
if *s.cfg.ParentType == "ssh" {
|
||||
err := s.ConnectSSH()
|
||||
if err != nil {
|
||||
log.Fatalf("init service fail, ERR: %s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
func (s *Socks) StopService() {
|
||||
if s.sshClient != nil {
|
||||
s.sshClient.Close()
|
||||
}
|
||||
}
|
||||
func (s *Socks) Start(args interface{}) (err error) {
|
||||
//start()
|
||||
s.cfg = args.(SocksArgs)
|
||||
s.CheckArgs()
|
||||
s.InitService()
|
||||
if *s.cfg.Parent != "" {
|
||||
log.Printf("use %s parent %s", *s.cfg.ParentType, *s.cfg.Parent)
|
||||
}
|
||||
sc := utils.NewServerChannelHost(*s.cfg.Local)
|
||||
if *s.cfg.LocalType == TYPE_TCP {
|
||||
err = sc.ListenTCP(s.callback)
|
||||
} else {
|
||||
err = sc.ListenTls(s.cfg.CertBytes, s.cfg.KeyBytes, s.callback)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
log.Printf("%s socks proxy on %s", *s.cfg.LocalType, (*sc.Listener).Addr())
|
||||
return
|
||||
}
|
||||
func (s *Socks) Clean() {
|
||||
s.StopService()
|
||||
}
|
||||
func (s *Socks) callback(inConn net.Conn) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
//log.Printf("socks conn handler crashed with err : %s \nstack: %s", err, string(debug.Stack()))
|
||||
}
|
||||
utils.CloseConn(&inConn)
|
||||
}()
|
||||
var outConn net.Conn
|
||||
defer utils.CloseConn(&outConn)
|
||||
|
||||
var b [1024]byte
|
||||
n, err := inConn.Read(b[:])
|
||||
if err != nil {
|
||||
if err != io.EOF {
|
||||
log.Printf("read request data fail,ERR: %s", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var reqBytes = b[:n]
|
||||
//log.Printf("% x", b[:n])
|
||||
|
||||
//reply
|
||||
n, err = inConn.Write([]byte{0x05, 0x00})
|
||||
if err != nil {
|
||||
log.Printf("reply answer data fail,ERR: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
//read answer
|
||||
n, err = inConn.Read(b[:])
|
||||
if err != nil {
|
||||
log.Printf("read answer data fail,ERR: %s", err)
|
||||
return
|
||||
}
|
||||
var headBytes = b[:n]
|
||||
// log.Printf("% x", b[:n])
|
||||
var addr string
|
||||
switch b[3] {
|
||||
case 0x01:
|
||||
sip := sockIP{}
|
||||
if err := binary.Read(bytes.NewReader(b[4:n]), binary.BigEndian, &sip); err != nil {
|
||||
log.Printf("read ip fail,ERR: %s", err)
|
||||
return
|
||||
}
|
||||
addr = sip.toAddr()
|
||||
case 0x03:
|
||||
host := string(b[5 : n-2])
|
||||
var port uint16
|
||||
err = binary.Read(bytes.NewReader(b[n-2:n]), binary.BigEndian, &port)
|
||||
if err != nil {
|
||||
log.Printf("read domain fail,ERR: %s", err)
|
||||
return
|
||||
}
|
||||
addr = fmt.Sprintf("%s:%d", host, port)
|
||||
}
|
||||
useProxy := true
|
||||
if *s.cfg.Always {
|
||||
outConn, err = s.getOutConn(reqBytes, headBytes, addr)
|
||||
} else {
|
||||
if *s.cfg.Parent != "" {
|
||||
s.checker.Add(addr, true, "", "", nil)
|
||||
useProxy, _, _ = s.checker.IsBlocked(addr)
|
||||
if useProxy {
|
||||
outConn, err = s.getOutConn(reqBytes, headBytes, addr)
|
||||
} else {
|
||||
outConn, err = utils.ConnectHost(addr, *s.cfg.Timeout)
|
||||
}
|
||||
} else {
|
||||
outConn, err = utils.ConnectHost(addr, *s.cfg.Timeout)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
log.Printf("get out conn fail,%s", err)
|
||||
inConn.Write([]byte{0x05, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
|
||||
return
|
||||
}
|
||||
log.Printf("use proxy %v : %s", useProxy, addr)
|
||||
|
||||
inConn.Write([]byte{0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
|
||||
|
||||
inAddr := inConn.RemoteAddr().String()
|
||||
inLocalAddr := inConn.LocalAddr().String()
|
||||
|
||||
log.Printf("conn %s - %s connected [%s]", inAddr, inLocalAddr, addr)
|
||||
// utils.IoBind(outConn, inConn, func(err error) {
|
||||
// log.Printf("conn %s - %s released [%s]", inAddr, inLocalAddr, addr)
|
||||
|
||||
// }, func(i int, b bool) {}, 0)
|
||||
var bind = func() (err interface{}) {
|
||||
defer func() {
|
||||
if err == nil {
|
||||
if err = recover(); err != nil {
|
||||
log.Printf("bind crashed %s", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
defer func() {
|
||||
if err == nil {
|
||||
if err = recover(); err != nil {
|
||||
log.Printf("bind crashed %s", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
_, err = io.Copy(outConn, inConn)
|
||||
}()
|
||||
_, err = io.Copy(inConn, outConn)
|
||||
return
|
||||
}
|
||||
bind()
|
||||
log.Printf("conn %s - %s released [%s]", inAddr, inLocalAddr, addr)
|
||||
utils.CloseConn(&inConn)
|
||||
utils.CloseConn(&outConn)
|
||||
}
|
||||
func (s *Socks) getOutConn(reqBytes, headBytes []byte, host string) (outConn net.Conn, err error) {
|
||||
switch *s.cfg.ParentType {
|
||||
case "tls":
|
||||
fallthrough
|
||||
case "tcp":
|
||||
if *s.cfg.ParentType == "tls" {
|
||||
var _outConn tls.Conn
|
||||
_outConn, err = utils.TlsConnectHost(*s.cfg.Parent, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes)
|
||||
outConn = net.Conn(&_outConn)
|
||||
} else {
|
||||
outConn, err = utils.ConnectHost(*s.cfg.Parent, *s.cfg.Timeout)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var buf = make([]byte, 1024)
|
||||
//var n int
|
||||
_, err = outConn.Write(reqBytes)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_, err = outConn.Read(buf)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
//resp := buf[:n]
|
||||
//log.Printf("resp:%v", resp)
|
||||
|
||||
outConn.Write(headBytes)
|
||||
_, err = outConn.Read(buf)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
//result := buf[:n]
|
||||
//log.Printf("result:%v", result)
|
||||
|
||||
case "ssh":
|
||||
maxTryCount := 1
|
||||
tryCount := 0
|
||||
RETRY:
|
||||
if tryCount >= maxTryCount {
|
||||
return
|
||||
}
|
||||
outConn, err = s.sshClient.Dial("tcp", host)
|
||||
if err != nil {
|
||||
log.Printf("connect ssh fail, ERR: %s, retrying...", err)
|
||||
s.sshClient.Close()
|
||||
e := s.ConnectSSH()
|
||||
if e == nil {
|
||||
tryCount++
|
||||
time.Sleep(time.Second * 3)
|
||||
goto RETRY
|
||||
} else {
|
||||
err = e
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
func (s *Socks) ConnectSSH() (err error) {
|
||||
config := ssh.ClientConfig{
|
||||
Timeout: time.Duration(*s.cfg.Timeout) * time.Millisecond,
|
||||
User: *s.cfg.SSHUser,
|
||||
Auth: []ssh.AuthMethod{s.cfg.SSHAuthMethod},
|
||||
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
|
||||
return nil
|
||||
},
|
||||
}
|
||||
s.sshClient, err = ssh.Dial("tcp", *s.cfg.Parent, &config)
|
||||
return
|
||||
}
|
||||
|
||||
type sockIP struct {
|
||||
A, B, C, D byte
|
||||
PORT uint16
|
||||
}
|
||||
|
||||
func (ip sockIP) toAddr() string {
|
||||
return fmt.Sprintf("%d.%d.%d.%d:%d", ip.A, ip.B, ip.C, ip.D, ip.PORT)
|
||||
}
|
||||
@ -24,6 +24,17 @@ func NewTCP() Service {
|
||||
cfg: TCPArgs{},
|
||||
}
|
||||
}
|
||||
func (s *TCP) CheckArgs() {
|
||||
if *s.cfg.Parent == "" {
|
||||
log.Fatalf("parent required for %s %s", s.cfg.Protocol(), *s.cfg.Local)
|
||||
}
|
||||
if *s.cfg.ParentType == "" {
|
||||
log.Fatalf("parent type unkown,use -T <tls|tcp>")
|
||||
}
|
||||
if *s.cfg.ParentType == "tls" || *s.cfg.IsTLS {
|
||||
s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
|
||||
}
|
||||
}
|
||||
func (s *TCP) InitService() {
|
||||
s.InitOutConnPool()
|
||||
}
|
||||
@ -34,12 +45,8 @@ func (s *TCP) StopService() {
|
||||
}
|
||||
func (s *TCP) Start(args interface{}) (err error) {
|
||||
s.cfg = args.(TCPArgs)
|
||||
if *s.cfg.Parent != "" {
|
||||
log.Printf("use %s parent %s", *s.cfg.ParentType, *s.cfg.Parent)
|
||||
} else {
|
||||
log.Fatalf("parent required for %s %s", s.cfg.Protocol(), *s.cfg.Local)
|
||||
}
|
||||
|
||||
s.CheckArgs()
|
||||
log.Printf("use %s parent %s", *s.cfg.ParentType, *s.cfg.Parent)
|
||||
s.InitService()
|
||||
|
||||
host, port, _ := net.SplitHostPort(*s.cfg.Local)
|
||||
@ -99,11 +106,11 @@ func (s *TCP) OutToTCP(inConn *net.Conn) (err error) {
|
||||
outAddr := outConn.RemoteAddr().String()
|
||||
outLocalAddr := outConn.LocalAddr().String()
|
||||
utils.IoBind((*inConn), outConn, func(err error) {
|
||||
log.Printf("conn %s - %s - %s -%s released", inAddr, inLocalAddr, outLocalAddr, outAddr)
|
||||
log.Printf("conn %s - %s - %s - %s released", inAddr, inLocalAddr, outLocalAddr, outAddr)
|
||||
utils.CloseConn(inConn)
|
||||
utils.CloseConn(&outConn)
|
||||
}, func(n int, d bool) {}, 0)
|
||||
log.Printf("conn %s - %s - %s -%s connected", inAddr, inLocalAddr, outLocalAddr, outAddr)
|
||||
log.Printf("conn %s - %s - %s - %s connected", inAddr, inLocalAddr, outLocalAddr, outAddr)
|
||||
return
|
||||
}
|
||||
func (s *TCP) OutToUDP(inConn *net.Conn) (err error) {
|
||||
|
||||
@ -32,18 +32,18 @@ func NewTunnelBridge() Service {
|
||||
func (s *TunnelBridge) InitService() {
|
||||
|
||||
}
|
||||
func (s *TunnelBridge) Check() {
|
||||
if s.cfg.CertBytes == nil || s.cfg.KeyBytes == nil {
|
||||
func (s *TunnelBridge) CheckArgs() {
|
||||
if *s.cfg.CertFile == "" || *s.cfg.KeyFile == "" {
|
||||
log.Fatalf("cert and key file required")
|
||||
}
|
||||
|
||||
s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
|
||||
}
|
||||
func (s *TunnelBridge) StopService() {
|
||||
|
||||
}
|
||||
func (s *TunnelBridge) Start(args interface{}) (err error) {
|
||||
s.cfg = args.(TunnelBridgeArgs)
|
||||
s.Check()
|
||||
s.CheckArgs()
|
||||
s.InitService()
|
||||
host, port, _ := net.SplitHostPort(*s.cfg.Local)
|
||||
p, _ := strconv.Atoi(port)
|
||||
|
||||
@ -25,21 +25,22 @@ func NewTunnelClient() Service {
|
||||
|
||||
func (s *TunnelClient) InitService() {
|
||||
}
|
||||
func (s *TunnelClient) Check() {
|
||||
func (s *TunnelClient) CheckArgs() {
|
||||
if *s.cfg.Parent != "" {
|
||||
log.Printf("use tls parent %s", *s.cfg.Parent)
|
||||
} else {
|
||||
log.Fatalf("parent required")
|
||||
}
|
||||
if s.cfg.CertBytes == nil || s.cfg.KeyBytes == nil {
|
||||
if *s.cfg.CertFile == "" || *s.cfg.KeyFile == "" {
|
||||
log.Fatalf("cert and key file required")
|
||||
}
|
||||
s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
|
||||
}
|
||||
func (s *TunnelClient) StopService() {
|
||||
}
|
||||
func (s *TunnelClient) Start(args interface{}) (err error) {
|
||||
s.cfg = args.(TunnelClientArgs)
|
||||
s.Check()
|
||||
s.CheckArgs()
|
||||
s.InitService()
|
||||
log.Printf("proxy on tunnel client mode")
|
||||
for {
|
||||
@ -146,7 +147,7 @@ func (s *TunnelClient) ServeUDP(localAddr, ID string) {
|
||||
} else if err != nil {
|
||||
log.Printf("udp packet revecived fail, err: %s", err)
|
||||
} else {
|
||||
log.Printf("udp packet revecived:%s,%v", srcAddr, body)
|
||||
//log.Printf("udp packet revecived:%s,%v", srcAddr, body)
|
||||
go s.processUDPPacket(&inConn, srcAddr, localAddr, body)
|
||||
}
|
||||
|
||||
@ -180,7 +181,7 @@ func (s *TunnelClient) processUDPPacket(inConn *net.Conn, srcAddr, localAddr str
|
||||
return
|
||||
}
|
||||
respBody := buf[0:length]
|
||||
log.Printf("revecived udp packet from %s , %v", dstAddr.String(), respBody)
|
||||
//log.Printf("revecived udp packet from %s , %v", dstAddr.String(), respBody)
|
||||
bs := utils.UDPPacket(srcAddr, respBody)
|
||||
_, err = (*inConn).Write(bs)
|
||||
if err != nil {
|
||||
@ -188,7 +189,7 @@ func (s *TunnelClient) processUDPPacket(inConn *net.Conn, srcAddr, localAddr str
|
||||
utils.CloseConn(inConn)
|
||||
return
|
||||
}
|
||||
log.Printf("send udp response success ,from:%s ,%d ,%v", dstAddr.String(), len(bs), bs)
|
||||
//log.Printf("send udp response success ,from:%s ,%d ,%v", dstAddr.String(), len(bs), bs)
|
||||
}
|
||||
func (s *TunnelClient) ServeConn(localAddr, ID string) {
|
||||
var inConn, outConn net.Conn
|
||||
|
||||
@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
@ -40,18 +41,34 @@ func (s *TunnelServerManager) Start(args interface{}) (err error) {
|
||||
log.Fatalf("parent required")
|
||||
}
|
||||
//log.Printf("route:%v", *s.cfg.Route)
|
||||
for _, info := range *s.cfg.Route {
|
||||
for _, _info := range *s.cfg.Route {
|
||||
IsUDP := *s.cfg.IsUDP
|
||||
if strings.HasPrefix(_info, "udp://") {
|
||||
IsUDP = true
|
||||
}
|
||||
info := strings.TrimPrefix(_info, "udp://")
|
||||
info = strings.TrimPrefix(info, "tcp://")
|
||||
_routeInfo := strings.Split(info, "@")
|
||||
server := NewTunnelServer()
|
||||
local := _routeInfo[0]
|
||||
remote := _routeInfo[1]
|
||||
KEY := *s.cfg.Key
|
||||
if strings.HasPrefix(remote, "[") {
|
||||
KEY = remote[1:strings.LastIndex(remote, "]")]
|
||||
remote = remote[strings.LastIndex(remote, "]")+1:]
|
||||
}
|
||||
if strings.HasPrefix(remote, ":") {
|
||||
remote = fmt.Sprintf("127.0.0.1%s", remote)
|
||||
}
|
||||
err = server.Start(TunnelServerArgs{
|
||||
Args: s.cfg.Args,
|
||||
Local: &local,
|
||||
IsUDP: s.cfg.IsUDP,
|
||||
Remote: &remote,
|
||||
Key: s.cfg.Key,
|
||||
Timeout: s.cfg.Timeout,
|
||||
CertBytes: s.cfg.CertBytes,
|
||||
KeyBytes: s.cfg.KeyBytes,
|
||||
Parent: s.cfg.Parent,
|
||||
Local: &local,
|
||||
IsUDP: &IsUDP,
|
||||
Remote: &remote,
|
||||
Key: &KEY,
|
||||
Timeout: s.cfg.Timeout,
|
||||
})
|
||||
if err != nil {
|
||||
return
|
||||
@ -78,19 +95,20 @@ type UDPItem struct {
|
||||
func (s *TunnelServer) InitService() {
|
||||
s.UDPConnDeamon()
|
||||
}
|
||||
func (s *TunnelServer) Check() {
|
||||
func (s *TunnelServer) CheckArgs() {
|
||||
if *s.cfg.Remote == "" {
|
||||
log.Fatalf("remote required")
|
||||
}
|
||||
if s.cfg.CertBytes == nil || s.cfg.KeyBytes == nil {
|
||||
if *s.cfg.CertFile == "" || *s.cfg.KeyFile == "" {
|
||||
log.Fatalf("cert and key file required")
|
||||
}
|
||||
s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
|
||||
}
|
||||
func (s *TunnelServer) StopService() {
|
||||
}
|
||||
func (s *TunnelServer) Start(args interface{}) (err error) {
|
||||
s.cfg = args.(TunnelServerArgs)
|
||||
s.Check()
|
||||
s.CheckArgs()
|
||||
s.InitService()
|
||||
host, port, _ := net.SplitHostPort(*s.cfg.Local)
|
||||
p, _ := strconv.Atoi(port)
|
||||
@ -204,8 +222,7 @@ func (s *TunnelServer) UDPConnDeamon() {
|
||||
var outConn net.Conn
|
||||
// var hb utils.HeartbeatReadWriter
|
||||
var ID string
|
||||
var cmdChn = make(chan bool, 1)
|
||||
|
||||
// var cmdChn = make(chan bool, 1000)
|
||||
var err error
|
||||
for {
|
||||
item := <-s.udpChn
|
||||
@ -214,25 +231,19 @@ func (s *TunnelServer) UDPConnDeamon() {
|
||||
for {
|
||||
outConn, ID, err = s.GetOutConn("")
|
||||
if err != nil {
|
||||
cmdChn <- true
|
||||
// cmdChn <- true
|
||||
outConn = nil
|
||||
utils.CloseConn(&outConn)
|
||||
log.Printf("connect to %s fail, err: %s, retrying...", *s.cfg.Parent, err)
|
||||
time.Sleep(time.Second * 3)
|
||||
continue
|
||||
} else {
|
||||
// hb = utils.NewHeartbeatReadWriter(&outConn, 3, func(err error, hb *utils.HeartbeatReadWriter) {
|
||||
// log.Printf("%s conn %s to bridge released", *s.cfg.Key, ID)
|
||||
// hb.Close()
|
||||
// })
|
||||
// go func(outConn net.Conn, hb utils.HeartbeatReadWriter, ID string) {
|
||||
go func(outConn net.Conn, ID string) {
|
||||
go func() {
|
||||
<-cmdChn
|
||||
outConn.Close()
|
||||
// <-cmdChn
|
||||
// outConn.Close()
|
||||
}()
|
||||
for {
|
||||
//srcAddrFromConn, body, err := utils.ReadUDPPacket(&hb)
|
||||
srcAddrFromConn, body, err := utils.ReadUDPPacket(outConn)
|
||||
if err == io.EOF || err == io.ErrUnexpectedEOF {
|
||||
log.Printf("UDP deamon connection %s exited", ID)
|
||||
@ -257,18 +268,13 @@ func (s *TunnelServer) UDPConnDeamon() {
|
||||
}
|
||||
//log.Printf("udp response to local %s success , %v", srcAddrFromConn, body)
|
||||
}
|
||||
// }(outConn, hb, ID)
|
||||
}(outConn, ID)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
outConn.SetWriteDeadline(time.Now().Add(time.Second))
|
||||
// _, err = hb.Write(utils.UDPPacket(item.srcAddr.String(), *item.packet))
|
||||
_, err = outConn.Write(utils.UDPPacket(item.srcAddr.String(), *item.packet))
|
||||
// writer := bufio.NewWriter(outConn)
|
||||
// writer.Write(utils.UDPPacket(item.srcAddr.String(), *item.packet))
|
||||
// err := writer.Flush()
|
||||
outConn.SetWriteDeadline(time.Time{})
|
||||
if err != nil {
|
||||
utils.CloseConn(&outConn)
|
||||
|
||||
@ -27,6 +27,17 @@ func NewUDP() Service {
|
||||
p: utils.NewConcurrentMap(),
|
||||
}
|
||||
}
|
||||
func (s *UDP) CheckArgs() {
|
||||
if *s.cfg.Parent == "" {
|
||||
log.Fatalf("parent required for udp %s", *s.cfg.Local)
|
||||
}
|
||||
if *s.cfg.ParentType == "" {
|
||||
log.Fatalf("parent type unkown,use -T <tls|tcp>")
|
||||
}
|
||||
if *s.cfg.ParentType == "tls" {
|
||||
s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
|
||||
}
|
||||
}
|
||||
func (s *UDP) InitService() {
|
||||
if *s.cfg.ParentType != TYPE_UDP {
|
||||
s.InitOutConnPool()
|
||||
@ -39,12 +50,8 @@ func (s *UDP) StopService() {
|
||||
}
|
||||
func (s *UDP) Start(args interface{}) (err error) {
|
||||
s.cfg = args.(UDPArgs)
|
||||
if *s.cfg.Parent != "" {
|
||||
log.Printf("use %s parent %s", *s.cfg.ParentType, *s.cfg.Parent)
|
||||
} else {
|
||||
log.Fatalf("parent required for udp %s", *s.cfg.Local)
|
||||
}
|
||||
|
||||
s.CheckArgs()
|
||||
log.Printf("use %s parent %s", *s.cfg.ParentType, *s.cfg.Parent)
|
||||
s.InitService()
|
||||
|
||||
host, port, _ := net.SplitHostPort(*s.cfg.Local)
|
||||
|
||||
@ -9,6 +9,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"math/rand"
|
||||
"net"
|
||||
@ -311,6 +312,19 @@ func Uniqueid() string {
|
||||
s := fmt.Sprintf("%d", src.Int63())
|
||||
return s[len(s)-5:len(s)-1] + fmt.Sprintf("%d", uint64(time.Now().UnixNano()))[8:]
|
||||
}
|
||||
func TlsBytes(cert, key string) (certBytes, keyBytes []byte) {
|
||||
certBytes, err := ioutil.ReadFile(cert)
|
||||
if err != nil {
|
||||
log.Fatalf("err : %s", err)
|
||||
return
|
||||
}
|
||||
keyBytes, err = ioutil.ReadFile(key)
|
||||
if err != nil {
|
||||
log.Fatalf("err : %s", err)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// type sockaddr struct {
|
||||
// family uint16
|
||||
|
||||
@ -5,6 +5,7 @@ import (
|
||||
"log"
|
||||
"net"
|
||||
"runtime/debug"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type ServerChannel struct {
|
||||
@ -24,6 +25,17 @@ func NewServerChannel(ip string, port int) ServerChannel {
|
||||
},
|
||||
}
|
||||
}
|
||||
func NewServerChannelHost(host string) ServerChannel {
|
||||
h, port, _ := net.SplitHostPort(host)
|
||||
p, _ := strconv.Atoi(port)
|
||||
return ServerChannel{
|
||||
ip: h,
|
||||
port: p,
|
||||
errAcceptHandler: func(err error) {
|
||||
log.Printf("accept error , ERR:%s", err)
|
||||
},
|
||||
}
|
||||
}
|
||||
func (sc *ServerChannel) SetErrAcceptHandler(fn func(err error)) {
|
||||
sc.errAcceptHandler = fn
|
||||
}
|
||||
|
||||