diff --git a/README.md b/README.md index 464612a..11cdaf6 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,8 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5代理服务 - ...   -本页是最新v3.3手册,其他版本手册请点击下面链接查看. +本页是v3.4手册,其他版本手册请点击下面链接查看. +- [v3.3手册](https://github.com/snail007/goproxy/tree/v3.3) - [v3.2手册](https://github.com/snail007/goproxy/tree/v3.2) - [v3.1手册](https://github.com/snail007/goproxy/tree/v3.1) - [v3.0手册](https://github.com/snail007/goproxy/tree/v3.0) diff --git a/install_auto.sh b/install_auto.sh index b48a25d..56eaa4b 100755 --- a/install_auto.sh +++ b/install_auto.sh @@ -6,7 +6,7 @@ fi mkdir /tmp/proxy cd /tmp/proxy wget https://github.com/reddec/monexec/releases/download/v0.1.1/monexec_0.1.1_linux_amd64.tar.gz -wget https://github.com/snail007/goproxy/releases/download/v3.3/proxy-linux-amd64.tar.gz +wget https://github.com/snail007/goproxy/releases/download/v3.4/proxy-linux-amd64.tar.gz # install monexec tar zxvf monexec_0.1.1_linux_amd64.tar.gz diff --git a/services/args.go b/services/args.go index d3bde40..1c21461 100644 --- a/services/args.go +++ b/services/args.go @@ -6,15 +6,16 @@ import "golang.org/x/crypto/ssh" // t := tcp.Flag("tcp-timeout", "tcp timeout milliseconds when connect to real server or parent proxy").Default("2000").Int() const ( - TYPE_TCP = "tcp" - TYPE_UDP = "udp" - TYPE_HTTP = "http" - TYPE_TLS = "tls" - TYPE_KCP = "kcp" - CONN_CLIENT_CONTROL = uint8(1) - CONN_SERVER_CONTROL = uint8(2) - CONN_SERVER = uint8(3) - CONN_CLIENT = uint8(4) + TYPE_TCP = "tcp" + TYPE_UDP = "udp" + TYPE_HTTP = "http" + TYPE_TLS = "tls" + TYPE_KCP = "kcp" + CONN_CLIENT_CONTROL = uint8(1) + CONN_CLIENT_HEARBEAT = uint8(2) + CONN_SERVER_HEARBEAT = uint8(3) + CONN_SERVER = uint8(4) + CONN_CLIENT = uint8(5) ) type TunnelServerArgs struct { diff --git a/services/tunnel_bridge.go b/services/tunnel_bridge.go index 8460e76..2dc4d0e 100644 --- a/services/tunnel_bridge.go +++ b/services/tunnel_bridge.go @@ -137,28 +137,15 @@ func (s *TunnelBridge) Start(args interface{}) (err error) { } s.clientControlConns.Set(key, &inConn) log.Printf("set client %s control conn", key) - go func() { - for { - var b = make([]byte, 1) - _, err = inConn.Read(b) - if err != nil { - inConn.Close() - log.Printf("%s control conn from client released", key) - s.cmClient.Remove(key) - break - } else { - // log.Printf("heartbeat from client %s", key) - } - } - }() - case CONN_SERVER_CONTROL: + + case CONN_SERVER_HEARBEAT: var serverID string err = utils.ReadPacketData(reader, &serverID) if err != nil { log.Printf("read error,ERR:%s", err) return } - log.Printf("server control connection, id: %s", serverID) + log.Printf("server heartbeat connection, id: %s", serverID) writeDie := make(chan bool) readDie := make(chan bool) go func() { @@ -167,7 +154,7 @@ func (s *TunnelBridge) Start(args interface{}) (err error) { _, err = inConn.Write([]byte{0x00}) inConn.SetWriteDeadline(time.Time{}) if err != nil { - log.Printf("server control connection write err %s", err) + log.Printf("server heartbeat connection write err %s", err) break } time.Sleep(time.Second * 3) @@ -177,11 +164,11 @@ func (s *TunnelBridge) Start(args interface{}) (err error) { go func() { for { signal := make([]byte, 1) - inConn.SetReadDeadline(time.Now().Add(time.Second * 10)) + inConn.SetReadDeadline(time.Now().Add(time.Second * 6)) _, err := inConn.Read(signal) inConn.SetReadDeadline(time.Time{}) if err != nil { - log.Printf("server control connection read err: %s", err) + log.Printf("server heartbeat connection read err: %s", err) break } else { // log.Printf("heartbeat from server ,id:%s", serverID) @@ -195,7 +182,57 @@ func (s *TunnelBridge) Start(args interface{}) (err error) { } utils.CloseConn(&inConn) s.cmServer.Remove(serverID) - log.Printf("server control conn %s released", serverID) + log.Printf("server heartbeat conn %s released", serverID) + case CONN_CLIENT_HEARBEAT: + var clientID string + err = utils.ReadPacketData(reader, &clientID) + if err != nil { + log.Printf("read error,ERR:%s", err) + return + } + log.Printf("client heartbeat connection, id: %s", clientID) + writeDie := make(chan bool) + readDie := make(chan bool) + go func() { + for { + inConn.SetWriteDeadline(time.Now().Add(time.Second * 3)) + _, err = inConn.Write([]byte{0x00}) + inConn.SetWriteDeadline(time.Time{}) + if err != nil { + log.Printf("client heartbeat connection write err %s", err) + break + } + time.Sleep(time.Second * 3) + } + close(writeDie) + }() + go func() { + for { + signal := make([]byte, 1) + inConn.SetReadDeadline(time.Now().Add(time.Second * 6)) + _, err := inConn.Read(signal) + inConn.SetReadDeadline(time.Time{}) + if err != nil { + log.Printf("client control connection read err: %s", err) + break + } else { + // log.Printf("heartbeat from client ,id:%s", clientID) + } + } + close(readDie) + }() + select { + case <-readDie: + case <-writeDie: + } + utils.CloseConn(&inConn) + s.cmClient.Remove(clientID) + if s.clientControlConns.Has(clientID) { + item, _ := s.clientControlConns.Get(clientID) + (*item.(*net.Conn)).Close() + } + s.clientControlConns.Remove(clientID) + log.Printf("client heartbeat conn %s released", clientID) } }) if err != nil { diff --git a/services/tunnel_client.go b/services/tunnel_client.go index 61b1aa6..ea5a080 100644 --- a/services/tunnel_client.go +++ b/services/tunnel_client.go @@ -11,8 +11,9 @@ import ( ) type TunnelClient struct { - cfg TunnelClientArgs - cm utils.ConnManager + cfg TunnelClientArgs + cm utils.ConnManager + ctrlConn net.Conn } func NewTunnelClient() Service { @@ -23,6 +24,65 @@ func NewTunnelClient() Service { } func (s *TunnelClient) InitService() { + s.InitHeartbeatDeamon() +} +func (s *TunnelClient) InitHeartbeatDeamon() { + log.Printf("heartbeat started") + go func() { + var heartbeatConn net.Conn + var ID = *s.cfg.Key + for { + + //close all connection + s.cm.RemoveAll() + if s.ctrlConn != nil { + s.ctrlConn.Close() + } + utils.CloseConn(&heartbeatConn) + heartbeatConn, err := s.GetInConn(CONN_CLIENT_HEARBEAT, ID) + if err != nil { + log.Printf("heartbeat connection err: %s, retrying...", err) + time.Sleep(time.Second * 3) + utils.CloseConn(&heartbeatConn) + continue + } + log.Printf("heartbeat connection created,id:%s", ID) + writeDie := make(chan bool) + readDie := make(chan bool) + go func() { + for { + heartbeatConn.SetWriteDeadline(time.Now().Add(time.Second * 3)) + _, err = heartbeatConn.Write([]byte{0x00}) + heartbeatConn.SetWriteDeadline(time.Time{}) + if err != nil { + log.Printf("heartbeat connection write err %s", err) + break + } + time.Sleep(time.Second * 3) + } + close(writeDie) + }() + go func() { + for { + signal := make([]byte, 1) + heartbeatConn.SetReadDeadline(time.Now().Add(time.Second * 6)) + _, err := heartbeatConn.Read(signal) + heartbeatConn.SetReadDeadline(time.Time{}) + if err != nil { + log.Printf("heartbeat connection read err: %s", err) + break + } else { + log.Printf("heartbeat from bridge") + } + } + close(readDie) + }() + select { + case <-readDie: + case <-writeDie: + } + } + }() } func (s *TunnelClient) CheckArgs() { if *s.cfg.Parent != "" { @@ -43,40 +103,30 @@ func (s *TunnelClient) Start(args interface{}) (err error) { s.CheckArgs() s.InitService() log.Printf("proxy on tunnel client mode") - var ctrlConn net.Conn + for { //close all conn s.cm.Remove(*s.cfg.Key) - utils.CloseConn(&ctrlConn) + if s.ctrlConn != nil { + s.ctrlConn.Close() + } - ctrlConn, err = s.GetInConn(CONN_CLIENT_CONTROL, *s.cfg.Key) + s.ctrlConn, err = s.GetInConn(CONN_CLIENT_CONTROL, *s.cfg.Key) if err != nil { log.Printf("control connection err: %s, retrying...", err) time.Sleep(time.Second * 3) - utils.CloseConn(&ctrlConn) + if s.ctrlConn != nil { + s.ctrlConn.Close() + } continue } - go func() { - for { - if ctrlConn == nil { - break - } - ctrlConn.SetWriteDeadline(time.Now().Add(time.Second * 3)) - _, err = ctrlConn.Write([]byte{0x00}) - ctrlConn.SetWriteDeadline(time.Time{}) - if err != nil { - utils.CloseConn(&ctrlConn) - log.Printf("ctrlConn err %s", err) - break - } - time.Sleep(time.Second * 3) - } - }() for { var ID, clientLocalAddr, serverID string - err = utils.ReadPacketData(ctrlConn, &ID, &clientLocalAddr, &serverID) + err = utils.ReadPacketData(s.ctrlConn, &ID, &clientLocalAddr, &serverID) if err != nil { - utils.CloseConn(&ctrlConn) + if s.ctrlConn != nil { + s.ctrlConn.Close() + } log.Printf("read connection signal err: %s, retrying...", err) break } diff --git a/services/tunnel_server.go b/services/tunnel_server.go index e333106..2f38136 100644 --- a/services/tunnel_server.go +++ b/services/tunnel_server.go @@ -100,33 +100,34 @@ func (s *TunnelServerManager) CheckArgs() { s.cfg.CertBytes, s.cfg.KeyBytes = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile) } func (s *TunnelServerManager) InitService() { - s.InitControlDeamon() + s.InitHeartbeatDeamon() } -func (s *TunnelServerManager) InitControlDeamon() { +func (s *TunnelServerManager) InitHeartbeatDeamon() { + log.Printf("heartbeat started") go func() { - var ctrlConn net.Conn + var heartbeatConn net.Conn var ID string for { //close all connection s.cm.Remove(ID) - utils.CloseConn(&ctrlConn) - ctrlConn, ID, err := s.GetOutConn(CONN_SERVER_CONTROL) + utils.CloseConn(&heartbeatConn) + heartbeatConn, ID, err := s.GetOutConn(CONN_SERVER_HEARBEAT) if err != nil { - log.Printf("control connection err: %s, retrying...", err) + log.Printf("heartbeat connection err: %s, retrying...", err) time.Sleep(time.Second * 3) - utils.CloseConn(&ctrlConn) + utils.CloseConn(&heartbeatConn) continue } - log.Printf("control connection created,id:%s", ID) + log.Printf("heartbeat connection created,id:%s", ID) writeDie := make(chan bool) readDie := make(chan bool) go func() { for { - ctrlConn.SetWriteDeadline(time.Now().Add(time.Second * 3)) - _, err = ctrlConn.Write([]byte{0x00}) - ctrlConn.SetWriteDeadline(time.Time{}) + heartbeatConn.SetWriteDeadline(time.Now().Add(time.Second * 3)) + _, err = heartbeatConn.Write([]byte{0x00}) + heartbeatConn.SetWriteDeadline(time.Time{}) if err != nil { - log.Printf("control connection write err %s", err) + log.Printf("heartbeat connection write err %s", err) break } time.Sleep(time.Second * 3) @@ -136,11 +137,11 @@ func (s *TunnelServerManager) InitControlDeamon() { go func() { for { signal := make([]byte, 1) - ctrlConn.SetReadDeadline(time.Now().Add(time.Second * 10)) - _, err := ctrlConn.Read(signal) - ctrlConn.SetReadDeadline(time.Time{}) + heartbeatConn.SetReadDeadline(time.Now().Add(time.Second * 6)) + _, err := heartbeatConn.Read(signal) + heartbeatConn.SetReadDeadline(time.Time{}) if err != nil { - log.Printf("control connection read err: %s", err) + log.Printf("heartbeat connection read err: %s", err) break } else { // log.Printf("heartbeat from bridge")