v5.4
This commit is contained in:
@ -3,6 +3,9 @@ v5.4
|
|||||||
1.优化了获取本地IP信息导致CPU过高的问题.
|
1.优化了获取本地IP信息导致CPU过高的问题.
|
||||||
2.所有服务都增加了--nolog参数,可以关闭日志输出,节省CPU.
|
2.所有服务都增加了--nolog参数,可以关闭日志输出,节省CPU.
|
||||||
3.优化sdk,支持并发启动/关闭操作.
|
3.优化sdk,支持并发启动/关闭操作.
|
||||||
|
4.修复了多连接版本的内网穿透,tserver连接不能正确释放的bug.
|
||||||
|
5.内网穿透增加了client/tclient和server/tserver使用代理连接bridge/tbridge的功能,详细内容参考手册.
|
||||||
|
6.TCP端口映射(TCP代理)增加了使用代理连接上级的功能,详细内容参考手册.
|
||||||
|
|
||||||
v5.3
|
v5.3
|
||||||
1.优化了socks_client握手端口判断,避免了sstap测试UDP失败的问题.
|
1.优化了socks_client握手端口判断,避免了sstap测试UDP失败的问题.
|
||||||
|
|||||||
54
README_ZH.md
54
README_ZH.md
@ -87,14 +87,15 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5代理服务
|
|||||||
- [1.12 自定义加密](#112-自定义加密)
|
- [1.12 自定义加密](#112-自定义加密)
|
||||||
- [1.13 压缩传输](#113-压缩传输)
|
- [1.13 压缩传输](#113-压缩传输)
|
||||||
- [1.14 查看帮助](#114-查看帮助)
|
- [1.14 查看帮助](#114-查看帮助)
|
||||||
- [2. TCP代理](#2tcp代理)
|
- [2. TCP代理(端口映射)](#2tcp代理)
|
||||||
- [2.1 普通一级TCP代理](#21普通一级tcp代理)
|
- [2.1 普通一级TCP代理](#21普通一级tcp代理)
|
||||||
- [2.2 普通二级TCP代理](#22普通二级tcp代理)
|
- [2.2 普通二级TCP代理](#22普通二级tcp代理)
|
||||||
- [2.3 普通三级TCP代理](#23普通三级tcp代理)
|
- [2.3 普通三级TCP代理](#23普通三级tcp代理)
|
||||||
- [2.4 加密二级TCP代理](#24加密二级tcp代理)
|
- [2.4 加密二级TCP代理](#24加密二级tcp代理)
|
||||||
- [2.5 加密三级TCP代理](#25加密三级tcp代理)
|
- [2.5 加密三级TCP代理](#25加密三级tcp代理)
|
||||||
- [2.6 查看帮助](#26查看帮助)
|
- [2.6 通过代理连接上级](#26通过代理连接上级)
|
||||||
- [3. UDP代理](#3udp代理)
|
- [2.7 查看帮助](#27查看帮助)
|
||||||
|
- [3. UDP代理(端口映射)](#3udp代理)
|
||||||
- [3.1 普通一级UDP代理](#31普通一级udp代理)
|
- [3.1 普通一级UDP代理](#31普通一级udp代理)
|
||||||
- [3.2 普通二级UDP代理](#32普通二级udp代理)
|
- [3.2 普通二级UDP代理](#32普通二级udp代理)
|
||||||
- [3.3 普通三级UDP代理](#33普通三级udp代理)
|
- [3.3 普通三级UDP代理](#33普通三级udp代理)
|
||||||
@ -109,7 +110,8 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5代理服务
|
|||||||
- [4.5 高级用法一](#45高级用法一)
|
- [4.5 高级用法一](#45高级用法一)
|
||||||
- [4.6 高级用法一](#46高级用法二)
|
- [4.6 高级用法一](#46高级用法二)
|
||||||
- [4.7 server的-r参数](#47server的-r参数)
|
- [4.7 server的-r参数](#47server的-r参数)
|
||||||
- [4.8 查看帮助](#48查看帮助)
|
- [4.8 server和client通过代理连接bridge](#48server和client通过代理连接bridge)
|
||||||
|
- [4.9 查看帮助](#49查看帮助)
|
||||||
- [5. SOCKS5代理](#5socks5代理)
|
- [5. SOCKS5代理](#5socks5代理)
|
||||||
- [5.1 普通SOCKS5代理](#51普通socks5代理)
|
- [5.1 普通SOCKS5代理](#51普通socks5代理)
|
||||||
- [5.2 普通二级SOCKS5代理](#52普通二级socks5代理)
|
- [5.2 普通二级SOCKS5代理](#52普通二级socks5代理)
|
||||||
@ -506,7 +508,27 @@ VPS(IP:22.22.22.33)执行:
|
|||||||
`./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端口.
|
||||||
|
|
||||||
#### **2.6.查看帮助**
|
#### **2.6.通过代理连接上级**
|
||||||
|
有时候proxy所在的网络不能直接访问外网,需要通过一个https或者socks5代理才能上网,那么这个时候
|
||||||
|
-J参数就可以帮助你让proxy的tcp端口映射的时候通过https或者socks5代理去连接上级-P,将外部端口映射到本地.
|
||||||
|
-J参数格式如下:
|
||||||
|
|
||||||
|
https代理写法:
|
||||||
|
代理需要认证,用户名:username 密码:password
|
||||||
|
https://username:password@host:port
|
||||||
|
代理不需要认证
|
||||||
|
https://host:port
|
||||||
|
|
||||||
|
socks5代理写法:
|
||||||
|
代理需要认证,用户名:username 密码:password
|
||||||
|
socks5://username:password@host:port
|
||||||
|
代理不需要认证
|
||||||
|
socks5://host:port
|
||||||
|
|
||||||
|
host:代理的IP或者域名
|
||||||
|
port:代理的端口
|
||||||
|
|
||||||
|
#### **2.7.查看帮助**
|
||||||
`./proxy help tcp`
|
`./proxy help tcp`
|
||||||
|
|
||||||
### **3.UDP代理**
|
### **3.UDP代理**
|
||||||
@ -693,7 +715,27 @@ server连接到bridge的时候,如果同时有多个client连接到同一个brid
|
|||||||
|
|
||||||
4.7.3.LOCAL_IP为空默认是:`0.0.0.0`,CLIENT_LOCAL_HOST为空默认是:`127.0.0.1`;
|
4.7.3.LOCAL_IP为空默认是:`0.0.0.0`,CLIENT_LOCAL_HOST为空默认是:`127.0.0.1`;
|
||||||
|
|
||||||
#### **4.8.查看帮助**
|
#### **4.8.server和client通过代理连接bridge**
|
||||||
|
有时候server或者client所在的网络不能直接访问外网,需要通过一个https或者socks5代理才能上网,那么这个时候
|
||||||
|
-J参数就可以帮助你让server或者client通过https或者socks5代理去连接bridge.
|
||||||
|
-J参数格式如下:
|
||||||
|
|
||||||
|
https代理写法:
|
||||||
|
代理需要认证,用户名:username 密码:password
|
||||||
|
https://username:password@host:port
|
||||||
|
代理不需要认证
|
||||||
|
https://host:port
|
||||||
|
|
||||||
|
socks5代理写法:
|
||||||
|
代理需要认证,用户名:username 密码:password
|
||||||
|
socks5://username:password@host:port
|
||||||
|
代理不需要认证
|
||||||
|
socks5://host:port
|
||||||
|
|
||||||
|
host:代理的IP或者域名
|
||||||
|
port:代理的端口
|
||||||
|
|
||||||
|
#### **4.9.查看帮助**
|
||||||
`./proxy help bridge`
|
`./proxy help bridge`
|
||||||
`./proxy help server`
|
`./proxy help server`
|
||||||
`./proxy help client`
|
`./proxy help client`
|
||||||
|
|||||||
@ -124,8 +124,8 @@ func initConfig() (err error) {
|
|||||||
tcpArgs.Timeout = tcp.Flag("timeout", "tcp timeout milliseconds when connect to real server or parent proxy").Short('e').Default("2000").Int()
|
tcpArgs.Timeout = tcp.Flag("timeout", "tcp timeout milliseconds when connect to real server or parent proxy").Short('e').Default("2000").Int()
|
||||||
tcpArgs.ParentType = tcp.Flag("parent-type", "parent protocol type <tls|tcp|kcp|udp>").Short('T').Enum("tls", "tcp", "udp", "kcp")
|
tcpArgs.ParentType = tcp.Flag("parent-type", "parent protocol type <tls|tcp|kcp|udp>").Short('T').Enum("tls", "tcp", "udp", "kcp")
|
||||||
tcpArgs.LocalType = tcp.Flag("local-type", "local protocol type <tls|tcp|kcp>").Default("tcp").Short('t').Enum("tls", "tcp", "kcp")
|
tcpArgs.LocalType = tcp.Flag("local-type", "local protocol type <tls|tcp|kcp>").Default("tcp").Short('t').Enum("tls", "tcp", "kcp")
|
||||||
tcpArgs.CheckParentInterval = tcp.Flag("check-parent-interval", "check if proxy is okay every interval seconds,zero: means no check").Short('I').Default("3").Int()
|
|
||||||
tcpArgs.Local = tcp.Flag("local", "local ip:port to listen").Short('p').Default(":33080").String()
|
tcpArgs.Local = tcp.Flag("local", "local ip:port to listen").Short('p').Default(":33080").String()
|
||||||
|
tcpArgs.Jumper = tcp.Flag("jumper", "https or socks5 proxies used when connecting to parent, only worked of -T is tls or tcp, format is https://username:password@host:port https://host:port or socks5://username:password@host:port socks5://host:port").Short('J').Default("").String()
|
||||||
|
|
||||||
//########udp#########
|
//########udp#########
|
||||||
udp := app.Command("udp", "proxy on udp mode")
|
udp := app.Command("udp", "proxy on udp mode")
|
||||||
@ -149,6 +149,7 @@ func initConfig() (err error) {
|
|||||||
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|tls 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()
|
||||||
|
muxServerArgs.Jumper = muxServer.Flag("jumper", "https or socks5 proxies used when connecting to parent, only worked of -T is tls or tcp, format is https://username:password@host:port https://host:port or socks5://username:password@host:port socks5://host:port").Short('J').Default("").String()
|
||||||
|
|
||||||
//########mux-client#########
|
//########mux-client#########
|
||||||
muxClient := app.Command("client", "proxy on mux client mode")
|
muxClient := app.Command("client", "proxy on mux client mode")
|
||||||
@ -160,6 +161,7 @@ func initConfig() (err error) {
|
|||||||
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|tls 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()
|
||||||
|
muxClientArgs.Jumper = muxClient.Flag("jumper", "https or socks5 proxies used when connecting to parent, only worked of -T is tls or tcp, format is https://username:password@host:port https://host:port or socks5://username:password@host:port socks5://host:port").Short('J').Default("").String()
|
||||||
|
|
||||||
//########mux-bridge#########
|
//########mux-bridge#########
|
||||||
muxBridge := app.Command("bridge", "proxy on mux bridge mode")
|
muxBridge := app.Command("bridge", "proxy on mux bridge mode")
|
||||||
@ -178,6 +180,7 @@ func initConfig() (err error) {
|
|||||||
tunnelServerArgs.IsUDP = tunnelServer.Flag("udp", "proxy on udp tunnel server mode").Default("false").Bool()
|
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.Key = tunnelServer.Flag("k", "client key").Default("default").String()
|
||||||
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()
|
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()
|
||||||
|
tunnelServerArgs.Jumper = tunnelServer.Flag("jumper", "https or socks5 proxies used when connecting to parent, only worked of -T is tls or tcp, format is https://username:password@host:port https://host:port or socks5://username:password@host:port socks5://host:port").Short('J').Default("").String()
|
||||||
|
|
||||||
//########tunnel-client#########
|
//########tunnel-client#########
|
||||||
tunnelClient := app.Command("tclient", "proxy on tunnel client mode")
|
tunnelClient := app.Command("tclient", "proxy on tunnel client mode")
|
||||||
@ -186,6 +189,7 @@ func initConfig() (err error) {
|
|||||||
tunnelClientArgs.KeyFile = tunnelClient.Flag("key", "key file for tls").Short('K').Default("proxy.key").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.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()
|
tunnelClientArgs.Key = tunnelClient.Flag("k", "key same with server").Default("default").String()
|
||||||
|
tunnelClientArgs.Jumper = tunnelClient.Flag("jumper", "https or socks5 proxies used when connecting to parent, only worked of -T is tls or tcp, format is https://username:password@host:port https://host:port or socks5://username:password@host:port socks5://host:port").Short('J').Default("").String()
|
||||||
|
|
||||||
//########tunnel-bridge#########
|
//########tunnel-bridge#########
|
||||||
tunnelBridge := app.Command("tbridge", "proxy on tunnel bridge mode")
|
tunnelBridge := app.Command("tbridge", "proxy on tunnel bridge mode")
|
||||||
|
|||||||
@ -1,4 +1,7 @@
|
|||||||
SDK更新日志
|
SDK更新日志
|
||||||
|
v5.4
|
||||||
|
1.去掉了无用参数
|
||||||
|
|
||||||
|
|
||||||
v5.3
|
v5.3
|
||||||
1.增加了支持日志输出回调的方法:
|
1.增加了支持日志输出回调的方法:
|
||||||
|
|||||||
@ -139,8 +139,8 @@ func StartWithLog(serviceID, serviceArgsStr string, loggerCallback LogCallback)
|
|||||||
tcpArgs.Timeout = tcp.Flag("timeout", "tcp timeout milliseconds when connect to real server or parent proxy").Short('e').Default("2000").Int()
|
tcpArgs.Timeout = tcp.Flag("timeout", "tcp timeout milliseconds when connect to real server or parent proxy").Short('e').Default("2000").Int()
|
||||||
tcpArgs.ParentType = tcp.Flag("parent-type", "parent protocol type <tls|tcp|kcp|udp>").Short('T').Enum("tls", "tcp", "udp", "kcp")
|
tcpArgs.ParentType = tcp.Flag("parent-type", "parent protocol type <tls|tcp|kcp|udp>").Short('T').Enum("tls", "tcp", "udp", "kcp")
|
||||||
tcpArgs.LocalType = tcp.Flag("local-type", "local protocol type <tls|tcp|kcp>").Default("tcp").Short('t').Enum("tls", "tcp", "kcp")
|
tcpArgs.LocalType = tcp.Flag("local-type", "local protocol type <tls|tcp|kcp>").Default("tcp").Short('t').Enum("tls", "tcp", "kcp")
|
||||||
tcpArgs.CheckParentInterval = tcp.Flag("check-parent-interval", "check if proxy is okay every interval seconds,zero: means no check").Short('I').Default("3").Int()
|
|
||||||
tcpArgs.Local = tcp.Flag("local", "local ip:port to listen").Short('p').Default(":33080").String()
|
tcpArgs.Local = tcp.Flag("local", "local ip:port to listen").Short('p').Default(":33080").String()
|
||||||
|
tcpArgs.Jumper = tcp.Flag("jumper", "https or socks5 proxies used when connecting to parent, only worked of -T is tls or tcp, format is https://username:password@host:port https://host:port or socks5://username:password@host:port socks5://host:port").Short('J').Default("").String()
|
||||||
|
|
||||||
//########udp#########
|
//########udp#########
|
||||||
udp := app.Command("udp", "proxy on udp mode")
|
udp := app.Command("udp", "proxy on udp mode")
|
||||||
@ -164,6 +164,7 @@ func StartWithLog(serviceID, serviceArgsStr string, loggerCallback LogCallback)
|
|||||||
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|tls 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()
|
||||||
|
muxServerArgs.Jumper = muxServer.Flag("jumper", "https or socks5 proxies used when connecting to parent, only worked of -T is tls or tcp, format is https://username:password@host:port https://host:port or socks5://username:password@host:port socks5://host:port").Short('J').Default("").String()
|
||||||
|
|
||||||
//########mux-client#########
|
//########mux-client#########
|
||||||
muxClient := app.Command("client", "proxy on mux client mode")
|
muxClient := app.Command("client", "proxy on mux client mode")
|
||||||
@ -175,6 +176,7 @@ func StartWithLog(serviceID, serviceArgsStr string, loggerCallback LogCallback)
|
|||||||
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|tls 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()
|
||||||
|
muxClientArgs.Jumper = muxClient.Flag("jumper", "https or socks5 proxies used when connecting to parent, only worked of -T is tls or tcp, format is https://username:password@host:port https://host:port or socks5://username:password@host:port socks5://host:port").Short('J').Default("").String()
|
||||||
|
|
||||||
//########mux-bridge#########
|
//########mux-bridge#########
|
||||||
muxBridge := app.Command("bridge", "proxy on mux bridge mode")
|
muxBridge := app.Command("bridge", "proxy on mux bridge mode")
|
||||||
@ -193,6 +195,7 @@ func StartWithLog(serviceID, serviceArgsStr string, loggerCallback LogCallback)
|
|||||||
tunnelServerArgs.IsUDP = tunnelServer.Flag("udp", "proxy on udp tunnel server mode").Default("false").Bool()
|
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.Key = tunnelServer.Flag("k", "client key").Default("default").String()
|
||||||
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()
|
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()
|
||||||
|
tunnelServerArgs.Jumper = tunnelServer.Flag("jumper", "https or socks5 proxies used when connecting to parent, only worked of -T is tls or tcp, format is https://username:password@host:port https://host:port or socks5://username:password@host:port socks5://host:port").Short('J').Default("").String()
|
||||||
|
|
||||||
//########tunnel-client#########
|
//########tunnel-client#########
|
||||||
tunnelClient := app.Command("tclient", "proxy on tunnel client mode")
|
tunnelClient := app.Command("tclient", "proxy on tunnel client mode")
|
||||||
@ -201,6 +204,7 @@ func StartWithLog(serviceID, serviceArgsStr string, loggerCallback LogCallback)
|
|||||||
tunnelClientArgs.KeyFile = tunnelClient.Flag("key", "key file for tls").Short('K').Default("proxy.key").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.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()
|
tunnelClientArgs.Key = tunnelClient.Flag("k", "key same with server").Default("default").String()
|
||||||
|
tunnelClientArgs.Jumper = tunnelClient.Flag("jumper", "https or socks5 proxies used when connecting to parent, only worked of -T is tls or tcp, format is https://username:password@host:port https://host:port or socks5://username:password@host:port socks5://host:port").Short('J').Default("").String()
|
||||||
|
|
||||||
//########tunnel-bridge#########
|
//########tunnel-bridge#########
|
||||||
tunnelBridge := app.Command("tbridge", "proxy on tunnel bridge mode")
|
tunnelBridge := app.Command("tbridge", "proxy on tunnel bridge mode")
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/snail007/goproxy/services"
|
"github.com/snail007/goproxy/services"
|
||||||
"github.com/snail007/goproxy/services/kcpcfg"
|
"github.com/snail007/goproxy/services/kcpcfg"
|
||||||
"github.com/snail007/goproxy/utils"
|
"github.com/snail007/goproxy/utils"
|
||||||
|
"github.com/snail007/goproxy/utils/jumper"
|
||||||
//"github.com/xtaci/smux"
|
//"github.com/xtaci/smux"
|
||||||
smux "github.com/hashicorp/yamux"
|
smux "github.com/hashicorp/yamux"
|
||||||
)
|
)
|
||||||
@ -28,12 +29,14 @@ type MuxClientArgs struct {
|
|||||||
IsCompress *bool
|
IsCompress *bool
|
||||||
SessionCount *int
|
SessionCount *int
|
||||||
KCP kcpcfg.KCPConfigArgs
|
KCP kcpcfg.KCPConfigArgs
|
||||||
|
Jumper *string
|
||||||
}
|
}
|
||||||
type MuxClient struct {
|
type MuxClient struct {
|
||||||
cfg MuxClientArgs
|
cfg MuxClientArgs
|
||||||
isStop bool
|
isStop bool
|
||||||
sessions utils.ConcurrentMap
|
sessions utils.ConcurrentMap
|
||||||
log *logger.Logger
|
log *logger.Logger
|
||||||
|
jumper *jumper.Jumper
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMuxClient() services.Service {
|
func NewMuxClient() services.Service {
|
||||||
@ -65,6 +68,19 @@ func (s *MuxClient) CheckArgs() (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if *s.cfg.Jumper != "" {
|
||||||
|
if *s.cfg.ParentType != "tls" && *s.cfg.ParentType != "tcp" {
|
||||||
|
err = fmt.Errorf("jumper only worked of -T is tls or tcp")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var j jumper.Jumper
|
||||||
|
j, err = jumper.New(*s.cfg.Jumper, time.Millisecond*time.Duration(*s.cfg.Timeout))
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("parse jumper fail, err %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.jumper = &j
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
func (s *MuxClient) StopService() {
|
func (s *MuxClient) StopService() {
|
||||||
@ -182,15 +198,32 @@ func (s *MuxClient) Clean() {
|
|||||||
}
|
}
|
||||||
func (s *MuxClient) getParentConn() (conn net.Conn, err error) {
|
func (s *MuxClient) getParentConn() (conn net.Conn, err error) {
|
||||||
if *s.cfg.ParentType == "tls" {
|
if *s.cfg.ParentType == "tls" {
|
||||||
|
if s.jumper == nil {
|
||||||
var _conn tls.Conn
|
var _conn tls.Conn
|
||||||
_conn, err = utils.TlsConnectHost(*s.cfg.Parent, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes, nil)
|
_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)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
conf, err := utils.TlsConfig(s.cfg.CertBytes, s.cfg.KeyBytes, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var _c net.Conn
|
||||||
|
_c, err = s.jumper.Dial(*s.cfg.Parent, time.Millisecond*time.Duration(*s.cfg.Timeout))
|
||||||
|
if err == nil {
|
||||||
|
conn = net.Conn(tls.Client(_c, conf))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} else if *s.cfg.ParentType == "kcp" {
|
} else if *s.cfg.ParentType == "kcp" {
|
||||||
conn, err = utils.ConnectKCPHost(*s.cfg.Parent, s.cfg.KCP)
|
conn, err = utils.ConnectKCPHost(*s.cfg.Parent, s.cfg.KCP)
|
||||||
} else {
|
} else {
|
||||||
|
if s.jumper == nil {
|
||||||
conn, err = utils.ConnectHost(*s.cfg.Parent, *s.cfg.Timeout)
|
conn, err = utils.ConnectHost(*s.cfg.Parent, *s.cfg.Timeout)
|
||||||
|
} else {
|
||||||
|
conn, err = s.jumper.Dial(*s.cfg.Parent, time.Millisecond*time.Duration(*s.cfg.Timeout))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import (
|
|||||||
"github.com/snail007/goproxy/services"
|
"github.com/snail007/goproxy/services"
|
||||||
"github.com/snail007/goproxy/services/kcpcfg"
|
"github.com/snail007/goproxy/services/kcpcfg"
|
||||||
"github.com/snail007/goproxy/utils"
|
"github.com/snail007/goproxy/utils"
|
||||||
|
"github.com/snail007/goproxy/utils/jumper"
|
||||||
|
|
||||||
"github.com/golang/snappy"
|
"github.com/golang/snappy"
|
||||||
//"github.com/xtaci/smux"
|
//"github.com/xtaci/smux"
|
||||||
@ -38,6 +39,7 @@ type MuxServerArgs struct {
|
|||||||
IsCompress *bool
|
IsCompress *bool
|
||||||
SessionCount *int
|
SessionCount *int
|
||||||
KCP kcpcfg.KCPConfigArgs
|
KCP kcpcfg.KCPConfigArgs
|
||||||
|
Jumper *string
|
||||||
}
|
}
|
||||||
|
|
||||||
type MuxUDPItem struct {
|
type MuxUDPItem struct {
|
||||||
@ -121,6 +123,7 @@ func (s *MuxServerManager) Start(args interface{}, log *logger.Logger) (err erro
|
|||||||
SessionCount: s.cfg.SessionCount,
|
SessionCount: s.cfg.SessionCount,
|
||||||
KCP: s.cfg.KCP,
|
KCP: s.cfg.KCP,
|
||||||
ParentType: s.cfg.ParentType,
|
ParentType: s.cfg.ParentType,
|
||||||
|
Jumper: s.cfg.Jumper,
|
||||||
}, log)
|
}, log)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -164,6 +167,7 @@ type MuxServer struct {
|
|||||||
isStop bool
|
isStop bool
|
||||||
udpConn *net.Conn
|
udpConn *net.Conn
|
||||||
log *logger.Logger
|
log *logger.Logger
|
||||||
|
jumper *jumper.Jumper
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMuxServer() services.Service {
|
func NewMuxServer() services.Service {
|
||||||
@ -208,6 +212,19 @@ func (s *MuxServer) CheckArgs() (err error) {
|
|||||||
err = fmt.Errorf("remote required")
|
err = fmt.Errorf("remote required")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if *s.cfg.Jumper != "" {
|
||||||
|
if *s.cfg.ParentType != "tls" && *s.cfg.ParentType != "tcp" {
|
||||||
|
err = fmt.Errorf("jumper only worked of -T is tls or tcp")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var j jumper.Jumper
|
||||||
|
j, err = jumper.New(*s.cfg.Jumper, time.Millisecond*time.Duration(*s.cfg.Timeout))
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("parse jumper fail, err %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.jumper = &j
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -378,15 +395,32 @@ func (s *MuxServer) GetConn(index string) (conn net.Conn, err error) {
|
|||||||
}
|
}
|
||||||
func (s *MuxServer) getParentConn() (conn net.Conn, err error) {
|
func (s *MuxServer) getParentConn() (conn net.Conn, err error) {
|
||||||
if *s.cfg.ParentType == "tls" {
|
if *s.cfg.ParentType == "tls" {
|
||||||
|
if s.jumper == nil {
|
||||||
var _conn tls.Conn
|
var _conn tls.Conn
|
||||||
_conn, err = utils.TlsConnectHost(*s.cfg.Parent, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes, nil)
|
_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)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
conf, err := utils.TlsConfig(s.cfg.CertBytes, s.cfg.KeyBytes, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var _c net.Conn
|
||||||
|
_c, err = s.jumper.Dial(*s.cfg.Parent, time.Millisecond*time.Duration(*s.cfg.Timeout))
|
||||||
|
if err == nil {
|
||||||
|
conn = net.Conn(tls.Client(_c, conf))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} else if *s.cfg.ParentType == "kcp" {
|
} else if *s.cfg.ParentType == "kcp" {
|
||||||
conn, err = utils.ConnectKCPHost(*s.cfg.Parent, s.cfg.KCP)
|
conn, err = utils.ConnectKCPHost(*s.cfg.Parent, s.cfg.KCP)
|
||||||
} else {
|
} else {
|
||||||
|
if s.jumper == nil {
|
||||||
conn, err = utils.ConnectHost(*s.cfg.Parent, *s.cfg.Timeout)
|
conn, err = utils.ConnectHost(*s.cfg.Parent, *s.cfg.Timeout)
|
||||||
|
} else {
|
||||||
|
conn, err = s.jumper.Dial(*s.cfg.Parent, time.Millisecond*time.Duration(*s.cfg.Timeout))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package tcp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
logger "log"
|
logger "log"
|
||||||
@ -12,6 +13,7 @@ import (
|
|||||||
"github.com/snail007/goproxy/services"
|
"github.com/snail007/goproxy/services"
|
||||||
"github.com/snail007/goproxy/services/kcpcfg"
|
"github.com/snail007/goproxy/services/kcpcfg"
|
||||||
"github.com/snail007/goproxy/utils"
|
"github.com/snail007/goproxy/utils"
|
||||||
|
"github.com/snail007/goproxy/utils/jumper"
|
||||||
|
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
@ -26,22 +28,21 @@ type TCPArgs struct {
|
|||||||
ParentType *string
|
ParentType *string
|
||||||
LocalType *string
|
LocalType *string
|
||||||
Timeout *int
|
Timeout *int
|
||||||
CheckParentInterval *int
|
|
||||||
KCP kcpcfg.KCPConfigArgs
|
KCP kcpcfg.KCPConfigArgs
|
||||||
|
Jumper *string
|
||||||
}
|
}
|
||||||
|
|
||||||
type TCP struct {
|
type TCP struct {
|
||||||
outPool utils.OutConn
|
|
||||||
cfg TCPArgs
|
cfg TCPArgs
|
||||||
sc *utils.ServerChannel
|
sc *utils.ServerChannel
|
||||||
isStop bool
|
isStop bool
|
||||||
userConns utils.ConcurrentMap
|
userConns utils.ConcurrentMap
|
||||||
log *logger.Logger
|
log *logger.Logger
|
||||||
|
jumper *jumper.Jumper
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTCP() services.Service {
|
func NewTCP() services.Service {
|
||||||
return &TCP{
|
return &TCP{
|
||||||
outPool: utils.OutConn{},
|
|
||||||
cfg: TCPArgs{},
|
cfg: TCPArgs{},
|
||||||
isStop: false,
|
isStop: false,
|
||||||
userConns: utils.NewConcurrentMap(),
|
userConns: utils.NewConcurrentMap(),
|
||||||
@ -62,10 +63,23 @@ func (s *TCP) CheckArgs() (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if *s.cfg.Jumper != "" {
|
||||||
|
if *s.cfg.ParentType != "tls" && *s.cfg.ParentType != "tcp" {
|
||||||
|
err = fmt.Errorf("jumper only worked of -T is tls or tcp")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var j jumper.Jumper
|
||||||
|
j, err = jumper.New(*s.cfg.Jumper, time.Millisecond*time.Duration(*s.cfg.Timeout))
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("parse jumper fail, err %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.jumper = &j
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
func (s *TCP) InitService() (err error) {
|
func (s *TCP) InitService() (err error) {
|
||||||
s.InitOutConnPool()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
func (s *TCP) StopService() {
|
func (s *TCP) StopService() {
|
||||||
@ -146,7 +160,7 @@ func (s *TCP) callback(inConn net.Conn) {
|
|||||||
}
|
}
|
||||||
func (s *TCP) OutToTCP(inConn *net.Conn) (err error) {
|
func (s *TCP) OutToTCP(inConn *net.Conn) (err error) {
|
||||||
var outConn net.Conn
|
var outConn net.Conn
|
||||||
outConn, err = s.outPool.Get()
|
outConn, err = s.GetParentConn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log.Printf("connect to %s , err:%s", *s.cfg.Parent, err)
|
s.log.Printf("connect to %s , err:%s", *s.cfg.Parent, err)
|
||||||
utils.CloseConn(inConn)
|
utils.CloseConn(inConn)
|
||||||
@ -219,17 +233,34 @@ func (s *TCP) OutToUDP(inConn *net.Conn) (err error) {
|
|||||||
return
|
return
|
||||||
|
|
||||||
}
|
}
|
||||||
func (s *TCP) InitOutConnPool() {
|
func (s *TCP) GetParentConn() (conn net.Conn, err error) {
|
||||||
if *s.cfg.ParentType == "tls" || *s.cfg.ParentType == "tcp" || *s.cfg.ParentType == "kcp" {
|
if *s.cfg.ParentType == "tls" {
|
||||||
//dur int, isTLS bool, certBytes, keyBytes []byte,
|
if s.jumper == nil {
|
||||||
//parent string, timeout int, InitialCap int, MaxCap int
|
var _conn tls.Conn
|
||||||
s.outPool = utils.NewOutConn(
|
_conn, err = utils.TlsConnectHost(*s.cfg.Parent, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes, nil)
|
||||||
*s.cfg.CheckParentInterval,
|
if err == nil {
|
||||||
*s.cfg.ParentType,
|
conn = net.Conn(&_conn)
|
||||||
s.cfg.KCP,
|
|
||||||
s.cfg.CertBytes, s.cfg.KeyBytes, nil,
|
|
||||||
*s.cfg.Parent,
|
|
||||||
*s.cfg.Timeout,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
conf, err := utils.TlsConfig(s.cfg.CertBytes, s.cfg.KeyBytes, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var _c net.Conn
|
||||||
|
_c, err = s.jumper.Dial(*s.cfg.Parent, time.Millisecond*time.Duration(*s.cfg.Timeout))
|
||||||
|
if err == nil {
|
||||||
|
conn = net.Conn(tls.Client(_c, conf))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if *s.cfg.ParentType == "kcp" {
|
||||||
|
conn, err = utils.ConnectKCPHost(*s.cfg.Parent, s.cfg.KCP)
|
||||||
|
} else {
|
||||||
|
if s.jumper == nil {
|
||||||
|
conn, err = utils.ConnectHost(*s.cfg.Parent, *s.cfg.Timeout)
|
||||||
|
} else {
|
||||||
|
conn, err = s.jumper.Dial(*s.cfg.Parent, time.Millisecond*time.Duration(*s.cfg.Timeout))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,7 +30,6 @@ type TunnelBridgeArgs struct {
|
|||||||
KeyBytes []byte
|
KeyBytes []byte
|
||||||
Local *string
|
Local *string
|
||||||
Timeout *int
|
Timeout *int
|
||||||
Mux *bool
|
|
||||||
}
|
}
|
||||||
type ServerConn struct {
|
type ServerConn struct {
|
||||||
//ClientLocalAddr string //tcp:2.2.22:333@ID
|
//ClientLocalAddr string //tcp:2.2.22:333@ID
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import (
|
|||||||
|
|
||||||
"github.com/snail007/goproxy/services"
|
"github.com/snail007/goproxy/services"
|
||||||
"github.com/snail007/goproxy/utils"
|
"github.com/snail007/goproxy/utils"
|
||||||
|
"github.com/snail007/goproxy/utils/jumper"
|
||||||
//"github.com/xtaci/smux"
|
//"github.com/xtaci/smux"
|
||||||
smux "github.com/hashicorp/yamux"
|
smux "github.com/hashicorp/yamux"
|
||||||
)
|
)
|
||||||
@ -28,7 +29,7 @@ type TunnelClientArgs struct {
|
|||||||
KeyBytes []byte
|
KeyBytes []byte
|
||||||
Key *string
|
Key *string
|
||||||
Timeout *int
|
Timeout *int
|
||||||
Mux *bool
|
Jumper *string
|
||||||
}
|
}
|
||||||
type TunnelClient struct {
|
type TunnelClient struct {
|
||||||
cfg TunnelClientArgs
|
cfg TunnelClientArgs
|
||||||
@ -36,6 +37,7 @@ type TunnelClient struct {
|
|||||||
isStop bool
|
isStop bool
|
||||||
userConns utils.ConcurrentMap
|
userConns utils.ConcurrentMap
|
||||||
log *logger.Logger
|
log *logger.Logger
|
||||||
|
jumper *jumper.Jumper
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTunnelClient() services.Service {
|
func NewTunnelClient() services.Service {
|
||||||
@ -62,6 +64,18 @@ func (s *TunnelClient) CheckArgs() (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.cfg.CertBytes, s.cfg.KeyBytes, err = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
|
s.cfg.CertBytes, s.cfg.KeyBytes, err = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if *s.cfg.Jumper != "" {
|
||||||
|
var j jumper.Jumper
|
||||||
|
j, err = jumper.New(*s.cfg.Jumper, time.Millisecond*time.Duration(*s.cfg.Timeout))
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("parse jumper fail, err %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.jumper = &j
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
func (s *TunnelClient) StopService() {
|
func (s *TunnelClient) StopService() {
|
||||||
@ -151,10 +165,24 @@ func (s *TunnelClient) GetInConn(typ uint8, data ...string) (outConn net.Conn, e
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
func (s *TunnelClient) GetConn() (conn net.Conn, err error) {
|
func (s *TunnelClient) GetConn() (conn net.Conn, err error) {
|
||||||
|
if s.jumper == nil {
|
||||||
var _conn tls.Conn
|
var _conn tls.Conn
|
||||||
_conn, err = utils.TlsConnectHost(*s.cfg.Parent, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes, nil)
|
_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)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
conf, err := utils.TlsConfig(s.cfg.CertBytes, s.cfg.KeyBytes, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var _c net.Conn
|
||||||
|
_c, err = s.jumper.Dial(*s.cfg.Parent, time.Millisecond*time.Duration(*s.cfg.Timeout))
|
||||||
|
if err == nil {
|
||||||
|
conn = net.Conn(tls.Client(_c, conf))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
c, e := smux.Client(conn, &smux.Config{
|
c, e := smux.Client(conn, &smux.Config{
|
||||||
AcceptBacklog: 256,
|
AcceptBacklog: 256,
|
||||||
EnableKeepAlive: true,
|
EnableKeepAlive: true,
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import (
|
|||||||
|
|
||||||
"github.com/snail007/goproxy/services"
|
"github.com/snail007/goproxy/services"
|
||||||
"github.com/snail007/goproxy/utils"
|
"github.com/snail007/goproxy/utils"
|
||||||
|
"github.com/snail007/goproxy/utils/jumper"
|
||||||
|
|
||||||
//"github.com/xtaci/smux"
|
//"github.com/xtaci/smux"
|
||||||
smux "github.com/hashicorp/yamux"
|
smux "github.com/hashicorp/yamux"
|
||||||
@ -32,7 +33,7 @@ type TunnelServerArgs struct {
|
|||||||
Timeout *int
|
Timeout *int
|
||||||
Route *[]string
|
Route *[]string
|
||||||
Mgr *TunnelServerManager
|
Mgr *TunnelServerManager
|
||||||
Mux *bool
|
Jumper *string
|
||||||
}
|
}
|
||||||
type UDPItem struct {
|
type UDPItem struct {
|
||||||
packet *[]byte
|
packet *[]byte
|
||||||
@ -105,6 +106,7 @@ func (s *TunnelServerManager) Start(args interface{}, log *logger.Logger) (err e
|
|||||||
Key: &KEY,
|
Key: &KEY,
|
||||||
Timeout: s.cfg.Timeout,
|
Timeout: s.cfg.Timeout,
|
||||||
Mgr: s,
|
Mgr: s,
|
||||||
|
Jumper: s.cfg.Jumper,
|
||||||
}, log)
|
}, log)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -134,30 +136,6 @@ func (s *TunnelServerManager) InitService() (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TunnelServerManager) GetOutConn(typ uint8) (outConn net.Conn, ID string, err error) {
|
|
||||||
outConn, err = s.GetConn()
|
|
||||||
if err != nil {
|
|
||||||
s.log.Printf("connection err: %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ID = s.serverID
|
|
||||||
_, err = outConn.Write(utils.BuildPacket(typ, s.serverID))
|
|
||||||
if err != nil {
|
|
||||||
s.log.Printf("write connection data err: %s ,retrying...", err)
|
|
||||||
utils.CloseConn(&outConn)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
func (s *TunnelServerManager) GetConn() (conn net.Conn, err error) {
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
type TunnelServer struct {
|
type TunnelServer struct {
|
||||||
cfg TunnelServerArgs
|
cfg TunnelServerArgs
|
||||||
udpChn chan UDPItem
|
udpChn chan UDPItem
|
||||||
@ -166,6 +144,7 @@ type TunnelServer struct {
|
|||||||
udpConn *net.Conn
|
udpConn *net.Conn
|
||||||
userConns utils.ConcurrentMap
|
userConns utils.ConcurrentMap
|
||||||
log *logger.Logger
|
log *logger.Logger
|
||||||
|
jumper *jumper.Jumper
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTunnelServer() services.Service {
|
func NewTunnelServer() services.Service {
|
||||||
@ -210,6 +189,15 @@ func (s *TunnelServer) CheckArgs() (err error) {
|
|||||||
err = fmt.Errorf("remote required")
|
err = fmt.Errorf("remote required")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if *s.cfg.Jumper != "" {
|
||||||
|
var j jumper.Jumper
|
||||||
|
j, err = jumper.New(*s.cfg.Jumper, time.Millisecond*time.Duration(*s.cfg.Timeout))
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("parse jumper fail, err %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.jumper = &j
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,11 +289,26 @@ func (s *TunnelServer) GetOutConn(typ uint8) (outConn net.Conn, ID string, err e
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
func (s *TunnelServer) GetConn() (conn net.Conn, err error) {
|
func (s *TunnelServer) GetConn() (conn net.Conn, err error) {
|
||||||
|
var dconn net.Conn
|
||||||
|
if s.jumper == nil {
|
||||||
var _conn tls.Conn
|
var _conn tls.Conn
|
||||||
_conn, err = utils.TlsConnectHost(*s.cfg.Parent, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes, nil)
|
_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)
|
dconn = net.Conn(&_conn)
|
||||||
c, e := smux.Client(conn, &smux.Config{
|
}
|
||||||
|
} else {
|
||||||
|
conf, err := utils.TlsConfig(s.cfg.CertBytes, s.cfg.KeyBytes, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var _c net.Conn
|
||||||
|
_c, err = s.jumper.Dial(*s.cfg.Parent, time.Millisecond*time.Duration(*s.cfg.Timeout))
|
||||||
|
if err == nil {
|
||||||
|
dconn = net.Conn(tls.Client(_c, conf))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
sess, e := smux.Client(dconn, &smux.Config{
|
||||||
AcceptBacklog: 256,
|
AcceptBacklog: 256,
|
||||||
EnableKeepAlive: true,
|
EnableKeepAlive: true,
|
||||||
KeepAliveInterval: 9 * time.Second,
|
KeepAliveInterval: 9 * time.Second,
|
||||||
@ -316,14 +319,30 @@ func (s *TunnelServer) GetConn() (conn net.Conn, err error) {
|
|||||||
if e != nil {
|
if e != nil {
|
||||||
s.log.Printf("new mux client conn error,ERR:%s", e)
|
s.log.Printf("new mux client conn error,ERR:%s", e)
|
||||||
err = e
|
err = e
|
||||||
|
dconn.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
conn, e = c.OpenStream()
|
conn, e = sess.OpenStream()
|
||||||
if e != nil {
|
if e != nil {
|
||||||
s.log.Printf("mux client conn open stream error,ERR:%s", e)
|
s.log.Printf("mux client conn open stream error,ERR:%s", e)
|
||||||
err = e
|
err = e
|
||||||
|
dconn.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
go func() {
|
||||||
|
defer func() {
|
||||||
|
_ = recover()
|
||||||
|
}()
|
||||||
|
timer := time.NewTicker(time.Second * 3)
|
||||||
|
for {
|
||||||
|
<-timer.C
|
||||||
|
if sess.NumStreams() == 0 {
|
||||||
|
sess.Close()
|
||||||
|
timer.Stop()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -108,6 +108,9 @@ func TlsConnect(host string, port, timeout int, certBytes, keyBytes, caCertBytes
|
|||||||
}
|
}
|
||||||
return *tls.Client(_conn, conf), err
|
return *tls.Client(_conn, conf), err
|
||||||
}
|
}
|
||||||
|
func TlsConfig(certBytes, keyBytes, caCertBytes []byte) (conf *tls.Config, err error) {
|
||||||
|
return getRequestTlsConfig(certBytes, keyBytes, caCertBytes)
|
||||||
|
}
|
||||||
func getRequestTlsConfig(certBytes, keyBytes, caCertBytes []byte) (conf *tls.Config, err error) {
|
func getRequestTlsConfig(certBytes, keyBytes, caCertBytes []byte) (conf *tls.Config, err error) {
|
||||||
|
|
||||||
var cert tls.Certificate
|
var cert tls.Certificate
|
||||||
|
|||||||
100
utils/jumper/jumper.go
Normal file
100
utils/jumper/jumper.go
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
package jumper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/base64"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/url"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/net/proxy"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Jumper struct {
|
||||||
|
proxyURL *url.URL
|
||||||
|
timeout time.Duration
|
||||||
|
}
|
||||||
|
type socks5Dialer struct {
|
||||||
|
timeout time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s socks5Dialer) Dial(network, addr string) (net.Conn, error) {
|
||||||
|
return net.DialTimeout(network, addr, s.timeout)
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(proxyURL string, timeout time.Duration) (j Jumper, err error) {
|
||||||
|
u, err := url.Parse(proxyURL)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
j = Jumper{
|
||||||
|
proxyURL: u,
|
||||||
|
timeout: timeout,
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func (j *Jumper) Dial(address string, timeout time.Duration) (conn net.Conn, err error) {
|
||||||
|
switch j.proxyURL.Scheme {
|
||||||
|
case "https":
|
||||||
|
return j.dialHTTPS(address, timeout)
|
||||||
|
case "socks5":
|
||||||
|
return j.dialSOCKS5(address, timeout)
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unkown scheme of %s", j.proxyURL.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (j *Jumper) dialHTTPS(address string, timeout time.Duration) (conn net.Conn, err error) {
|
||||||
|
conn, err = net.DialTimeout("tcp", j.proxyURL.Host, timeout)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
pb := new(bytes.Buffer)
|
||||||
|
pb.Write([]byte(fmt.Sprintf("CONNECT %s HTTP/1.1\r\n", address)))
|
||||||
|
pb.WriteString("Proxy-Connection: Keep-Alive\r\n")
|
||||||
|
if j.proxyURL.User != nil {
|
||||||
|
p, _ := j.proxyURL.User.Password()
|
||||||
|
u := fmt.Sprintf("%s:%s", j.proxyURL.User.Username(), p)
|
||||||
|
pb.Write([]byte(fmt.Sprintf("Proxy-Authorization: Basic %s\r\n", base64.StdEncoding.EncodeToString([]byte(u)))))
|
||||||
|
}
|
||||||
|
pb.Write([]byte("\r\n"))
|
||||||
|
_, err = conn.Write(pb.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
conn.Close()
|
||||||
|
conn = nil
|
||||||
|
err = fmt.Errorf("error connecting to proxy: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
reply := make([]byte, 1024)
|
||||||
|
conn.SetDeadline(time.Now().Add(timeout))
|
||||||
|
n, err := conn.Read(reply)
|
||||||
|
conn.SetDeadline(time.Time{})
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("error read reply from proxy: %s", err)
|
||||||
|
conn.Close()
|
||||||
|
conn = nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if bytes.Index(reply[:n], []byte("200")) == -1 {
|
||||||
|
err = fmt.Errorf("error greeting to proxy, response: %s", string(reply[:n]))
|
||||||
|
conn.Close()
|
||||||
|
conn = nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func (j *Jumper) dialSOCKS5(address string, timeout time.Duration) (conn net.Conn, err error) {
|
||||||
|
auth := &proxy.Auth{}
|
||||||
|
if j.proxyURL.User != nil {
|
||||||
|
auth.User = j.proxyURL.User.Username()
|
||||||
|
auth.Password, _ = j.proxyURL.User.Password()
|
||||||
|
} else {
|
||||||
|
auth = nil
|
||||||
|
}
|
||||||
|
dialSocksProxy, err := proxy.SOCKS5("tcp", j.proxyURL.Host, auth, socks5Dialer{timeout: timeout})
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("error connecting to proxy: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return dialSocksProxy.Dial("tcp", address)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user