From aab899397ef921a25b30d58ae16f3f73b1de1fb4 Mon Sep 17 00:00:00 2001 From: "arraykeys@gmail.com" Date: Tue, 21 Aug 2018 10:29:51 +0800 Subject: [PATCH 1/6] fix GetAllInterfaceAddr cpu high --- README_ZH.md | 4 ++-- docs/old-release.md | 1 + install_auto.sh | 2 +- main.go | 2 +- release.sh | 2 +- utils/functions.go | 14 +++++++++----- 6 files changed, 15 insertions(+), 10 deletions(-) diff --git a/README_ZH.md b/README_ZH.md index fd831d4..e86a901 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -48,7 +48,7 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5代理服务 - ... -本页是v5.3手册,其他版本手册请点击[这里](docs/old-release.md)查看. +本页是v5.4手册,其他版本手册请点击[这里](docs/old-release.md)查看. ### 怎么找到组织? @@ -159,7 +159,7 @@ curl -L https://raw.githubusercontent.com/snail007/goproxy/master/install_auto.s 下载地址:https://github.com/snail007/goproxy/releases ```shell cd /root/proxy/ -wget https://github.com/snail007/goproxy/releases/download/v5.3/proxy-linux-amd64.tar.gz +wget https://github.com/snail007/goproxy/releases/download/v5.4/proxy-linux-amd64.tar.gz ``` #### **2.下载自动安装脚本** ```shell diff --git a/docs/old-release.md b/docs/old-release.md index d7c3c40..5ac0994 100644 --- a/docs/old-release.md +++ b/docs/old-release.md @@ -1,5 +1,6 @@ # Old Versions of Proxy +- [v5.3手册](https://github.com/snail007/goproxy/tree/v5.3) - [v5.2手册](https://github.com/snail007/goproxy/tree/v5.2) - [v5.1手册](https://github.com/snail007/goproxy/tree/v5.1) - [v5.0手册](https://github.com/snail007/goproxy/tree/v5.0) diff --git a/install_auto.sh b/install_auto.sh index 515a2a7..295a483 100755 --- a/install_auto.sh +++ b/install_auto.sh @@ -5,7 +5,7 @@ if [ -e /tmp/proxy ]; then fi mkdir /tmp/proxy cd /tmp/proxy -wget https://github.com/snail007/goproxy/releases/download/v5.3/proxy-linux-amd64.tar.gz +wget https://github.com/snail007/goproxy/releases/download/v5.4/proxy-linux-amd64.tar.gz # #install proxy tar zxvf proxy-linux-amd64.tar.gz diff --git a/main.go b/main.go index 900bab4..9d0cd56 100644 --- a/main.go +++ b/main.go @@ -9,7 +9,7 @@ import ( "github.com/snail007/goproxy/services" ) -const APP_VERSION = "5.3" +const APP_VERSION = "5.4" func main() { err := initConfig() diff --git a/release.sh b/release.sh index 98508d6..afbd889 100755 --- a/release.sh +++ b/release.sh @@ -1,5 +1,5 @@ #!/bin/bash -VER="5.3" +VER="5.4" RELEASE="release-${VER}" rm -rf .cert mkdir .cert diff --git a/utils/functions.go b/utils/functions.go index f25ee2a..0e960fb 100755 --- a/utils/functions.go +++ b/utils/functions.go @@ -22,15 +22,14 @@ import ( "golang.org/x/crypto/pbkdf2" + "context" "strconv" "strings" "time" - "context" "github.com/snail007/goproxy/utils/id" kcp "github.com/xtaci/kcp-go" - ) func IoBind(dst io.ReadWriteCloser, src io.ReadWriteCloser, fn func(err interface{}), log *logger.Logger) { @@ -210,8 +209,13 @@ func CloseConn(conn *net.Conn) { (*conn).Close() } } -func GetAllInterfaceAddr() ([]net.IP, error) { +var allInterfaceAddrCache []net.IP + +func GetAllInterfaceAddr() ([]net.IP, error) { + if allInterfaceAddrCache != nil { + return allInterfaceAddrCache, nil + } ifaces, err := net.Interfaces() if err != nil { return nil, err @@ -252,6 +256,7 @@ func GetAllInterfaceAddr() ([]net.IP, error) { return nil, fmt.Errorf("no address Found, net.InterfaceAddrs: %v", addresses) } //only need first + allInterfaceAddrCache = addresses return addresses, nil } func UDPPacket(srcAddr string, packet []byte) []byte { @@ -635,14 +640,13 @@ func InsertProxyHeaders(head []byte, headers string) []byte { // return // } - /* net.LookupIP may cause deadlock in windows https://github.com/golang/go/issues/24178 */ func MyLookupIP(host string) ([]net.IP, error) { - ctx ,cancel := context.WithTimeout(context.Background(),time.Second *time.Duration(3)) + ctx, cancel := context.WithTimeout(context.Background(), time.Second*time.Duration(3)) defer func() { cancel() //ctx.Done() From c9f8f6c6fb6bfe1c2c820ae9ddd14d8a57ae61bf Mon Sep 17 00:00:00 2001 From: "arraykeys@gmail.com" Date: Tue, 21 Aug 2018 10:52:18 +0800 Subject: [PATCH 2/6] fix GetAllInterfaceAddr cpu high --- CHANGELOG | 4 ++++ config.go | 6 +++++- sdk/android-ios/sdk.go | 6 +++++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 2eb1f0e..f572678 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,8 @@ proxy更新日志 +v5.4 +1.优化了获取本地IP信息导致CPU过高的问题. +2.所有服务都增加了--nolog参数,可以关闭日志输出,节省CPU. + v5.3 1.优化了socks_client握手端口判断,避免了sstap测试UDP失败的问题. diff --git a/config.go b/config.go index 4aeeb9a..00c56f9 100755 --- a/config.go +++ b/config.go @@ -4,6 +4,7 @@ import ( "bufio" "crypto/sha1" "fmt" + "io/ioutil" logger "log" "os" "os/exec" @@ -62,6 +63,7 @@ func initConfig() (err error) { daemon := app.Flag("daemon", "run proxy in background").Default("false").Bool() forever := app.Flag("forever", "run proxy in forever,fail and retry").Default("false").Bool() logfile := app.Flag("log", "log file path").Default("").String() + nolog := app.Flag("nolog", "turn off logging").Default("false").Bool() kcpArgs.Key = app.Flag("kcp-key", "pre-shared secret between client and server").Default("secrect").String() kcpArgs.Crypt = app.Flag("kcp-method", "encrypt/decrypt method, can be: aes, aes-128, aes-192, salsa20, blowfish, twofish, cast5, 3des, tea, xtea, xor, sm4, none").Default("aes").Enum("aes", "aes-128", "aes-192", "salsa20", "blowfish", "twofish", "cast5", "3des", "tea", "xtea", "xor", "sm4", "none") kcpArgs.Mode = app.Flag("kcp-mode", "profiles: fast3, fast2, fast, normal, manual").Default("fast").Enum("fast3", "fast2", "fast", "normal", "manual") @@ -352,7 +354,9 @@ func initConfig() (err error) { } log.SetFlags(flags) - if *logfile != "" { + if *nolog { + log.SetOutput(ioutil.Discard) + } else if *logfile != "" { f, e := os.OpenFile(*logfile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600) if e != nil { log.Fatal(e) diff --git a/sdk/android-ios/sdk.go b/sdk/android-ios/sdk.go index 55873e7..ec058e9 100644 --- a/sdk/android-ios/sdk.go +++ b/sdk/android-ios/sdk.go @@ -3,6 +3,7 @@ package proxy import ( "crypto/sha1" "fmt" + "io/ioutil" logger "log" "os" "path" @@ -77,6 +78,7 @@ func StartWithLog(serviceID, serviceArgsStr string, loggerCallback LogCallback) app.Author("snail").Version(SDK_VERSION) debug := app.Flag("debug", "debug log output").Default("false").Bool() logfile := app.Flag("log", "log file path").Default("").String() + nolog := app.Flag("nolog", "turn off logging").Default("false").Bool() kcpArgs.Key = app.Flag("kcp-key", "pre-shared secret between client and server").Default("secrect").String() kcpArgs.Crypt = app.Flag("kcp-method", "encrypt/decrypt method, can be: aes, aes-128, aes-192, salsa20, blowfish, twofish, cast5, 3des, tea, xtea, xor, sm4, none").Default("aes").Enum("aes", "aes-128", "aes-192", "salsa20", "blowfish", "twofish", "cast5", "3des", "tea", "xtea", "xor", "sm4", "none") kcpArgs.Mode = app.Flag("kcp-mode", "profiles: fast3, fast2, fast, normal, manual").Default("fast3").Enum("fast3", "fast2", "fast", "normal", "manual") @@ -357,7 +359,9 @@ func StartWithLog(serviceID, serviceArgsStr string, loggerCallback LogCallback) log.SetFlags(flags) if loggerCallback == nil { - if *logfile != "" { + if *nolog { + log.SetOutput(ioutil.Discard) + } else if *logfile != "" { f, e := os.OpenFile(*logfile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600) if e != nil { log.Fatal(e) From abdcae31c9595aefb2e2a080e541c3e209bd295f Mon Sep 17 00:00:00 2001 From: "arraykeys@gmail.com" Date: Fri, 24 Aug 2018 11:40:36 +0800 Subject: [PATCH 3/6] =?UTF-8?q?=E4=BC=98=E5=8C=96sdk,=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=B9=B6=E5=8F=91=E5=90=AF=E5=8A=A8/=E5=85=B3=E9=97=AD?= =?UTF-8?q?=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- services/service.go | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/services/service.go b/services/service.go index 4a4040f..d126642 100644 --- a/services/service.go +++ b/services/service.go @@ -4,6 +4,7 @@ import ( "fmt" logger "log" "runtime/debug" + "sync" ) type Service interface { @@ -17,31 +18,31 @@ type ServiceItem struct { Log *logger.Logger } -var servicesMap = map[string]*ServiceItem{} +var servicesMap = sync.Map{} func Regist(name string, s Service, args interface{}, log *logger.Logger) { Stop(name) - servicesMap[name] = &ServiceItem{ + servicesMap.Store(name, &ServiceItem{ S: s, Args: args, Name: name, Log: log, - } + }) } func GetService(name string) *ServiceItem { - if s, ok := servicesMap[name]; ok && s.S != nil { - return s + if s, ok := servicesMap.Load(name); ok && s.(*ServiceItem).S != nil { + return s.(*ServiceItem) } return nil } func Stop(name string) { - if s, ok := servicesMap[name]; ok && s.S != nil { - s.S.Clean() + if s, ok := servicesMap.Load(name); ok && s.(*ServiceItem).S != nil { + s.(*ServiceItem).S.Clean() } } func Run(name string, args interface{}) (service *ServiceItem, err error) { - service, ok := servicesMap[name] + _service, ok := servicesMap.Load(name) if ok { defer func() { e := recover() @@ -49,6 +50,7 @@ func Run(name string, args interface{}) (service *ServiceItem, err error) { err = fmt.Errorf("%s servcie crashed, ERR: %s\ntrace:%s", name, e, string(debug.Stack())) } }() + service = _service.(*ServiceItem) if args != nil { err = service.S.Start(args, service.Log) } else { From 889ce7667686122ff0fd883d2e2638ba3ae200ec Mon Sep 17 00:00:00 2001 From: "arraykeys@gmail.com" Date: Fri, 24 Aug 2018 11:41:15 +0800 Subject: [PATCH 4/6] =?UTF-8?q?=E4=BC=98=E5=8C=96sdk,=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=B9=B6=E5=8F=91=E5=90=AF=E5=8A=A8/=E5=85=B3=E9=97=AD?= =?UTF-8?q?=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index f572678..d38072f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,7 @@ proxy更新日志 v5.4 1.优化了获取本地IP信息导致CPU过高的问题. 2.所有服务都增加了--nolog参数,可以关闭日志输出,节省CPU. +3.优化sdk,支持并发启动/关闭操作. v5.3 1.优化了socks_client握手端口判断,避免了sstap测试UDP失败的问题. From 375eb9aa665276babda5d5beffe053177f72e6b0 Mon Sep 17 00:00:00 2001 From: "arraykeys@gmail.com" Date: Thu, 30 Aug 2018 15:34:13 +0800 Subject: [PATCH 5/6] v5.4 --- CHANGELOG | 3 + README_ZH.md | 54 +++++++++++++++-- config.go | 6 +- sdk/CHANGELOG | 3 + sdk/android-ios/sdk.go | 6 +- services/mux/mux_client.go | 43 +++++++++++-- services/mux/mux_server.go | 44 ++++++++++++-- services/tcp/tcp.go | 85 +++++++++++++++++--------- services/tunnel/tunnel_bridge.go | 1 - services/tunnel/tunnel_client.go | 36 +++++++++-- services/tunnel/tunnel_server.go | 79 ++++++++++++++---------- utils/functions.go | 3 + utils/jumper/jumper.go | 100 +++++++++++++++++++++++++++++++ 13 files changed, 383 insertions(+), 80 deletions(-) create mode 100644 utils/jumper/jumper.go diff --git a/CHANGELOG b/CHANGELOG index d38072f..71c2141 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,6 +3,9 @@ v5.4 1.优化了获取本地IP信息导致CPU过高的问题. 2.所有服务都增加了--nolog参数,可以关闭日志输出,节省CPU. 3.优化sdk,支持并发启动/关闭操作. +4.修复了多连接版本的内网穿透,tserver连接不能正确释放的bug. +5.内网穿透增加了client/tclient和server/tserver使用代理连接bridge/tbridge的功能,详细内容参考手册. +6.TCP端口映射(TCP代理)增加了使用代理连接上级的功能,详细内容参考手册. v5.3 1.优化了socks_client握手端口判断,避免了sstap测试UDP失败的问题. diff --git a/README_ZH.md b/README_ZH.md index e86a901..80668a5 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -87,14 +87,15 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5代理服务 - [1.12 自定义加密](#112-自定义加密) - [1.13 压缩传输](#113-压缩传输) - [1.14 查看帮助](#114-查看帮助) -- [2. TCP代理](#2tcp代理) +- [2. TCP代理(端口映射)](#2tcp代理) - [2.1 普通一级TCP代理](#21普通一级tcp代理) - [2.2 普通二级TCP代理](#22普通二级tcp代理) - [2.3 普通三级TCP代理](#23普通三级tcp代理) - [2.4 加密二级TCP代理](#24加密二级tcp代理) - [2.5 加密三级TCP代理](#25加密三级tcp代理) - - [2.6 查看帮助](#26查看帮助) -- [3. UDP代理](#3udp代理) + - [2.6 通过代理连接上级](#26通过代理连接上级) + - [2.7 查看帮助](#27查看帮助) +- [3. UDP代理(端口映射)](#3udp代理) - [3.1 普通一级UDP代理](#31普通一级udp代理) - [3.2 普通二级UDP代理](#32普通二级udp代理) - [3.3 普通三级UDP代理](#33普通三级udp代理) @@ -109,7 +110,8 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5代理服务 - [4.5 高级用法一](#45高级用法一) - [4.6 高级用法一](#46高级用法二) - [4.7 server的-r参数](#47server的-r参数) - - [4.8 查看帮助](#48查看帮助) + - [4.8 server和client通过代理连接bridge](#48server和client通过代理连接bridge) + - [4.9 查看帮助](#49查看帮助) - [5. SOCKS5代理](#5socks5代理) - [5.1 普通SOCKS5代理](#51普通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` 那么访问本地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` ### **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.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 server` `./proxy help client` diff --git a/config.go b/config.go index 00c56f9..0e9da16 100755 --- a/config.go +++ b/config.go @@ -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.ParentType = tcp.Flag("parent-type", "parent protocol type ").Short('T').Enum("tls", "tcp", "udp", "kcp") tcpArgs.LocalType = tcp.Flag("local-type", "local protocol type ").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.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 := 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.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.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######### 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.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.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######### 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.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.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######### 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.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.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######### tunnelBridge := app.Command("tbridge", "proxy on tunnel bridge mode") diff --git a/sdk/CHANGELOG b/sdk/CHANGELOG index fd37799..9336b59 100644 --- a/sdk/CHANGELOG +++ b/sdk/CHANGELOG @@ -1,4 +1,7 @@ SDK更新日志 +v5.4 +1.去掉了无用参数 + v5.3 1.增加了支持日志输出回调的方法: diff --git a/sdk/android-ios/sdk.go b/sdk/android-ios/sdk.go index ec058e9..576cd5d 100644 --- a/sdk/android-ios/sdk.go +++ b/sdk/android-ios/sdk.go @@ -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.ParentType = tcp.Flag("parent-type", "parent protocol type ").Short('T').Enum("tls", "tcp", "udp", "kcp") tcpArgs.LocalType = tcp.Flag("local-type", "local protocol type ").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.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 := 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.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.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######### 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.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.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######### 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.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.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######### 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.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.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######### tunnelBridge := app.Command("tbridge", "proxy on tunnel bridge mode") diff --git a/services/mux/mux_client.go b/services/mux/mux_client.go index 3b55819..a40914f 100644 --- a/services/mux/mux_client.go +++ b/services/mux/mux_client.go @@ -12,6 +12,7 @@ import ( "github.com/snail007/goproxy/services" "github.com/snail007/goproxy/services/kcpcfg" "github.com/snail007/goproxy/utils" + "github.com/snail007/goproxy/utils/jumper" //"github.com/xtaci/smux" smux "github.com/hashicorp/yamux" ) @@ -28,12 +29,14 @@ type MuxClientArgs struct { IsCompress *bool SessionCount *int KCP kcpcfg.KCPConfigArgs + Jumper *string } type MuxClient struct { cfg MuxClientArgs isStop bool sessions utils.ConcurrentMap log *logger.Logger + jumper *jumper.Jumper } func NewMuxClient() services.Service { @@ -65,6 +68,19 @@ func (s *MuxClient) CheckArgs() (err error) { 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 } func (s *MuxClient) StopService() { @@ -182,15 +198,32 @@ func (s *MuxClient) Clean() { } func (s *MuxClient) getParentConn() (conn net.Conn, err error) { if *s.cfg.ParentType == "tls" { - var _conn tls.Conn - _conn, err = utils.TlsConnectHost(*s.cfg.Parent, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes, nil) - if err == nil { - conn = net.Conn(&_conn) + if s.jumper == nil { + var _conn tls.Conn + _conn, err = utils.TlsConnectHost(*s.cfg.Parent, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes, nil) + if err == nil { + conn = net.Conn(&_conn) + } + } else { + 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 { - conn, err = utils.ConnectHost(*s.cfg.Parent, *s.cfg.Timeout) + 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 } diff --git a/services/mux/mux_server.go b/services/mux/mux_server.go index d6ebef8..b9321fe 100644 --- a/services/mux/mux_server.go +++ b/services/mux/mux_server.go @@ -15,6 +15,7 @@ import ( "github.com/snail007/goproxy/services" "github.com/snail007/goproxy/services/kcpcfg" "github.com/snail007/goproxy/utils" + "github.com/snail007/goproxy/utils/jumper" "github.com/golang/snappy" //"github.com/xtaci/smux" @@ -38,6 +39,7 @@ type MuxServerArgs struct { IsCompress *bool SessionCount *int KCP kcpcfg.KCPConfigArgs + Jumper *string } type MuxUDPItem struct { @@ -121,6 +123,7 @@ func (s *MuxServerManager) Start(args interface{}, log *logger.Logger) (err erro SessionCount: s.cfg.SessionCount, KCP: s.cfg.KCP, ParentType: s.cfg.ParentType, + Jumper: s.cfg.Jumper, }, log) if err != nil { @@ -164,6 +167,7 @@ type MuxServer struct { isStop bool udpConn *net.Conn log *logger.Logger + jumper *jumper.Jumper } func NewMuxServer() services.Service { @@ -208,6 +212,19 @@ func (s *MuxServer) CheckArgs() (err error) { err = fmt.Errorf("remote required") 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 } @@ -378,15 +395,32 @@ func (s *MuxServer) GetConn(index string) (conn net.Conn, err error) { } func (s *MuxServer) getParentConn() (conn net.Conn, err error) { if *s.cfg.ParentType == "tls" { - var _conn tls.Conn - _conn, err = utils.TlsConnectHost(*s.cfg.Parent, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes, nil) - if err == nil { - conn = net.Conn(&_conn) + if s.jumper == nil { + var _conn tls.Conn + _conn, err = utils.TlsConnectHost(*s.cfg.Parent, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes, nil) + if err == nil { + conn = net.Conn(&_conn) + } + } else { + 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 { - conn, err = utils.ConnectHost(*s.cfg.Parent, *s.cfg.Timeout) + 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 } diff --git a/services/tcp/tcp.go b/services/tcp/tcp.go index 8f7dd75..1ca2105 100644 --- a/services/tcp/tcp.go +++ b/services/tcp/tcp.go @@ -2,6 +2,7 @@ package tcp import ( "bufio" + "crypto/tls" "fmt" "io" logger "log" @@ -12,36 +13,36 @@ import ( "github.com/snail007/goproxy/services" "github.com/snail007/goproxy/services/kcpcfg" "github.com/snail007/goproxy/utils" + "github.com/snail007/goproxy/utils/jumper" "strconv" ) type TCPArgs struct { - Parent *string - CertFile *string - KeyFile *string - CertBytes []byte - KeyBytes []byte - Local *string - ParentType *string - LocalType *string - Timeout *int - CheckParentInterval *int - KCP kcpcfg.KCPConfigArgs + Parent *string + CertFile *string + KeyFile *string + CertBytes []byte + KeyBytes []byte + Local *string + ParentType *string + LocalType *string + Timeout *int + KCP kcpcfg.KCPConfigArgs + Jumper *string } type TCP struct { - outPool utils.OutConn cfg TCPArgs sc *utils.ServerChannel isStop bool userConns utils.ConcurrentMap log *logger.Logger + jumper *jumper.Jumper } func NewTCP() services.Service { return &TCP{ - outPool: utils.OutConn{}, cfg: TCPArgs{}, isStop: false, userConns: utils.NewConcurrentMap(), @@ -62,10 +63,23 @@ func (s *TCP) CheckArgs() (err error) { 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 } func (s *TCP) InitService() (err error) { - s.InitOutConnPool() + return } func (s *TCP) StopService() { @@ -146,7 +160,7 @@ func (s *TCP) callback(inConn net.Conn) { } func (s *TCP) OutToTCP(inConn *net.Conn) (err error) { var outConn net.Conn - outConn, err = s.outPool.Get() + outConn, err = s.GetParentConn() if err != nil { s.log.Printf("connect to %s , err:%s", *s.cfg.Parent, err) utils.CloseConn(inConn) @@ -219,17 +233,34 @@ func (s *TCP) OutToUDP(inConn *net.Conn) (err error) { return } -func (s *TCP) InitOutConnPool() { - if *s.cfg.ParentType == "tls" || *s.cfg.ParentType == "tcp" || *s.cfg.ParentType == "kcp" { - //dur int, isTLS bool, certBytes, keyBytes []byte, - //parent string, timeout int, InitialCap int, MaxCap int - s.outPool = utils.NewOutConn( - *s.cfg.CheckParentInterval, - *s.cfg.ParentType, - s.cfg.KCP, - s.cfg.CertBytes, s.cfg.KeyBytes, nil, - *s.cfg.Parent, - *s.cfg.Timeout, - ) +func (s *TCP) GetParentConn() (conn net.Conn, err error) { + if *s.cfg.ParentType == "tls" { + if s.jumper == nil { + var _conn tls.Conn + _conn, err = utils.TlsConnectHost(*s.cfg.Parent, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes, nil) + if err == nil { + conn = net.Conn(&_conn) + } + } else { + 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 } diff --git a/services/tunnel/tunnel_bridge.go b/services/tunnel/tunnel_bridge.go index d409a61..f02981c 100644 --- a/services/tunnel/tunnel_bridge.go +++ b/services/tunnel/tunnel_bridge.go @@ -30,7 +30,6 @@ type TunnelBridgeArgs struct { KeyBytes []byte Local *string Timeout *int - Mux *bool } type ServerConn struct { //ClientLocalAddr string //tcp:2.2.22:333@ID diff --git a/services/tunnel/tunnel_client.go b/services/tunnel/tunnel_client.go index d759e2e..d83c3f6 100644 --- a/services/tunnel/tunnel_client.go +++ b/services/tunnel/tunnel_client.go @@ -11,6 +11,7 @@ import ( "github.com/snail007/goproxy/services" "github.com/snail007/goproxy/utils" + "github.com/snail007/goproxy/utils/jumper" //"github.com/xtaci/smux" smux "github.com/hashicorp/yamux" ) @@ -28,7 +29,7 @@ type TunnelClientArgs struct { KeyBytes []byte Key *string Timeout *int - Mux *bool + Jumper *string } type TunnelClient struct { cfg TunnelClientArgs @@ -36,6 +37,7 @@ type TunnelClient struct { isStop bool userConns utils.ConcurrentMap log *logger.Logger + jumper *jumper.Jumper } func NewTunnelClient() services.Service { @@ -62,6 +64,18 @@ func (s *TunnelClient) CheckArgs() (err error) { return } 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 } func (s *TunnelClient) StopService() { @@ -151,10 +165,24 @@ func (s *TunnelClient) GetInConn(typ uint8, data ...string) (outConn net.Conn, e return } func (s *TunnelClient) 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 s.jumper == nil { + var _conn tls.Conn + _conn, err = utils.TlsConnectHost(*s.cfg.Parent, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes, nil) + if err == nil { + conn = net.Conn(&_conn) + } + } else { + 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 { - conn = net.Conn(&_conn) c, e := smux.Client(conn, &smux.Config{ AcceptBacklog: 256, EnableKeepAlive: true, diff --git a/services/tunnel/tunnel_server.go b/services/tunnel/tunnel_server.go index 858f168..98f4904 100644 --- a/services/tunnel/tunnel_server.go +++ b/services/tunnel/tunnel_server.go @@ -14,6 +14,7 @@ import ( "github.com/snail007/goproxy/services" "github.com/snail007/goproxy/utils" + "github.com/snail007/goproxy/utils/jumper" //"github.com/xtaci/smux" smux "github.com/hashicorp/yamux" @@ -32,7 +33,7 @@ type TunnelServerArgs struct { Timeout *int Route *[]string Mgr *TunnelServerManager - Mux *bool + Jumper *string } type UDPItem struct { packet *[]byte @@ -105,6 +106,7 @@ func (s *TunnelServerManager) Start(args interface{}, log *logger.Logger) (err e Key: &KEY, Timeout: s.cfg.Timeout, Mgr: s, + Jumper: s.cfg.Jumper, }, log) if err != nil { @@ -134,30 +136,6 @@ func (s *TunnelServerManager) InitService() (err error) { 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 { cfg TunnelServerArgs udpChn chan UDPItem @@ -166,6 +144,7 @@ type TunnelServer struct { udpConn *net.Conn userConns utils.ConcurrentMap log *logger.Logger + jumper *jumper.Jumper } func NewTunnelServer() services.Service { @@ -210,6 +189,15 @@ func (s *TunnelServer) CheckArgs() (err error) { err = fmt.Errorf("remote required") 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 } @@ -301,11 +289,26 @@ func (s *TunnelServer) GetOutConn(typ uint8) (outConn net.Conn, ID string, err e return } func (s *TunnelServer) 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) + var dconn net.Conn + if s.jumper == nil { + var _conn tls.Conn + _conn, err = utils.TlsConnectHost(*s.cfg.Parent, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes, nil) + if err == nil { + dconn = 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 { + dconn = net.Conn(tls.Client(_c, conf)) + } + } if err == nil { - conn = net.Conn(&_conn) - c, e := smux.Client(conn, &smux.Config{ + sess, e := smux.Client(dconn, &smux.Config{ AcceptBacklog: 256, EnableKeepAlive: true, KeepAliveInterval: 9 * time.Second, @@ -316,14 +319,30 @@ func (s *TunnelServer) GetConn() (conn net.Conn, err error) { if e != nil { s.log.Printf("new mux client conn error,ERR:%s", e) err = e + dconn.Close() return } - conn, e = c.OpenStream() + conn, e = sess.OpenStream() if e != nil { s.log.Printf("mux client conn open stream error,ERR:%s", e) err = e + dconn.Close() 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 } diff --git a/utils/functions.go b/utils/functions.go index 0e960fb..9cca81a 100755 --- a/utils/functions.go +++ b/utils/functions.go @@ -108,6 +108,9 @@ func TlsConnect(host string, port, timeout int, certBytes, keyBytes, caCertBytes } 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) { var cert tls.Certificate diff --git a/utils/jumper/jumper.go b/utils/jumper/jumper.go new file mode 100644 index 0000000..e66c85a --- /dev/null +++ b/utils/jumper/jumper.go @@ -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) +} From 33e665631de3840f02cfd9d1b229954d7fabf33d Mon Sep 17 00:00:00 2001 From: "arraykeys@gmail.com" Date: Thu, 30 Aug 2018 16:09:58 +0800 Subject: [PATCH 6/6] v5.4 --- release.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/release.sh b/release.sh index afbd889..4f11736 100755 --- a/release.sh +++ b/release.sh @@ -60,12 +60,12 @@ CGO_ENABLED=0 GOOS=plan9 GOARCH=arm go build -o proxy && tar zcfv "${RELEASE}/pr #solaris CGO_ENABLED=0 GOOS=solaris GOARCH=amd64 go build -o proxy && tar zcfv "${RELEASE}/proxy-solaris-amd64.tar.gz" proxy direct blocked #windows -CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -ldflags="-H=windowsgui" -o proxy-wingui.exe -CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -o proxy.exe && tar zcfv "${RELEASE}/proxy-windows-386.tar.gz" proxy.exe proxy-wingui.exe direct blocked .cert/proxy.crt .cert/proxy.key -CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags="-H=windowsgui" -o proxy-wingui.exe -CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o proxy.exe && tar zcfv "${RELEASE}/proxy-windows-amd64.tar.gz" proxy.exe proxy-wingui.exe direct blocked .cert/proxy.crt .cert/proxy.key +CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -ldflags="-H=windowsgui" -o proxy-noconsole.exe +CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -o proxy.exe && tar zcfv "${RELEASE}/proxy-windows-386.tar.gz" proxy.exe proxy-noconsole.exe direct blocked .cert/proxy.crt .cert/proxy.key +CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags="-H=windowsgui" -o proxy-noconsole.exe +CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o proxy.exe && tar zcfv "${RELEASE}/proxy-windows-amd64.tar.gz" proxy.exe proxy-noconsole.exe direct blocked .cert/proxy.crt .cert/proxy.key -rm -rf proxy proxy.exe proxy-wingui.exe .cert +rm -rf proxy proxy.exe proxy-noconsole.exe .cert #todo #1.release.sh VER="xxx"