From 0ee7abbd6a3614386e0b5389e05bb1800bcdea87 Mon Sep 17 00:00:00 2001 From: yincongcyincong <648588267@qq.com> Date: Thu, 28 Jun 2018 18:07:48 +0800 Subject: [PATCH 01/44] Update README.md --- README.md | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index eb5c163..5957011 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,8 @@ Proxy is a high performance HTTP, HTTPS, HTTPS, websocket, TCP, UDP, Socks5 prox - ...   -This page is the v5.0 manual, and the other version of the manual can be checked by the following link. +This page is the v5.1 manual, and the other version of the manual can be checked by the following link. +- [v5.1 manual](https://github.com/snail007/goproxy/tree/v5.1) - [v4.9 manual](https://github.com/snail007/goproxy/tree/v4.9) - [v4.8 manual](https://github.com/snail007/goproxy/tree/v4.8) - [v4.7 manual](https://github.com/snail007/goproxy/tree/v4.7) @@ -204,9 +205,18 @@ for example, --log proxy.log, The log will be exported to proxy.log file which i ### **Generating a communication certificate file** HTTP, TCP, UDP proxy process will communicate with parent proxy. In order to secure, we use encrypted communication. Of course, we can choose not to encrypted communication. All communication with parent proxy in this tutorial is encrypted, requiring certificate files. -The OpenSSL command is installed on the Linux and encrypted certificate can be generated directly through the following command. -`./proxy keygen` -By default, the certificate file proxy.crt and the key file proxy.key are generated under the current program directory. + +1.Generate signed certificates and key files through the following commands. +`./proxy keygen -C proxy` +The certificate file proxy.crt and key file proxy.key will be generated under the current directory. + +2.Through the following commands, use the signed certificate proxy.crt and key file proxy.key to issue new certificates: goproxy.crt and goproxy.key. +`./proxy keygen -s -C proxy -c goproxy` +The certificate file goproxy.crt and key file goproxy.key will be generated under the current program directory. + +3.By default, the domain name in the certificate is a random domain and can be specified using the `-n test.com` parameter. + +4.More usage:`proxy keygen --help`。 ### **Daemon mode** After the default execution of proxy, if you want to keep proxy running, you can't close the command line. From 9b430b5ba4742d38dd2498631693cb967619e077 Mon Sep 17 00:00:00 2001 From: arraykeys Date: Thu, 28 Jun 2018 23:05:48 +0800 Subject: [PATCH 02/44] fix create root certificate --- utils/cert/cert.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/cert/cert.go b/utils/cert/cert.go index 58b2356..858f6e5 100644 --- a/utils/cert/cert.go +++ b/utils/cert/cert.go @@ -109,7 +109,7 @@ func CreateCa(organization string, expireDays int) (certBytes []byte, keyBytes [ NotAfter: time.Now().Add(time.Hour * 24 * time.Duration(expireDays)), KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, BasicConstraintsValid: true, IsCA: true, } From 2336e77ac4b0412c84be5d790e0996b7b11f6747 Mon Sep 17 00:00:00 2001 From: "arraykeys@gmail.com" Date: Fri, 29 Jun 2018 17:55:19 +0800 Subject: [PATCH 03/44] Signed-off-by: arraykeys@gmail.com --- CHANGELOG | 4 ++++ services/sps/sps.go | 9 +++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index a241863..08b0e1b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,8 @@ proxy更新日志 +v5.2 +1.修复了反向代理无法正常工作的问题. +2.修复了自定义加密导致HTTP(S)\SPS反向代理无法正常工作的问题. + v5.1 1.优化了kcp默认mtu配置,调整为450. 2.优化了HTTP(S)\SOCKS5代理智能判断,更加精确。 diff --git a/services/sps/sps.go b/services/sps/sps.go index 68591c7..60b6f29 100644 --- a/services/sps/sps.go +++ b/services/sps/sps.go @@ -17,6 +17,7 @@ import ( "github.com/snail007/goproxy/services/kcpcfg" "github.com/snail007/goproxy/utils" "github.com/snail007/goproxy/utils/conncrypt" + "github.com/snail007/goproxy/utils/sni" "github.com/snail007/goproxy/utils/socks" ) @@ -218,7 +219,7 @@ func (s *SPS) OutToTCP(inConn *net.Conn) (err error) { bInConn.ReadByte() bInConn.UnreadByte() - n := 8 + n := 2048 if n > bInConn.Buffered() { n = bInConn.Buffered() } @@ -228,12 +229,12 @@ func (s *SPS) OutToTCP(inConn *net.Conn) (err error) { (*inConn).Close() return } - + isSNI, _ := sni.ServerNameFromBytes(h) *inConn = bInConn address := "" var auth socks.Auth var forwardBytes []byte - //fmt.Printf("%v", header) + //fmt.Printf("%v", h) if utils.IsSocks5(h) { if *s.cfg.DisableSocks5 { (*inConn).Close() @@ -251,7 +252,7 @@ func (s *SPS) OutToTCP(inConn *net.Conn) (err error) { } address = serverConn.Target() auth = serverConn.AuthData() - } else if utils.IsHTTP(h) { + } else if utils.IsHTTP(h) || isSNI != "" { if *s.cfg.DisableHTTP { (*inConn).Close() return From 0932aecff3c0a0e0ecf13cee6d02e29a5fcd7721 Mon Sep 17 00:00:00 2001 From: "arraykeys@gmail.com" Date: Fri, 29 Jun 2018 18:54:24 +0800 Subject: [PATCH 04/44] Signed-off-by: arraykeys@gmail.com --- services/http/http.go | 5 ++--- utils/conncrypt/conncrypt.go | 4 ++-- utils/structs.go | 2 ++ 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/services/http/http.go b/services/http/http.go index 16d41a3..51e7771 100644 --- a/services/http/http.go +++ b/services/http/http.go @@ -344,7 +344,6 @@ func (s *HTTP) OutToTCP(useProxy bool, address string, inConn *net.Conn, req *ut Password: *s.cfg.ParentKey, }) } - outAddr := outConn.RemoteAddr().String() //outLocalAddr := outConn.LocalAddr().String() if req.IsHTTPS() && (!useProxy || *s.cfg.ParentType == "ssh") { @@ -353,8 +352,8 @@ func (s *HTTP) OutToTCP(useProxy bool, address string, inConn *net.Conn, req *ut } else { //https或者http,上级是代理,proxy需要转发 outConn.SetDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout))) - //直连目标或上级非代理,清理HTTP头部的代理头信息 - if !useProxy || *s.cfg.ParentType == "ssh" { + //直连目标或上级非代理或非SNI,清理HTTP头部的代理头信息. + if (!useProxy || *s.cfg.ParentType == "ssh") && !req.IsSNI { _, err = outConn.Write(utils.RemoveProxyHeaders(req.HeadBuf)) } else { _, err = outConn.Write(req.HeadBuf) diff --git a/utils/conncrypt/conncrypt.go b/utils/conncrypt/conncrypt.go index f3115e7..82641e8 100644 --- a/utils/conncrypt/conncrypt.go +++ b/utils/conncrypt/conncrypt.go @@ -12,8 +12,8 @@ import ( ) //Confg defaults -const DefaultIterations = 2048 -const DefaultKeySize = 32 //256bits +const DefaultIterations = 1024 +const DefaultKeySize = 24 //256bits var DefaultHashFunc = sha256.New var DefaultSalt = []byte(` (;QUHj.BQ?RXzYSO]ifkXp/G!kFmWyXyEV6Nt!d|@bo+N$L9+ Date: Fri, 29 Jun 2018 18:55:18 +0800 Subject: [PATCH 05/44] Signed-off-by: arraykeys@gmail.com --- CHANGELOG | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 08b0e1b..ff0ce10 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,7 +1,6 @@ proxy更新日志 v5.2 -1.修复了反向代理无法正常工作的问题. -2.修复了自定义加密导致HTTP(S)\SPS反向代理无法正常工作的问题. +1.修复了HTTP(S)\SPS反向代理无法正常工作的问题. v5.1 1.优化了kcp默认mtu配置,调整为450. From 05d2f16777b4c52613cfcb79112b81799391b703 Mon Sep 17 00:00:00 2001 From: "arraykeys@gmail.com" Date: Fri, 29 Jun 2018 19:21:04 +0800 Subject: [PATCH 06/44] Signed-off-by: arraykeys@gmail.com --- services/http/http.go | 1 + services/socks/socks.go | 1 + services/sps/sps.go | 1 + 3 files changed, 3 insertions(+) diff --git a/services/http/http.go b/services/http/http.go index 51e7771..9159c7b 100644 --- a/services/http/http.go +++ b/services/http/http.go @@ -523,6 +523,7 @@ func (s *HTTP) Resolve(address string) string { ip, err := s.domainResolver.Resolve(address) if err != nil { s.log.Printf("dns error %s , ERR:%s", address, err) + return address } return ip } diff --git a/services/socks/socks.go b/services/socks/socks.go index b740966..9069447 100644 --- a/services/socks/socks.go +++ b/services/socks/socks.go @@ -804,6 +804,7 @@ func (s *Socks) Resolve(address string) string { ip, err := s.domainResolver.Resolve(address) if err != nil { s.log.Printf("dns error %s , ERR:%s", address, err) + return address } return ip } diff --git a/services/sps/sps.go b/services/sps/sps.go index 60b6f29..e3a7fdf 100644 --- a/services/sps/sps.go +++ b/services/sps/sps.go @@ -496,6 +496,7 @@ func (s *SPS) Resolve(address string) string { ip, err := s.domainResolver.Resolve(address) if err != nil { s.log.Printf("dns error %s , ERR:%s", address, err) + return address } return ip } From d84a4bec86b6490d1aa5d6a4acceb675e25f95c6 Mon Sep 17 00:00:00 2001 From: "arraykeys@gmail.com" Date: Tue, 3 Jul 2018 17:35:05 +0800 Subject: [PATCH 07/44] Signed-off-by: arraykeys@gmail.com --- CHANGELOG | 1 + sdk/android-ios/dns.go | 2 +- services/http/http.go | 9 +++++---- services/socks/socks.go | 8 +++++--- utils/structs.go | 10 +++++----- 5 files changed, 17 insertions(+), 13 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index ff0ce10..a87ca95 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ proxy更新日志 v5.2 1.修复了HTTP(S)\SPS反向代理无法正常工作的问题. +2.优化了智能判断,减少不必要的DNS解析. v5.1 1.优化了kcp默认mtu配置,调整为450. diff --git a/sdk/android-ios/dns.go b/sdk/android-ios/dns.go index bb2dc4a..b08290d 100644 --- a/sdk/android-ios/dns.go +++ b/sdk/android-ios/dns.go @@ -76,7 +76,7 @@ func (s *DNS) InitService() (err error) { nil, &net.Dialer{ Timeout: 5 * time.Second, - KeepAlive: 5 * time.Second, + KeepAlive: 2 * time.Second, }, ) if err != nil { diff --git a/services/http/http.go b/services/http/http.go index 9159c7b..a1a14aa 100644 --- a/services/http/http.go +++ b/services/http/http.go @@ -277,10 +277,11 @@ func (s *HTTP) callback(inConn net.Conn) { } else if *s.cfg.Always { useProxy = true } else { - k := s.Resolve(address) - s.checker.Add(address, k) - //var n, m uint - useProxy, _, _ = s.checker.IsBlocked(k) + var isInMap bool + useProxy, isInMap, _, _ = s.checker.IsBlocked(address) + if !isInMap { + s.checker.Add(address, s.Resolve(address)) + } //s.log.Printf("blocked ? : %v, %s , fail:%d ,success:%d", useProxy, address, n, m) } } diff --git a/services/socks/socks.go b/services/socks/socks.go index 9069447..0f762d3 100644 --- a/services/socks/socks.go +++ b/services/socks/socks.go @@ -562,9 +562,11 @@ func (s *Socks) proxyTCP(inConn *net.Conn, methodReq socks.MethodsRequest, reque if utils.IsIternalIP(host, *s.cfg.Always) { useProxy = false } else { - k := s.Resolve(request.Addr()) - s.checker.Add(request.Addr(), k) - useProxy, _, _ = s.checker.IsBlocked(k) + var isInMap bool + useProxy, isInMap, _, _ = s.checker.IsBlocked(request.Addr()) + if !isInMap { + s.checker.Add(request.Addr(), s.Resolve(request.Addr())) + } } if useProxy { outConn, err = s.getOutConn(methodReq.Bytes(), request.Bytes(), request.Addr()) diff --git a/utils/structs.go b/utils/structs.go index d098240..62eec27 100644 --- a/utils/structs.go +++ b/utils/structs.go @@ -132,24 +132,24 @@ func (c *Checker) isNeedCheck(item CheckerItem) bool { } return true } -func (c *Checker) IsBlocked(address string) (blocked bool, failN, successN uint) { +func (c *Checker) IsBlocked(address string) (blocked, isInMap bool, failN, successN uint) { if c.domainIsInMap(address, true) { //log.Printf("%s in blocked ? true", address) - return true, 0, 0 + return true, true, 0, 0 } if c.domainIsInMap(address, false) { //log.Printf("%s in direct ? true", address) - return false, 0, 0 + return false, true, 0, 0 } _item, ok := c.data.Get(address) if !ok { //log.Printf("%s not in map, blocked true", address) - return true, 0, 0 + return true, false, 0, 0 } item := _item.(CheckerItem) - return item.FailCount >= item.SuccessCount, item.FailCount, item.SuccessCount + return item.FailCount >= item.SuccessCount, true, item.FailCount, item.SuccessCount } func (c *Checker) domainIsInMap(address string, blockedMap bool) bool { u, err := url.Parse("http://" + address) From 20c31b0c68969e133ead1393720602699853292b Mon Sep 17 00:00:00 2001 From: "arraykeys@gmail.com" Date: Tue, 3 Jul 2018 17:37:17 +0800 Subject: [PATCH 08/44] Signed-off-by: arraykeys@gmail.com --- README_ZH.md | 2 +- docs/old-release.md | 1 + install_auto.sh | 2 +- main.go | 2 +- release.sh | 2 +- 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/README_ZH.md b/README_ZH.md index 07b2ebc..59a0aef 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -38,7 +38,7 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5代理服务 - ... -本页是v5.1手册,其他版本手册请点击[这里](docs/old-release.md)查看. +本页是v5.2手册,其他版本手册请点击[这里](docs/old-release.md)查看. ### 怎么找到组织? diff --git a/docs/old-release.md b/docs/old-release.md index aba1110..7204b03 100644 --- a/docs/old-release.md +++ b/docs/old-release.md @@ -1,5 +1,6 @@ # Old Versions of Proxy +- [v5.1手册](https://github.com/snail007/goproxy/tree/v5.1) - [v5.0手册](https://github.com/snail007/goproxy/tree/v5.0) - [v4.9手册](https://github.com/snail007/goproxy/tree/v4.9) - [v4.8手册](https://github.com/snail007/goproxy/tree/v4.8) diff --git a/install_auto.sh b/install_auto.sh index 6f1723f..63b7672 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.1/proxy-linux-amd64.tar.gz +wget https://github.com/snail007/goproxy/releases/download/v5.2/proxy-linux-amd64.tar.gz # #install proxy tar zxvf proxy-linux-amd64.tar.gz diff --git a/main.go b/main.go index 66239c7..9d56bb9 100644 --- a/main.go +++ b/main.go @@ -9,7 +9,7 @@ import ( "github.com/snail007/goproxy/services" ) -const APP_VERSION = "5.1" +const APP_VERSION = "5.2" func main() { err := initConfig() diff --git a/release.sh b/release.sh index 2c505c5..19c7481 100755 --- a/release.sh +++ b/release.sh @@ -1,5 +1,5 @@ #!/bin/bash -VER="5.1" +VER="5.2" RELEASE="release-${VER}" rm -rf .cert mkdir .cert From 846956a9fede2970594620ae8dbc47abf3b7b4bf Mon Sep 17 00:00:00 2001 From: arraykeys Date: Tue, 3 Jul 2018 21:38:35 +0800 Subject: [PATCH 09/44] no message --- utils/structs.go | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/utils/structs.go b/utils/structs.go index 62eec27..dfc0c90 100644 --- a/utils/structs.go +++ b/utils/structs.go @@ -33,15 +33,11 @@ type Checker struct { log *logger.Logger } type CheckerItem struct { - IsHTTPS bool - Method string - URL string Domain string - Host string - Data []byte + Address string SuccessCount uint FailCount uint - Key string + Lasttime int64 } //NewChecker args: @@ -101,7 +97,7 @@ func (c *Checker) start() { //log.Printf("check %s", item.Host) var conn net.Conn var err error - conn, err = ConnectHost(item.Host, c.timeout) + conn, err = ConnectHost(item.Address, c.timeout) if err == nil { conn.SetDeadline(time.Now().Add(time.Millisecond)) conn.Close() @@ -111,7 +107,8 @@ func (c *Checker) start() { } else { item.SuccessCount = item.SuccessCount + 1 } - c.data.Set(item.Host, item) + item.Lasttime = time.Now().Unix() + c.data.Set(item.Domain, item) } }(v.(CheckerItem)) } @@ -126,23 +123,28 @@ func (c *Checker) isNeedCheck(item CheckerItem) bool { var minCount uint = 5 if (item.SuccessCount >= minCount && item.SuccessCount > item.FailCount) || (item.FailCount >= minCount && item.SuccessCount > item.FailCount) || - c.domainIsInMap(item.Host, false) || - c.domainIsInMap(item.Host, true) { + c.domainIsInMap(item.Domain, false) || + c.domainIsInMap(item.Domain, true) || + time.Now().Unix()-item.Lasttime > 1800 { return false } return true } -func (c *Checker) IsBlocked(address string) (blocked, isInMap bool, failN, successN uint) { - if c.domainIsInMap(address, true) { +func (c *Checker) IsBlocked(domain string) (blocked, isInMap bool, failN, successN uint) { + h, _, _ := net.SplitHostPort(domain) + if h != "" { + domain = h + } + if c.domainIsInMap(domain, true) { //log.Printf("%s in blocked ? true", address) return true, true, 0, 0 } - if c.domainIsInMap(address, false) { + if c.domainIsInMap(domain, false) { //log.Printf("%s in direct ? true", address) return false, true, 0, 0 } - _item, ok := c.data.Get(address) + _item, ok := c.data.Get(domain) if !ok { //log.Printf("%s not in map, blocked true", address) return true, false, 0, 0 @@ -174,16 +176,20 @@ func (c *Checker) domainIsInMap(address string, blockedMap bool) bool { } return false } -func (c *Checker) Add(key, address string) { - if c.domainIsInMap(key, false) || c.domainIsInMap(key, true) { +func (c *Checker) Add(domain, address string) { + h, _, _ := net.SplitHostPort(domain) + if h != "" { + domain = h + } + if c.domainIsInMap(domain, false) || c.domainIsInMap(domain, true) { return } var item CheckerItem item = CheckerItem{ - Host: address, - Key: key, + Domain: domain, + Address: address, } - c.data.SetIfAbsent(item.Host, item) + c.data.SetIfAbsent(item.Domain, item) } type BasicAuth struct { From bf72325fc0b3c4132003c87fd1af84026c280eb7 Mon Sep 17 00:00:00 2001 From: "arraykeys@gmail.com" Date: Wed, 4 Jul 2018 17:44:24 +0800 Subject: [PATCH 10/44] Signed-off-by: arraykeys@gmail.com --- services/socks/socks.go | 180 +++++++++++++++++++++++++++++++++++----- utils/socks/client.go | 6 +- 2 files changed, 160 insertions(+), 26 deletions(-) diff --git a/services/socks/socks.go b/services/socks/socks.go index 0f762d3..acf6a9d 100644 --- a/services/socks/socks.go +++ b/services/socks/socks.go @@ -3,10 +3,12 @@ package socks import ( "crypto/tls" "fmt" + "io" "io/ioutil" logger "log" "net" "runtime/debug" + "strconv" "strings" "time" @@ -59,27 +61,29 @@ type SocksArgs struct { ParentCompress *bool } type Socks struct { - cfg SocksArgs - checker utils.Checker - basicAuth utils.BasicAuth - sshClient *ssh.Client - lockChn chan bool - udpSC utils.ServerChannel - sc *utils.ServerChannel - domainResolver utils.DomainResolver - isStop bool - userConns utils.ConcurrentMap - log *logger.Logger + cfg SocksArgs + checker utils.Checker + basicAuth utils.BasicAuth + sshClient *ssh.Client + lockChn chan bool + udpSC utils.ServerChannel + sc *utils.ServerChannel + domainResolver utils.DomainResolver + isStop bool + userConns utils.ConcurrentMap + log *logger.Logger + udpRelatedPacketConns utils.ConcurrentMap } func NewSocks() services.Service { return &Socks{ - cfg: SocksArgs{}, - checker: utils.Checker{}, - basicAuth: utils.BasicAuth{}, - lockChn: make(chan bool, 1), - isStop: false, - userConns: utils.NewConcurrentMap(), + cfg: SocksArgs{}, + checker: utils.Checker{}, + basicAuth: utils.BasicAuth{}, + lockChn: make(chan bool, 1), + isStop: false, + userConns: utils.NewConcurrentMap(), + udpRelatedPacketConns: utils.NewConcurrentMap(), } } @@ -220,6 +224,9 @@ func (s *Socks) StopService() { for _, c := range s.userConns.Items() { (*c.(*net.Conn)).Close() } + for _, c := range s.udpRelatedPacketConns.Items() { + (*c.(*net.UDPConn)).Close() + } } func (s *Socks) Start(args interface{}, log *logger.Logger) (err error) { s.log = log @@ -438,7 +445,9 @@ func (s *Socks) socksConnCallback(inConn net.Conn) { if err != nil { methodReq.Reply(socks.Method_NONE_ACCEPTABLE) utils.CloseConn(&inConn) - s.log.Printf("new methods request fail,ERR: %s", err) + if err != io.EOF { + s.log.Printf("new methods request fail,ERR: %s", err) + } return } @@ -531,10 +540,132 @@ func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, reque utils.CloseConn(inConn) return } + inconnRemoteAddr := (*inConn).RemoteAddr().String() + localAddr := &net.UDPAddr{IP: net.IPv4zero, Port: 0} + udpListener, err := net.ListenUDP("udp", localAddr) + if err != nil { + (*inConn).Close() + udpListener.Close() + s.log.Printf("udp bind fail , %s", err) + return + } host, _, _ := net.SplitHostPort((*inConn).LocalAddr().String()) - _, port, _ := net.SplitHostPort(s.udpSC.UDPListener.LocalAddr().String()) - s.log.Printf("proxy udp on %s", net.JoinHostPort(host, port)) + _, port, _ := net.SplitHostPort(udpListener.LocalAddr().String()) + s.log.Printf("proxy udp on %s , for %s", udpListener.LocalAddr(), inconnRemoteAddr) request.UDPReply(socks.REP_SUCCESS, net.JoinHostPort(host, port)) + + s.userConns.Set(inconnRemoteAddr, inConn) + var outUDPConn *net.UDPConn + go func() { + buf := make([]byte, 1) + if _, err := (*inConn).Read(buf); err != nil { + laddr := "" + if outUDPConn != nil { + laddr = outUDPConn.LocalAddr().String() + } + s.log.Printf("udp related tcp conn disconnected , %s -> %s , %s", inconnRemoteAddr, laddr, err) + (*inConn).Close() + udpListener.Close() + s.userConns.Remove(inconnRemoteAddr) + if outUDPConn != nil { + outUDPConn.Close() + } + } + }() + if *s.cfg.Parent != "" { + outconn, err := s.getOutConn(nil, nil, "", false) + if err != nil { + (*inConn).Close() + udpListener.Close() + s.log.Printf("connect fail , %s", err) + return + } + client := socks.NewClientConn(&outconn, "udp", "", time.Millisecond*time.Duration(*s.cfg.Timeout), nil, nil) + if err = client.Handshake(); err != nil { + (*inConn).Close() + udpListener.Close() + s.log.Printf("handshake fail , %s", err) + } + outconnRemoteAddr := outconn.RemoteAddr().String() + outconnLocalAddr := outconn.LocalAddr().String() + s.userConns.Set(outconnLocalAddr, &outconn) + s.log.Printf("parent udp address %s", client.UDPAddr) + go func() { + buf := make([]byte, 1) + if _, err := outconn.Read(buf); err != nil { + s.log.Printf("udp parent net conn offline , %s", outconnRemoteAddr) + (*inConn).Close() + udpListener.Close() + s.userConns.Remove(outconnLocalAddr) + } + }() + } else { + for { + buf := utils.LeakyBuffer.Get() + defer utils.LeakyBuffer.Put(buf) + n, srcAddr, err := udpListener.ReadFromUDP(buf) + if err != nil { + (*inConn).Close() + udpListener.Close() + s.userConns.Remove(inconnRemoteAddr) + s.log.Printf("udp listener read fail , %s", err) + return + } + p := socks.NewPacketUDP() + err = p.Parse(buf[:n]) + if err != nil { + (*inConn).Close() + udpListener.Close() + s.userConns.Remove(inconnRemoteAddr) + s.log.Printf("udp listener parse packet fail , %s , from : %s", err, srcAddr) + return + } + + port, _ := strconv.Atoi(p.Port()) + destAddr := &net.UDPAddr{IP: net.ParseIP(p.Host()), Port: port} + if v, ok := s.udpRelatedPacketConns.Get(srcAddr.String()); !ok { + outUDPConn, err = net.DialUDP("udp", localAddr, destAddr) + if err != nil { + s.log.Printf("create out udp conn fail , %s , from : %s", err, srcAddr) + continue + } + s.udpRelatedPacketConns.Set(srcAddr.String(), outUDPConn) + go func() { + //bind + for { + buf := utils.LeakyBuffer.Get() + defer utils.LeakyBuffer.Put(buf) + n, err := outUDPConn.Read(buf) + if err != nil { + s.udpRelatedPacketConns.Remove(srcAddr.String()) + s.log.Printf("read out udp data fail , %s , from : %s", err, srcAddr) + if strings.Contains(err.Error(), "use of closed network connection") { + break + } + continue + } + rp := socks.NewPacketUDP() + rp.Build(srcAddr.String(), buf[:n]) + _, err = udpListener.WriteTo(rp.Bytes(), srcAddr) + if err != nil { + s.udpRelatedPacketConns.Remove(srcAddr.String()) + s.log.Printf("write out data to local fail , %s , from : %s", err, srcAddr) + if strings.Contains(err.Error(), "use of closed network connection") { + break + } + } + } + }() + } else { + outUDPConn = v.(*net.UDPConn) + } + _, err = outUDPConn.Write(p.Data()) + if err != nil { + s.log.Printf("send out udp data fail , %s , from : %s", err, srcAddr) + continue + } + } + } } func (s *Socks) proxyTCP(inConn *net.Conn, methodReq socks.MethodsRequest, request socks.Request) { var outConn net.Conn @@ -554,7 +685,7 @@ func (s *Socks) proxyTCP(inConn *net.Conn, methodReq socks.MethodsRequest, reque return } if *s.cfg.Always { - outConn, err = s.getOutConn(methodReq.Bytes(), request.Bytes(), request.Addr()) + outConn, err = s.getOutConn(methodReq.Bytes(), request.Bytes(), request.Addr(), true) } else { if *s.cfg.Parent != "" { host, _, _ := net.SplitHostPort(request.Addr()) @@ -569,7 +700,7 @@ func (s *Socks) proxyTCP(inConn *net.Conn, methodReq socks.MethodsRequest, reque } } if useProxy { - outConn, err = s.getOutConn(methodReq.Bytes(), request.Bytes(), request.Addr()) + outConn, err = s.getOutConn(methodReq.Bytes(), request.Bytes(), request.Addr(), true) } else { outConn, err = utils.ConnectHost(s.Resolve(request.Addr()), *s.cfg.Timeout) } @@ -609,7 +740,7 @@ func (s *Socks) proxyTCP(inConn *net.Conn, methodReq socks.MethodsRequest, reque } s.userConns.Set(inAddr, inConn) } -func (s *Socks) getOutConn(methodBytes, reqBytes []byte, host string) (outConn net.Conn, err interface{}) { +func (s *Socks) getOutConn(methodBytes, reqBytes []byte, host string, handshake bool) (outConn net.Conn, err interface{}) { switch *s.cfg.ParentType { case "kcp": fallthrough @@ -637,6 +768,9 @@ func (s *Socks) getOutConn(methodBytes, reqBytes []byte, host string) (outConn n Password: *s.cfg.ParentKey, }) } + if !handshake { + return + } var buf = make([]byte, 1024) //var n int outConn.SetDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout))) diff --git a/utils/socks/client.go b/utils/socks/client.go index 619e3c7..7b06c1d 100644 --- a/utils/socks/client.go +++ b/utils/socks/client.go @@ -33,7 +33,7 @@ type ClientConn struct { timeout time.Duration addr string network string - udpAddr string + UDPAddr string } // SOCKS5 returns a Dialer that makes SOCKSv5 connections to the given address @@ -168,14 +168,14 @@ func (s *ClientConn) Handshake() error { } p := binary.BigEndian.Uint16([]byte{buf[0], buf[1]}) //log.Printf("%v", p) - s.udpAddr = net.JoinHostPort(ipStr, fmt.Sprintf("%d", p)) + s.UDPAddr = net.JoinHostPort(ipStr, fmt.Sprintf("%d", p)) //log.Printf("%v", s.udpAddr) (*s.conn).SetDeadline(time.Time{}) return nil } func (s *ClientConn) SendUDP(data []byte, addr string) (respData []byte, err error) { - c, err := net.DialTimeout("udp", s.udpAddr, s.timeout) + c, err := net.DialTimeout("udp", s.UDPAddr, s.timeout) if err != nil { return } From eaf836eff33dca62d383d04101d8924b2e26217b Mon Sep 17 00:00:00 2001 From: arraykeys Date: Wed, 4 Jul 2018 21:43:30 +0800 Subject: [PATCH 11/44] no message --- services/socks/socks.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/services/socks/socks.go b/services/socks/socks.go index acf6a9d..873a477 100644 --- a/services/socks/socks.go +++ b/services/socks/socks.go @@ -559,11 +559,11 @@ func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, reque go func() { buf := make([]byte, 1) if _, err := (*inConn).Read(buf); err != nil { - laddr := "" + raddr := "" if outUDPConn != nil { - laddr = outUDPConn.LocalAddr().String() + raddr = outUDPConn.RemoteAddr().String() } - s.log.Printf("udp related tcp conn disconnected , %s -> %s , %s", inconnRemoteAddr, laddr, err) + s.log.Printf("udp related tcp conn disconnected , %s -> %s", inconnRemoteAddr, raddr) (*inConn).Close() udpListener.Close() s.userConns.Remove(inconnRemoteAddr) @@ -646,13 +646,16 @@ func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, reque } rp := socks.NewPacketUDP() rp.Build(srcAddr.String(), buf[:n]) - _, err = udpListener.WriteTo(rp.Bytes(), srcAddr) + d := rp.Bytes() + _, err = udpListener.WriteTo(d, srcAddr) if err != nil { s.udpRelatedPacketConns.Remove(srcAddr.String()) s.log.Printf("write out data to local fail , %s , from : %s", err, srcAddr) if strings.Contains(err.Error(), "use of closed network connection") { break } + } else { + s.log.Printf("send udp data to local success , len %d, for : %s", len(d), srcAddr) } } }() @@ -663,6 +666,8 @@ func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, reque if err != nil { s.log.Printf("send out udp data fail , %s , from : %s", err, srcAddr) continue + } else { + s.log.Printf("send udp data to remote success , len %d, for : %s", len(p.Data()), srcAddr) } } } From 50886bd69a77533edf09db328941a25c159f77fa Mon Sep 17 00:00:00 2001 From: arraykeys Date: Wed, 4 Jul 2018 21:51:59 +0800 Subject: [PATCH 12/44] no message --- services/socks/socks.go | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/services/socks/socks.go b/services/socks/socks.go index 873a477..d18490f 100644 --- a/services/socks/socks.go +++ b/services/socks/socks.go @@ -563,7 +563,7 @@ func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, reque if outUDPConn != nil { raddr = outUDPConn.RemoteAddr().String() } - s.log.Printf("udp related tcp conn disconnected , %s -> %s", inconnRemoteAddr, raddr) + s.log.Printf("udp related tcp conn disconnected with read , %s -> %s", inconnRemoteAddr, raddr) (*inConn).Close() udpListener.Close() s.userConns.Remove(inconnRemoteAddr) @@ -572,6 +572,25 @@ func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, reque } } }() + go func() { + for { + if _, err := (*inConn).Write([]byte{0x00}); err != nil { + raddr := "" + if outUDPConn != nil { + raddr = outUDPConn.RemoteAddr().String() + } + s.log.Printf("udp related tcp conn disconnected with write , %s -> %s", inconnRemoteAddr, raddr) + (*inConn).Close() + udpListener.Close() + s.userConns.Remove(inconnRemoteAddr) + if outUDPConn != nil { + outUDPConn.Close() + } + return + } + time.Sleep(time.Second * 5) + } + }() if *s.cfg.Parent != "" { outconn, err := s.getOutConn(nil, nil, "", false) if err != nil { From c20e19d74f1bddcc633036b4b5dbd0a54f673b10 Mon Sep 17 00:00:00 2001 From: arraykeys Date: Wed, 4 Jul 2018 23:58:09 +0800 Subject: [PATCH 13/44] no message --- services/socks/socks.go | 115 +++++++++++++++++++++------------------- 1 file changed, 61 insertions(+), 54 deletions(-) diff --git a/services/socks/socks.go b/services/socks/socks.go index d18490f..d888618 100644 --- a/services/socks/socks.go +++ b/services/socks/socks.go @@ -553,39 +553,49 @@ func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, reque _, port, _ := net.SplitHostPort(udpListener.LocalAddr().String()) s.log.Printf("proxy udp on %s , for %s", udpListener.LocalAddr(), inconnRemoteAddr) request.UDPReply(socks.REP_SUCCESS, net.JoinHostPort(host, port)) - s.userConns.Set(inconnRemoteAddr, inConn) - var outUDPConn *net.UDPConn + var ( + outUDPConn *net.UDPConn + outconn net.Conn + outconnLocalAddr string + isClosedErr = func(err error) bool { + return err != nil && strings.Contains(err.Error(), "use of closed network connection") + } + ) + var clean = func(msg, err string) { + raddr := "" + if outUDPConn != nil { + raddr = outUDPConn.RemoteAddr().String() + outUDPConn.Close() + } + if msg != "" { + if raddr != "" { + s.log.Printf("%s , %s , %s -> %s", msg, err, inconnRemoteAddr, raddr) + } else { + s.log.Printf("%s , %s , from : %s", msg, err, inconnRemoteAddr) + } + } + (*inConn).Close() + udpListener.Close() + s.userConns.Remove(inconnRemoteAddr) + if outconn != nil { + outconn.Close() + } + if outconnLocalAddr != "" { + s.userConns.Remove(outconnLocalAddr) + } + } + defer clean("", "") go func() { buf := make([]byte, 1) if _, err := (*inConn).Read(buf); err != nil { - raddr := "" - if outUDPConn != nil { - raddr = outUDPConn.RemoteAddr().String() - } - s.log.Printf("udp related tcp conn disconnected with read , %s -> %s", inconnRemoteAddr, raddr) - (*inConn).Close() - udpListener.Close() - s.userConns.Remove(inconnRemoteAddr) - if outUDPConn != nil { - outUDPConn.Close() - } + clean("udp related tcp conn disconnected with read", err.Error()) } }() go func() { for { if _, err := (*inConn).Write([]byte{0x00}); err != nil { - raddr := "" - if outUDPConn != nil { - raddr = outUDPConn.RemoteAddr().String() - } - s.log.Printf("udp related tcp conn disconnected with write , %s -> %s", inconnRemoteAddr, raddr) - (*inConn).Close() - udpListener.Close() - s.userConns.Remove(inconnRemoteAddr) - if outUDPConn != nil { - outUDPConn.Close() - } + clean("udp related tcp conn disconnected with write", err.Error()) return } time.Sleep(time.Second * 5) @@ -594,50 +604,43 @@ func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, reque if *s.cfg.Parent != "" { outconn, err := s.getOutConn(nil, nil, "", false) if err != nil { - (*inConn).Close() - udpListener.Close() - s.log.Printf("connect fail , %s", err) + clean("connnect fail", fmt.Sprintf("%s", err)) return } client := socks.NewClientConn(&outconn, "udp", "", time.Millisecond*time.Duration(*s.cfg.Timeout), nil, nil) if err = client.Handshake(); err != nil { - (*inConn).Close() - udpListener.Close() - s.log.Printf("handshake fail , %s", err) + clean("handshake fail", fmt.Sprintf("%s", err)) + return } - outconnRemoteAddr := outconn.RemoteAddr().String() - outconnLocalAddr := outconn.LocalAddr().String() + //outconnRemoteAddr := outconn.RemoteAddr().String() + outconnLocalAddr = outconn.LocalAddr().String() s.userConns.Set(outconnLocalAddr, &outconn) - s.log.Printf("parent udp address %s", client.UDPAddr) go func() { buf := make([]byte, 1) if _, err := outconn.Read(buf); err != nil { - s.log.Printf("udp parent net conn offline , %s", outconnRemoteAddr) - (*inConn).Close() - udpListener.Close() - s.userConns.Remove(outconnLocalAddr) + clean("udp parent tcp conn disconnected", fmt.Sprintf("%s", err)) } }() + //forward to parent udp + s.log.Printf("parent udp address %s", client.UDPAddr) + } else { for { buf := utils.LeakyBuffer.Get() defer utils.LeakyBuffer.Put(buf) n, srcAddr, err := udpListener.ReadFromUDP(buf) if err != nil { - (*inConn).Close() - udpListener.Close() - s.userConns.Remove(inconnRemoteAddr) - s.log.Printf("udp listener read fail , %s", err) - return + s.log.Printf("udp listener read fail, %s", err.Error()) + if isClosedErr(err) { + return + } + continue } p := socks.NewPacketUDP() err = p.Parse(buf[:n]) if err != nil { - (*inConn).Close() - udpListener.Close() - s.userConns.Remove(inconnRemoteAddr) - s.log.Printf("udp listener parse packet fail , %s , from : %s", err, srcAddr) - return + s.log.Printf("udp listener parse packet fail, %s", err.Error()) + continue } port, _ := strconv.Atoi(p.Port()) @@ -650,16 +653,16 @@ func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, reque } s.udpRelatedPacketConns.Set(srcAddr.String(), outUDPConn) go func() { + defer s.udpRelatedPacketConns.Remove(srcAddr.String()) //bind + buf := utils.LeakyBuffer.Get() + defer utils.LeakyBuffer.Put(buf) for { - buf := utils.LeakyBuffer.Get() - defer utils.LeakyBuffer.Put(buf) n, err := outUDPConn.Read(buf) if err != nil { - s.udpRelatedPacketConns.Remove(srcAddr.String()) s.log.Printf("read out udp data fail , %s , from : %s", err, srcAddr) - if strings.Contains(err.Error(), "use of closed network connection") { - break + if isClosedErr(err) { + return } continue } @@ -670,9 +673,10 @@ func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, reque if err != nil { s.udpRelatedPacketConns.Remove(srcAddr.String()) s.log.Printf("write out data to local fail , %s , from : %s", err, srcAddr) - if strings.Contains(err.Error(), "use of closed network connection") { - break + if isClosedErr(err) { + return } + continue } else { s.log.Printf("send udp data to local success , len %d, for : %s", len(d), srcAddr) } @@ -683,6 +687,9 @@ func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, reque } _, err = outUDPConn.Write(p.Data()) if err != nil { + if isClosedErr(err) { + return + } s.log.Printf("send out udp data fail , %s , from : %s", err, srcAddr) continue } else { From e92375f6a9c6cf44c7df259f0be5abc89f02b823 Mon Sep 17 00:00:00 2001 From: arraykeys Date: Thu, 5 Jul 2018 00:03:46 +0800 Subject: [PATCH 14/44] no message --- services/socks/socks.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/services/socks/socks.go b/services/socks/socks.go index d888618..2fb4541 100644 --- a/services/socks/socks.go +++ b/services/socks/socks.go @@ -602,6 +602,7 @@ func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, reque } }() if *s.cfg.Parent != "" { + //parent proxy outconn, err := s.getOutConn(nil, nil, "", false) if err != nil { clean("connnect fail", fmt.Sprintf("%s", err)) @@ -625,6 +626,7 @@ func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, reque s.log.Printf("parent udp address %s", client.UDPAddr) } else { + //local proxy for { buf := utils.LeakyBuffer.Get() defer utils.LeakyBuffer.Put(buf) @@ -652,9 +654,10 @@ func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, reque continue } s.udpRelatedPacketConns.Set(srcAddr.String(), outUDPConn) + go func() { defer s.udpRelatedPacketConns.Remove(srcAddr.String()) - //bind + //out->local io copy buf := utils.LeakyBuffer.Get() defer utils.LeakyBuffer.Put(buf) for { @@ -685,6 +688,7 @@ func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, reque } else { outUDPConn = v.(*net.UDPConn) } + //local->out io copy _, err = outUDPConn.Write(p.Data()) if err != nil { if isClosedErr(err) { From cb8d0c0b4228f2eaf220e2382e7f586751f852ef Mon Sep 17 00:00:00 2001 From: arraykeys Date: Thu, 5 Jul 2018 01:03:37 +0800 Subject: [PATCH 15/44] no message --- services/socks/socks.go | 156 ++++++++++++++++++++++++---------------- 1 file changed, 94 insertions(+), 62 deletions(-) diff --git a/services/socks/socks.go b/services/socks/socks.go index 2fb4541..99427a9 100644 --- a/services/socks/socks.go +++ b/services/socks/socks.go @@ -561,6 +561,7 @@ func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, reque isClosedErr = func(err error) bool { return err != nil && strings.Contains(err.Error(), "use of closed network connection") } + destAddr *net.UDPAddr ) var clean = func(msg, err string) { raddr := "" @@ -601,7 +602,18 @@ func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, reque time.Sleep(time.Second * 5) } }() + useProxy := true if *s.cfg.Parent != "" { + dstHost, _, _ := net.SplitHostPort(request.Addr()) + if utils.IsIternalIP(dstHost, *s.cfg.Always) { + useProxy = false + } else { + var isInMap bool + useProxy, isInMap, _, _ = s.checker.IsBlocked(request.Addr()) + if !isInMap { + s.checker.Add(request.Addr(), s.Resolve(request.Addr())) + } + } //parent proxy outconn, err := s.getOutConn(nil, nil, "", false) if err != nil { @@ -624,83 +636,103 @@ func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, reque }() //forward to parent udp s.log.Printf("parent udp address %s", client.UDPAddr) - + destAddr, _ = net.ResolveUDPAddr("udp", client.UDPAddr) } else { - //local proxy - for { - buf := utils.LeakyBuffer.Get() - defer utils.LeakyBuffer.Put(buf) - n, srcAddr, err := udpListener.ReadFromUDP(buf) + useProxy = false + } + s.log.Printf("use proxy %v , udp %s", useProxy, request.Addr()) + //relay + for { + buf := utils.LeakyBuffer.Get() + defer utils.LeakyBuffer.Put(buf) + n, srcAddr, err := udpListener.ReadFromUDP(buf) + if err != nil { + s.log.Printf("udp listener read fail, %s", err.Error()) + if isClosedErr(err) { + return + } + continue + } + p := socks.NewPacketUDP() + err = p.Parse(buf[:n]) + if err != nil { + s.log.Printf("udp listener parse packet fail, %s", err.Error()) + continue + } + + port, _ := strconv.Atoi(p.Port()) + + if v, ok := s.udpRelatedPacketConns.Get(srcAddr.String()); !ok { + if destAddr == nil { + destAddr = &net.UDPAddr{IP: net.ParseIP(p.Host()), Port: port} + } + outUDPConn, err = net.DialUDP("udp", localAddr, destAddr) if err != nil { - s.log.Printf("udp listener read fail, %s", err.Error()) - if isClosedErr(err) { - return - } - continue - } - p := socks.NewPacketUDP() - err = p.Parse(buf[:n]) - if err != nil { - s.log.Printf("udp listener parse packet fail, %s", err.Error()) + s.log.Printf("create out udp conn fail , %s , from : %s", err, srcAddr) continue } + s.udpRelatedPacketConns.Set(srcAddr.String(), outUDPConn) - port, _ := strconv.Atoi(p.Port()) - destAddr := &net.UDPAddr{IP: net.ParseIP(p.Host()), Port: port} - if v, ok := s.udpRelatedPacketConns.Get(srcAddr.String()); !ok { - outUDPConn, err = net.DialUDP("udp", localAddr, destAddr) - if err != nil { - s.log.Printf("create out udp conn fail , %s , from : %s", err, srcAddr) - continue - } - s.udpRelatedPacketConns.Set(srcAddr.String(), outUDPConn) - - go func() { - defer s.udpRelatedPacketConns.Remove(srcAddr.String()) - //out->local io copy - buf := utils.LeakyBuffer.Get() - defer utils.LeakyBuffer.Put(buf) - for { - n, err := outUDPConn.Read(buf) - if err != nil { - s.log.Printf("read out udp data fail , %s , from : %s", err, srcAddr) - if isClosedErr(err) { - return - } - continue + go func() { + defer s.udpRelatedPacketConns.Remove(srcAddr.String()) + //out->local io copy + buf := utils.LeakyBuffer.Get() + defer utils.LeakyBuffer.Put(buf) + for { + n, err := outUDPConn.Read(buf) + if err != nil { + s.log.Printf("read out udp data fail , %s , from : %s", err, srcAddr) + if isClosedErr(err) { + return } + continue + } + + var dlen = n + if useProxy { + //forward to local + _, err = udpListener.WriteTo(buf[:n], srcAddr) + } else { rp := socks.NewPacketUDP() rp.Build(srcAddr.String(), buf[:n]) d := rp.Bytes() + dlen = len(d) _, err = udpListener.WriteTo(d, srcAddr) - if err != nil { - s.udpRelatedPacketConns.Remove(srcAddr.String()) - s.log.Printf("write out data to local fail , %s , from : %s", err, srcAddr) - if isClosedErr(err) { - return - } - continue - } else { - s.log.Printf("send udp data to local success , len %d, for : %s", len(d), srcAddr) - } } - }() - } else { - outUDPConn = v.(*net.UDPConn) - } - //local->out io copy - _, err = outUDPConn.Write(p.Data()) - if err != nil { - if isClosedErr(err) { - return + + if err != nil { + s.udpRelatedPacketConns.Remove(srcAddr.String()) + s.log.Printf("write out data to local fail , %s , from : %s", err, srcAddr) + if isClosedErr(err) { + return + } + continue + } else { + s.log.Printf("send udp data to local success , len %d, for : %s", dlen, srcAddr) + } } - s.log.Printf("send out udp data fail , %s , from : %s", err, srcAddr) - continue - } else { - s.log.Printf("send udp data to remote success , len %d, for : %s", len(p.Data()), srcAddr) + }() + } else { + outUDPConn = v.(*net.UDPConn) + } + //local->out io copy + if useProxy { + //forward to parent + _, err = outUDPConn.Write(buf[:n]) + } else { + _, err = outUDPConn.Write(p.Data()) + } + if err != nil { + if isClosedErr(err) { + return } + s.log.Printf("send out udp data fail , %s , from : %s", err, srcAddr) + continue + } else { + s.log.Printf("send udp data to remote success , len %d, for : %s", len(p.Data()), srcAddr) } } + } func (s *Socks) proxyTCP(inConn *net.Conn, methodReq socks.MethodsRequest, request socks.Request) { var outConn net.Conn From 3b49f17e019c0cebe41c20582c78bb8feac51ee5 Mon Sep 17 00:00:00 2001 From: arraykeys Date: Thu, 5 Jul 2018 01:56:18 +0800 Subject: [PATCH 16/44] no message --- utils/structs.go | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/utils/structs.go b/utils/structs.go index dfc0c90..079c6d5 100644 --- a/utils/structs.go +++ b/utils/structs.go @@ -97,17 +97,22 @@ func (c *Checker) start() { //log.Printf("check %s", item.Host) var conn net.Conn var err error + var now = time.Now().Unix() conn, err = ConnectHost(item.Address, c.timeout) if err == nil { conn.SetDeadline(time.Now().Add(time.Millisecond)) conn.Close() } + if now-item.Lasttime > 1800 { + item.FailCount = 0 + item.SuccessCount = 0 + } if err != nil { item.FailCount = item.FailCount + 1 } else { item.SuccessCount = item.SuccessCount + 1 } - item.Lasttime = time.Now().Unix() + item.Lasttime = now c.data.Set(item.Domain, item) } }(v.(CheckerItem)) @@ -121,11 +126,11 @@ func (c *Checker) start() { } func (c *Checker) isNeedCheck(item CheckerItem) bool { var minCount uint = 5 - if (item.SuccessCount >= minCount && item.SuccessCount > item.FailCount) || - (item.FailCount >= minCount && item.SuccessCount > item.FailCount) || + var now = time.Now().Unix() + if (item.SuccessCount >= minCount && item.SuccessCount > item.FailCount && now-item.Lasttime < 1800) || + (item.FailCount >= minCount && item.SuccessCount > item.FailCount && now-item.Lasttime < 1800) || c.domainIsInMap(item.Domain, false) || - c.domainIsInMap(item.Domain, true) || - time.Now().Unix()-item.Lasttime > 1800 { + c.domainIsInMap(item.Domain, true) { return false } return true From 12dd591c58890579c4e1c5419ca698b340592ec2 Mon Sep 17 00:00:00 2001 From: "arraykeys@gmail.com" Date: Thu, 5 Jul 2018 15:56:26 +0800 Subject: [PATCH 17/44] add fully socks5 UDP support Signed-off-by: arraykeys@gmail.com --- config.go | 2 - sdk/android-ios/sdk.go | 2 - services/socks/socks.go | 293 +++++++++++++--------------------------- utils/functions.go | 93 ------------- 4 files changed, 95 insertions(+), 295 deletions(-) diff --git a/config.go b/config.go index 7b633db..547f26f 100755 --- a/config.go +++ b/config.go @@ -198,8 +198,6 @@ func initConfig() (err error) { socksArgs.ParentType = socks.Flag("parent-type", "parent protocol type ").Default("tcp").Short('T').Enum("tls", "tcp", "kcp", "ssh") socksArgs.LocalType = socks.Flag("local-type", "local protocol type ").Default("tcp").Short('t').Enum("tls", "tcp", "kcp") socksArgs.Local = socks.Flag("local", "local ip:port to listen").Short('p').Default(":33080").String() - socksArgs.UDPParent = socks.Flag("udp-parent", "udp parent address, such as: \"23.32.32.19:33090\"").Default("").Short('X').String() - socksArgs.UDPLocal = socks.Flag("udp-local", "udp local ip:port to listen").Short('x').Default(":33090").String() socksArgs.CertFile = socks.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String() socksArgs.CaCertFile = socks.Flag("ca", "ca cert file for tls").Default("").String() socksArgs.KeyFile = socks.Flag("key", "key file for tls").Short('K').Default("proxy.key").String() diff --git a/sdk/android-ios/sdk.go b/sdk/android-ios/sdk.go index 1033d62..db1882a 100644 --- a/sdk/android-ios/sdk.go +++ b/sdk/android-ios/sdk.go @@ -194,8 +194,6 @@ func Start(serviceID, serviceArgsStr string) (errStr string) { socksArgs.ParentType = socks.Flag("parent-type", "parent protocol type ").Default("tcp").Short('T').Enum("tls", "tcp", "kcp", "ssh") socksArgs.LocalType = socks.Flag("local-type", "local protocol type ").Default("tcp").Short('t').Enum("tls", "tcp", "kcp") socksArgs.Local = socks.Flag("local", "local ip:port to listen").Short('p').Default(":33080").String() - socksArgs.UDPParent = socks.Flag("udp-parent", "udp parent address, such as: \"23.32.32.19:33090\"").Default("").Short('X').String() - socksArgs.UDPLocal = socks.Flag("udp-local", "udp local ip:port to listen").Short('x').Default(":33090").String() socksArgs.CertFile = socks.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String() socksArgs.CaCertFile = socks.Flag("ca", "ca cert file for tls").Default("").String() socksArgs.KeyFile = socks.Flag("key", "key file for tls").Short('K').Default("proxy.key").String() diff --git a/services/socks/socks.go b/services/socks/socks.go index 99427a9..4aa35d0 100644 --- a/services/socks/socks.go +++ b/services/socks/socks.go @@ -1,6 +1,7 @@ package socks import ( + "crypto/md5" "crypto/tls" "fmt" "io" @@ -15,7 +16,7 @@ import ( "github.com/snail007/goproxy/services" "github.com/snail007/goproxy/services/kcpcfg" "github.com/snail007/goproxy/utils" - "github.com/snail007/goproxy/utils/aes" + goaes "github.com/snail007/goproxy/utils/aes" "github.com/snail007/goproxy/utils/conncrypt" "github.com/snail007/goproxy/utils/socks" "golang.org/x/crypto/ssh" @@ -50,8 +51,6 @@ type SocksArgs struct { AuthURLTimeout *int AuthURLRetry *int KCP kcpcfg.KCPConfigArgs - UDPParent *string - UDPLocal *string LocalIPS *[]string DNSAddress *string DNSTTL *int @@ -73,6 +72,8 @@ type Socks struct { userConns utils.ConcurrentMap log *logger.Logger udpRelatedPacketConns utils.ConcurrentMap + udpLocalKey []byte + udpParentKey []byte } func NewSocks() services.Service { @@ -107,17 +108,6 @@ func (s *Socks) CheckArgs() (err error) { err = fmt.Errorf("parent type unkown,use -T ") return } - host, _, e := net.SplitHostPort(*s.cfg.Parent) - if e != nil { - err = fmt.Errorf("parent format error : %s", e) - return - } - if *s.cfg.UDPParent == "" { - *s.cfg.UDPParent = net.JoinHostPort(host, "33090") - } - if strings.HasPrefix(*s.cfg.UDPParent, ":") { - *s.cfg.UDPParent = net.JoinHostPort(host, strings.TrimLeft(*s.cfg.UDPParent, ":")) - } if *s.cfg.ParentType == "ssh" { if *s.cfg.SSHUser == "" { err = fmt.Errorf("ssh user required") @@ -149,6 +139,9 @@ func (s *Socks) CheckArgs() (err error) { } } } + s.udpLocalKey = s.LocalUDPKey() + s.udpParentKey = s.ParentUDPKey() + //s.log.Printf("udpLocalKey : %v , udpParentKey : %v", s.udpLocalKey, s.udpParentKey) return } func (s *Socks) InitService() (err error) { @@ -190,14 +183,6 @@ func (s *Socks) InitService() (err error) { } if *s.cfg.ParentType == "ssh" { s.log.Printf("warn: socks udp not suppored for ssh") - } else { - s.udpSC = utils.NewServerChannelHost(*s.cfg.UDPLocal, s.log) - e := s.udpSC.ListenUDP(s.udpCallback) - if e != nil { - err = fmt.Errorf("init udp service fail, ERR: %s", e) - return - } - s.log.Printf("udp socks proxy on %s", s.udpSC.UDPListener.LocalAddr()) } return } @@ -241,9 +226,6 @@ func (s *Socks) Start(args interface{}, log *logger.Logger) (err error) { if *s.cfg.Parent != "" { s.log.Printf("use %s parent %s", *s.cfg.ParentType, *s.cfg.Parent) } - if *s.cfg.UDPParent != "" { - s.log.Printf("use socks udp parent %s", *s.cfg.UDPParent) - } sc := utils.NewServerChannelHost(*s.cfg.Local, s.log) if *s.cfg.LocalType == "tcp" { err = sc.ListenTCP(s.socksConnCallback) @@ -262,165 +244,7 @@ func (s *Socks) Start(args interface{}, log *logger.Logger) (err error) { func (s *Socks) Clean() { s.StopService() } -func (s *Socks) UDPKey() []byte { - return s.cfg.KeyBytes[:32] -} -func (s *Socks) udpCallback(b []byte, localAddr, srcAddr *net.UDPAddr) { - rawB := b - var err error - if *s.cfg.LocalType == "tls" { - //decode b - rawB, err = goaes.Decrypt(s.UDPKey(), b) - if err != nil { - s.log.Printf("decrypt udp packet fail from %s", srcAddr.String()) - return - } - } - p, err := socks.ParseUDPPacket(rawB) - s.log.Printf("udp revecived:%v", len(p.Data())) - if err != nil { - s.log.Printf("parse udp packet fail, ERR:%s", err) - return - } - //防止死循环 - if s.IsDeadLoop((*localAddr).String(), p.Host()) { - s.log.Printf("dead loop detected , %s", p.Host()) - return - } - //s.log.Printf("##########udp to -> %s:%s###########", p.Host(), p.Port()) - if *s.cfg.Parent != "" { - //有上级代理,转发给上级 - if *s.cfg.ParentType == "tls" { - //encode b - rawB, err = goaes.Encrypt(s.UDPKey(), rawB) - if err != nil { - s.log.Printf("encrypt udp data fail to %s", *s.cfg.Parent) - return - } - } - parent := *s.cfg.UDPParent - if parent == "" { - parent = *s.cfg.Parent - } - dstAddr, err := net.ResolveUDPAddr("udp", s.Resolve(parent)) - if err != nil { - s.log.Printf("can't resolve address: %s", err) - return - } - clientSrcAddr := &net.UDPAddr{IP: net.IPv4zero, Port: 0} - conn, err := net.DialUDP("udp", clientSrcAddr, dstAddr) - if err != nil { - s.log.Printf("connect to udp %s fail,ERR:%s", dstAddr.String(), err) - return - } - conn.SetDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout*5))) - _, err = conn.Write(rawB) - conn.SetDeadline(time.Time{}) - s.log.Printf("udp request:%v", len(rawB)) - if err != nil { - s.log.Printf("send udp packet to %s fail,ERR:%s", dstAddr.String(), err) - conn.Close() - return - } - //s.log.Printf("send udp packet to %s success", dstAddr.String()) - buf := make([]byte, 10*1024) - conn.SetDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout))) - length, _, err := conn.ReadFromUDP(buf) - conn.SetDeadline(time.Time{}) - if err != nil { - s.log.Printf("read udp response from %s fail ,ERR:%s", dstAddr.String(), err) - conn.Close() - return - } - respBody := buf[0:length] - s.log.Printf("udp response:%v", len(respBody)) - //s.log.Printf("revecived udp packet from %s", dstAddr.String()) - if *s.cfg.ParentType == "tls" { - //decode b - respBody, err = goaes.Decrypt(s.UDPKey(), respBody) - if err != nil { - s.log.Printf("encrypt udp data fail to %s", *s.cfg.Parent) - conn.Close() - return - } - } - if *s.cfg.LocalType == "tls" { - d, err := goaes.Encrypt(s.UDPKey(), respBody) - if err != nil { - s.log.Printf("encrypt udp data fail from %s", dstAddr.String()) - conn.Close() - return - } - s.udpSC.UDPListener.SetDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout))) - s.udpSC.UDPListener.WriteToUDP(d, srcAddr) - s.udpSC.UDPListener.SetDeadline(time.Time{}) - s.log.Printf("udp reply:%v", len(d)) - d = nil - } else { - s.udpSC.UDPListener.SetDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout))) - s.udpSC.UDPListener.WriteToUDP(respBody, srcAddr) - s.udpSC.UDPListener.SetDeadline(time.Time{}) - s.log.Printf("udp reply:%v", len(respBody)) - } - - } else { - //本地代理 - dstAddr, err := net.ResolveUDPAddr("udp", net.JoinHostPort(s.Resolve(p.Host()), p.Port())) - if err != nil { - s.log.Printf("can't resolve address: %s", err) - return - } - clientSrcAddr := &net.UDPAddr{IP: net.IPv4zero, Port: 0} - conn, err := net.DialUDP("udp", clientSrcAddr, dstAddr) - if err != nil { - s.log.Printf("connect to udp %s fail,ERR:%s", dstAddr.String(), err) - return - } - conn.SetDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout*3))) - _, err = conn.Write(p.Data()) - conn.SetDeadline(time.Time{}) - s.log.Printf("udp send:%v", len(p.Data())) - if err != nil { - s.log.Printf("send udp packet to %s fail,ERR:%s", dstAddr.String(), err) - conn.Close() - return - } - //s.log.Printf("send udp packet to %s success", dstAddr.String()) - buf := make([]byte, 10*1024) - conn.SetDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout))) - length, _, err := conn.ReadFromUDP(buf) - conn.SetDeadline(time.Time{}) - - if err != nil { - s.log.Printf("read udp response from %s fail ,ERR:%s", dstAddr.String(), err) - conn.Close() - return - } - respBody := buf[0:length] - //封装来自真实服务器的数据,返回给访问者 - respPacket := p.NewReply(respBody) - //s.log.Printf("revecived udp packet from %s", dstAddr.String()) - if *s.cfg.LocalType == "tls" { - d, err := goaes.Encrypt(s.UDPKey(), respPacket) - if err != nil { - s.log.Printf("encrypt udp data fail from %s", dstAddr.String()) - conn.Close() - return - } - s.udpSC.UDPListener.SetDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout))) - s.udpSC.UDPListener.WriteToUDP(d, srcAddr) - s.udpSC.UDPListener.SetDeadline(time.Time{}) - d = nil - } else { - s.udpSC.UDPListener.SetDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout))) - s.udpSC.UDPListener.WriteToUDP(respPacket, srcAddr) - s.udpSC.UDPListener.SetDeadline(time.Time{}) - } - s.log.Printf("udp reply:%v", len(respPacket)) - } - -} func (s *Socks) socksConnCallback(inConn net.Conn) { defer func() { if err := recover(); err != nil { @@ -535,6 +359,36 @@ func (s *Socks) socksConnCallback(inConn net.Conn) { } } +func (s *Socks) ParentUDPKey() (key []byte) { + switch *s.cfg.ParentType { + case "tcp": + if *s.cfg.ParentKey != "" { + v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.ParentKey))) + return []byte(v)[:24] + } + case "tls": + return s.cfg.KeyBytes[:24] + case "kcp": + v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.KCP.Key))) + return []byte(v)[:24] + } + return +} +func (s *Socks) LocalUDPKey() (key []byte) { + switch *s.cfg.LocalType { + case "tcp": + if *s.cfg.LocalKey != "" { + v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.LocalKey))) + return []byte(v)[:24] + } + case "tls": + return s.cfg.KeyBytes[:24] + case "kcp": + v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.KCP.Key))) + return []byte(v)[:24] + } + return +} func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, request socks.Request) { if *s.cfg.ParentType == "ssh" { utils.CloseConn(inConn) @@ -589,16 +443,19 @@ func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, reque defer clean("", "") go func() { buf := make([]byte, 1) + (*inConn).SetReadDeadline(time.Time{}) if _, err := (*inConn).Read(buf); err != nil { clean("udp related tcp conn disconnected with read", err.Error()) } }() go func() { for { + (*inConn).SetWriteDeadline(time.Now().Add(time.Second * 5)) if _, err := (*inConn).Write([]byte{0x00}); err != nil { clean("udp related tcp conn disconnected with write", err.Error()) return } + (*inConn).SetWriteDeadline(time.Time{}) time.Sleep(time.Second * 5) } }() @@ -614,13 +471,17 @@ func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, reque s.checker.Add(request.Addr(), s.Resolve(request.Addr())) } } + } else { + useProxy = false + } + if useProxy { //parent proxy outconn, err := s.getOutConn(nil, nil, "", false) if err != nil { clean("connnect fail", fmt.Sprintf("%s", err)) return } - client := socks.NewClientConn(&outconn, "udp", "", time.Millisecond*time.Duration(*s.cfg.Timeout), nil, nil) + client := socks.NewClientConn(&outconn, "udp", request.Addr(), time.Millisecond*time.Duration(*s.cfg.Timeout), nil, nil) if err = client.Handshake(); err != nil { clean("handshake fail", fmt.Sprintf("%s", err)) return @@ -630,17 +491,16 @@ func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, reque s.userConns.Set(outconnLocalAddr, &outconn) go func() { buf := make([]byte, 1) + outconn.SetReadDeadline(time.Time{}) if _, err := outconn.Read(buf); err != nil { clean("udp parent tcp conn disconnected", fmt.Sprintf("%s", err)) } }() //forward to parent udp - s.log.Printf("parent udp address %s", client.UDPAddr) + //s.log.Printf("parent udp address %s", client.UDPAddr) destAddr, _ = net.ResolveUDPAddr("udp", client.UDPAddr) - } else { - useProxy = false } - s.log.Printf("use proxy %v , udp %s", useProxy, request.Addr()) + s.log.Printf("use proxy %v : udp %s", useProxy, request.Addr()) //relay for { buf := utils.LeakyBuffer.Get() @@ -654,7 +514,17 @@ func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, reque continue } p := socks.NewPacketUDP() - err = p.Parse(buf[:n]) + //convert data to raw + if len(s.udpLocalKey) > 0 { + var v []byte + v, err = goaes.Decrypt(s.udpLocalKey, buf[:n]) + if err == nil { + err = p.Parse(v) + } + } else { + err = p.Parse(buf[:n]) + } + //err = p.Parse(buf[:n]) if err != nil { s.log.Printf("udp listener parse packet fail, %s", err.Error()) continue @@ -672,7 +542,6 @@ func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, reque continue } s.udpRelatedPacketConns.Set(srcAddr.String(), outUDPConn) - go func() { defer s.udpRelatedPacketConns.Remove(srcAddr.String()) //out->local io copy @@ -688,16 +557,36 @@ func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, reque continue } - var dlen = n + //var dlen = n if useProxy { //forward to local - _, err = udpListener.WriteTo(buf[:n], srcAddr) + var v []byte + //convert parent data to raw + if len(s.udpParentKey) > 0 { + v, err = goaes.Decrypt(s.udpParentKey, buf[:n]) + if err != nil { + s.log.Printf("udp outconn parse packet fail, %s", err.Error()) + continue + } + } else { + v = buf[:n] + } + //now v is raw, try convert v to local + if len(s.udpLocalKey) > 0 { + v, _ = goaes.Encrypt(s.udpLocalKey, v) + } + _, err = udpListener.WriteTo(v, srcAddr) + // _, err = udpListener.WriteTo(buf[:n], srcAddr) } else { rp := socks.NewPacketUDP() rp.Build(srcAddr.String(), buf[:n]) - d := rp.Bytes() - dlen = len(d) - _, err = udpListener.WriteTo(d, srcAddr) + v := rp.Bytes() + //dlen = len(v) + //rp.Bytes() v is raw, try convert to local + if len(s.udpLocalKey) > 0 { + v, _ = goaes.Encrypt(s.udpLocalKey, v) + } + _, err = udpListener.WriteTo(v, srcAddr) } if err != nil { @@ -708,7 +597,7 @@ func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, reque } continue } else { - s.log.Printf("send udp data to local success , len %d, for : %s", dlen, srcAddr) + //s.log.Printf("send udp data to local success , len %d, for : %s", dlen, srcAddr) } } }() @@ -718,7 +607,15 @@ func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, reque //local->out io copy if useProxy { //forward to parent - _, err = outUDPConn.Write(buf[:n]) + //p is raw, now convert it to parent + var v []byte + if len(s.udpParentKey) > 0 { + v, _ = goaes.Encrypt(s.udpParentKey, p.Bytes()) + } else { + v = p.Bytes() + } + _, err = outUDPConn.Write(v) + // _, err = outUDPConn.Write(p.Bytes()) } else { _, err = outUDPConn.Write(p.Data()) } @@ -729,7 +626,7 @@ func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, reque s.log.Printf("send out udp data fail , %s , from : %s", err, srcAddr) continue } else { - s.log.Printf("send udp data to remote success , len %d, for : %s", len(p.Data()), srcAddr) + //s.log.Printf("send udp data to remote success , len %d, for : %s", len(p.Data()), srcAddr) } } diff --git a/utils/functions.go b/utils/functions.go index 29b4851..4d20b7c 100755 --- a/utils/functions.go +++ b/utils/functions.go @@ -17,7 +17,6 @@ import ( "net" "net/http" "os" - "os/exec" "github.com/snail007/goproxy/services/kcpcfg" @@ -209,98 +208,6 @@ func CloseConn(conn *net.Conn) { (*conn).Close() } } -func Keygen() (err error) { - CList := []string{"AD", "AE", "AF", "AG", "AI", "AL", "AM", "AO", "AR", "AT", "AU", "AZ", "BB", "BD", "BE", "BF", "BG", "BH", "BI", "BJ", "BL", "BM", "BN", "BO", "BR", "BS", "BW", "BY", "BZ", "CA", "CF", "CG", "CH", "CK", "CL", "CM", "CN", "CO", "CR", "CS", "CU", "CY", "CZ", "DE", "DJ", "DK", "DO", "DZ", "EC", "EE", "EG", "ES", "ET", "FI", "FJ", "FR", "GA", "GB", "GD", "GE", "GF", "GH", "GI", "GM", "GN", "GR", "GT", "GU", "GY", "HK", "HN", "HT", "HU", "ID", "IE", "IL", "IN", "IQ", "IR", "IS", "IT", "JM", "JO", "JP", "KE", "KG", "KH", "KP", "KR", "KT", "KW", "KZ", "LA", "LB", "LC", "LI", "LK", "LR", "LS", "LT", "LU", "LV", "LY", "MA", "MC", "MD", "MG", "ML", "MM", "MN", "MO", "MS", "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA", "NE", "NG", "NI", "NL", "NO", "NP", "NR", "NZ", "OM", "PA", "PE", "PF", "PG", "PH", "PK", "PL", "PR", "PT", "PY", "QA", "RO", "RU", "SA", "SB", "SC", "SD", "SE", "SG", "SI", "SK", "SL", "SM", "SN", "SO", "SR", "ST", "SV", "SY", "SZ", "TD", "TG", "TH", "TJ", "TM", "TN", "TO", "TR", "TT", "TW", "TZ", "UA", "UG", "US", "UY", "UZ", "VC", "VE", "VN", "YE", "YU", "ZA", "ZM", "ZR", "ZW"} - domainSubfixList := []string{".com", ".edu", ".gov", ".int", ".mil", ".net", ".org", ".biz", ".info", ".pro", ".name", ".museum", ".coop", ".aero", ".xxx", ".idv", ".ac", ".ad", ".ae", ".af", ".ag", ".ai", ".al", ".am", ".an", ".ao", ".aq", ".ar", ".as", ".at", ".au", ".aw", ".az", ".ba", ".bb", ".bd", ".be", ".bf", ".bg", ".bh", ".bi", ".bj", ".bm", ".bn", ".bo", ".br", ".bs", ".bt", ".bv", ".bw", ".by", ".bz", ".ca", ".cc", ".cd", ".cf", ".cg", ".ch", ".ci", ".ck", ".cl", ".cm", ".cn", ".co", ".cr", ".cu", ".cv", ".cx", ".cy", ".cz", ".de", ".dj", ".dk", ".dm", ".do", ".dz", ".ec", ".ee", ".eg", ".eh", ".er", ".es", ".et", ".eu", ".fi", ".fj", ".fk", ".fm", ".fo", ".fr", ".ga", ".gd", ".ge", ".gf", ".gg", ".gh", ".gi", ".gl", ".gm", ".gn", ".gp", ".gq", ".gr", ".gs", ".gt", ".gu", ".gw", ".gy", ".hk", ".hm", ".hn", ".hr", ".ht", ".hu", ".id", ".ie", ".il", ".im", ".in", ".io", ".iq", ".ir", ".is", ".it", ".je", ".jm", ".jo", ".jp", ".ke", ".kg", ".kh", ".ki", ".km", ".kn", ".kp", ".kr", ".kw", ".ky", ".kz", ".la", ".lb", ".lc", ".li", ".lk", ".lr", ".ls", ".lt", ".lu", ".lv", ".ly", ".ma", ".mc", ".md", ".mg", ".mh", ".mk", ".ml", ".mm", ".mn", ".mo", ".mp", ".mq", ".mr", ".ms", ".mt", ".mu", ".mv", ".mw", ".mx", ".my", ".mz", ".na", ".nc", ".ne", ".nf", ".ng", ".ni", ".nl", ".no", ".np", ".nr", ".nu", ".nz", ".om", ".pa", ".pe", ".pf", ".pg", ".ph", ".pk", ".pl", ".pm", ".pn", ".pr", ".ps", ".pt", ".pw", ".py", ".qa", ".re", ".ro", ".ru", ".rw", ".sa", ".sb", ".sc", ".sd", ".se", ".sg", ".sh", ".si", ".sj", ".sk", ".sl", ".sm", ".sn", ".so", ".sr", ".st", ".sv", ".sy", ".sz", ".tc", ".td", ".tf", ".tg", ".th", ".tj", ".tk", ".tl", ".tm", ".tn", ".to", ".tp", ".tr", ".tt", ".tv", ".tw", ".tz", ".ua", ".ug", ".uk", ".um", ".us", ".uy", ".uz", ".va", ".vc", ".ve", ".vg", ".vi", ".vn", ".vu", ".wf", ".ws", ".ye", ".yt", ".yu", ".yr", ".za", ".zm", ".zw"} - C := CList[int(RandInt(4))%len(CList)] - ST := RandString(int(RandInt(4) % 10)) - O := RandString(int(RandInt(4) % 10)) - CN := strings.ToLower(RandString(int(RandInt(4)%10)) + domainSubfixList[int(RandInt(4))%len(domainSubfixList)]) - //log.Printf("C: %s, ST: %s, O: %s, CN: %s", C, ST, O, CN) - var out []byte - if len(os.Args) == 3 && os.Args[2] == "ca" { - cmd := exec.Command("sh", "-c", "openssl genrsa -out ca.key 2048") - out, err = cmd.CombinedOutput() - if err != nil { - logger.Printf("err:%s", err) - return - } - fmt.Println(string(out)) - - cmdStr := fmt.Sprintf("openssl req -new -key ca.key -x509 -days 36500 -out ca.crt -subj /C=%s/ST=%s/O=%s/CN=%s", C, ST, O, "*."+CN) - cmd = exec.Command("sh", "-c", cmdStr) - out, err = cmd.CombinedOutput() - if err != nil { - logger.Printf("err:%s", err) - return - } - fmt.Println(string(out)) - } else if len(os.Args) == 5 && os.Args[2] == "ca" && os.Args[3] != "" && os.Args[4] != "" { - certBytes, _ := ioutil.ReadFile("ca.crt") - block, _ := pem.Decode(certBytes) - if block == nil || certBytes == nil { - panic("failed to parse ca certificate PEM") - } - x509Cert, _ := x509.ParseCertificate(block.Bytes) - if x509Cert == nil { - panic("failed to parse block") - } - name := os.Args[3] - days := os.Args[4] - cmd := exec.Command("sh", "-c", "openssl genrsa -out "+name+".key 2048") - out, err = cmd.CombinedOutput() - if err != nil { - logger.Printf("err:%s", err) - return - } - fmt.Println(string(out)) - - cmdStr := fmt.Sprintf("openssl req -new -key %s.key -out %s.csr -subj /C=%s/ST=%s/O=%s/CN=%s", name, name, C, ST, O, CN) - fmt.Printf("%s", cmdStr) - cmd = exec.Command("sh", "-c", cmdStr) - out, err = cmd.CombinedOutput() - if err != nil { - logger.Printf("err:%s", err) - return - } - fmt.Println(string(out)) - - cmdStr = fmt.Sprintf("openssl x509 -req -days %s -in %s.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out %s.crt", days, name, name) - fmt.Printf("%s", cmdStr) - cmd = exec.Command("sh", "-c", cmdStr) - out, err = cmd.CombinedOutput() - if err != nil { - logger.Printf("err:%s", err) - return - } - - fmt.Println(string(out)) - } else if len(os.Args) == 3 && os.Args[2] == "usage" { - fmt.Println(`proxy keygen //generate proxy.crt and proxy.key -proxy keygen ca //generate ca.crt and ca.key -proxy keygen ca client0 30 //generate client0.crt client0.key and use ca.crt sign it with 30 days - `) - } else if len(os.Args) == 2 { - cmd := exec.Command("sh", "-c", "openssl genrsa -out proxy.key 2048") - out, err = cmd.CombinedOutput() - if err != nil { - logger.Printf("err:%s", err) - return - } - fmt.Println(string(out)) - - cmdStr := fmt.Sprintf("openssl req -new -key proxy.key -x509 -days 36500 -out proxy.crt -subj /C=%s/ST=%s/O=%s/CN=%s", C, ST, O, CN) - cmd = exec.Command("sh", "-c", cmdStr) - out, err = cmd.CombinedOutput() - if err != nil { - logger.Printf("err:%s", err) - return - } - fmt.Println(string(out)) - } - - return -} func GetAllInterfaceAddr() ([]net.IP, error) { ifaces, err := net.Interfaces() From 6b4ee97f05177a92b2b6a6c0fc252a64eddee0ff Mon Sep 17 00:00:00 2001 From: arraykeys Date: Thu, 5 Jul 2018 20:18:12 +0800 Subject: [PATCH 18/44] no message --- README_ZH.md | 9 ++++++++- services/socks/socks.go | 5 ++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/README_ZH.md b/README_ZH.md index 59a0aef..d325b61 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -689,7 +689,14 @@ server连接到bridge的时候,如果同时有多个client连接到同一个brid `./proxy help client` ### **5.SOCKS5代理** -提示:SOCKS5代理,支持CONNECT,UDP协议,不支持BIND,支持用户名密码认证. +提示: + +SOCKS5代理,支持CONNECT,UDP协议,不支持BIND,支持用户名密码认证. + +***如果你的VPS是阿里云,腾讯云这种VPS,就是ifconfig看不见你的公网IP,只能看见内网IP,*** + +***那么需要加上`-g VPS公网IP`参数,SOCKS5代理的UDP功能才能正常工作。*** + #### **5.1.普通SOCKS5代理** `./proxy socks -t tcp -p "0.0.0.0:38080"` diff --git a/services/socks/socks.go b/services/socks/socks.go index 4aa35d0..b4c7933 100644 --- a/services/socks/socks.go +++ b/services/socks/socks.go @@ -405,7 +405,10 @@ func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, reque } host, _, _ := net.SplitHostPort((*inConn).LocalAddr().String()) _, port, _ := net.SplitHostPort(udpListener.LocalAddr().String()) - s.log.Printf("proxy udp on %s , for %s", udpListener.LocalAddr(), inconnRemoteAddr) + if len(*s.cfg.LocalIPS) > 0 { + host = (*s.cfg.LocalIPS)[0] + } + s.log.Printf("proxy udp on %s , for %s", net.JoinHostPort(host, port), inconnRemoteAddr) request.UDPReply(socks.REP_SUCCESS, net.JoinHostPort(host, port)) s.userConns.Set(inconnRemoteAddr, inConn) var ( From f5d09b878b2ee974b888374e0603768e1efd80a5 Mon Sep 17 00:00:00 2001 From: "arraykeys@gmail.com" Date: Fri, 6 Jul 2018 18:24:12 +0800 Subject: [PATCH 19/44] fix socks udp reply wrong dst addr Signed-off-by: arraykeys@gmail.com --- services/socks/socks.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/socks/socks.go b/services/socks/socks.go index 4aa35d0..690fdaa 100644 --- a/services/socks/socks.go +++ b/services/socks/socks.go @@ -579,7 +579,7 @@ func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, reque // _, err = udpListener.WriteTo(buf[:n], srcAddr) } else { rp := socks.NewPacketUDP() - rp.Build(srcAddr.String(), buf[:n]) + rp.Build(destAddr.String(), buf[:n]) v := rp.Bytes() //dlen = len(v) //rp.Bytes() v is raw, try convert to local From 0226d2cde367956f15253c8aaf26821f2327df8d Mon Sep 17 00:00:00 2001 From: arraykeys Date: Sat, 7 Jul 2018 23:56:56 +0800 Subject: [PATCH 20/44] add sps : socks->udp support --- services/socks/socks.go | 277 ---------------------------------- services/socks/udp.go | 315 +++++++++++++++++++++++++++++++++++++++ services/sps/socksudp.go | 302 +++++++++++++++++++++++++++++++++++++ services/sps/sps.go | 43 ++++-- utils/socks/server.go | 64 +++++--- 5 files changed, 691 insertions(+), 310 deletions(-) create mode 100644 services/socks/udp.go create mode 100644 services/sps/socksudp.go diff --git a/services/socks/socks.go b/services/socks/socks.go index 6bae3ec..5020c50 100644 --- a/services/socks/socks.go +++ b/services/socks/socks.go @@ -1,7 +1,6 @@ package socks import ( - "crypto/md5" "crypto/tls" "fmt" "io" @@ -9,14 +8,12 @@ import ( logger "log" "net" "runtime/debug" - "strconv" "strings" "time" "github.com/snail007/goproxy/services" "github.com/snail007/goproxy/services/kcpcfg" "github.com/snail007/goproxy/utils" - goaes "github.com/snail007/goproxy/utils/aes" "github.com/snail007/goproxy/utils/conncrypt" "github.com/snail007/goproxy/utils/socks" "golang.org/x/crypto/ssh" @@ -359,281 +356,7 @@ func (s *Socks) socksConnCallback(inConn net.Conn) { } } -func (s *Socks) ParentUDPKey() (key []byte) { - switch *s.cfg.ParentType { - case "tcp": - if *s.cfg.ParentKey != "" { - v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.ParentKey))) - return []byte(v)[:24] - } - case "tls": - return s.cfg.KeyBytes[:24] - case "kcp": - v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.KCP.Key))) - return []byte(v)[:24] - } - return -} -func (s *Socks) LocalUDPKey() (key []byte) { - switch *s.cfg.LocalType { - case "tcp": - if *s.cfg.LocalKey != "" { - v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.LocalKey))) - return []byte(v)[:24] - } - case "tls": - return s.cfg.KeyBytes[:24] - case "kcp": - v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.KCP.Key))) - return []byte(v)[:24] - } - return -} -func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, request socks.Request) { - if *s.cfg.ParentType == "ssh" { - utils.CloseConn(inConn) - return - } - inconnRemoteAddr := (*inConn).RemoteAddr().String() - localAddr := &net.UDPAddr{IP: net.IPv4zero, Port: 0} - udpListener, err := net.ListenUDP("udp", localAddr) - if err != nil { - (*inConn).Close() - udpListener.Close() - s.log.Printf("udp bind fail , %s", err) - return - } - host, _, _ := net.SplitHostPort((*inConn).LocalAddr().String()) - _, port, _ := net.SplitHostPort(udpListener.LocalAddr().String()) - if len(*s.cfg.LocalIPS) > 0 { - host = (*s.cfg.LocalIPS)[0] - } - s.log.Printf("proxy udp on %s , for %s", net.JoinHostPort(host, port), inconnRemoteAddr) - request.UDPReply(socks.REP_SUCCESS, net.JoinHostPort(host, port)) - s.userConns.Set(inconnRemoteAddr, inConn) - var ( - outUDPConn *net.UDPConn - outconn net.Conn - outconnLocalAddr string - isClosedErr = func(err error) bool { - return err != nil && strings.Contains(err.Error(), "use of closed network connection") - } - destAddr *net.UDPAddr - ) - var clean = func(msg, err string) { - raddr := "" - if outUDPConn != nil { - raddr = outUDPConn.RemoteAddr().String() - outUDPConn.Close() - } - if msg != "" { - if raddr != "" { - s.log.Printf("%s , %s , %s -> %s", msg, err, inconnRemoteAddr, raddr) - } else { - s.log.Printf("%s , %s , from : %s", msg, err, inconnRemoteAddr) - } - } - (*inConn).Close() - udpListener.Close() - s.userConns.Remove(inconnRemoteAddr) - if outconn != nil { - outconn.Close() - } - if outconnLocalAddr != "" { - s.userConns.Remove(outconnLocalAddr) - } - } - defer clean("", "") - go func() { - buf := make([]byte, 1) - (*inConn).SetReadDeadline(time.Time{}) - if _, err := (*inConn).Read(buf); err != nil { - clean("udp related tcp conn disconnected with read", err.Error()) - } - }() - go func() { - for { - (*inConn).SetWriteDeadline(time.Now().Add(time.Second * 5)) - if _, err := (*inConn).Write([]byte{0x00}); err != nil { - clean("udp related tcp conn disconnected with write", err.Error()) - return - } - (*inConn).SetWriteDeadline(time.Time{}) - time.Sleep(time.Second * 5) - } - }() - useProxy := true - if *s.cfg.Parent != "" { - dstHost, _, _ := net.SplitHostPort(request.Addr()) - if utils.IsIternalIP(dstHost, *s.cfg.Always) { - useProxy = false - } else { - var isInMap bool - useProxy, isInMap, _, _ = s.checker.IsBlocked(request.Addr()) - if !isInMap { - s.checker.Add(request.Addr(), s.Resolve(request.Addr())) - } - } - } else { - useProxy = false - } - if useProxy { - //parent proxy - outconn, err := s.getOutConn(nil, nil, "", false) - if err != nil { - clean("connnect fail", fmt.Sprintf("%s", err)) - return - } - client := socks.NewClientConn(&outconn, "udp", request.Addr(), time.Millisecond*time.Duration(*s.cfg.Timeout), nil, nil) - if err = client.Handshake(); err != nil { - clean("handshake fail", fmt.Sprintf("%s", err)) - return - } - //outconnRemoteAddr := outconn.RemoteAddr().String() - outconnLocalAddr = outconn.LocalAddr().String() - s.userConns.Set(outconnLocalAddr, &outconn) - go func() { - buf := make([]byte, 1) - outconn.SetReadDeadline(time.Time{}) - if _, err := outconn.Read(buf); err != nil { - clean("udp parent tcp conn disconnected", fmt.Sprintf("%s", err)) - } - }() - //forward to parent udp - //s.log.Printf("parent udp address %s", client.UDPAddr) - destAddr, _ = net.ResolveUDPAddr("udp", client.UDPAddr) - } - s.log.Printf("use proxy %v : udp %s", useProxy, request.Addr()) - //relay - for { - buf := utils.LeakyBuffer.Get() - defer utils.LeakyBuffer.Put(buf) - n, srcAddr, err := udpListener.ReadFromUDP(buf) - if err != nil { - s.log.Printf("udp listener read fail, %s", err.Error()) - if isClosedErr(err) { - return - } - continue - } - p := socks.NewPacketUDP() - //convert data to raw - if len(s.udpLocalKey) > 0 { - var v []byte - v, err = goaes.Decrypt(s.udpLocalKey, buf[:n]) - if err == nil { - err = p.Parse(v) - } - } else { - err = p.Parse(buf[:n]) - } - //err = p.Parse(buf[:n]) - if err != nil { - s.log.Printf("udp listener parse packet fail, %s", err.Error()) - continue - } - port, _ := strconv.Atoi(p.Port()) - - if v, ok := s.udpRelatedPacketConns.Get(srcAddr.String()); !ok { - if destAddr == nil { - destAddr = &net.UDPAddr{IP: net.ParseIP(p.Host()), Port: port} - } - outUDPConn, err = net.DialUDP("udp", localAddr, destAddr) - if err != nil { - s.log.Printf("create out udp conn fail , %s , from : %s", err, srcAddr) - continue - } - s.udpRelatedPacketConns.Set(srcAddr.String(), outUDPConn) - go func() { - defer s.udpRelatedPacketConns.Remove(srcAddr.String()) - //out->local io copy - buf := utils.LeakyBuffer.Get() - defer utils.LeakyBuffer.Put(buf) - for { - n, err := outUDPConn.Read(buf) - if err != nil { - s.log.Printf("read out udp data fail , %s , from : %s", err, srcAddr) - if isClosedErr(err) { - return - } - continue - } - - //var dlen = n - if useProxy { - //forward to local - var v []byte - //convert parent data to raw - if len(s.udpParentKey) > 0 { - v, err = goaes.Decrypt(s.udpParentKey, buf[:n]) - if err != nil { - s.log.Printf("udp outconn parse packet fail, %s", err.Error()) - continue - } - } else { - v = buf[:n] - } - //now v is raw, try convert v to local - if len(s.udpLocalKey) > 0 { - v, _ = goaes.Encrypt(s.udpLocalKey, v) - } - _, err = udpListener.WriteTo(v, srcAddr) - // _, err = udpListener.WriteTo(buf[:n], srcAddr) - } else { - rp := socks.NewPacketUDP() - rp.Build(destAddr.String(), buf[:n]) - v := rp.Bytes() - //dlen = len(v) - //rp.Bytes() v is raw, try convert to local - if len(s.udpLocalKey) > 0 { - v, _ = goaes.Encrypt(s.udpLocalKey, v) - } - _, err = udpListener.WriteTo(v, srcAddr) - } - - if err != nil { - s.udpRelatedPacketConns.Remove(srcAddr.String()) - s.log.Printf("write out data to local fail , %s , from : %s", err, srcAddr) - if isClosedErr(err) { - return - } - continue - } else { - //s.log.Printf("send udp data to local success , len %d, for : %s", dlen, srcAddr) - } - } - }() - } else { - outUDPConn = v.(*net.UDPConn) - } - //local->out io copy - if useProxy { - //forward to parent - //p is raw, now convert it to parent - var v []byte - if len(s.udpParentKey) > 0 { - v, _ = goaes.Encrypt(s.udpParentKey, p.Bytes()) - } else { - v = p.Bytes() - } - _, err = outUDPConn.Write(v) - // _, err = outUDPConn.Write(p.Bytes()) - } else { - _, err = outUDPConn.Write(p.Data()) - } - if err != nil { - if isClosedErr(err) { - return - } - s.log.Printf("send out udp data fail , %s , from : %s", err, srcAddr) - continue - } else { - //s.log.Printf("send udp data to remote success , len %d, for : %s", len(p.Data()), srcAddr) - } - } - -} func (s *Socks) proxyTCP(inConn *net.Conn, methodReq socks.MethodsRequest, request socks.Request) { var outConn net.Conn var err interface{} diff --git a/services/socks/udp.go b/services/socks/udp.go new file mode 100644 index 0000000..ad66a55 --- /dev/null +++ b/services/socks/udp.go @@ -0,0 +1,315 @@ +package socks + +import ( + "crypto/md5" + "fmt" + "net" + "runtime/debug" + "strconv" + "strings" + "time" + + "github.com/snail007/goproxy/utils" + goaes "github.com/snail007/goproxy/utils/aes" + "github.com/snail007/goproxy/utils/socks" +) + +func (s *Socks) ParentUDPKey() (key []byte) { + switch *s.cfg.ParentType { + case "tcp": + if *s.cfg.ParentKey != "" { + v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.ParentKey))) + return []byte(v)[:24] + } + case "tls": + return s.cfg.KeyBytes[:24] + case "kcp": + v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.KCP.Key))) + return []byte(v)[:24] + } + return +} +func (s *Socks) LocalUDPKey() (key []byte) { + switch *s.cfg.LocalType { + case "tcp": + if *s.cfg.LocalKey != "" { + v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.LocalKey))) + return []byte(v)[:24] + } + case "tls": + return s.cfg.KeyBytes[:24] + case "kcp": + v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.KCP.Key))) + return []byte(v)[:24] + } + return +} +func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, request socks.Request) { + defer func() { + if e := recover(); e != nil { + s.log.Printf("udp local->out io copy crashed:\n%s\n%s", e, string(debug.Stack())) + } + }() + if *s.cfg.ParentType == "ssh" { + utils.CloseConn(inConn) + return + } + inconnRemoteAddr := (*inConn).RemoteAddr().String() + localAddr := &net.UDPAddr{IP: net.IPv4zero, Port: 0} + udpListener, err := net.ListenUDP("udp", localAddr) + if err != nil { + (*inConn).Close() + udpListener.Close() + s.log.Printf("udp bind fail , %s", err) + return + } + host, _, _ := net.SplitHostPort((*inConn).LocalAddr().String()) + _, port, _ := net.SplitHostPort(udpListener.LocalAddr().String()) + if len(*s.cfg.LocalIPS) > 0 { + host = (*s.cfg.LocalIPS)[0] + } + s.log.Printf("proxy udp on %s , for %s", net.JoinHostPort(host, port), inconnRemoteAddr) + request.UDPReply(socks.REP_SUCCESS, net.JoinHostPort(host, port)) + s.userConns.Set(inconnRemoteAddr, inConn) + var ( + outUDPConn *net.UDPConn + outconn net.Conn + outconnLocalAddr string + isClosedErr = func(err error) bool { + return err != nil && strings.Contains(err.Error(), "use of closed network connection") + } + destAddr *net.UDPAddr + ) + var clean = func(msg, err string) { + raddr := "" + if outUDPConn != nil { + raddr = outUDPConn.RemoteAddr().String() + outUDPConn.Close() + } + if msg != "" { + if raddr != "" { + s.log.Printf("%s , %s , %s -> %s", msg, err, inconnRemoteAddr, raddr) + } else { + s.log.Printf("%s , %s , from : %s", msg, err, inconnRemoteAddr) + } + } + (*inConn).Close() + udpListener.Close() + s.userConns.Remove(inconnRemoteAddr) + if outconn != nil { + outconn.Close() + } + if outconnLocalAddr != "" { + s.userConns.Remove(outconnLocalAddr) + } + } + defer clean("", "") + go func() { + defer func() { + if e := recover(); e != nil { + s.log.Printf("udp related client tcp conn read crashed:\n%s\n%s", e, string(debug.Stack())) + } + }() + buf := make([]byte, 1) + (*inConn).SetReadDeadline(time.Time{}) + if _, err := (*inConn).Read(buf); err != nil { + clean("udp related tcp conn disconnected with read", err.Error()) + } + }() + go func() { + defer func() { + if e := recover(); e != nil { + s.log.Printf("udp related client tcp conn write crashed:\n%s\n%s", e, string(debug.Stack())) + } + }() + for { + (*inConn).SetWriteDeadline(time.Now().Add(time.Second * 5)) + if _, err := (*inConn).Write([]byte{0x00}); err != nil { + clean("udp related tcp conn disconnected with write", err.Error()) + return + } + (*inConn).SetWriteDeadline(time.Time{}) + time.Sleep(time.Second * 5) + } + }() + useProxy := true + if *s.cfg.Parent != "" { + dstHost, _, _ := net.SplitHostPort(request.Addr()) + if utils.IsIternalIP(dstHost, *s.cfg.Always) { + useProxy = false + } else { + var isInMap bool + useProxy, isInMap, _, _ = s.checker.IsBlocked(request.Addr()) + if !isInMap { + s.checker.Add(request.Addr(), s.Resolve(request.Addr())) + } + } + } else { + useProxy = false + } + if useProxy { + //parent proxy + outconn, err := s.getOutConn(nil, nil, "", false) + if err != nil { + clean("connnect fail", fmt.Sprintf("%s", err)) + return + } + client := socks.NewClientConn(&outconn, "udp", request.Addr(), time.Millisecond*time.Duration(*s.cfg.Timeout), nil, nil) + if err = client.Handshake(); err != nil { + clean("handshake fail", fmt.Sprintf("%s", err)) + return + } + //outconnRemoteAddr := outconn.RemoteAddr().String() + outconnLocalAddr = outconn.LocalAddr().String() + s.userConns.Set(outconnLocalAddr, &outconn) + go func() { + defer func() { + if e := recover(); e != nil { + s.log.Printf("udp related parent tcp conn read crashed:\n%s\n%s", e, string(debug.Stack())) + } + }() + buf := make([]byte, 1) + outconn.SetReadDeadline(time.Time{}) + if _, err := outconn.Read(buf); err != nil { + clean("udp parent tcp conn disconnected", fmt.Sprintf("%s", err)) + } + }() + //forward to parent udp + //s.log.Printf("parent udp address %s", client.UDPAddr) + destAddr, _ = net.ResolveUDPAddr("udp", client.UDPAddr) + } + s.log.Printf("use proxy %v : udp %s", useProxy, request.Addr()) + //relay + for { + buf := utils.LeakyBuffer.Get() + defer utils.LeakyBuffer.Put(buf) + n, srcAddr, err := udpListener.ReadFromUDP(buf) + if err != nil { + s.log.Printf("udp listener read fail, %s", err.Error()) + if isClosedErr(err) { + return + } + continue + } + p := socks.NewPacketUDP() + //convert data to raw + if len(s.udpLocalKey) > 0 { + var v []byte + v, err = goaes.Decrypt(s.udpLocalKey, buf[:n]) + if err == nil { + err = p.Parse(v) + } + } else { + err = p.Parse(buf[:n]) + } + //err = p.Parse(buf[:n]) + if err != nil { + s.log.Printf("udp listener parse packet fail, %s", err.Error()) + continue + } + + port, _ := strconv.Atoi(p.Port()) + + if v, ok := s.udpRelatedPacketConns.Get(srcAddr.String()); !ok { + if destAddr == nil { + destAddr = &net.UDPAddr{IP: net.ParseIP(p.Host()), Port: port} + } + outUDPConn, err = net.DialUDP("udp", localAddr, destAddr) + if err != nil { + s.log.Printf("create out udp conn fail , %s , from : %s", err, srcAddr) + continue + } + s.udpRelatedPacketConns.Set(srcAddr.String(), outUDPConn) + go func() { + defer func() { + if e := recover(); e != nil { + s.log.Printf("udp out->local io copy crashed:\n%s\n%s", e, string(debug.Stack())) + } + }() + defer s.udpRelatedPacketConns.Remove(srcAddr.String()) + //out->local io copy + buf := utils.LeakyBuffer.Get() + defer utils.LeakyBuffer.Put(buf) + for { + n, err := outUDPConn.Read(buf) + if err != nil { + s.log.Printf("read out udp data fail , %s , from : %s", err, srcAddr) + if isClosedErr(err) { + return + } + continue + } + //var dlen = n + if useProxy { + //forward to local + var v []byte + //convert parent data to raw + if len(s.udpParentKey) > 0 { + v, err = goaes.Decrypt(s.udpParentKey, buf[:n]) + if err != nil { + s.log.Printf("udp outconn parse packet fail, %s", err.Error()) + continue + } + } else { + v = buf[:n] + } + //now v is raw, try convert v to local + if len(s.udpLocalKey) > 0 { + v, _ = goaes.Encrypt(s.udpLocalKey, v) + } + _, err = udpListener.WriteTo(v, srcAddr) + // _, err = udpListener.WriteTo(buf[:n], srcAddr) + } else { + rp := socks.NewPacketUDP() + rp.Build(destAddr.String(), buf[:n]) + v := rp.Bytes() + //dlen = len(v) + //rp.Bytes() v is raw, try convert to local + if len(s.udpLocalKey) > 0 { + v, _ = goaes.Encrypt(s.udpLocalKey, v) + } + _, err = udpListener.WriteTo(v, srcAddr) + } + + if err != nil { + s.udpRelatedPacketConns.Remove(srcAddr.String()) + s.log.Printf("write out data to local fail , %s , from : %s", err, srcAddr) + if isClosedErr(err) { + return + } + continue + } else { + //s.log.Printf("send udp data to local success , len %d, for : %s", dlen, srcAddr) + } + } + }() + } else { + outUDPConn = v.(*net.UDPConn) + } + //local->out io copy + if useProxy { + //forward to parent + //p is raw, now convert it to parent + var v []byte + if len(s.udpParentKey) > 0 { + v, _ = goaes.Encrypt(s.udpParentKey, p.Bytes()) + } else { + v = p.Bytes() + } + _, err = outUDPConn.Write(v) + // _, err = outUDPConn.Write(p.Bytes()) + } else { + _, err = outUDPConn.Write(p.Data()) + } + if err != nil { + if isClosedErr(err) { + return + } + s.log.Printf("send out udp data fail , %s , from : %s", err, srcAddr) + continue + } else { + //s.log.Printf("send udp data to remote success , len %d, for : %s", len(p.Data()), srcAddr) + } + } + +} diff --git a/services/sps/socksudp.go b/services/sps/socksudp.go new file mode 100644 index 0000000..6ab08f8 --- /dev/null +++ b/services/sps/socksudp.go @@ -0,0 +1,302 @@ +package sps + +import ( + "crypto/md5" + "fmt" + "net" + "runtime/debug" + "strconv" + "strings" + "time" + + "github.com/snail007/goproxy/utils" + goaes "github.com/snail007/goproxy/utils/aes" + "github.com/snail007/goproxy/utils/conncrypt" + "github.com/snail007/goproxy/utils/socks" +) + +func (s *SPS) ParentUDPKey() (key []byte) { + switch *s.cfg.ParentType { + case "tcp": + if *s.cfg.ParentKey != "" { + v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.ParentKey))) + return []byte(v)[:24] + } + case "tls": + return s.cfg.KeyBytes[:24] + case "kcp": + v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.KCP.Key))) + return []byte(v)[:24] + } + return +} +func (s *SPS) LocalUDPKey() (key []byte) { + switch *s.cfg.LocalType { + case "tcp": + if *s.cfg.LocalKey != "" { + v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.LocalKey))) + return []byte(v)[:24] + } + case "tls": + return s.cfg.KeyBytes[:24] + case "kcp": + v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.KCP.Key))) + return []byte(v)[:24] + } + return +} +func (s *SPS) proxyUDP(inConn *net.Conn, serverConn *socks.ServerConn) { + defer func() { + if e := recover(); e != nil { + s.log.Printf("udp local->out io copy crashed:\n%s\n%s", e, string(debug.Stack())) + } + }() + if *s.cfg.ParentType == "ssh" { + utils.CloseConn(inConn) + return + } + inconnRemoteAddr := (*inConn).RemoteAddr().String() + localAddr := &net.UDPAddr{IP: net.IPv4zero, Port: 0} + udpListener := serverConn.UDPConnListener + s.log.Printf("proxy udp on %s , for %s", udpListener.LocalAddr(), inconnRemoteAddr) + s.userConns.Set(inconnRemoteAddr, inConn) + var ( + outUDPConn *net.UDPConn + outconn net.Conn + outconnLocalAddr string + isClosedErr = func(err error) bool { + return err != nil && strings.Contains(err.Error(), "use of closed network connection") + } + destAddr *net.UDPAddr + ) + var clean = func(msg, err string) { + raddr := "" + if outUDPConn != nil { + raddr = outUDPConn.RemoteAddr().String() + outUDPConn.Close() + } + if msg != "" { + if raddr != "" { + s.log.Printf("%s , %s , %s -> %s", msg, err, inconnRemoteAddr, raddr) + } else { + s.log.Printf("%s , %s , from : %s", msg, err, inconnRemoteAddr) + } + } + (*inConn).Close() + udpListener.Close() + s.userConns.Remove(inconnRemoteAddr) + if outconn != nil { + outconn.Close() + } + if outconnLocalAddr != "" { + s.userConns.Remove(outconnLocalAddr) + } + } + defer clean("", "") + go func() { + defer func() { + if e := recover(); e != nil { + s.log.Printf("udp related client tcp conn read crashed:\n%s\n%s", e, string(debug.Stack())) + } + }() + buf := make([]byte, 1) + (*inConn).SetReadDeadline(time.Time{}) + if _, err := (*inConn).Read(buf); err != nil { + clean("udp related tcp conn disconnected with read", err.Error()) + } + }() + go func() { + defer func() { + if e := recover(); e != nil { + s.log.Printf("udp related client tcp conn write crashed:\n%s\n%s", e, string(debug.Stack())) + } + }() + for { + (*inConn).SetWriteDeadline(time.Now().Add(time.Second * 5)) + if _, err := (*inConn).Write([]byte{0x00}); err != nil { + clean("udp related tcp conn disconnected with write", err.Error()) + return + } + (*inConn).SetWriteDeadline(time.Time{}) + time.Sleep(time.Second * 5) + } + }() + //parent proxy + outconn, err := s.outPool.Get() + //outconn, err := s.GetParentConn(nil, nil, "", false) + if err != nil { + clean("connnect fail", fmt.Sprintf("%s", err)) + return + } + if *s.cfg.ParentCompress { + outconn = utils.NewCompConn(outconn) + } + if *s.cfg.ParentKey != "" { + outconn = conncrypt.New(outconn, &conncrypt.Config{ + Password: *s.cfg.ParentKey, + }) + } + + //client := socks.NewClientConn(&outconn, "udp", serverConn.Target(), time.Millisecond*time.Duration(*s.cfg.Timeout), nil, nil) + + s.log.Printf("connect %s for udp", serverConn.Target()) + //socks client + var client *socks.ClientConn + auth := serverConn.AuthData() + if *s.cfg.ParentAuth != "" { + a := strings.Split(*s.cfg.ParentAuth, ":") + if len(a) != 2 { + err = fmt.Errorf("parent auth data format error") + return + } + client = socks.NewClientConn(&outconn, "udp", serverConn.Target(), time.Millisecond*time.Duration(*s.cfg.Timeout), &socks.Auth{User: a[0], Password: a[1]}, nil) + } else { + if !s.IsBasicAuth() && auth.Password != "" && auth.User != "" { + client = socks.NewClientConn(&outconn, "udp", serverConn.Target(), time.Millisecond*time.Duration(*s.cfg.Timeout), &auth, nil) + } else { + client = socks.NewClientConn(&outconn, "udp", serverConn.Target(), time.Millisecond*time.Duration(*s.cfg.Timeout), nil, nil) + } + } + + if err = client.Handshake(); err != nil { + clean("handshake fail", fmt.Sprintf("%s", err)) + return + } + + //outconnRemoteAddr := outconn.RemoteAddr().String() + outconnLocalAddr = outconn.LocalAddr().String() + s.userConns.Set(outconnLocalAddr, &outconn) + go func() { + defer func() { + if e := recover(); e != nil { + s.log.Printf("udp related parent tcp conn read crashed:\n%s\n%s", e, string(debug.Stack())) + } + }() + buf := make([]byte, 1) + outconn.SetReadDeadline(time.Time{}) + if _, err := outconn.Read(buf); err != nil { + clean("udp parent tcp conn disconnected", fmt.Sprintf("%s", err)) + } + }() + //forward to parent udp + //s.log.Printf("parent udp address %s", client.UDPAddr) + destAddr, _ = net.ResolveUDPAddr("udp", client.UDPAddr) + //relay + for { + buf := utils.LeakyBuffer.Get() + defer utils.LeakyBuffer.Put(buf) + n, srcAddr, err := udpListener.ReadFromUDP(buf) + if err != nil { + s.log.Printf("udp listener read fail, %s", err.Error()) + if isClosedErr(err) { + return + } + continue + } + p := socks.NewPacketUDP() + //convert data to raw + if len(s.udpLocalKey) > 0 { + var v []byte + v, err = goaes.Decrypt(s.udpLocalKey, buf[:n]) + if err == nil { + err = p.Parse(v) + } + } else { + err = p.Parse(buf[:n]) + } + //err = p.Parse(buf[:n]) + if err != nil { + s.log.Printf("udp listener parse packet fail, %s", err.Error()) + continue + } + + port, _ := strconv.Atoi(p.Port()) + + if v, ok := s.udpRelatedPacketConns.Get(srcAddr.String()); !ok { + if destAddr == nil { + destAddr = &net.UDPAddr{IP: net.ParseIP(p.Host()), Port: port} + } + outUDPConn, err = net.DialUDP("udp", localAddr, destAddr) + if err != nil { + s.log.Printf("create out udp conn fail , %s , from : %s", err, srcAddr) + continue + } + s.udpRelatedPacketConns.Set(srcAddr.String(), outUDPConn) + go func() { + defer func() { + if e := recover(); e != nil { + s.log.Printf("udp out->local io copy crashed:\n%s\n%s", e, string(debug.Stack())) + } + }() + defer s.udpRelatedPacketConns.Remove(srcAddr.String()) + //out->local io copy + buf := utils.LeakyBuffer.Get() + defer utils.LeakyBuffer.Put(buf) + for { + n, err := outUDPConn.Read(buf) + if err != nil { + s.log.Printf("read out udp data fail , %s , from : %s", err, srcAddr) + if isClosedErr(err) { + return + } + continue + } + + //var dlen = n + //forward to local + var v []byte + //convert parent data to raw + if len(s.udpParentKey) > 0 { + v, err = goaes.Decrypt(s.udpParentKey, buf[:n]) + if err != nil { + s.log.Printf("udp outconn parse packet fail, %s", err.Error()) + continue + } + } else { + v = buf[:n] + } + //now v is raw, try convert v to local + if len(s.udpLocalKey) > 0 { + v, _ = goaes.Encrypt(s.udpLocalKey, v) + } + _, err = udpListener.WriteTo(v, srcAddr) + // _, err = udpListener.WriteTo(buf[:n], srcAddr) + + if err != nil { + s.udpRelatedPacketConns.Remove(srcAddr.String()) + s.log.Printf("write out data to local fail , %s , from : %s", err, srcAddr) + if isClosedErr(err) { + return + } + continue + } else { + //s.log.Printf("send udp data to local success , len %d, for : %s", dlen, srcAddr) + } + } + }() + } else { + outUDPConn = v.(*net.UDPConn) + } + //local->out io copy + //forward to parent + //p is raw, now convert it to parent + var v []byte + if len(s.udpParentKey) > 0 { + v, _ = goaes.Encrypt(s.udpParentKey, p.Bytes()) + } else { + v = p.Bytes() + } + _, err = outUDPConn.Write(v) + // _, err = outUDPConn.Write(p.Bytes()) + if err != nil { + if isClosedErr(err) { + return + } + s.log.Printf("send out udp data fail , %s , from : %s", err, srcAddr) + continue + } else { + //s.log.Printf("send udp data to remote success , len %d, for : %s", len(p.Data()), srcAddr) + } + } + +} diff --git a/services/sps/sps.go b/services/sps/sps.go index e3a7fdf..8060987 100644 --- a/services/sps/sps.go +++ b/services/sps/sps.go @@ -53,22 +53,26 @@ type SPSArgs struct { DisableSocks5 *bool } type SPS struct { - outPool utils.OutConn - cfg SPSArgs - domainResolver utils.DomainResolver - basicAuth utils.BasicAuth - serverChannels []*utils.ServerChannel - userConns utils.ConcurrentMap - log *logger.Logger + outPool utils.OutConn + cfg SPSArgs + domainResolver utils.DomainResolver + basicAuth utils.BasicAuth + serverChannels []*utils.ServerChannel + userConns utils.ConcurrentMap + log *logger.Logger + udpRelatedPacketConns utils.ConcurrentMap + udpLocalKey []byte + udpParentKey []byte } func NewSPS() services.Service { return &SPS{ - outPool: utils.OutConn{}, - cfg: SPSArgs{}, - basicAuth: utils.BasicAuth{}, - serverChannels: []*utils.ServerChannel{}, - userConns: utils.NewConcurrentMap(), + outPool: utils.OutConn{}, + cfg: SPSArgs{}, + basicAuth: utils.BasicAuth{}, + serverChannels: []*utils.ServerChannel{}, + userConns: utils.NewConcurrentMap(), + udpRelatedPacketConns: utils.NewConcurrentMap(), } } func (s *SPS) CheckArgs() (err error) { @@ -93,6 +97,8 @@ func (s *SPS) CheckArgs() (err error) { } } } + s.udpLocalKey = s.LocalUDPKey() + s.udpParentKey = s.ParentUDPKey() return } func (s *SPS) InitService() (err error) { @@ -210,6 +216,11 @@ func (s *SPS) callback(inConn net.Conn) { } } func (s *SPS) OutToTCP(inConn *net.Conn) (err error) { + enableUDP := *s.cfg.ParentServiceType == "socks" + udpIP, _, _ := net.SplitHostPort((*inConn).LocalAddr().String()) + if len(*s.cfg.LocalIPS) > 0 { + udpIP = (*s.cfg.LocalIPS)[0] + } bInConn := utils.NewBufferedConn(*inConn) //important //action read will regist read event to system, @@ -243,15 +254,19 @@ func (s *SPS) OutToTCP(inConn *net.Conn) (err error) { //socks5 server var serverConn *socks.ServerConn if s.IsBasicAuth() { - serverConn = socks.NewServerConn(inConn, time.Millisecond*time.Duration(*s.cfg.Timeout), &s.basicAuth, "", nil) + serverConn = socks.NewServerConn(inConn, time.Millisecond*time.Duration(*s.cfg.Timeout), &s.basicAuth, enableUDP, udpIP, nil) } else { - serverConn = socks.NewServerConn(inConn, time.Millisecond*time.Duration(*s.cfg.Timeout), nil, "", nil) + serverConn = socks.NewServerConn(inConn, time.Millisecond*time.Duration(*s.cfg.Timeout), nil, enableUDP, udpIP, nil) } if err = serverConn.Handshake(); err != nil { return } address = serverConn.Target() auth = serverConn.AuthData() + if serverConn.IsUDP() { + s.proxyUDP(inConn, serverConn) + return + } } else if utils.IsHTTP(h) || isSNI != "" { if *s.cfg.DisableHTTP { (*inConn).Close() diff --git a/utils/socks/server.go b/utils/socks/server.go index 67f26bf..8808562 100644 --- a/utils/socks/server.go +++ b/utils/socks/server.go @@ -2,10 +2,11 @@ package socks import ( "fmt" - "github.com/snail007/goproxy/utils" "net" "strings" "time" + + "github.com/snail007/goproxy/utils" ) const ( @@ -54,26 +55,27 @@ type ServerConn struct { methods []uint8 method uint8 //request - cmd uint8 - reserve uint8 - addressType uint8 - dstAddr string - dstPort string - dstHost string - udpAddress string + cmd uint8 + reserve uint8 + addressType uint8 + dstAddr string + dstPort string + dstHost string + UDPConnListener *net.UDPConn + enableUDP bool + udpIP string } -func NewServerConn(conn *net.Conn, timeout time.Duration, auth *utils.BasicAuth, udpAddress string, header []byte) *ServerConn { - if udpAddress == "" { - udpAddress = "0.0.0.0:16666" - } +func NewServerConn(conn *net.Conn, timeout time.Duration, auth *utils.BasicAuth, enableUDP bool, udpHost string, header []byte) *ServerConn { + s := &ServerConn{ - conn: conn, - timeout: timeout, - auth: auth, - header: header, - ver: VERSION_V5, - udpAddress: udpAddress, + conn: conn, + timeout: timeout, + auth: auth, + header: header, + ver: VERSION_V5, + enableUDP: enableUDP, + udpIP: udpHost, } return s @@ -84,6 +86,12 @@ func (s *ServerConn) Close() { func (s *ServerConn) AuthData() Auth { return Auth{s.user, s.password} } +func (s *ServerConn) IsUDP() bool { + return s.cmd == CMD_ASSOCIATE +} +func (s *ServerConn) IsTCP() bool { + return s.cmd == CMD_CONNECT +} func (s *ServerConn) Method() uint8 { return s.method } @@ -205,11 +213,29 @@ func (s *ServerConn) Handshake() (err error) { return } case CMD_ASSOCIATE: - err = request.UDPReply(REP_SUCCESS, s.udpAddress) + if !s.enableUDP { + request.UDPReply(REP_UNKNOWN, "0.0.0.0:0") + if err != nil { + err = fmt.Errorf("UDPReply REP_UNKNOWN to %s fail,ERR: %s", remoteAddr, err) + return + } + err = fmt.Errorf("cmd associate not supported, form: %s", remoteAddr) + return + } + a, _ := net.ResolveUDPAddr("udp", ":0") + s.UDPConnListener, err = net.ListenUDP("udp", a) + if err != nil { + request.UDPReply(REP_UNKNOWN, "0.0.0.0:0") + err = fmt.Errorf("udp bind fail,ERR: %s , for %s", err, remoteAddr) + return + } + _, port, _ := net.SplitHostPort(s.UDPConnListener.LocalAddr().String()) + err = request.UDPReply(REP_SUCCESS, net.JoinHostPort(s.udpIP, port)) if err != nil { err = fmt.Errorf("UDPReply REP_SUCCESS to %s fail,ERR: %s", remoteAddr, err) return } + } //fill socks info From 1f655808c6b6ab72f1bb4a32a9b8a740acf11306 Mon Sep 17 00:00:00 2001 From: Wenhui Shen Date: Sun, 8 Jul 2018 19:52:46 +0800 Subject: [PATCH 21/44] bugfixed --- services/mux/mux_bridge.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/mux/mux_bridge.go b/services/mux/mux_bridge.go index e80b7c5..73ed365 100644 --- a/services/mux/mux_bridge.go +++ b/services/mux/mux_bridge.go @@ -88,7 +88,7 @@ func (s *MuxBridge) StopService() { (*(*s.sc).Listener).Close() } for _, g := range s.clientControlConns.Items() { - for _, session := range g.(utils.ConcurrentMap).Items() { + for _, session := range g.(*utils.ConcurrentMap).Items() { (session.(*smux.Session)).Close() } } From 04ef33880754cb8fa338df65fc7ad7bc1650b970 Mon Sep 17 00:00:00 2001 From: "arraykeys@gmail.com" Date: Mon, 9 Jul 2018 16:32:04 +0800 Subject: [PATCH 22/44] add secure IP check for socks udp --- services/sps/socksudp.go | 16 ++++++++++------ utils/cert/cert.go | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/services/sps/socksudp.go b/services/sps/socksudp.go index 6ab08f8..e59c7d9 100644 --- a/services/sps/socksudp.go +++ b/services/sps/socksudp.go @@ -55,6 +55,7 @@ func (s *SPS) proxyUDP(inConn *net.Conn, serverConn *socks.ServerConn) { utils.CloseConn(inConn) return } + srcIP, _, _ := net.SplitHostPort((*inConn).RemoteAddr().String()) inconnRemoteAddr := (*inConn).RemoteAddr().String() localAddr := &net.UDPAddr{IP: net.IPv4zero, Port: 0} udpListener := serverConn.UDPConnListener @@ -137,8 +138,6 @@ func (s *SPS) proxyUDP(inConn *net.Conn, serverConn *socks.ServerConn) { }) } - //client := socks.NewClientConn(&outconn, "udp", serverConn.Target(), time.Millisecond*time.Duration(*s.cfg.Timeout), nil, nil) - s.log.Printf("connect %s for udp", serverConn.Target()) //socks client var client *socks.ClientConn @@ -182,9 +181,9 @@ func (s *SPS) proxyUDP(inConn *net.Conn, serverConn *socks.ServerConn) { //s.log.Printf("parent udp address %s", client.UDPAddr) destAddr, _ = net.ResolveUDPAddr("udp", client.UDPAddr) //relay + buf := utils.LeakyBuffer.Get() + defer utils.LeakyBuffer.Put(buf) for { - buf := utils.LeakyBuffer.Get() - defer utils.LeakyBuffer.Put(buf) n, srcAddr, err := udpListener.ReadFromUDP(buf) if err != nil { s.log.Printf("udp listener read fail, %s", err.Error()) @@ -193,6 +192,11 @@ func (s *SPS) proxyUDP(inConn *net.Conn, serverConn *socks.ServerConn) { } continue } + srcIP0, _, _ := net.SplitHostPort(srcAddr.String()) + //IP not match drop it + if srcIP != srcIP0 { + continue + } p := socks.NewPacketUDP() //convert data to raw if len(s.udpLocalKey) > 0 { @@ -204,7 +208,6 @@ func (s *SPS) proxyUDP(inConn *net.Conn, serverConn *socks.ServerConn) { } else { err = p.Parse(buf[:n]) } - //err = p.Parse(buf[:n]) if err != nil { s.log.Printf("udp listener parse packet fail, %s", err.Error()) continue @@ -233,7 +236,9 @@ func (s *SPS) proxyUDP(inConn *net.Conn, serverConn *socks.ServerConn) { buf := utils.LeakyBuffer.Get() defer utils.LeakyBuffer.Put(buf) for { + outUDPConn.SetReadDeadline(time.Now().Add(time.Second * 5)) n, err := outUDPConn.Read(buf) + outUDPConn.SetReadDeadline(time.Time{}) if err != nil { s.log.Printf("read out udp data fail , %s , from : %s", err, srcAddr) if isClosedErr(err) { @@ -241,7 +246,6 @@ func (s *SPS) proxyUDP(inConn *net.Conn, serverConn *socks.ServerConn) { } continue } - //var dlen = n //forward to local var v []byte diff --git a/utils/cert/cert.go b/utils/cert/cert.go index 858f6e5..ac25ba5 100644 --- a/utils/cert/cert.go +++ b/utils/cert/cert.go @@ -73,7 +73,7 @@ func CreateSignCert(rootCa *x509.Certificate, rootKey *rsa.PrivateKey, domainOrI buf := x509.MarshalPKCS1PrivateKey(priKey) keyPem := &pem.Block{ - Type: "PRIVATE KEY", + Type: "RSA PRIVATE KEY", Bytes: buf, } keyBytes = pem.EncodeToMemory(keyPem) From 3a4a9a3a27047e7cbd3ee96d9571ca6eac8ee9ec Mon Sep 17 00:00:00 2001 From: "arraykeys@gmail.com" Date: Mon, 9 Jul 2018 16:41:48 +0800 Subject: [PATCH 23/44] a --- services/socks/udp.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/services/socks/udp.go b/services/socks/udp.go index ad66a55..ad71a01 100644 --- a/services/socks/udp.go +++ b/services/socks/udp.go @@ -54,6 +54,7 @@ func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, reque utils.CloseConn(inConn) return } + srcIP, _, _ := net.SplitHostPort((*inConn).RemoteAddr().String()) inconnRemoteAddr := (*inConn).RemoteAddr().String() localAddr := &net.UDPAddr{IP: net.IPv4zero, Port: 0} udpListener, err := net.ListenUDP("udp", localAddr) @@ -191,6 +192,11 @@ func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, reque } continue } + srcIP0, _, _ := net.SplitHostPort(srcAddr.String()) + //IP not match drop it + if srcIP != srcIP0 { + continue + } p := socks.NewPacketUDP() //convert data to raw if len(s.udpLocalKey) > 0 { From 29e4cdf4e28f3af2bed91a00efc0db3cb51106b7 Mon Sep 17 00:00:00 2001 From: "arraykeys@gmail.com" Date: Mon, 9 Jul 2018 17:22:10 +0800 Subject: [PATCH 24/44] v5.2 --- CHANGELOG | 1 + README.md | 50 ++++++++++++++++++------------------------------ README_ZH.md | 19 ++++++++++-------- utils/structs.go | 2 +- 4 files changed, 32 insertions(+), 40 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index a87ca95..53d67bd 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,7 @@ proxy更新日志 v5.2 1.修复了HTTP(S)\SPS反向代理无法正常工作的问题. 2.优化了智能判断,减少不必要的DNS解析. +3.重构了SOCKS和SPS的UDP功能,基于UDP的游戏加速嗖嗖的. v5.1 1.优化了kcp默认mtu配置,调整为450. diff --git a/README.md b/README.md index 595f9bd..33648c0 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,24 @@ Proxy is a high performance HTTP, HTTPS, HTTPS, websocket, TCP, UDP, Socks5 prox [![stable](https://img.shields.io/badge/stable-stable-green.svg)](https://github.com/snail007/goproxy/) [![license](https://img.shields.io/github/license/snail007/goproxy.svg?style=plastic)]() [![download_count](https://img.shields.io/github/downloads/snail007/goproxy/total.svg?style=plastic)](https://github.com/snail007/goproxy/releases) [![download](https://img.shields.io/github/release/snail007/goproxy.svg?style=plastic)](https://github.com/snail007/goproxy/releases) -[中文手册](/README_ZH.md) **[全平台GUI版本](/gui/README.md)** **[全平台SDK](/sdk/README.md)** +**[中文手册](/README_ZH.md)** + +**[全平台图形界面版本](/gui/README.md)** + +**[全平台SDK](/sdk/README.md)** + + +### How to use the source code? + +Pull Request is welcomed. +Recommend go1.10.1. +`go get github.com/snail007/goproxy` +use command cd to enter your go SRC directory +then cd to enter `github.com/snail007/goproxy`. +Direct compilation:`go build -o proxy` +execution: `go run *.go` +`utils` is a toolkit, and `service` is a specific service class. + ### Features - chain-style proxy: the program itself can be a primary proxy, and if a parent proxy is set, it can be used as a second level proxy or even a N level proxy. @@ -37,27 +54,7 @@ Proxy is a high performance HTTP, HTTPS, HTTPS, websocket, TCP, UDP, Socks5 prox - ...   -This page is the v5.1 manual, and the other version of the manual can be checked by the following link. -- [v5.1 manual](https://github.com/snail007/goproxy/tree/v5.1) -- [v4.9 manual](https://github.com/snail007/goproxy/tree/v4.9) -- [v4.8 manual](https://github.com/snail007/goproxy/tree/v4.8) -- [v4.7 manual](https://github.com/snail007/goproxy/tree/v4.7) -- [v4.6 manual](https://github.com/snail007/goproxy/tree/v4.6) -- [v4.5 manual](https://github.com/snail007/goproxy/tree/v4.5) -- [v4.4 manual](https://github.com/snail007/goproxy/tree/v4.4) -- [v4.3 manual](https://github.com/snail007/goproxy/tree/v4.3) -- [v4.2 manual](https://github.com/snail007/goproxy/tree/v4.2) -- [v4.0-4.1 manual](https://github.com/snail007/goproxy/tree/v4.1) -- [v3.9 manual](https://github.com/snail007/goproxy/tree/v3.9) -- [v3.8 manual](https://github.com/snail007/goproxy/tree/v3.8) -- [v3.6-v3.7 manual](https://github.com/snail007/goproxy/tree/v3.6) -- [v3.5 manual](https://github.com/snail007/goproxy/tree/v3.5) -- [v3.4 manual](https://github.com/snail007/goproxy/tree/v3.4) -- [v3.3 manual](https://github.com/snail007/goproxy/tree/v3.3) -- [v3.2 manual](https://github.com/snail007/goproxy/tree/v3.2) -- [v3.1 manual](https://github.com/snail007/goproxy/tree/v3.1) -- [v3.0 manual](https://github.com/snail007/goproxy/tree/v3.0) -- [v2.x manual](https://github.com/snail007/goproxy/tree/v2.2) +This page is the v5.2 manual, and the other version of the manual can be checked by the following [link](docs/old-release.md). ### How to find the organization? [Click to join the proxy group of gitter](https://gitter.im/go-proxy/Lobby?utm_source=share-link&utm_medium=link&utm_campaign=share-link)   @@ -1088,15 +1085,6 @@ First, you need to clone the project to your account, and then modify the code o Finally, Pull Request to dev branch of goproxy project, and contribute code for efficiency. PR needs to explain what changes have been made and why you change them. -### How to use the source code? -Recommend go1.10.1. -`go get github.com/snail007/goproxy` -use command cd to enter your go SRC directory -then cd to enter `github.com/snail007/goproxy`. -Direct compilation:`go build -o proxy` -execution: `go run *.go` -`utils` is a toolkit, and `service` is a specific service class. - ### License Proxy is licensed under GPLv3 license. ### Contact diff --git a/README_ZH.md b/README_ZH.md index d325b61..6860b20 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -7,7 +7,17 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5代理服务 [![stable](https://img.shields.io/badge/stable-stable-green.svg)](https://github.com/snail007/goproxy/) [![license](https://img.shields.io/github/license/snail007/goproxy.svg?style=plastic)]() [![download_count](https://img.shields.io/github/downloads/snail007/goproxy/total.svg?style=plastic)](https://github.com/snail007/goproxy/releases) [![download](https://img.shields.io/github/release/snail007/goproxy.svg?style=plastic)](https://github.com/snail007/goproxy/releases) -**[English Manual](/README.md)** **[全平台GUI版本](/gui/README.md)** **[全平台SDK](/sdk/README.md)** +**[English Manual](/README.md)** + +**[全平台图形界面版本](/gui/README.md)** + +**[全平台SDK](/sdk/README.md)** + +### 如何贡献代码(Pull Request)? + +欢迎加入一起发展壮大proxy.首先需要clone本项目到自己的帐号下面, +然后在dev分支上面修改代码,最后发Pull Request到goproxy项目的dev分支即可, +为了高效贡献代码,pr的时候需要说明做了什么变更,原因是什么. ### Features - 链式代理,程序本身可以作为一级代理,如果设置了上级代理那么可以作为二级代理,乃至N级代理. @@ -1116,11 +1126,6 @@ fast3:`--nodelay=1 --interval=10 --resend=2 --nc=1` - http(s)代理增加pac支持? - 欢迎加群反馈... -### 如何贡献代码(Pull Request)? -首先需要clone本项目到自己的帐号下面,然后在dev分支上面修改代码, -最后发Pull Request到goproxy项目的dev分支即可,为了高效贡献代码, -pr的时候需要说明做了什么变更,原因是什么. - ### 如何使用源码? 建议go1.10.1. `go get github.com/snail007/goproxy` @@ -1140,5 +1145,3 @@ QQ交流群:189618940 如果proxy帮助你解决了很多问题,你可以通过下面的捐赠更好的支持proxy. - - diff --git a/utils/structs.go b/utils/structs.go index 079c6d5..06a1ead 100644 --- a/utils/structs.go +++ b/utils/structs.go @@ -156,7 +156,7 @@ func (c *Checker) IsBlocked(domain string) (blocked, isInMap bool, failN, succes } item := _item.(CheckerItem) - return item.FailCount >= item.SuccessCount, true, item.FailCount, item.SuccessCount + return (item.FailCount >= item.SuccessCount) && (time.Now().Unix()-item.Lasttime < 1800), true, item.FailCount, item.SuccessCount } func (c *Checker) domainIsInMap(address string, blockedMap bool) bool { u, err := url.Parse("http://" + address) From af19e5d25be4c50125c866047cd018094791dded Mon Sep 17 00:00:00 2001 From: "arraykeys@gmail.com" Date: Mon, 9 Jul 2018 17:25:58 +0800 Subject: [PATCH 25/44] docs --- README.md | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 33648c0..a9de0af 100644 --- a/README.md +++ b/README.md @@ -12,18 +12,12 @@ Proxy is a high performance HTTP, HTTPS, HTTPS, websocket, TCP, UDP, Socks5 prox **[全平台SDK](/sdk/README.md)** +### How to contribute to the code (Pull Request)? -### How to use the source code? - -Pull Request is welcomed. -Recommend go1.10.1. -`go get github.com/snail007/goproxy` -use command cd to enter your go SRC directory -then cd to enter `github.com/snail007/goproxy`. -Direct compilation:`go build -o proxy` -execution: `go run *.go` -`utils` is a toolkit, and `service` is a specific service class. - +Pull Request is welcomed. +First, you need to clone the project to your account, and then modify the code on the dev branch. +Finally, Pull Request to dev branch of goproxy project, and contribute code for efficiency. +PR needs to explain what changes have been made and why you change them. ### Features - chain-style proxy: the program itself can be a primary proxy, and if a parent proxy is set, it can be used as a second level proxy or even a N level proxy. @@ -1080,10 +1074,15 @@ Then the local UDP port 53 provides a security and anti pollution DNS analysis. - HTTP (s) proxy support PAC? - Welcome joining group feedback... -### How to contribute to the code (Pull Request)? -First, you need to clone the project to your account, and then modify the code on the dev branch. -Finally, Pull Request to dev branch of goproxy project, and contribute code for efficiency. -PR needs to explain what changes have been made and why you change them. +### How to use the source code? + +Recommend go1.10.1. +`go get github.com/snail007/goproxy` +use command cd to enter your go SRC directory +then cd to enter `github.com/snail007/goproxy`. +Direct compilation:`go build -o proxy` +execution: `go run *.go` +`utils` is a toolkit, and `service` is a specific service class. ### License Proxy is licensed under GPLv3 license. From 2603802dd9d0c9c593f85ca7f10fee90133134ab Mon Sep 17 00:00:00 2001 From: arraykeys Date: Mon, 9 Jul 2018 20:18:30 +0800 Subject: [PATCH 26/44] no message --- README.md | 2 +- README_ZH.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a9de0af..7d5771d 100644 --- a/README.md +++ b/README.md @@ -832,7 +832,7 @@ through this way, When you visits the website by local proxy 8080, it visits the ### **6.Proxy protocol conversion** #### **6.1.Functional introduction** -The proxy protocol conversion use the SPS subcommand (abbreviation of socks+https), SPS itself does not provide the proxy function, just accept the proxy request and then converse protocol and forwarded to the existing HTTP (s) or Socks5 proxy. SPS can use existing HTTP (s) or Socks5 proxy converse to support HTTP (s) and Socks5 HTTP (s) proxy at the same time by one port, and proxy supports forward and reverse proxy (SNI), SOCKS5 proxy which is conversed does not support UDP. in addition to the existing HTTP or Socks5 proxy, which supports TLS, TCP, KCP three modes and chain-style connection. That is more than one SPS node connection can build encryption channel. +The proxy protocol conversion use the SPS subcommand (abbreviation of socks+https), SPS itself does not provide the proxy function, just accept the proxy request and then converse protocol and forwarded to the existing HTTP (s) or Socks5 proxy. SPS can use existing HTTP (s) or Socks5 proxy converse to support HTTP (s) and Socks5 HTTP (s) proxy at the same time by one port, and proxy supports forward and reverse proxy (SNI), SOCKS5 proxy which is also does support UDP when parent is Socks5. in addition to the existing HTTP or Socks5 proxy, which supports TLS, TCP, KCP three modes and chain-style connection. That is more than one SPS node connection can build encryption channel. #### **6.2.HTTP(S) to HTTP(S) + SOCKS5** Suppose there is a common HTTP (s) proxy: 127.0.0.1:8080. Now we turn it into a common proxy that supports HTTP (s) and Socks5 at the same time. The local port after transformation is 18080. diff --git a/README_ZH.md b/README_ZH.md index 6860b20..ab923b6 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -854,7 +854,7 @@ proxy的socks代理在tcp之上可以通过自定义加密和tls标准加密以 ### **6.代理协议转换** #### **6.1 功能介绍** -代理协议转换使用的是sps子命令(socks+https的缩写),sps本身不提供代理功能,只是接受代理请求"转换并转发"给已经存在的http(s)代理或者socks5代理;sps可以把已经存在的http(s)代理或者socks5代理转换为一个端口同时支持http(s)和socks5代理,而且http(s)代理支持正向代理和反向代理(SNI),转换后的SOCKS5代理不支持UDP功能;另外对于已经存在的http(s)代理或者socks5代理,支持tls、tcp、kcp三种模式,支持链式连接,也就是可以多个sps结点层级连接构建加密通道。 +代理协议转换使用的是sps子命令(socks+https的缩写),sps本身不提供代理功能,只是接受代理请求"转换并转发"给已经存在的http(s)代理或者socks5代理;sps可以把已经存在的http(s)代理或者socks5代理转换为一个端口同时支持http(s)和socks5代理,而且http(s)代理支持正向代理和反向代理(SNI),转换后的SOCKS5代理,当上级是SOCKS5时仍然支持UDP功能;另外对于已经存在的http(s)代理或者socks5代理,支持tls、tcp、kcp三种模式,支持链式连接,也就是可以多个sps结点层级连接构建加密通道。 #### **6.2 HTTP(S)转HTTP(S)+SOCKS5** 假设已经存在一个普通的http(s)代理:127.0.0.1:8080,现在我们把它转为同时支持http(s)和socks5的普通代理,转换后的本地端口为18080。 From 1e1999dedeeda97a183daea0f0c200ddef3e253a Mon Sep 17 00:00:00 2001 From: "arraykeys@gmail.com" Date: Tue, 10 Jul 2018 13:37:00 +0800 Subject: [PATCH 27/44] a --- config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.go b/config.go index 547f26f..4aeeb9a 100755 --- a/config.go +++ b/config.go @@ -386,6 +386,7 @@ func initConfig() (err error) { for { if cmd != nil { cmd.Process.Kill() + time.Sleep(time.Second * 5) } cmd = exec.Command(os.Args[0], args...) cmdReaderStderr, err := cmd.StderrPipe() @@ -421,7 +422,6 @@ func initConfig() (err error) { continue } log.Printf("worker %s [PID] %d unexpected exited, restarting...\n", os.Args[0], pid) - time.Sleep(time.Second * 5) } }() return From dd355b5d98395c92b56e98e9f88a949c969cbe3e Mon Sep 17 00:00:00 2001 From: "arraykeys@gmail.com" Date: Tue, 10 Jul 2018 16:26:26 +0800 Subject: [PATCH 28/44] fix socks client check port range --- CHANGELOG | 3 +++ README_ZH.md | 2 +- docs/old-release.md | 1 + install_auto.sh | 2 +- main.go | 2 +- release.sh | 2 +- utils/socks/client.go | 2 +- 7 files changed, 9 insertions(+), 5 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 53d67bd..2c5d6d9 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,7 @@ proxy更新日志 +v5.3 +1.优化了socks_client握手端口判断,避免了sstap测试UDP失败的问题.. + v5.2 1.修复了HTTP(S)\SPS反向代理无法正常工作的问题. 2.优化了智能判断,减少不必要的DNS解析. diff --git a/README_ZH.md b/README_ZH.md index ab923b6..fd5a770 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -48,7 +48,7 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5代理服务 - ... -本页是v5.2手册,其他版本手册请点击[这里](docs/old-release.md)查看. +本页是v5.3手册,其他版本手册请点击[这里](docs/old-release.md)查看. ### 怎么找到组织? diff --git a/docs/old-release.md b/docs/old-release.md index 7204b03..d7c3c40 100644 --- a/docs/old-release.md +++ b/docs/old-release.md @@ -1,5 +1,6 @@ # Old Versions of Proxy +- [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) - [v4.9手册](https://github.com/snail007/goproxy/tree/v4.9) diff --git a/install_auto.sh b/install_auto.sh index 63b7672..515a2a7 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.2/proxy-linux-amd64.tar.gz +wget https://github.com/snail007/goproxy/releases/download/v5.3/proxy-linux-amd64.tar.gz # #install proxy tar zxvf proxy-linux-amd64.tar.gz diff --git a/main.go b/main.go index 9d56bb9..900bab4 100644 --- a/main.go +++ b/main.go @@ -9,7 +9,7 @@ import ( "github.com/snail007/goproxy/services" ) -const APP_VERSION = "5.2" +const APP_VERSION = "5.3" func main() { err := initConfig() diff --git a/release.sh b/release.sh index 19c7481..98508d6 100755 --- a/release.sh +++ b/release.sh @@ -1,5 +1,5 @@ #!/bin/bash -VER="5.2" +VER="5.3" RELEASE="release-${VER}" rm -rf .cert mkdir .cert diff --git a/utils/socks/client.go b/utils/socks/client.go index 7b06c1d..2460b3b 100644 --- a/utils/socks/client.go +++ b/utils/socks/client.go @@ -72,7 +72,7 @@ func (s *ClientConn) Handshake() error { if err != nil { return errors.New("proxy: failed to parse port number: " + portStr) } - if port < 1 || port > 0xffff { + if s.network == "tcp" && (port < 1 || port > 0xffff) { return errors.New("proxy: port number out of range: " + portStr) } From dd8d7dd0d4b61fa9361d05c2b282327b24ff8b60 Mon Sep 17 00:00:00 2001 From: boboan Date: Wed, 11 Jul 2018 17:45:35 +0800 Subject: [PATCH 29/44] net.LookupIP may cause deadlock in windows https://github.com/golang/go/issues/24178 --- services/http/http.go | 2 +- services/socks/socks.go | 2 +- utils/functions.go | 29 ++++++++++++++++++++++++++++- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/services/http/http.go b/services/http/http.go index a1a14aa..73dd4b5 100644 --- a/services/http/http.go +++ b/services/http/http.go @@ -492,7 +492,7 @@ func (s *HTTP) IsDeadLoop(inLocalAddr string, host string) bool { if *s.cfg.DNSAddress != "" { outIPs = []net.IP{net.ParseIP(s.Resolve(outDomain))} } else { - outIPs, err = net.LookupIP(outDomain) + outIPs, err = utils.MyLookupIP(outDomain) } if err == nil { for _, ip := range outIPs { diff --git a/services/socks/socks.go b/services/socks/socks.go index 5020c50..901e001 100644 --- a/services/socks/socks.go +++ b/services/socks/socks.go @@ -598,7 +598,7 @@ func (s *Socks) IsDeadLoop(inLocalAddr string, host string) bool { if *s.cfg.DNSAddress != "" { outIPs = []net.IP{net.ParseIP(s.Resolve(outDomain))} } else { - outIPs, err = net.LookupIP(outDomain) + outIPs, err = utils.MyLookupIP(outDomain) } if err == nil { for _, ip := range outIPs { diff --git a/utils/functions.go b/utils/functions.go index 4d20b7c..ecb8afe 100755 --- a/utils/functions.go +++ b/utils/functions.go @@ -29,6 +29,8 @@ import ( "github.com/snail007/goproxy/utils/id" kcp "github.com/xtaci/kcp-go" + + "context" ) func IoBind(dst io.ReadWriteCloser, src io.ReadWriteCloser, fn func(err interface{}), log *logger.Logger) { @@ -497,7 +499,7 @@ func IsIternalIP(domainOrIP string, always bool) bool { } if isDomain { - outIPs, err = net.LookupIP(domainOrIP) + outIPs, err = MyLookupIP(domainOrIP) } else { outIPs = []net.IP{net.ParseIP(domainOrIP)} } @@ -632,3 +634,28 @@ 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)) + defer func() { + cancel() + //ctx.Done() + }() + addrs, err := net.DefaultResolver.LookupIPAddr(ctx, host) + if err != nil { + return nil, err + } + ips := make([]net.IP, len(addrs)) + for i, ia := range addrs { + ips[i] = ia.IP + } + return ips, nil +} From 8dce99fec6a7de14c681bb43cecc9be058e30977 Mon Sep 17 00:00:00 2001 From: arraykeys Date: Wed, 11 Jul 2018 21:35:02 +0800 Subject: [PATCH 30/44] a --- sdk/android-ios/release_android.sh | 2 +- sdk/android-ios/release_ios.sh | 2 +- sdk/android-ios/sdk.go | 2 +- sdk/windows-linux/release_linux.sh | 2 +- sdk/windows-linux/release_mac.sh | 2 +- sdk/windows-linux/release_windows.sh | 10 +++++----- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/sdk/android-ios/release_android.sh b/sdk/android-ios/release_android.sh index d591df8..7d12525 100755 --- a/sdk/android-ios/release_android.sh +++ b/sdk/android-ios/release_android.sh @@ -1,5 +1,5 @@ #/bin/bash -VER="v5.0" +VER="v5.2" rm -rf sdk-android-*.tar.gz rm -rf android mkdir android diff --git a/sdk/android-ios/release_ios.sh b/sdk/android-ios/release_ios.sh index d7b6e00..96a50af 100755 --- a/sdk/android-ios/release_ios.sh +++ b/sdk/android-ios/release_ios.sh @@ -1,5 +1,5 @@ #/bin/bash -VER="v5.0" +VER="v5.2" rm -rf sdk-ios-*.tar.gz rm -rf ios mkdir ios diff --git a/sdk/android-ios/sdk.go b/sdk/android-ios/sdk.go index db1882a..fd5c898 100644 --- a/sdk/android-ios/sdk.go +++ b/sdk/android-ios/sdk.go @@ -23,7 +23,7 @@ import ( kingpin "gopkg.in/alecthomas/kingpin.v2" ) -const SDK_VERSION = "5.0" +const SDK_VERSION = "5.2" var ( app *kingpin.Application diff --git a/sdk/windows-linux/release_linux.sh b/sdk/windows-linux/release_linux.sh index de15e3d..a6653d8 100755 --- a/sdk/windows-linux/release_linux.sh +++ b/sdk/windows-linux/release_linux.sh @@ -1,5 +1,5 @@ #/bin/bash -VER="v5.0" +VER="v5.2" rm -rf sdk-linux-*.tar.gz rm -rf README.md libproxy-sdk.so libproxy-sdk.h libproxy-sdk.a diff --git a/sdk/windows-linux/release_mac.sh b/sdk/windows-linux/release_mac.sh index afa9a02..a872e3c 100755 --- a/sdk/windows-linux/release_mac.sh +++ b/sdk/windows-linux/release_mac.sh @@ -1,5 +1,5 @@ #/bin/bash -VER="v5.0" +VER="v5.2" rm -rf *.tar.gz rm -rf README.md libproxy-sdk.dylib libproxy-sdk.h diff --git a/sdk/windows-linux/release_windows.sh b/sdk/windows-linux/release_windows.sh index 7a3b06d..176f832 100755 --- a/sdk/windows-linux/release_windows.sh +++ b/sdk/windows-linux/release_windows.sh @@ -1,8 +1,8 @@ #/bin/bash -VER="v5.0" +VER="v5.2" -sudo rm /usr/local/go -sudo ln -s /usr/local/go1.10.1 /usr/local/go +#sudo rm /usr/local/go +#sudo ln -s /usr/local/go1.10.1 /usr/local/go rm -rf sdk-windows-*.tar.gz rm -rf README.md proxy-sdk.h proxy-sdk.dll @@ -22,7 +22,7 @@ cp ../README.md . tar zcf sdk-windows-32bit-${VER}.tar.gz README.md proxy-sdk.dll proxy-sdk.h ieshims.dll rm -rf README.md proxy-sdk.h proxy-sdk.dll -sudo rm /usr/local/go -sudo ln -s /usr/local/go1.8.5 /usr/local/go +#sudo rm /usr/local/go +#sudo ln -s /usr/local/go1.8.5 /usr/local/go echo "done." From 907dec42e0bdae6bb44286328cdaa4f553bc0055 Mon Sep 17 00:00:00 2001 From: boboan Date: Thu, 12 Jul 2018 10:21:28 +0800 Subject: [PATCH 31/44] net.LookupIP may cause deadlock in windows https://github.com/golang/go/issues/24178 --- services/http/http.go | 2 +- services/socks/socks.go | 2 +- utils/functions.go | 27 ++++++++++++++++++++++++++- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/services/http/http.go b/services/http/http.go index a1a14aa..73dd4b5 100644 --- a/services/http/http.go +++ b/services/http/http.go @@ -492,7 +492,7 @@ func (s *HTTP) IsDeadLoop(inLocalAddr string, host string) bool { if *s.cfg.DNSAddress != "" { outIPs = []net.IP{net.ParseIP(s.Resolve(outDomain))} } else { - outIPs, err = net.LookupIP(outDomain) + outIPs, err = utils.MyLookupIP(outDomain) } if err == nil { for _, ip := range outIPs { diff --git a/services/socks/socks.go b/services/socks/socks.go index 5020c50..901e001 100644 --- a/services/socks/socks.go +++ b/services/socks/socks.go @@ -598,7 +598,7 @@ func (s *Socks) IsDeadLoop(inLocalAddr string, host string) bool { if *s.cfg.DNSAddress != "" { outIPs = []net.IP{net.ParseIP(s.Resolve(outDomain))} } else { - outIPs, err = net.LookupIP(outDomain) + outIPs, err = utils.MyLookupIP(outDomain) } if err == nil { for _, ip := range outIPs { diff --git a/utils/functions.go b/utils/functions.go index 4d20b7c..fe9d470 100755 --- a/utils/functions.go +++ b/utils/functions.go @@ -25,6 +25,7 @@ import ( "strconv" "strings" "time" + "context" "github.com/snail007/goproxy/utils/id" @@ -497,7 +498,7 @@ func IsIternalIP(domainOrIP string, always bool) bool { } if isDomain { - outIPs, err = net.LookupIP(domainOrIP) + outIPs, err = MyLookupIP(domainOrIP) } else { outIPs = []net.IP{net.ParseIP(domainOrIP)} } @@ -632,3 +633,27 @@ 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)) + defer func() { + cancel() + //ctx.Done() + }() + addrs, err := net.DefaultResolver.LookupIPAddr(ctx, host) + if err != nil { + return nil, err + } + ips := make([]net.IP, len(addrs)) + for i, ia := range addrs { + ips[i] = ia.IP + } + return ips, nil +} \ No newline at end of file From 5980fee7887f0cca4d061762d5cc451df1dd754c Mon Sep 17 00:00:00 2001 From: boboan Date: Thu, 12 Jul 2018 10:31:54 +0800 Subject: [PATCH 32/44] net.LookupIP may cause deadlock in windows --- utils/functions.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/utils/functions.go b/utils/functions.go index 305ccc1..f25ee2a 100755 --- a/utils/functions.go +++ b/utils/functions.go @@ -30,8 +30,7 @@ import ( "github.com/snail007/goproxy/utils/id" kcp "github.com/xtaci/kcp-go" - - "context" + ) func IoBind(dst io.ReadWriteCloser, src io.ReadWriteCloser, fn func(err interface{}), log *logger.Logger) { From f65677385865813dac6440293fd551525b21cd26 Mon Sep 17 00:00:00 2001 From: "arraykeys@gmail.com" Date: Thu, 12 Jul 2018 13:32:46 +0800 Subject: [PATCH 33/44] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=99=BA=E8=83=BD?= =?UTF-8?q?=E6=A3=80=E6=9F=A5=E7=9A=84=E5=88=9D=E5=A7=8B=E5=8C=96=E6=97=B6?= =?UTF-8?q?=E6=9C=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- services/http/http.go | 4 +++- services/socks/socks.go | 8 ++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/services/http/http.go b/services/http/http.go index 73dd4b5..efdde0d 100644 --- a/services/http/http.go +++ b/services/http/http.go @@ -189,7 +189,9 @@ func (s *HTTP) StopService() { } }() s.isStop = true - s.checker.Stop() + if *s.cfg.Parent != "" { + s.checker.Stop() + } if s.sshClient != nil { s.sshClient.Close() } diff --git a/services/socks/socks.go b/services/socks/socks.go index 901e001..0eca018 100644 --- a/services/socks/socks.go +++ b/services/socks/socks.go @@ -146,7 +146,9 @@ func (s *Socks) InitService() (err error) { if *s.cfg.DNSAddress != "" { (*s).domainResolver = utils.NewDomainResolver(*s.cfg.DNSAddress, *s.cfg.DNSTTL, s.log) } - s.checker = utils.NewChecker(*s.cfg.Timeout, int64(*s.cfg.Interval), *s.cfg.Blocked, *s.cfg.Direct, s.log) + if *s.cfg.Parent != "" { + s.checker = utils.NewChecker(*s.cfg.Timeout, int64(*s.cfg.Interval), *s.cfg.Blocked, *s.cfg.Direct, s.log) + } if *s.cfg.ParentType == "ssh" { e := s.ConnectSSH() if e != nil { @@ -193,7 +195,9 @@ func (s *Socks) StopService() { } }() s.isStop = true - s.checker.Stop() + if *s.cfg.Parent != "" { + s.checker.Stop() + } if s.sshClient != nil { s.sshClient.Close() } From 7fc5c30f60f1143bd6e596217af5ad3b3c3ffb0b Mon Sep 17 00:00:00 2001 From: "arraykeys@gmail.com" Date: Mon, 16 Jul 2018 15:54:55 +0800 Subject: [PATCH 34/44] fix docker file --- Dockerfile | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 91863f3..786de97 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,13 @@ FROM golang:1.10.3-alpine as builder ARG GOPROXY_VERSION=master RUN apk update && apk upgrade && \ - apk add --no-cache git && cd /go/src/ && git clone https://github.com/snail007/goproxy && \ - cd goproxy && git checkout ${GOPROXY_VERSION} && \ - go get && CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o proxy + apk add --no-cache git && \ + cd /go/src/ && \ + mkdir snail007 && \ + cd snail007 && \ + git clone https://github.com/snail007/goproxy.git && \ + cd goproxy && \ + git checkout ${GOPROXY_VERSION} && \ + CGO_ENABLED=0 GOOS=linux go build -ldflags "-s -w" -o /proxy FROM alpine:3.7 -COPY --from=builder /go/src/goproxy/proxy / CMD /proxy ${OPTS} From af9192107059149aa5d55d4aea525160575f0496 Mon Sep 17 00:00:00 2001 From: "arraykeys@gmail.com" Date: Mon, 16 Jul 2018 16:18:34 +0800 Subject: [PATCH 35/44] a --- Dockerfile | 2 +- README.md | 10 +++++----- README_ZH.md | 14 +++++++------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Dockerfile b/Dockerfile index 786de97..1d4e07b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.10.3-alpine as builder +FROM golang:1.10.3-alpine ARG GOPROXY_VERSION=master RUN apk update && apk upgrade && \ apk add --no-cache git && \ diff --git a/README.md b/README.md index 7d5771d..285206d 100644 --- a/README.md +++ b/README.md @@ -173,12 +173,12 @@ chmod +x install.sh #### Docker installation -Dockerfile root of project uses multistage build and alpine project to comply with best practices. Uses golang 1.10.3 for building as noted in the project README.md and will be pretty small image. total extracted size will be 17.3MB for goproxy version 5.0. +Dockerfile root of project uses multistage build and alpine project to comply with best practices. Uses golang 1.10.3 for building as noted in the project README.md and will be pretty small image. total extracted size will be 17.3MB for goproxy latest version. -The default build process builds the master branch (latest commits/ cutting edge), and it can be configured to build specific version, just edit Dockerfile before build, following builds release version 4.7: +The default build process builds the master branch (latest commits/ cutting edge), and it can be configured to build specific version, just edit Dockerfile before build, following builds release version 5.2: ``` -ARG GOPROXY_VERSION=v5.0 +ARG GOPROXY_VERSION=v5.2 ``` To Run: @@ -188,12 +188,12 @@ sudo docker build . ``` 2. Tag the image: ``` -sudo docker tag goproxy/goproxy:latest +sudo docker tag snail007/goproxy:latest ``` 3. Run! Just put your arguments to proxy binary in the OPTS environmental variable (this is just a sample http proxy): ``` -sudo docker run -d --restart=always --name goproxy -e OPTS="http -p :33080" -p 33080:33080 goproxy/goproxy:latest +sudo docker run -d --restart=always --name goproxy -e OPTS="http -p :33080" -p 33080:33080 snail007/goproxy:latest ``` 4. View logs: ``` diff --git a/README_ZH.md b/README_ZH.md index fd5a770..c69bea5 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -170,12 +170,12 @@ chmod +x install.sh ``` #### Docker安装 -项目根目录的Dockerfile文件用来构建,使用golang 1.10.3,构建基于goproxy v5.1, -全部大小17.3MB,默认情况下使用master分支,不过可以通过修改配置文件Dockerfile -或者使用参数GOPROXY_VERSION指定构建的goproxy版本. +项目根目录的Dockerfile文件用来构建,使用golang 1.10.3,构建基于goproxy的master分支最新版本, +全部大小17.3MB,默认情况下使用master分支,不过可以通过修改配置文件Dockerfile +或者使用参数GOPROXY_VERSION指定构建的goproxy版本. ``` -ARG GOPROXY_VERSION=v5.1 +ARG GOPROXY_VERSION=v5.2 ``` 步骤: @@ -185,14 +185,14 @@ sudo docker build . ``` 2. 镜像打标签: ``` -sudo docker tag <上一步的结果ID> goproxy/goproxy:latest +sudo docker tag <上一步的结果ID> snail007/goproxy:latest ``` 3. 运行 参数OPTS的值就是传递给proxy的所有参数 -比如下面的例子启动了一个http服务: +比如下面的例子启动了一个http服务: ``` -sudo docker run -d --restart=always --name goproxy -e OPTS="http -p :33080" -p 33080:33080 goproxy/goproxy:latest +sudo docker run -d --restart=always --name goproxy -e OPTS="http -p :33080" -p 33080:33080 snail007/goproxy:latest ``` 4. 查看日志: ``` From 3cf7788f3411a48ad03c4321f21c0500e9a1160c Mon Sep 17 00:00:00 2001 From: "arraykeys@gmail.com" Date: Mon, 16 Jul 2018 18:10:21 +0800 Subject: [PATCH 36/44] a --- Dockerfile | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/Dockerfile b/Dockerfile index 1d4e07b..e693f38 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,13 +1,15 @@ FROM golang:1.10.3-alpine ARG GOPROXY_VERSION=master -RUN apk update && apk upgrade && \ - apk add --no-cache git && \ - cd /go/src/ && \ - mkdir snail007 && \ - cd snail007 && \ - git clone https://github.com/snail007/goproxy.git && \ - cd goproxy && \ - git checkout ${GOPROXY_VERSION} && \ - CGO_ENABLED=0 GOOS=linux go build -ldflags "-s -w" -o /proxy +RUN apk update; apk upgrade; \ + apk add --no-cache git; \ + cd /go/src/; \ + mkdir github.com; \ + mkdir github.com/snail007; \ + cd github.com/snail007; \ + git clone https://github.com/snail007/goproxy.git; \ + cd goproxy; \ + git checkout ${GOPROXY_VERSION}; \ + go build -ldflags "-s -w" -o proxy; \ + cp proxy /proxy FROM alpine:3.7 -CMD /proxy ${OPTS} +CMD /proxy ${OPTS} \ No newline at end of file From df94ca560113458ac2caab13bc310e1f1d0eb4c7 Mon Sep 17 00:00:00 2001 From: "arraykeys@gmail.com" Date: Mon, 16 Jul 2018 18:32:53 +0800 Subject: [PATCH 37/44] a --- Dockerfile | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index e693f38..e4555ba 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ FROM golang:1.10.3-alpine -ARG GOPROXY_VERSION=master +ARG GOPROXY_VERSION=v5.2 RUN apk update; apk upgrade; \ apk add --no-cache git; \ cd /go/src/; \ @@ -9,7 +9,6 @@ RUN apk update; apk upgrade; \ git clone https://github.com/snail007/goproxy.git; \ cd goproxy; \ git checkout ${GOPROXY_VERSION}; \ - go build -ldflags "-s -w" -o proxy; \ - cp proxy /proxy + go build -ldflags "-s -w" -o proxy; FROM alpine:3.7 -CMD /proxy ${OPTS} \ No newline at end of file +CMD cd /go/src/github.com/snail007/goproxy/ && ./proxy ${OPTS} \ No newline at end of file From 747a94a1c896f20c3b271be2a82119a76c4e1985 Mon Sep 17 00:00:00 2001 From: "arraykeys@gmail.com" Date: Tue, 17 Jul 2018 16:00:48 +0800 Subject: [PATCH 38/44] fix #113 --- Dockerfile | 78 +++++++++++++++++++++++++++++++++++++++++++++++---- sdk/README.md | 2 +- 2 files changed, 74 insertions(+), 6 deletions(-) diff --git a/Dockerfile b/Dockerfile index e4555ba..e2a5099 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,69 @@ -FROM golang:1.10.3-alpine -ARG GOPROXY_VERSION=v5.2 +FROM alpine:3.7 AS builder + +RUN apk add --no-cache \ + ca-certificates + +# set up nsswitch.conf for Go's "netgo" implementation +# - https://github.com/golang/go/blob/go1.9.1/src/net/conf.go#L194-L275 +# - docker run --rm debian:stretch grep '^hosts:' /etc/nsswitch.conf +RUN [ ! -e /etc/nsswitch.conf ] && echo 'hosts: files dns' > /etc/nsswitch.conf + +ENV GOLANG_VERSION 1.10.3 + +# make-sure-R0-is-zero-before-main-on-ppc64le.patch: https://github.com/golang/go/commit/9aea0e89b6df032c29d0add8d69ba2c95f1106d9 (Go 1.9) +#COPY *.patch /go-alpine-patches/ + +RUN set -eux; \ + apk add --no-cache --virtual .build-deps \ + bash \ + gcc \ + musl-dev \ + openssl \ + go \ + ; \ + export \ +# set GOROOT_BOOTSTRAP such that we can actually build Go + GOROOT_BOOTSTRAP="$(go env GOROOT)" \ +# ... and set "cross-building" related vars to the installed system's values so that we create a build targeting the proper arch +# (for example, if our build host is GOARCH=amd64, but our build env/image is GOARCH=386, our build needs GOARCH=386) + GOOS="$(go env GOOS)" \ + GOARCH="$(go env GOARCH)" \ + GOHOSTOS="$(go env GOHOSTOS)" \ + GOHOSTARCH="$(go env GOHOSTARCH)" \ + ; \ +# also explicitly set GO386 and GOARM if appropriate +# https://github.com/docker-library/golang/issues/184 + apkArch="$(apk --print-arch)"; \ + case "$apkArch" in \ + armhf) export GOARM='6' ;; \ + x86) export GO386='387' ;; \ + esac; \ + \ + wget -O go.tgz "https://golang.org/dl/go$GOLANG_VERSION.src.tar.gz"; \ + echo '567b1cc66c9704d1c019c50bef946272e911ec6baf244310f87f4e678be155f2 *go.tgz' | sha256sum -c -; \ + tar -C /usr/local -xzf go.tgz; \ + rm go.tgz; \ + \ + cd /usr/local/go/src; \ + for p in /go-alpine-patches/*.patch; do \ + [ -f "$p" ] || continue; \ + patch -p2 -i "$p"; \ + done; \ + ./make.bash; \ + \ + rm -rf /go-alpine-patches; \ + apk del .build-deps; \ + \ + export PATH="/usr/local/go/bin:$PATH"; \ + go version + +ENV GOPATH /go +ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH + +RUN mkdir -p "$GOPATH/src" "$GOPATH/bin" && chmod -R 777 "$GOPATH" +WORKDIR $GOPATH + +ARG GOPROXY_VERSION=master RUN apk update; apk upgrade; \ apk add --no-cache git; \ cd /go/src/; \ @@ -9,6 +73,10 @@ RUN apk update; apk upgrade; \ git clone https://github.com/snail007/goproxy.git; \ cd goproxy; \ git checkout ${GOPROXY_VERSION}; \ - go build -ldflags "-s -w" -o proxy; -FROM alpine:3.7 -CMD cd /go/src/github.com/snail007/goproxy/ && ./proxy ${OPTS} \ No newline at end of file + CGO_ENABLED=0 GOOS=linux go build -ldflags "-s -w" -a -installsuffix cgo -o proxy; \ + chmod 0777 proxy + +FROM 1.10.3-stretch +RUN mkdir /proxy && chmod 0777 /proxy +COPY --from=builder builder /go/src/github.com/snail007/goproxy/proxy /proxy/ +CMD cd /proxy && /proxy ${OPTS} \ No newline at end of file diff --git a/sdk/README.md b/sdk/README.md index d65c405..f21503e 100644 --- a/sdk/README.md +++ b/sdk/README.md @@ -25,7 +25,7 @@ proxy使用gombile实现了一份go代码编译为android和ios平台下面可 #### 1.导入包 ```java -import snail007.proxy.Porxy +import snail007.proxy.Proxy ``` #### 2.启动一个服务 From 53153da2e66524458331cd2133f9e81a54ca0e20 Mon Sep 17 00:00:00 2001 From: "arraykeys@gmail.com" Date: Tue, 17 Jul 2018 17:55:54 +0800 Subject: [PATCH 39/44] a --- keygen.sh | 3 --- 1 file changed, 3 deletions(-) delete mode 100755 keygen.sh diff --git a/keygen.sh b/keygen.sh deleted file mode 100755 index 69a4f80..0000000 --- a/keygen.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -openssl genrsa -out proxy.key 2048 -openssl req -new -key proxy.key -x509 -days 3650 -out proxy.crt -subj /C=CN/ST=BJ/O="Localhost Ltd"/CN=proxy \ No newline at end of file From 317d0113fb7ee369af24225003db4495c31ecf04 Mon Sep 17 00:00:00 2001 From: Chris Schmich Date: Tue, 17 Jul 2018 14:02:38 -0700 Subject: [PATCH 40/44] Fix typo: 'stoped' -> 'stopped'. --- sdk/android-ios/dns.go | 2 +- services/http/http.go | 2 +- services/mux/mux_bridge.go | 2 +- services/mux/mux_client.go | 2 +- services/mux/mux_server.go | 2 +- services/socks/socks.go | 2 +- services/sps/sps.go | 2 +- services/tcp/tcp.go | 2 +- services/tunnel/tunnel_bridge.go | 2 +- services/tunnel/tunnel_client.go | 2 +- services/tunnel/tunnel_server.go | 2 +- services/udp/udp.go | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/sdk/android-ios/dns.go b/sdk/android-ios/dns.go index b08290d..375016d 100644 --- a/sdk/android-ios/dns.go +++ b/sdk/android-ios/dns.go @@ -117,7 +117,7 @@ func (s *DNS) StopService() { if e != nil { s.log.Printf("stop dns service crashed,%s", e) } else { - s.log.Printf("service dns stoped") + s.log.Printf("service dns stopped") } }() Stop(s.serviceKey) diff --git a/services/http/http.go b/services/http/http.go index a1a14aa..a59ac9e 100644 --- a/services/http/http.go +++ b/services/http/http.go @@ -185,7 +185,7 @@ func (s *HTTP) StopService() { if e != nil { s.log.Printf("stop http(s) service crashed,%s", e) } else { - s.log.Printf("service http(s) stoped") + s.log.Printf("service http(s) stopped") } }() s.isStop = true diff --git a/services/mux/mux_bridge.go b/services/mux/mux_bridge.go index 73ed365..5268151 100644 --- a/services/mux/mux_bridge.go +++ b/services/mux/mux_bridge.go @@ -80,7 +80,7 @@ func (s *MuxBridge) StopService() { if e != nil { s.log.Printf("stop bridge service crashed,%s", e) } else { - s.log.Printf("service bridge stoped") + s.log.Printf("service bridge stopped") } }() s.isStop = true diff --git a/services/mux/mux_client.go b/services/mux/mux_client.go index b5c263a..3b55819 100644 --- a/services/mux/mux_client.go +++ b/services/mux/mux_client.go @@ -73,7 +73,7 @@ func (s *MuxClient) StopService() { if e != nil { s.log.Printf("stop client service crashed,%s", e) } else { - s.log.Printf("service client stoped") + s.log.Printf("service client stopped") } }() s.isStop = true diff --git a/services/mux/mux_server.go b/services/mux/mux_server.go index 5f34715..d6ebef8 100644 --- a/services/mux/mux_server.go +++ b/services/mux/mux_server.go @@ -182,7 +182,7 @@ func (s *MuxServer) StopService() { if e != nil { s.log.Printf("stop server service crashed,%s", e) } else { - s.log.Printf("service server stoped") + s.log.Printf("service server stopped") } }() s.isStop = true diff --git a/services/socks/socks.go b/services/socks/socks.go index 5020c50..7cd50a1 100644 --- a/services/socks/socks.go +++ b/services/socks/socks.go @@ -189,7 +189,7 @@ func (s *Socks) StopService() { if e != nil { s.log.Printf("stop socks service crashed,%s", e) } else { - s.log.Printf("service socks stoped") + s.log.Printf("service socks stopped") } }() s.isStop = true diff --git a/services/sps/sps.go b/services/sps/sps.go index 8060987..343f69b 100644 --- a/services/sps/sps.go +++ b/services/sps/sps.go @@ -130,7 +130,7 @@ func (s *SPS) StopService() { if e != nil { s.log.Printf("stop sps service crashed,%s", e) } else { - s.log.Printf("service sps stoped") + s.log.Printf("service sps stopped") } }() for _, sc := range s.serverChannels { diff --git a/services/tcp/tcp.go b/services/tcp/tcp.go index 652b539..8f7dd75 100644 --- a/services/tcp/tcp.go +++ b/services/tcp/tcp.go @@ -74,7 +74,7 @@ func (s *TCP) StopService() { if e != nil { s.log.Printf("stop tcp service crashed,%s", e) } else { - s.log.Printf("service tcp stoped") + s.log.Printf("service tcp stopped") } }() s.isStop = true diff --git a/services/tunnel/tunnel_bridge.go b/services/tunnel/tunnel_bridge.go index 8f27284..d409a61 100644 --- a/services/tunnel/tunnel_bridge.go +++ b/services/tunnel/tunnel_bridge.go @@ -70,7 +70,7 @@ func (s *TunnelBridge) StopService() { if e != nil { s.log.Printf("stop tbridge service crashed,%s", e) } else { - s.log.Printf("service tbridge stoped") + s.log.Printf("service tbridge stopped") } }() s.isStop = true diff --git a/services/tunnel/tunnel_client.go b/services/tunnel/tunnel_client.go index 6e80dfd..d759e2e 100644 --- a/services/tunnel/tunnel_client.go +++ b/services/tunnel/tunnel_client.go @@ -70,7 +70,7 @@ func (s *TunnelClient) StopService() { if e != nil { s.log.Printf("stop tclient service crashed,%s", e) } else { - s.log.Printf("service tclient stoped") + s.log.Printf("service tclient stopped") } }() s.isStop = true diff --git a/services/tunnel/tunnel_server.go b/services/tunnel/tunnel_server.go index 594033e..858f168 100644 --- a/services/tunnel/tunnel_server.go +++ b/services/tunnel/tunnel_server.go @@ -183,7 +183,7 @@ func (s *TunnelServer) StopService() { if e != nil { s.log.Printf("stop server service crashed,%s", e) } else { - s.log.Printf("service server stoped") + s.log.Printf("service server stopped") } }() s.isStop = true diff --git a/services/udp/udp.go b/services/udp/udp.go index a9388e2..cf2d46f 100644 --- a/services/udp/udp.go +++ b/services/udp/udp.go @@ -73,7 +73,7 @@ func (s *UDP) StopService() { if e != nil { s.log.Printf("stop udp service crashed,%s", e) } else { - s.log.Printf("service udp stoped") + s.log.Printf("service udp stopped") } }() s.isStop = true From a1a2c3f9854a99f9ab9078512551f34e4d738c25 Mon Sep 17 00:00:00 2001 From: "arraykeys@gmail.com" Date: Tue, 24 Jul 2018 11:31:16 +0800 Subject: [PATCH 41/44] sdk5.3 --- sdk/CHANGELOG | 8 ++++++++ sdk/android-ios/sdk.go | 40 +++++++++++++++++++++++++++++++++------- 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/sdk/CHANGELOG b/sdk/CHANGELOG index e2d614a..fd37799 100644 --- a/sdk/CHANGELOG +++ b/sdk/CHANGELOG @@ -1,5 +1,13 @@ SDK更新日志 +v5.3 +1.增加了支持日志输出回调的方法: + StartWithLog(serviceID, serviceArgsStr string, loggerCallback LogCallback) +2.优化了socks_client握手端口判断,避免了sstap测试UDP失败的问题.. +3.修复了HTTP(S)\SPS反向代理无法正常工作的问题. +4.优化了智能判断,减少不必要的DNS解析. +5.重构了SOCKS和SPS的UDP功能,基于UDP的游戏加速嗖嗖的. + v4.9 1.修复了HTTP Basic代理返回不合适的头部,导致浏览器不会弹框,个别代理插件无法认证的问题. 2.内网穿透切换smux到yamux. diff --git a/sdk/android-ios/sdk.go b/sdk/android-ios/sdk.go index fd5c898..67a6934 100644 --- a/sdk/android-ios/sdk.go +++ b/sdk/android-ios/sdk.go @@ -23,12 +23,31 @@ import ( kingpin "gopkg.in/alecthomas/kingpin.v2" ) -const SDK_VERSION = "5.2" +const SDK_VERSION = "5.3" var ( app *kingpin.Application ) +type LogCallback interface { + Write(line string) +} +type logCallback interface { + Write(line string) +} +type logWriter struct { + callback LogCallback +} + +func (s *logWriter) Write(p []byte) (n int, err error) { + s.callback.Write(string(p)) + return +} + +func Start(serviceID, serviceArgsStr string) (errStr string) { + return StartWithLog(serviceID, serviceArgsStr, nil) +} + //Start //serviceID : is service identify id,different service's id should be difference //serviceArgsStr: is the whole command line args string @@ -38,7 +57,7 @@ var ( //and so on. //if an error occured , errStr will be the error reason //if start success, errStr is empty. -func Start(serviceID, serviceArgsStr string) (errStr string) { +func StartWithLog(serviceID, serviceArgsStr string, loggerCallback LogCallback) (errStr string) { //define args tcpArgs := tcpx.TCPArgs{} httpArgs := httpx.HTTPArgs{} @@ -337,12 +356,19 @@ func Start(serviceID, serviceArgsStr string) (errStr string) { } log.SetFlags(flags) - if *logfile != "" { - f, e := os.OpenFile(*logfile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600) - if e != nil { - log.Fatal(e) + if loggerCallback == nil { + if *logfile != "" { + f, e := os.OpenFile(*logfile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600) + if e != nil { + log.Fatal(e) + } + log.SetOutput(f) } - log.SetOutput(f) + } else { + + log.SetOutput(&logWriter{ + callback: loggerCallback, + }) } //regist services and run service From e427263ccf691239d02bc6b186f112dda425427e Mon Sep 17 00:00:00 2001 From: "arraykeys@gmail.com" Date: Tue, 24 Jul 2018 12:10:24 +0800 Subject: [PATCH 42/44] a --- sdk/android-ios/release_android.sh | 2 +- sdk/android-ios/release_ios.sh | 2 +- sdk/windows-linux/release_linux.sh | 2 +- sdk/windows-linux/release_mac.sh | 2 +- sdk/windows-linux/release_windows.sh | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sdk/android-ios/release_android.sh b/sdk/android-ios/release_android.sh index 7d12525..a52adfa 100755 --- a/sdk/android-ios/release_android.sh +++ b/sdk/android-ios/release_android.sh @@ -1,5 +1,5 @@ #/bin/bash -VER="v5.2" +VER="v5.3" rm -rf sdk-android-*.tar.gz rm -rf android mkdir android diff --git a/sdk/android-ios/release_ios.sh b/sdk/android-ios/release_ios.sh index 96a50af..633981c 100755 --- a/sdk/android-ios/release_ios.sh +++ b/sdk/android-ios/release_ios.sh @@ -1,5 +1,5 @@ #/bin/bash -VER="v5.2" +VER="v5.3" rm -rf sdk-ios-*.tar.gz rm -rf ios mkdir ios diff --git a/sdk/windows-linux/release_linux.sh b/sdk/windows-linux/release_linux.sh index a6653d8..76aaf4b 100755 --- a/sdk/windows-linux/release_linux.sh +++ b/sdk/windows-linux/release_linux.sh @@ -1,5 +1,5 @@ #/bin/bash -VER="v5.2" +VER="v5.3" rm -rf sdk-linux-*.tar.gz rm -rf README.md libproxy-sdk.so libproxy-sdk.h libproxy-sdk.a diff --git a/sdk/windows-linux/release_mac.sh b/sdk/windows-linux/release_mac.sh index a872e3c..b2b5e4e 100755 --- a/sdk/windows-linux/release_mac.sh +++ b/sdk/windows-linux/release_mac.sh @@ -1,5 +1,5 @@ #/bin/bash -VER="v5.2" +VER="v5.3" rm -rf *.tar.gz rm -rf README.md libproxy-sdk.dylib libproxy-sdk.h diff --git a/sdk/windows-linux/release_windows.sh b/sdk/windows-linux/release_windows.sh index 176f832..ab26512 100755 --- a/sdk/windows-linux/release_windows.sh +++ b/sdk/windows-linux/release_windows.sh @@ -1,5 +1,5 @@ #/bin/bash -VER="v5.2" +VER="v5.3" #sudo rm /usr/local/go #sudo ln -s /usr/local/go1.10.1 /usr/local/go From 5c2e6fd10933d56068074cf25548431143e64cbf Mon Sep 17 00:00:00 2001 From: "arraykeys@gmail.com" Date: Tue, 24 Jul 2018 17:25:04 +0800 Subject: [PATCH 43/44] a --- sdk/android-ios/sdk.go | 1 - 1 file changed, 1 deletion(-) diff --git a/sdk/android-ios/sdk.go b/sdk/android-ios/sdk.go index 67a6934..55873e7 100644 --- a/sdk/android-ios/sdk.go +++ b/sdk/android-ios/sdk.go @@ -365,7 +365,6 @@ func StartWithLog(serviceID, serviceArgsStr string, loggerCallback LogCallback) log.SetOutput(f) } } else { - log.SetOutput(&logWriter{ callback: loggerCallback, }) From b9f054c4951a045d4393dc4f4d87cb5b8a3d8131 Mon Sep 17 00:00:00 2001 From: "arraykeys@gmail.com" Date: Mon, 6 Aug 2018 16:06:43 +0800 Subject: [PATCH 44/44] v5.3 --- CHANGELOG | 2 +- README.md | 8 ++++---- README_ZH.md | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 2c5d6d9..2eb1f0e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,6 @@ proxy更新日志 v5.3 -1.优化了socks_client握手端口判断,避免了sstap测试UDP失败的问题.. +1.优化了socks_client握手端口判断,避免了sstap测试UDP失败的问题. v5.2 1.修复了HTTP(S)\SPS反向代理无法正常工作的问题. diff --git a/README.md b/README.md index 285206d..96ef72d 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ PR needs to explain what changes have been made and why you change them. - ...   -This page is the v5.2 manual, and the other version of the manual can be checked by the following [link](docs/old-release.md). +This page is the v5.3 manual, and the other version of the manual can be checked by the following [link](docs/old-release.md). ### How to find the organization? [Click to join the proxy group of gitter](https://gitter.im/go-proxy/Lobby?utm_source=share-link&utm_medium=link&utm_campaign=share-link)   @@ -161,7 +161,7 @@ If the installation fails or your VPS is not a linux64 system, please follow the Download address: https://github.com/snail007/goproxy/releases ```shell cd /root/proxy/ -wget https://github.com/snail007/goproxy/releases/download/v5.0/proxy-linux-amd64.tar.gz +wget https://github.com/snail007/goproxy/releases/download/v5.3/proxy-linux-amd64.tar.gz ``` #### **2.Download the automatic installation script** ```shell @@ -175,10 +175,10 @@ chmod +x install.sh Dockerfile root of project uses multistage build and alpine project to comply with best practices. Uses golang 1.10.3 for building as noted in the project README.md and will be pretty small image. total extracted size will be 17.3MB for goproxy latest version. -The default build process builds the master branch (latest commits/ cutting edge), and it can be configured to build specific version, just edit Dockerfile before build, following builds release version 5.2: +The default build process builds the master branch (latest commits/ cutting edge), and it can be configured to build specific version, just edit Dockerfile before build, following builds release version 5.3: ``` -ARG GOPROXY_VERSION=v5.2 +ARG GOPROXY_VERSION=v5.3 ``` To Run: diff --git a/README_ZH.md b/README_ZH.md index c69bea5..fd831d4 100644 --- a/README_ZH.md +++ b/README_ZH.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.1/proxy-linux-amd64.tar.gz +wget https://github.com/snail007/goproxy/releases/download/v5.3/proxy-linux-amd64.tar.gz ``` #### **2.下载自动安装脚本** ```shell @@ -175,7 +175,7 @@ chmod +x install.sh 或者使用参数GOPROXY_VERSION指定构建的goproxy版本. ``` -ARG GOPROXY_VERSION=v5.2 +ARG GOPROXY_VERSION=v5.3 ``` 步骤: