diff --git a/CHANGELOG b/CHANGELOG index 5b96db9..36e12be 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -5,6 +5,8 @@ v4.3 用于自己指定proxy访问域名的时候使用的dns(--dns-address)以及解析结果缓存时间(--dns-ttl)秒数, 避免系统dns对proxy的干扰,另外缓存功能还能减少dns解析时间提高访问速度。 3.优化了http代理的basic认证逻辑。 +提示: +v4.3生成的证书不适用于v4.2及以下版本。 v4.2 1.优化了内网穿透,避免了client意外下线,导致链接信息残留的问题. diff --git a/README.md b/README.md index 57c787a..5a90b65 100644 --- a/README.md +++ b/README.md @@ -132,7 +132,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/v4.3/proxy-linux-amd64.tar.gz +wget https://github.com/snail007/goproxy/releases/download/v4.4/proxy-linux-amd64.tar.gz ``` #### **2.Download the automatic installation script** ```shell diff --git a/README_ZH.md b/README_ZH.md index 2144ba6..4a9316f 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -134,7 +134,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/v4.3/proxy-linux-amd64.tar.gz +wget https://github.com/snail007/goproxy/releases/download/v4.4/proxy-linux-amd64.tar.gz ``` #### **2.下载自动安装脚本** ```shell diff --git a/config.go b/config.go index b2de361..1da4c3e 100755 --- a/config.go +++ b/config.go @@ -39,6 +39,7 @@ func initConfig() (err error) { muxBridgeArgs := services.MuxBridgeArgs{} udpArgs := services.UDPArgs{} socksArgs := services.SocksArgs{} + spsArgs := services.SPSArgs{} //build srvice args app = kingpin.New("proxy", "happy with proxy") app.Author("snail").Version(APP_VERSION) @@ -186,6 +187,16 @@ func initConfig() (err error) { socksArgs.AuthURLRetry = socks.Flag("auth-retry", "access 'auth-url' fail and retry count").Default("0").Int() socksArgs.DNSAddress = socks.Flag("dns-address", "if set this, proxy will use this dns for resolve doamin").Short('q').Default("").String() socksArgs.DNSTTL = socks.Flag("dns-ttl", "caching seconds of dns query result").Short('e').Default("300").Int() + //########socks+http(s)######### + sps := app.Command("sps", "proxy on socks+http(s) mode") + spsArgs.Parent = sps.Flag("parent", "parent address, such as: \"23.32.32.19:28008\"").Default("").Short('P').String() + spsArgs.CertFile = sps.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String() + spsArgs.KeyFile = sps.Flag("key", "key file for tls").Short('K').Default("proxy.key").String() + spsArgs.Timeout = sps.Flag("timeout", "tcp timeout milliseconds when connect to real server or parent proxy").Short('e').Default("2000").Int() + spsArgs.ParentServiceType = sps.Flag("parent-service-type", "parent service type ").Short('S').Enum("http", "socks") + spsArgs.ParentType = sps.Flag("parent-type", "parent protocol type ").Short('T').Enum("tls", "tcp") + spsArgs.LocalType = sps.Flag("local-type", "local protocol type ").Default("tcp").Short('t').Enum("tls", "tcp") + spsArgs.Local = sps.Flag("local", "local ip:port to listen").Short('p').Default(":33080").String() //parse args serviceName := kingpin.MustParse(app.Parse(os.Args[1:])) @@ -285,6 +296,7 @@ func initConfig() (err error) { services.Regist("client", services.NewMuxClient(), muxClientArgs) services.Regist("bridge", services.NewMuxBridge(), muxBridgeArgs) services.Regist("socks", services.NewSocks(), socksArgs) + services.Regist("sps", services.NewSPS(), spsArgs) service, err = services.Run(serviceName) if err != nil { log.Fatalf("run service [%s] fail, ERR:%s", serviceName, err) diff --git a/install_auto.sh b/install_auto.sh index 495bd2c..6a5b874 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/v4.3/proxy-linux-amd64.tar.gz +wget https://github.com/snail007/goproxy/releases/download/v4.4/proxy-linux-amd64.tar.gz # #install proxy tar zxvf proxy-linux-amd64.tar.gz diff --git a/main.go b/main.go index 93abc31..f01ec8c 100644 --- a/main.go +++ b/main.go @@ -8,7 +8,7 @@ import ( "syscall" ) -const APP_VERSION = "4.3" +const APP_VERSION = "4.4" func main() { err := initConfig() diff --git a/release.sh b/release.sh index 0684f57..3125887 100755 --- a/release.sh +++ b/release.sh @@ -1,5 +1,5 @@ #!/bin/bash -VER="4.3" +VER="4.4" RELEASE="release-${VER}" rm -rf .cert mkdir .cert diff --git a/services/args.go b/services/args.go index 0482a0c..ceec143 100644 --- a/services/args.go +++ b/services/args.go @@ -187,7 +187,28 @@ type SocksArgs struct { DNSAddress *string DNSTTL *int } +type SPSArgs struct { + Parent *string + CertFile *string + KeyFile *string + CertBytes []byte + KeyBytes []byte + Local *string + ParentType *string + LocalType *string + Timeout *int + ParentServiceType *string +} +func (a *SPSArgs) Protocol() string { + switch *a.LocalType { + case TYPE_TLS: + return TYPE_TLS + case TYPE_TCP: + return TYPE_TCP + } + return "unknown" +} func (a *TCPArgs) Protocol() string { switch *a.LocalType { case TYPE_TLS: diff --git a/services/sps.go b/services/sps.go new file mode 100644 index 0000000..3cf51ad --- /dev/null +++ b/services/sps.go @@ -0,0 +1,110 @@ +package services + +import ( + "fmt" + "log" + "net" + "runtime/debug" + "snail007/proxy/utils" + "snail007/proxy/utils/socks" + "strconv" +) + +type SPS struct { + outPool utils.OutPool + cfg SPSArgs +} + +func NewSPS() Service { + return &SPS{ + outPool: utils.OutPool{}, + cfg: SPSArgs{}, + } +} +func (s *SPS) CheckArgs() { + if *s.cfg.Parent == "" { + log.Fatalf("parent required for %s %s", s.cfg.Protocol(), *s.cfg.Local) + } + if *s.cfg.ParentType == "" { + log.Fatalf("parent type unkown,use -T ") + } + if *s.cfg.ParentType == TYPE_TLS || *s.cfg.LocalType == TYPE_TLS { + s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile) + } +} +func (s *SPS) InitService() { + +} +func (s *SPS) StopService() { + if s.outPool.Pool != nil { + s.outPool.Pool.ReleaseAll() + } +} +func (s *SPS) Start(args interface{}) (err error) { + s.cfg = args.(SPSArgs) + s.CheckArgs() + log.Printf("use %s %s parent %s", *s.cfg.ParentType, *s.cfg.ParentServiceType, *s.cfg.Parent) + s.InitService() + + host, port, _ := net.SplitHostPort(*s.cfg.Local) + p, _ := strconv.Atoi(port) + sc := utils.NewServerChannel(host, p) + + if *s.cfg.LocalType == TYPE_TCP { + err = sc.ListenTCP(s.callback) + } else if *s.cfg.LocalType == TYPE_TLS { + err = sc.ListenTls(s.cfg.CertBytes, s.cfg.KeyBytes, s.callback) + } + if err != nil { + return + } + log.Printf("%s http(s)+socks proxy on %s", s.cfg.Protocol(), (*sc.Listener).Addr()) + return +} + +func (s *SPS) Clean() { + s.StopService() +} +func (s *SPS) callback(inConn net.Conn) { + defer func() { + if err := recover(); err != nil { + log.Printf("%s conn handler crashed with err : %s \nstack: %s", s.cfg.Protocol(), err, string(debug.Stack())) + } + }() + var err error + switch *s.cfg.ParentType { + case TYPE_TCP: + fallthrough + case TYPE_TLS: + err = s.OutToTCP(&inConn) + default: + err = fmt.Errorf("unkown parent type %s", *s.cfg.ParentType) + } + if err != nil { + log.Printf("connect to %s parent %s fail, ERR:%s", *s.cfg.ParentType, *s.cfg.Parent, err) + utils.CloseConn(&inConn) + } +} +func (s *SPS) OutToTCP(inConn *net.Conn) (err error) { + buf := make([]byte, 1024) + n, err := (*inConn).Read(buf) + header := buf[:n] + if err != nil { + log.Printf("ERR:%s", err) + utils.CloseConn(inConn) + return + } + fmt.Printf("%v", header[0]) + + if header[0] == socks.VERSION_V5 { + req, e := socks.NewMethodsRequest(*inConn, header) + if e != nil { + log.Printf("ERR:%s", e) + utils.CloseConn(inConn) + err = e.(error) + return + } + fmt.Printf("address:%v", req.Version()) + } + return +} diff --git a/utils/socks/structs.go b/utils/socks/structs.go index 4e04b54..ef5b51b 100644 --- a/utils/socks/structs.go +++ b/utils/socks/structs.go @@ -53,14 +53,19 @@ type Request struct { rw io.ReadWriter } -func NewRequest(rw io.ReadWriter) (req Request, err interface{}) { - var b [1024]byte +func NewRequest(rw io.ReadWriter, header ...[]byte) (req Request, err interface{}) { + var b = make([]byte, 1024) var n int req = Request{rw: rw} - n, err = rw.Read(b[:]) - if err != nil { - err = fmt.Errorf("read req data fail,ERR: %s", err) - return + if len(header) == 1 { + b = header[0] + n = len(header[0]) + } else { + n, err = rw.Read(b[:]) + if err != nil { + err = fmt.Errorf("read req data fail,ERR: %s", err) + return + } } req.ver = uint8(b[0]) req.cmd = uint8(b[1]) @@ -150,7 +155,7 @@ type MethodsRequest struct { rw *io.ReadWriter } -func NewMethodsRequest(r io.ReadWriter) (s MethodsRequest, err interface{}) { +func NewMethodsRequest(r io.ReadWriter, header ...[]byte) (s MethodsRequest, err interface{}) { defer func() { if err == nil { err = recover() @@ -160,9 +165,14 @@ func NewMethodsRequest(r io.ReadWriter) (s MethodsRequest, err interface{}) { s.rw = &r var buf = make([]byte, 300) var n int - n, err = r.Read(buf) - if err != nil { - return + if len(header) == 1 { + buf = header[0] + n = len(header[0]) + } else { + n, err = r.Read(buf) + if err != nil { + return + } } if buf[0] != 0x05 { err = fmt.Errorf("socks version not supported") diff --git a/utils/structs.go b/utils/structs.go index da0d2b9..fe22c47 100644 --- a/utils/structs.go +++ b/utils/structs.go @@ -309,21 +309,27 @@ type HTTPRequest struct { basicAuth *BasicAuth } -func NewHTTPRequest(inConn *net.Conn, bufSize int, isBasicAuth bool, basicAuth *BasicAuth) (req HTTPRequest, err error) { +func NewHTTPRequest(inConn *net.Conn, bufSize int, isBasicAuth bool, basicAuth *BasicAuth, header ...[]byte) (req HTTPRequest, err error) { buf := make([]byte, bufSize) - len := 0 + n := 0 req = HTTPRequest{ conn: inConn, } - len, err = (*inConn).Read(buf[:]) - if err != nil { - if err != io.EOF { - err = fmt.Errorf("http decoder read err:%s", err) + if len(header) == 1 { + buf = header[0] + n = len(header[0]) + } else { + n, err = (*inConn).Read(buf[:]) + if err != nil { + if err != io.EOF { + err = fmt.Errorf("http decoder read err:%s", err) + } + CloseConn(inConn) + return } - CloseConn(inConn) - return } - req.HeadBuf = buf[:len] + + req.HeadBuf = buf[:n] //fmt.Println(string(req.HeadBuf)) //try sni serverName, err0 := sni.ServerNameFromBytes(req.HeadBuf)