From 33f232475d00b16f3d0fa25d9353fac4a65ba53b Mon Sep 17 00:00:00 2001 From: Qian Wang Date: Fri, 2 Aug 2019 15:45:33 +0100 Subject: [PATCH] Improve logging --- cmd/ck-client/ck-client.go | 38 ++++++++-------- cmd/ck-client/log_android.go | 4 +- cmd/ck-client/protector_android.go | 2 +- cmd/ck-server/ck-server.go | 70 +++++++++++++++++++----------- cmd/ck-server/keygen.go | 4 +- go.mod | 2 +- go.sum | 15 ++++++- internal/multiplex/session.go | 2 - internal/multiplex/stream.go | 8 ++-- internal/multiplex/switchboard.go | 6 +-- internal/server/auth.go | 26 +++++++---- internal/server/um_local.go | 6 +-- internal/server/userpanel.go | 12 +++-- internal/util/util.go | 15 ------- 14 files changed, 119 insertions(+), 91 deletions(-) diff --git a/cmd/ck-client/ck-client.go b/cmd/ck-client/ck-client.go index 3665529..6ce0157 100644 --- a/cmd/ck-client/ck-client.go +++ b/cmd/ck-client/ck-client.go @@ -8,7 +8,6 @@ import ( "flag" "fmt" "io" - "log" "math/rand" "net" "os" @@ -20,6 +19,7 @@ import ( "github.com/cbeuw/Cloak/internal/client/TLS" mux "github.com/cbeuw/Cloak/internal/multiplex" "github.com/cbeuw/Cloak/internal/util" + log "github.com/sirupsen/logrus" ) var version string @@ -51,7 +51,7 @@ func makeRemoteConn(sta *client.State) (net.Conn, []byte, error) { // For android d := net.Dialer{Control: protector} - clientHello, sharedSecret := TLS.ComposeInitHandshake(sta) + clientHello, sharedSecret := TLS.ComposeClientHello(sta) connectingIP := sta.RemoteHost if net.ParseIP(connectingIP).To4() == nil { // IPv6 needs square brackets @@ -59,25 +59,25 @@ func makeRemoteConn(sta *client.State) (net.Conn, []byte, error) { } remoteConn, err := d.Dial("tcp", connectingIP+":"+sta.RemotePort) if err != nil { - log.Printf("Connecting to remote: %v\n", err) + log.WithField("error", err).Error("Failed to connect to remote") return nil, nil, err } _, err = remoteConn.Write(clientHello) if err != nil { - log.Printf("Sending ClientHello: %v\n", err) + log.WithField("error", err).Error("Failed to send ClientHello") return nil, nil, err } buf := make([]byte, 1024) _, err = util.ReadTLS(remoteConn, buf) if err != nil { - log.Printf("Reading ServerHello: %v\n", err) + log.WithField("error", err).Error("Failed to read ServerHello") } serverRandom := buf[11:43] sessionKey := client.DecryptSessionKey(serverRandom, sharedSecret) _, err = util.ReadTLS(remoteConn, buf) if err != nil { - log.Printf("Reading Change Cipher Spec %v\n", err) + log.WithField("error", err).Error("Failed to read ChangeCipherSpec") return nil, nil, err } @@ -86,7 +86,7 @@ func makeRemoteConn(sta *client.State) (net.Conn, []byte, error) { } func makeSession(sta *client.State) *mux.Session { - log.Println("Attemtping to start a new session") + log.Info("Attemtping to start a new session") if !sta.IsAdmin { // sessionID is usergenerated. There shouldn't be a security concern because the scope of // sessionID is limited to its UID. @@ -105,7 +105,8 @@ func makeSession(sta *client.State) *mux.Session { conn, sk, err := makeRemoteConn(sta) _sessionKey.Store(sk) if err != nil { - log.Printf("Failed to establish new connections to remote: %v\n", err) + log.Errorf("Failed to establish new connections to remote: %v", err) + // TODO increase the interval if failed multiple times time.Sleep(time.Second * 3) goto makeconn } @@ -127,7 +128,7 @@ func makeSession(sta *client.State) *mux.Session { sesh.AddConnection(conn) } - log.Printf("Session %v established", sta.SessionID) + log.Infof("Session %v established", sta.SessionID) return sesh } @@ -143,9 +144,8 @@ func main() { var config string var b64AdminUID string - log.SetFlags(log.LstdFlags | log.Lshortfile) - log_init() + log.SetLevel(log.DebugLevel) if os.Getenv("SS_LOCAL_HOST") != "" { localHost = os.Getenv("SS_LOCAL_HOST") @@ -165,7 +165,7 @@ func main() { flag.Parse() if *askVersion { - fmt.Printf("ck-client %s\n", version) + fmt.Printf("ck-client %s", version) return } @@ -174,7 +174,7 @@ func main() { return } - log.Println("Starting standalone mode") + log.Info("Starting standalone mode") } sta := client.InitState(localHost, localPort, remoteHost, remotePort, time.Now) @@ -200,7 +200,6 @@ func main() { listeningIP = "[" + listeningIP + "]" } listener, err := net.Listen("tcp", listeningIP+":"+sta.LocalPort) - log.Println("Listening on " + listeningIP + ":" + sta.LocalPort) if err != nil { log.Fatal(err) } @@ -214,10 +213,13 @@ func main() { } if adminUID != nil { + log.Infof("API base is %v:%v", listeningIP, sta.LocalPort) sta.IsAdmin = true sta.SessionID = 0 sta.UID = adminUID sta.NumConn = 1 + } else { + log.Infof("Listening on %v:%v for proxy clients", listeningIP, sta.LocalPort) } var sesh *mux.Session @@ -225,7 +227,7 @@ func main() { for { localConn, err := listener.Accept() if err != nil { - log.Println(err) + log.Error(err) continue } if sesh == nil || sesh.IsClosed() { @@ -235,19 +237,19 @@ func main() { data := make([]byte, 10240) i, err := io.ReadAtLeast(localConn, data, 1) if err != nil { - log.Println(err) + log.Errorf("Failed to read first packet from proxy client: %v", err) localConn.Close() return } stream, err := sesh.OpenStream() if err != nil { - log.Println(err) + log.Errorf("Failed to open stream: %v", err) localConn.Close() return } _, err = stream.Write(data[:i]) if err != nil { - log.Println(err) + log.Errorf("Failed to write to stream: %v", err) localConn.Close() stream.Close() return diff --git a/cmd/ck-client/log_android.go b/cmd/ck-client/log_android.go index d46a789..7c7b967 100644 --- a/cmd/ck-client/log_android.go +++ b/cmd/ck-client/log_android.go @@ -28,7 +28,7 @@ import "C" import ( "bufio" - "log" + log "github.com/sirupsen/logrus" "os" "unsafe" ) @@ -66,8 +66,6 @@ func lineLog(f *os.File, priority C.int) { func log_init() { log.SetOutput(infoWriter{}) - // android logcat includes all of log.LstdFlags - log.SetFlags(log.Flags() &^ log.LstdFlags) r, w, err := os.Pipe() if err != nil { diff --git a/cmd/ck-client/protector_android.go b/cmd/ck-client/protector_android.go index 7f635b9..ca43bf4 100644 --- a/cmd/ck-client/protector_android.go +++ b/cmd/ck-client/protector_android.go @@ -67,7 +67,7 @@ package main import "C" import ( - "log" + log "github.com/sirupsen/logrus" "syscall" ) diff --git a/cmd/ck-server/ck-server.go b/cmd/ck-server/ck-server.go index 826b778..437bd5e 100644 --- a/cmd/ck-server/ck-server.go +++ b/cmd/ck-server/ck-server.go @@ -7,7 +7,6 @@ import ( "flag" "fmt" "io" - "log" "net" "net/http" _ "net/http/pprof" @@ -19,9 +18,10 @@ import ( mux "github.com/cbeuw/Cloak/internal/multiplex" "github.com/cbeuw/Cloak/internal/server" "github.com/cbeuw/Cloak/internal/util" + log "github.com/sirupsen/logrus" ) -var b64 = base64.StdEncoding +var b64 = base64.StdEncoding.EncodeToString var version string func pipe(dst io.ReadWriteCloser, src io.ReadWriteCloser) { @@ -46,6 +46,12 @@ func pipe(dst io.ReadWriteCloser, src io.ReadWriteCloser) { } func dispatchConnection(conn net.Conn, sta *server.State) { + remoteAddr := conn.RemoteAddr() + var err error + rejectLogger := log.WithFields(log.Fields{ + "remoteAddr": remoteAddr, + "error": err, + }) buf := make([]byte, 1500) conn.SetReadDeadline(time.Now().Add(3 * time.Second)) @@ -60,7 +66,7 @@ func dispatchConnection(conn net.Conn, sta *server.State) { goWeb := func() { webConn, err := net.Dial("tcp", sta.RedirAddr) if err != nil { - log.Printf("Making connection to redirection server: %v\n", err) + log.Errorf("Making connection to redirection server: %v", err) return } webConn.Write(data) @@ -70,26 +76,33 @@ func dispatchConnection(conn net.Conn, sta *server.State) { ch, err := server.ParseClientHello(data) if err != nil { - log.Printf("+1 non Cloak non (or malformed) TLS traffic from %v\n", conn.RemoteAddr()) + rejectLogger.Warn("+1 non Cloak non (or malformed) TLS traffic") goWeb() return } - isCloak, UID, sessionID, proxyMethod, encryptionMethod, sharedSecret := server.TouchStone(ch, sta) - if !isCloak { - log.Printf("+1 non Cloak TLS traffic from %v\n", conn.RemoteAddr()) + UID, sessionID, proxyMethod, encryptionMethod, sharedSecret, err := server.TouchStone(ch, sta) + if err != nil { + rejectLogger.Warn("+1 non Cloak TLS traffic") goWeb() return } if _, ok := sta.ProxyBook[proxyMethod]; !ok { - log.Printf("+1 Cloak TLS traffic with invalid proxy method `%v` from %v\n", proxyMethod, conn.RemoteAddr()) + log.WithFields(log.Fields{ + "UID": UID, + "proxyMethod": proxyMethod, + }).Warn("+1 Cloak TLS traffic with invalid proxy method") goWeb() return } user, err := sta.Panel.GetUser(UID) if err != nil { - log.Printf("+1 unauthorised user from %v, uid: %v\n", conn.RemoteAddr(), base64.StdEncoding.EncodeToString(UID)) + log.WithFields(log.Fields{ + "UID": b64(UID), + "remoteAddr": remoteAddr, + "error": err, + }).Warn("+1 unauthorised UID") goWeb() return } @@ -108,21 +121,21 @@ func dispatchConnection(conn net.Conn, sta *server.State) { rand.Read(sessionKey) obfs, deobfs, err := util.GenerateObfs(encryptionMethod, sessionKey) if err != nil { - log.Println(err) + log.Error(err) goWeb() } sesh, existing, err := user.GetSession(sessionID, obfs, deobfs, sessionKey, util.ReadTLS) if err != nil { user.DelSession(sessionID) - log.Println(err) + log.Error(err) return } if existing { err = finishHandshake(sesh.SessionKey) if err != nil { - log.Println(err) + log.Error(err) return } sesh.AddConnection(conn) @@ -135,7 +148,7 @@ func dispatchConnection(conn net.Conn, sta *server.State) { if bytes.Equal(UID, sta.AdminUID) && sessionID == 0 { err = finishHandshake(sessionKey) if err != nil { - log.Println(err) + log.Error(err) return } sesh := mux.MakeSession(0, mux.UNLIMITED_VALVE, obfs, deobfs, sessionKey, util.ReadTLS) @@ -143,25 +156,32 @@ func dispatchConnection(conn net.Conn, sta *server.State) { //TODO: Router could be nil in cnc mode err = http.Serve(sesh, sta.LocalAPIRouter) if err != nil { - log.Println(err) + log.Error(err) return } } err = finishHandshake(sessionKey) if err != nil { - log.Println(err) + log.Error(err) return } - log.Printf("New session from UID:%v, sessionID:%v\n", b64.EncodeToString(UID), sessionID) + log.WithFields(log.Fields{ + "UID": b64(UID), + "sessionID": sessionID, + }).Info("New session") sesh.AddConnection(conn) for { newStream, err := sesh.Accept() if err != nil { if err == mux.ErrBrokenSession { - log.Printf("Session closed for UID:%v, sessionID:%v, reason:%v\n", b64.EncodeToString(UID), sessionID, sesh.TerminalMsg()) + log.WithFields(log.Fields{ + "UID": b64(UID), + "sessionID": sessionID, + "reason": sesh.TerminalMsg(), + }).Info("Session closed") user.DelSession(sessionID) return } else { @@ -170,7 +190,7 @@ func dispatchConnection(conn net.Conn, sta *server.State) { } localConn, err := net.Dial("tcp", sta.ProxyBook[proxyMethod]) if err != nil { - log.Printf("Failed to connect to %v: %v\n", proxyMethod, err) + log.Errorf("Failed to connect to %v: %v", proxyMethod, err) continue } go pipe(localConn, newStream) @@ -186,7 +206,7 @@ func main() { var bindPort string var config string - log.SetFlags(log.LstdFlags | log.Lshortfile) + log.SetLevel(log.DebugLevel) if os.Getenv("SS_LOCAL_HOST") != "" { bindHost = os.Getenv("SS_REMOTE_HOST") @@ -207,7 +227,7 @@ func main() { flag.Parse() if *askVersion { - fmt.Printf("ck-server %s\n", version) + fmt.Printf("ck-server %s", version) return } if *printUsage { @@ -227,13 +247,13 @@ func main() { if *pprofAddr != "" { runtime.SetBlockProfileRate(5) go func() { - log.Println(http.ListenAndServe(*pprofAddr, nil)) + log.Info(http.ListenAndServe(*pprofAddr, nil)) }() - log.Println("pprof listening on " + *pprofAddr) + log.Infof("pprof listening on %v", *pprofAddr) } - log.Printf("Starting standalone mode, listening on %v:%v", bindHost, bindPort) + log.Infof("Starting standalone mode, listening on %v:%v", bindHost, bindPort) } sta, _ := server.InitState(bindHost, bindPort, time.Now) @@ -254,14 +274,14 @@ func main() { listen := func(addr, port string) { listener, err := net.Listen("tcp", addr+":"+port) - log.Println("Listening on " + addr + ":" + port) + log.Infof("Listening on " + addr + ":" + port) if err != nil { log.Fatal(err) } for { conn, err := listener.Accept() if err != nil { - log.Printf("%v", err) + log.Errorf("%v", err) continue } go dispatchConnection(conn, sta) diff --git a/cmd/ck-server/keygen.go b/cmd/ck-server/keygen.go index a3093dc..3e84049 100644 --- a/cmd/ck-server/keygen.go +++ b/cmd/ck-server/keygen.go @@ -8,12 +8,12 @@ import ( func generateUID() string { UID := make([]byte, 16) rand.Read(UID) - return b64.EncodeToString(UID) + return b64(UID) } func generateKeyPair() (string, string) { staticPv, staticPub, _ := ecdh.GenerateKey(rand.Reader) marshPub := ecdh.Marshal(staticPub) marshPv := staticPv.(*[32]byte)[:] - return b64.EncodeToString(marshPub), b64.EncodeToString(marshPv) + return b64(marshPub), b64(marshPv) } diff --git a/go.mod b/go.mod index 204af24..4d3ca37 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ require ( github.com/gorilla/mux v1.7.3 github.com/juju/ratelimit v1.0.1 github.com/kr/pretty v0.1.0 // indirect + github.com/sirupsen/logrus v1.4.2 golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b - golang.org/x/sys v0.0.0-20190124100055-b90733256f2e // indirect gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect ) diff --git a/go.sum b/go.sum index ae0515a..a3e3b7a 100644 --- a/go.sum +++ b/go.sum @@ -1,17 +1,28 @@ github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/juju/ratelimit v1.0.1 h1:+7AIFJVQ0EQgq/K9+0Krm7m530Du7tIz0METWzN0RgY= github.com/juju/ratelimit v1.0.1/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk= +github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b h1:Elez2XeF2p9uyVj0yEUDqQ56NFcDtcBNkYP7yv8YbUE= golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/sys v0.0.0-20190124100055-b90733256f2e h1:3GIlrlVLfkoipSReOMNAgApI0ajnalyLa/EZHHca/XI= -golang.org/x/sys v0.0.0-20190124100055-b90733256f2e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/internal/multiplex/session.go b/internal/multiplex/session.go index bf2d146..7bd2df9 100644 --- a/internal/multiplex/session.go +++ b/internal/multiplex/session.go @@ -2,7 +2,6 @@ package multiplex import ( "errors" - //"log" "net" "sync" "sync/atomic" @@ -122,7 +121,6 @@ func (sesh *Session) getStream(id uint32, closingFrame bool) *Stream { stream = makeStream(id, sesh) sesh.streams[id] = stream sesh.acceptCh <- stream - //log.Printf("Adding stream %v\n", id) return stream } } diff --git a/internal/multiplex/stream.go b/internal/multiplex/stream.go index 7b3c679..c9f9009 100644 --- a/internal/multiplex/stream.go +++ b/internal/multiplex/stream.go @@ -5,7 +5,7 @@ import ( "net" "time" - //"log" + log "github.com/sirupsen/logrus" "math" prand "math/rand" "sync" @@ -48,6 +48,7 @@ func makeStream(id uint32, sesh *Session) *Stream { sortedBuf: NewBufferedPipe(), } go stream.recvNewFrame() + log.Tracef("stream %v opened", id) return stream } @@ -112,7 +113,7 @@ func (s *Stream) _close() { func (s *Stream) passiveClose() { s._close() s.session.delStream(s.id) - //log.Printf("%v passive closing\n", stream.id) + log.WithField("streamId", s.id).Trace("stream passively closed") } // active close. Close locally and tell the remote that this stream is being closed @@ -140,7 +141,7 @@ func (s *Stream) Close() error { s._close() s.session.delStream(s.id) - //log.Printf("%v actively closed\n", stream.id) + log.WithField("streamId", s.id).Trace("stream actively closed") return nil } @@ -149,6 +150,7 @@ func (s *Stream) Close() error { // We don't notify the remote because session.Close() is always // called when the session is passively closed func (s *Stream) closeNoDelMap() { + log.WithField("streamId", s.id).Trace("stream closed by session") s._close() } diff --git a/internal/multiplex/switchboard.go b/internal/multiplex/switchboard.go index 2fdc2fc..e3bc171 100644 --- a/internal/multiplex/switchboard.go +++ b/internal/multiplex/switchboard.go @@ -2,7 +2,7 @@ package multiplex import ( "errors" - "log" + log "github.com/sirupsen/logrus" "net" "sync" "sync/atomic" @@ -129,7 +129,7 @@ func (sb *switchboard) deplex(ce *connEnclave) { sb.rxWait(n) sb.Valve.AddRx(int64(n)) if err != nil { - //log.Println(err) + log.Tracef("a connection for session %v has closed: %v", sb.session.id, err) go ce.remoteConn.Close() sb.removeConn(ce) return @@ -137,7 +137,7 @@ func (sb *switchboard) deplex(ce *connEnclave) { frame, err := sb.session.deobfs(buf[:n]) if err != nil { - log.Println(err) + log.Debugf("Failed to decrypt a frame for session %v: %v", sb.session.id, err) continue } diff --git a/internal/server/auth.go b/internal/server/auth.go index 981b58f..aa13f47 100644 --- a/internal/server/auth.go +++ b/internal/server/auth.go @@ -3,12 +3,18 @@ package server import ( "bytes" "encoding/binary" + "errors" + "fmt" "github.com/cbeuw/Cloak/internal/ecdh" "github.com/cbeuw/Cloak/internal/util" - "log" ) -func TouchStone(ch *ClientHello, sta *State) (isCK bool, UID []byte, sessionID uint32, proxyMethod string, encryptionMethod byte, sharedSecret []byte) { +var ErrReplay = errors.New("duplicate random") +var ErrInvalidPubKey = errors.New("public key has invalid format") +var ErrCiphertextLength = errors.New("ciphertext has the wrong length") +var ErrTimestampOutOfWindow = errors.New("timestamp is outside of the accepting window") + +func TouchStone(ch *ClientHello, sta *State) (UID []byte, sessionID uint32, proxyMethod string, encryptionMethod byte, sharedSecret []byte, err error) { var random [32]byte copy(random[:], ch.random) @@ -18,27 +24,31 @@ func TouchStone(ch *ClientHello, sta *State) (isCK bool, UID []byte, sessionID u sta.usedRandomM.Unlock() if used != 0 { - log.Println("Replay! Duplicate random") + err = ErrReplay return } ephPub, ok := ecdh.Unmarshal(random[:]) if !ok { + err = ErrInvalidPubKey return } sharedSecret = ecdh.GenerateSharedSecret(sta.staticPv, ephPub) - keyShare, err := parseKeyShare(ch.extensions[[2]byte{0x00, 0x33}]) + var keyShare []byte + keyShare, err = parseKeyShare(ch.extensions[[2]byte{0x00, 0x33}]) if err != nil { return } - ciphertext := append(ch.sessionId, keyShare...) + ciphertext := append(ch.sessionId, keyShare...) if len(ciphertext) != 64 { + err = fmt.Errorf("%v: %v", ErrCiphertextLength, len(ciphertext)) return } - plaintext, err := util.AESGCMDecrypt(random[0:12], sharedSecret, ciphertext) + var plaintext []byte + plaintext, err = util.AESGCMDecrypt(random[0:12], sharedSecret, ciphertext) if err != nil { return } @@ -48,11 +58,9 @@ func TouchStone(ch *ClientHello, sta *State) (isCK bool, UID []byte, sessionID u encryptionMethod = plaintext[28] timestamp := int64(binary.BigEndian.Uint64(plaintext[29:37])) if timestamp/int64(TIMESTAMP_WINDOW.Seconds()) != sta.Now().Unix()/int64(TIMESTAMP_WINDOW.Seconds()) { - isCK = false + err = fmt.Errorf("%v: received timestamp %v", ErrTimestampOutOfWindow, timestamp) return } sessionID = binary.BigEndian.Uint32(plaintext[37:41]) - - isCK = true return } diff --git a/internal/server/um_local.go b/internal/server/um_local.go index 2c9cbec..423a4b8 100644 --- a/internal/server/um_local.go +++ b/internal/server/um_local.go @@ -2,7 +2,7 @@ package server import ( "encoding/binary" - "log" + log "github.com/sirupsen/logrus" "net/http" "time" @@ -157,7 +157,7 @@ func (manager *localManager) uploadStatus(uploads []statusUpdate) ([]statusRespo } err := bucket.Put([]byte("UpCredit"), i64ToB(newUp)) if err != nil { - log.Println(err) + log.Error(err) continue } @@ -174,7 +174,7 @@ func (manager *localManager) uploadStatus(uploads []statusUpdate) ([]statusRespo } err = bucket.Put([]byte("DownCredit"), i64ToB(newDown)) if err != nil { - log.Println(err) + log.Error(err) continue } diff --git a/internal/server/userpanel.go b/internal/server/userpanel.go index 9efade4..34bcdfb 100644 --- a/internal/server/userpanel.go +++ b/internal/server/userpanel.go @@ -1,12 +1,12 @@ package server import ( - "log" "sync" "sync/atomic" "time" mux "github.com/cbeuw/Cloak/internal/multiplex" + log "github.com/sirupsen/logrus" ) type userPanel struct { @@ -101,7 +101,7 @@ func (panel *userPanel) updateUsageQueueForOne(user *ActiveUser) { } -func (panel *userPanel) commitUpdate() { +func (panel *userPanel) commitUpdate() error { panel.usageUpdateQueueM.Lock() statuses := make([]statusUpdate, 0, len(panel.usageUpdateQueue)) for arrUID, usage := range panel.usageUpdateQueue { @@ -125,7 +125,7 @@ func (panel *userPanel) commitUpdate() { responses, err := panel.Manager.uploadStatus(statuses) if err != nil { - log.Println(err) + return err } for _, resp := range responses { var arrUID [16]byte @@ -142,6 +142,7 @@ func (panel *userPanel) commitUpdate() { } panel.usageUpdateQueue = make(map[[16]byte]*usagePair) panel.usageUpdateQueueM.Unlock() + return nil } func (panel *userPanel) regularQueueUpload() { @@ -149,7 +150,10 @@ func (panel *userPanel) regularQueueUpload() { time.Sleep(1 * time.Minute) go func() { panel.updateUsageQueue() - panel.commitUpdate() + err := panel.commitUpdate() + if err != nil { + log.Error(err) + } }() } } diff --git a/internal/util/util.go b/internal/util/util.go index 524ae69..ff26202 100644 --- a/internal/util/util.go +++ b/internal/util/util.go @@ -8,7 +8,6 @@ import ( mux "github.com/cbeuw/Cloak/internal/multiplex" "golang.org/x/crypto/chacha20poly1305" "io" - prand "math/rand" "net" "strconv" ) @@ -41,14 +40,6 @@ func AESGCMDecrypt(nonce []byte, key []byte, ciphertext []byte) ([]byte, error) return plain, nil } -// PsudoRandBytes returns a byte slice filled with psudorandom bytes generated by the seed -func PsudoRandBytes(length int, seed int64) []byte { - r := prand.New(prand.NewSource(seed)) - ret := make([]byte, length) - r.Read(ret) - return ret -} - // ReadTLS reads TLS data according to its record layer func ReadTLS(conn net.Conn, buffer []byte) (n int, err error) { // TCP is a stream. Multiple TLS messages can arrive at the same time, @@ -130,9 +121,3 @@ func AddRecordLayer(input []byte, typ []byte, ver []byte) []byte { copy(ret[5:], input) return ret } - -// PeelRecordLayer peels off the record layer -func PeelRecordLayer(data []byte) []byte { - ret := data[5:] - return ret -}